tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit b632604cf8b8f3fe769ddf1cf82f02627b29b915
parent a6fe17852ae81dec0d634665abac2de42d93cec0
Author: Karl Tomlinson <karlt+@karlt.net>
Date:   Wed, 17 Dec 2025 12:38:42 +0000

Bug 2005992 Switch MediaTrackGraph drivers only in CheckDriver() r=padenot

This coalesces changes and consolidates logic in one place.

DeviceInputTrack is an AUDIO track and so CloseAudioInputImpl() never switched
to a SystemClockDriver, until CheckDriver() reconsidered on the next iteration.

This covered over the omission of mPendingResumeOperations logic in the choice
of driver.

Differential Revision: https://phabricator.services.mozilla.com/D276412

Diffstat:
Mdom/media/GraphDriver.h | 8+++++---
Mdom/media/MediaTrackGraph.cpp | 163+++++++++++++++++++++++--------------------------------------------------------
Mdom/media/gtest/TestAudioTrackGraph.cpp | 2++
3 files changed, 54 insertions(+), 119 deletions(-)

diff --git a/dom/media/GraphDriver.h b/dom/media/GraphDriver.h @@ -631,11 +631,13 @@ class AudioCallbackDriver final : public GraphDriver, return this; } - uint32_t OutputChannelCount() { return mOutputChannelCount; } + uint32_t OutputChannelCount() const { return mOutputChannelCount; } - uint32_t InputChannelCount() { return mInputChannelCount; } + uint32_t InputChannelCount() const { return mInputChannelCount; } - AudioInputType InputDevicePreference() { + CubebUtils::AudioDeviceID InputDeviceID() const { return mInputDeviceID; } + + AudioInputType InputDevicePreference() const { if (mInputDevicePreference == CUBEB_DEVICE_PREF_VOICE) { return AudioInputType::Voice; } diff --git a/dom/media/MediaTrackGraph.cpp b/dom/media/MediaTrackGraph.cpp @@ -400,8 +400,7 @@ bool MediaTrackGraphImpl::AudioTrackPresent() { void MediaTrackGraphImpl::CheckDriver() { MOZ_ASSERT(OnGraphThread()); // An offline graph has only one driver. - // Otherwise, if a switch is already pending, let that happen. - if (!mRealtime || Switching()) { + if (!mRealtime) { return; } @@ -449,13 +448,16 @@ void MediaTrackGraphImpl::CheckDriver() { return; } - // Check if this graph should switch to a different number of output channels. - // Generally, a driver switch is explicitly made by an event (e.g., setting + // Check if a new driver is required for a configuration change. Generally, + // a driver switch is explicitly triggered by an event (e.g., setting // the AudioDestinationNode channelCount), but if an HTMLMediaElement is // directly playing back via another HTMLMediaElement, the number of channels // of the media determines how many channels to output, and it can change // dynamically. - if (primaryOutputChannelCount != audioCallbackDriver->OutputChannelCount()) { + if (primaryOutputChannelCount != audioCallbackDriver->OutputChannelCount() || + inputDevice != audioCallbackDriver->InputDeviceID() || + inputChannelCount != audioCallbackDriver->InputChannelCount() || + inputPreference != audioCallbackDriver->InputDevicePreference()) { AudioCallbackDriver* driver = new AudioCallbackDriver( this, CurrentDriver(), mSampleRate, primaryOutputChannelCount, inputChannelCount, PrimaryOutputDeviceID(), inputDevice, @@ -768,28 +770,19 @@ void MediaTrackGraphImpl::OpenAudioInputImpl(DeviceInputTrack* aTrack) { mDeviceInputTrackManagerGraphThread.Add(aTrack); if (aTrack->AsNativeInputTrack()) { - // Switch Drivers since we're adding input (to input-only or full-duplex) - AudioCallbackDriver* driver = new AudioCallbackDriver( - this, CurrentDriver(), mSampleRate, PrimaryOutputChannelCount(), - AudioInputChannelCount(aTrack->mDeviceId), PrimaryOutputDeviceID(), - aTrack->mDeviceId, AudioInputDevicePreference(aTrack->mDeviceId), - Some(aTrack->UpdateRequestedProcessingParams())); - LOG(LogLevel::Debug, - ("%p OpenAudioInputImpl: starting new AudioCallbackDriver(input) %p", - this, driver)); - SwitchAtNextIteration(driver); - } else { - NonNativeInputTrack* nonNative = aTrack->AsNonNativeInputTrack(); - MOZ_ASSERT(nonNative); - // Start non-native input right away. - nonNative->StartAudio(MakeRefPtr<AudioInputSource>( - MakeRefPtr<AudioInputSourceListener>(nonNative), - nonNative->GenerateSourceId(), nonNative->mDeviceId, - AudioInputChannelCount(nonNative->mDeviceId), - AudioInputDevicePreference(nonNative->mDeviceId) == - AudioInputType::Voice, - nonNative->mPrincipalHandle, nonNative->mSampleRate, GraphRate())); + // CheckDriver() will check for changes, after all control messages are + // processed. + return; } + NonNativeInputTrack* nonNative = aTrack->AsNonNativeInputTrack(); + MOZ_ASSERT(nonNative); + // Start non-native input right away. + nonNative->StartAudio(MakeRefPtr<AudioInputSource>( + MakeRefPtr<AudioInputSourceListener>(nonNative), + nonNative->GenerateSourceId(), nonNative->mDeviceId, + AudioInputChannelCount(nonNative->mDeviceId), + AudioInputDevicePreference(nonNative->mDeviceId) == AudioInputType::Voice, + nonNative->mPrincipalHandle, nonNative->mSampleRate, GraphRate())); } void MediaTrackGraphImpl::OpenAudioInput(DeviceInputTrack* aTrack) { @@ -832,30 +825,8 @@ void MediaTrackGraphImpl::CloseAudioInputImpl(DeviceInputTrack* aTrack) { MOZ_ASSERT(aTrack->AsNativeInputTrack()); mDeviceInputTrackManagerGraphThread.Remove(aTrack); - - // Switch Drivers since we're adding or removing an input (to nothing/system - // or output only) - bool audioTrackPresent = AudioTrackPresent(); - - GraphDriver* driver; - if (audioTrackPresent) { - // We still have audio output - LOG(LogLevel::Debug, - ("%p: CloseInput: output present (AudioCallback)", this)); - - driver = new AudioCallbackDriver( - this, CurrentDriver(), mSampleRate, PrimaryOutputChannelCount(), - AudioInputChannelCount(aTrack->mDeviceId), PrimaryOutputDeviceID(), - nullptr, AudioInputDevicePreference(aTrack->mDeviceId), - Some(aTrack->UpdateRequestedProcessingParams())); - SwitchAtNextIteration(driver); - } else if (CurrentDriver()->AsAudioCallbackDriver()) { - LOG(LogLevel::Debug, - ("%p: CloseInput: no output present (SystemClockCallback)", this)); - - driver = new SystemClockDriver(this, CurrentDriver(), mSampleRate); - SwitchAtNextIteration(driver); - } // else SystemClockDriver->SystemClockDriver, no switch + // CheckDriver() will check for changes, after all control messages are + // processed. } void MediaTrackGraphImpl::UnregisterAllAudioOutputs(MediaTrack* aTrack) { @@ -1083,79 +1054,39 @@ void MediaTrackGraphImpl::ReevaluateInputDevice(CubebUtils::AudioDeviceID aID) { ("%p: No DeviceInputTrack for this device. Ignore", this)); return; } - - bool needToSwitch = false; - - if (NonNativeInputTrack* nonNative = track->AsNonNativeInputTrack()) { - if (nonNative->NumberOfChannels() != AudioInputChannelCount(aID)) { - LOG(LogLevel::Debug, - ("%p: %u-channel non-native input device %p (track %p) is " - "re-configured to %d-channel", - this, nonNative->NumberOfChannels(), aID, track, - AudioInputChannelCount(aID))); - needToSwitch = true; - } - if (nonNative->DevicePreference() != AudioInputDevicePreference(aID)) { - LOG(LogLevel::Debug, - ("%p: %s-type non-native input device %p (track %p) is re-configured " - "to %s-type", - this, GetAudioInputTypeString(nonNative->DevicePreference()), aID, - track, GetAudioInputTypeString(AudioInputDevicePreference(aID)))); - needToSwitch = true; - } - - if (needToSwitch) { - nonNative->StopAudio(); - nonNative->StartAudio(MakeRefPtr<AudioInputSource>( - MakeRefPtr<AudioInputSourceListener>(nonNative), - nonNative->GenerateSourceId(), aID, AudioInputChannelCount(aID), - AudioInputDevicePreference(aID) == AudioInputType::Voice, - nonNative->mPrincipalHandle, nonNative->mSampleRate, GraphRate())); - } - + if (track->AsNativeInputTrack()) { + // CheckDriver() will check for changes, after all control messages are + // processed. return; } + bool needToSwitch = false; - MOZ_ASSERT(track->AsNativeInputTrack()); - - if (AudioCallbackDriver* audioCallbackDriver = - CurrentDriver()->AsAudioCallbackDriver()) { - if (audioCallbackDriver->InputChannelCount() != - AudioInputChannelCount(aID)) { - LOG(LogLevel::Debug, - ("%p: ReevaluateInputDevice: %u-channel AudioCallbackDriver %p is " - "re-configured to %d-channel", - this, audioCallbackDriver->InputChannelCount(), audioCallbackDriver, - AudioInputChannelCount(aID))); - needToSwitch = true; - } - if (audioCallbackDriver->InputDevicePreference() != - AudioInputDevicePreference(aID)) { - LOG(LogLevel::Debug, - ("%p: ReevaluateInputDevice: %s-type AudioCallbackDriver %p is " - "re-configured to %s-type", - this, - GetAudioInputTypeString( - audioCallbackDriver->InputDevicePreference()), - audioCallbackDriver, - GetAudioInputTypeString(AudioInputDevicePreference(aID)))); - needToSwitch = true; - } - } else if (Switching() && NextDriver()->AsAudioCallbackDriver()) { - // We're already in the process of switching to a audio callback driver, - // which will happen at the next iteration. - // However, maybe it's not the correct number of channels. Re-query the - // correct channel amount at this time. + NonNativeInputTrack* nonNative = track->AsNonNativeInputTrack(); + MOZ_ASSERT(nonNative); + if (nonNative->NumberOfChannels() != AudioInputChannelCount(aID)) { + LOG(LogLevel::Debug, + ("%p: %u-channel non-native input device %p (track %p) is " + "re-configured to %d-channel", + this, nonNative->NumberOfChannels(), aID, track, + AudioInputChannelCount(aID))); + needToSwitch = true; + } + if (nonNative->DevicePreference() != AudioInputDevicePreference(aID)) { + LOG(LogLevel::Debug, + ("%p: %s-type non-native input device %p (track %p) is re-configured " + "to %s-type", + this, GetAudioInputTypeString(nonNative->DevicePreference()), aID, + track, GetAudioInputTypeString(AudioInputDevicePreference(aID)))); needToSwitch = true; } if (needToSwitch) { - AudioCallbackDriver* newDriver = new AudioCallbackDriver( - this, CurrentDriver(), mSampleRate, PrimaryOutputChannelCount(), - AudioInputChannelCount(aID), PrimaryOutputDeviceID(), aID, - AudioInputDevicePreference(aID), - Some(track->UpdateRequestedProcessingParams())); - SwitchAtNextIteration(newDriver); + nonNative->StopAudio(); + nonNative->StartAudio(MakeRefPtr<AudioInputSource>( + MakeRefPtr<AudioInputSourceListener>(nonNative), + nonNative->GenerateSourceId(), aID, AudioInputChannelCount(aID), + AudioInputDevicePreference(aID) == AudioInputType::Voice, + nonNative->mPrincipalHandle, nonNative->mSampleRate, GraphRate())); } } diff --git a/dom/media/gtest/TestAudioTrackGraph.cpp b/dom/media/gtest/TestAudioTrackGraph.cpp @@ -2960,6 +2960,8 @@ TEST(TestAudioTrackGraph, PlatformProcessing) // Switch driver. EXPECT_CALL(*listener, RequestedInputChannelCount).WillRepeatedly(Return(2)); + // ReevaluateInputDevice() is not required for the native input, but is + // called anyway. DispatchFunction([&] { track->QueueControlMessageWithNoShutdown( [&] { graph->ReevaluateInputDevice(device); });