зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1651745 - Signal AudioInputProcessing on input stream stop instead of driver start. r=padenot
Without this patch, AudioInputProcessing wouldn't be aware of an audio driver changing to another driver, be it a system driver or an audio driver that starts on its fallback. It could fail an assert since neither of those new drivers would append any input data, so AudioInputProcessing would run out of buffered data but not know to reset the state doing the bookkeeping for this. Differential Revision: https://phabricator.services.mozilla.com/D95938
This commit is contained in:
Родитель
e6ea00c8f4
Коммит
124f2d951b
|
@ -387,8 +387,8 @@ class AudioCallbackDriver::FallbackWrapper : public GraphInterface {
|
|||
TrackRate aRate, uint32_t aChannels) override {
|
||||
MOZ_CRASH("Unexpected NotifyOutputData from fallback SystemClockDriver");
|
||||
}
|
||||
void NotifyStarted() override {
|
||||
MOZ_CRASH("Unexpected NotifyStarted from fallback SystemClockDriver");
|
||||
void NotifyInputStopped() override {
|
||||
MOZ_CRASH("Unexpected NotifyInputStopped from fallback SystemClockDriver");
|
||||
}
|
||||
void NotifyInputData(const AudioDataValue* aBuffer, size_t aFrames,
|
||||
TrackRate aRate, uint32_t aChannels) override {
|
||||
|
@ -730,7 +730,6 @@ void AudioCallbackDriver::Start() {
|
|||
MOZ_ASSERT(mAudioStreamState == AudioStreamState::None);
|
||||
MOZ_ASSERT_IF(PreviousDriver(), PreviousDriver()->InIteration());
|
||||
mAudioStreamState = AudioStreamState::Pending;
|
||||
mRanFirstIteration = false;
|
||||
|
||||
if (mFallbackDriverState == FallbackDriverState::None) {
|
||||
// Starting an audio driver could take a while. We start a system driver in
|
||||
|
@ -893,11 +892,6 @@ long AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer,
|
|||
AutoInCallback aic(this);
|
||||
#endif
|
||||
|
||||
if (!mRanFirstIteration) {
|
||||
Graph()->NotifyStarted();
|
||||
mRanFirstIteration = true;
|
||||
}
|
||||
|
||||
uint32_t durationMS = aFrames * 1000 / mSampleRate;
|
||||
|
||||
// For now, simply average the duration with the previous
|
||||
|
@ -1008,6 +1002,9 @@ long AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer,
|
|||
aFrames * mOutputChannelCount);
|
||||
|
||||
if (result.IsStop()) {
|
||||
if (mInputDeviceID) {
|
||||
mGraphInterface->NotifyInputStopped();
|
||||
}
|
||||
// Signal that we have stopped.
|
||||
result.Stopped();
|
||||
// Update the flag before handing over the graph and going to drain.
|
||||
|
@ -1022,6 +1019,9 @@ long AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer,
|
|||
LOG(LogLevel::Debug,
|
||||
("%p: Switching to %s driver.", Graph(),
|
||||
nextDriver->AsAudioCallbackDriver() ? "audio" : "system"));
|
||||
if (mInputDeviceID) {
|
||||
mGraphInterface->NotifyInputStopped();
|
||||
}
|
||||
result.Switched();
|
||||
mAudioStreamState = AudioStreamState::Stopping;
|
||||
nextDriver->SetState(mIterationStart, mIterationEnd, mStateComputedTime);
|
||||
|
@ -1075,6 +1075,14 @@ void AudioCallbackDriver::StateCallback(cubeb_state aState) {
|
|||
// Only switch to fallback if it's not already running. It could be
|
||||
// running with the callback driver having started but not seen a single
|
||||
// callback yet. I.e., handover from fallback to callback is not done.
|
||||
if (mInputDeviceID) {
|
||||
#ifdef DEBUG
|
||||
// No audio callback after an error. We're calling into the graph here
|
||||
// so we need to be regarded as "in iteration".
|
||||
AutoInCallback aic(this);
|
||||
#endif
|
||||
mGraphInterface->NotifyInputStopped();
|
||||
}
|
||||
FallbackToSystemClockDriver();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -179,9 +179,9 @@ struct GraphInterface : public nsISupports {
|
|||
* This is the mixed audio output of this MediaTrackGraph. */
|
||||
virtual void NotifyOutputData(AudioDataValue* aBuffer, size_t aFrames,
|
||||
TrackRate aRate, uint32_t aChannels) = 0;
|
||||
/* Called on the graph thread before the first Notify*Data after an
|
||||
* AudioCallbackDriver starts. */
|
||||
virtual void NotifyStarted() = 0;
|
||||
/* Called on the graph thread after an AudioCallbackDriver with an input
|
||||
* stream has stopped. */
|
||||
virtual void NotifyInputStopped() = 0;
|
||||
/* Called on the graph thread when there is new input data for listeners. This
|
||||
* is the raw audio input for this MediaTrackGraph. */
|
||||
virtual void NotifyInputData(const AudioDataValue* aBuffer, size_t aFrames,
|
||||
|
@ -767,9 +767,6 @@ class AudioCallbackDriver : public GraphDriver,
|
|||
/* SystemClockDriver used as fallback if this AudioCallbackDriver fails to
|
||||
* init or start. */
|
||||
DataMutex<RefPtr<FallbackWrapper>> mFallback;
|
||||
/* Set to true in the first iteration after starting. Accessed in data
|
||||
* callback while running, or in Start(). */
|
||||
bool mRanFirstIteration = false;
|
||||
/* If using a fallback driver, this is the duration to wait after failing to
|
||||
* start it before attempting to start it again. */
|
||||
TimeDuration mNextReInitBackoffStep;
|
||||
|
|
|
@ -816,7 +816,7 @@ void MediaTrackGraphImpl::NotifyOutputData(AudioDataValue* aBuffer,
|
|||
}
|
||||
}
|
||||
|
||||
void MediaTrackGraphImpl::NotifyStarted() {
|
||||
void MediaTrackGraphImpl::NotifyInputStopped() {
|
||||
#ifdef ANDROID
|
||||
if (!mInputDeviceUsers.GetValue(mInputDeviceID)) {
|
||||
return;
|
||||
|
@ -830,7 +830,7 @@ void MediaTrackGraphImpl::NotifyStarted() {
|
|||
mInputDeviceUsers.GetValue(mInputDeviceID);
|
||||
MOZ_ASSERT(listeners);
|
||||
for (auto& listener : *listeners) {
|
||||
listener->NotifyStarted(this);
|
||||
listener->NotifyInputStopped(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -116,10 +116,11 @@ class AudioDataListenerInterface {
|
|||
AudioDataValue* aBuffer, size_t aFrames,
|
||||
TrackRate aRate, uint32_t aChannels) = 0;
|
||||
/**
|
||||
* An AudioCallbackDriver signaling that it has started and may notify of data
|
||||
* soon.
|
||||
* An AudioCallbackDriver with an input stream signaling that it has stopped
|
||||
* for any reason and the AudioDataListener will not be notified of input data
|
||||
* until the driver is restarted or another driver has started.
|
||||
*/
|
||||
virtual void NotifyStarted(MediaTrackGraphImpl* aGraph) = 0;
|
||||
virtual void NotifyInputStopped(MediaTrackGraphImpl* aGraph) = 0;
|
||||
/**
|
||||
* Input data from a microphone (or other audio source. This is not
|
||||
* guaranteed to be in any particular size chunks.
|
||||
|
|
|
@ -424,9 +424,9 @@ class MediaTrackGraphImpl : public MediaTrackGraph,
|
|||
* This is the mixed audio output of this MediaTrackGraph. */
|
||||
void NotifyOutputData(AudioDataValue* aBuffer, size_t aFrames,
|
||||
TrackRate aRate, uint32_t aChannels) override;
|
||||
/* Called on the graph thread before the first Notify*Data after an
|
||||
* AudioCallbackDriver starts. */
|
||||
void NotifyStarted() override;
|
||||
/* Called on the graph thread after an AudioCallbackDriver with an input
|
||||
* stream has stopped. */
|
||||
void NotifyInputStopped() override;
|
||||
/* Called on the graph thread when there is new input data for listeners. This
|
||||
* is the raw audio input for this MediaTrackGraph. */
|
||||
void NotifyInputData(const AudioDataValue* aBuffer, size_t aFrames,
|
||||
|
|
|
@ -25,7 +25,7 @@ class MockGraphInterface : public GraphInterface {
|
|||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
MOCK_METHOD4(NotifyOutputData,
|
||||
void(AudioDataValue*, size_t, TrackRate, uint32_t));
|
||||
MOCK_METHOD0(NotifyStarted, void());
|
||||
MOCK_METHOD0(NotifyInputStopped, void());
|
||||
MOCK_METHOD4(NotifyInputData,
|
||||
void(const AudioDataValue*, size_t, TrackRate, uint32_t));
|
||||
MOCK_METHOD0(DeviceChanged, void());
|
||||
|
@ -58,7 +58,7 @@ MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
|
|||
|
||||
RefPtr<AudioCallbackDriver> driver;
|
||||
auto graph = MakeRefPtr<NiceMock<MockGraphInterface>>();
|
||||
EXPECT_CALL(*graph, NotifyStarted).Times(1);
|
||||
EXPECT_CALL(*graph, NotifyInputStopped).Times(0);
|
||||
ON_CALL(*graph, NotifyOutputData)
|
||||
.WillByDefault([&](AudioDataValue*, size_t, TrackRate, uint32_t) {});
|
||||
|
||||
|
|
|
@ -1118,7 +1118,7 @@ void AudioInputProcessing::InsertInGraph(MediaTrackGraphImpl* aGraph,
|
|||
mSegment.AppendFrames(buffer.forget(), channels, aFrames, mPrincipal);
|
||||
}
|
||||
|
||||
void AudioInputProcessing::NotifyStarted(MediaTrackGraphImpl* aGraph) {
|
||||
void AudioInputProcessing::NotifyInputStopped(MediaTrackGraphImpl* aGraph) {
|
||||
MOZ_ASSERT(aGraph->OnGraphThread());
|
||||
// This is called when an AudioCallbackDriver switch has happened for any
|
||||
// reason, including other reasons than starting this audio input stream. We
|
||||
|
|
|
@ -146,7 +146,7 @@ class AudioInputProcessing : public AudioDataListener {
|
|||
void NotifyOutputData(MediaTrackGraphImpl* aGraph, AudioDataValue* aBuffer,
|
||||
size_t aFrames, TrackRate aRate,
|
||||
uint32_t aChannels) override;
|
||||
void NotifyStarted(MediaTrackGraphImpl* aGraph) override;
|
||||
void NotifyInputStopped(MediaTrackGraphImpl* aGraph) override;
|
||||
void NotifyInputData(MediaTrackGraphImpl* aGraph,
|
||||
const AudioDataValue* aBuffer, size_t aFrames,
|
||||
TrackRate aRate, uint32_t aChannels) override;
|
||||
|
|
Загрузка…
Ссылка в новой задаче