tor-browser

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

commit 3f5d16c26e27ec58eda51483b368e9519213c911
parent acc5989a8cd4cdd29726fd441e5a3c852ae778ba
Author: Andreas Pehrson <apehrson@mozilla.com>
Date:   Thu, 23 Oct 2025 14:11:18 +0000

Bug 1771789 - Deep-clone track sources for correct settings synchronously. r=jib

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

Diffstat:
Mdom/media/MediaManager.cpp | 2++
Mdom/media/webrtc/MediaEngine.h | 7+++++++
Mdom/media/webrtc/MediaEngineFake.cpp | 28++++++++++++++++++++++++++++
Mdom/media/webrtc/MediaEngineFake.h | 2++
Mdom/media/webrtc/MediaEngineRemoteVideoSource.cpp | 20++++++++++++++++++--
Mdom/media/webrtc/MediaEngineRemoteVideoSource.h | 6+++++-
Mdom/media/webrtc/MediaEngineWebRTC.cpp | 19+++++++++++++++++++
Mdom/media/webrtc/MediaEngineWebRTC.h | 2++
Mdom/media/webrtc/MediaEngineWebRTCAudio.cpp | 11+++++++++++
Mdom/media/webrtc/MediaEngineWebRTCAudio.h | 4++++
10 files changed, 98 insertions(+), 3 deletions(-)

diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp @@ -1297,6 +1297,8 @@ nsresult LocalMediaDevice::Deallocate() { already_AddRefed<LocalMediaDevice> LocalMediaDevice::Clone() const { MOZ_ASSERT(NS_IsMainThread()); auto device = MakeRefPtr<LocalMediaDevice>(mRawDevice, mID, mGroupID, mName); + device->mSource = + mRawDevice->mEngine->CreateSourceFrom(mSource, device->mRawDevice); #ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED // The source is normally created on the MediaManager thread. But for cloning, // it ends up being created on main thread. Make sure its owning event target diff --git a/dom/media/webrtc/MediaEngine.h b/dom/media/webrtc/MediaEngine.h @@ -50,6 +50,13 @@ class MediaEngine { virtual RefPtr<MediaEngineSource> CreateSource( const MediaDevice* aDevice) = 0; + /** + * Like CreateSource but in addition copies over capabilities and settings + * from another source. + */ + virtual RefPtr<MediaEngineSource> CreateSourceFrom( + const MediaEngineSource* aSource, const MediaDevice* aDevice) = 0; + virtual MediaEventSource<void>& DeviceListChangeEvent() = 0; /** * Return true if devices returned from EnumerateDevices are emulated media diff --git a/dom/media/webrtc/MediaEngineFake.cpp b/dom/media/webrtc/MediaEngineFake.cpp @@ -86,6 +86,9 @@ class MediaEngineFakeVideoSource : public MediaEngineSource { public: MediaEngineFakeVideoSource(); + static already_AddRefed<MediaEngineFakeVideoSource> CreateFrom( + const MediaEngineFakeVideoSource* aSource); + static nsString GetGroupId(); nsresult Allocate(const dom::MediaTrackConstraints& aConstraints, @@ -143,6 +146,15 @@ MediaEngineFakeVideoSource::MediaEngineFakeVideoSource() dom::GetEnumString(dom::VideoResizeModeEnum::None))); } +/*static*/ already_AddRefed<MediaEngineFakeVideoSource> +MediaEngineFakeVideoSource::CreateFrom( + const MediaEngineFakeVideoSource* aSource) { + auto src = MakeRefPtr<MediaEngineFakeVideoSource>(); + *static_cast<MediaTrackSettings*>(src->mSettings) = *aSource->mSettings; + src->mOpts = aSource->mOpts; + return src.forget(); +} + nsString MediaEngineFakeVideoSource::GetGroupId() { return u"Fake Video Group"_ns; } @@ -616,4 +628,20 @@ RefPtr<MediaEngineSource> MediaEngineFake::CreateSource( } } +RefPtr<MediaEngineSource> MediaEngineFake::CreateSourceFrom( + const MediaEngineSource* aSource, const MediaDevice* aMediaDevice) { + MOZ_ASSERT(aMediaDevice->mEngine == this); + switch (aMediaDevice->mMediaSource) { + case MediaSourceEnum::Camera: + return MediaEngineFakeVideoSource::CreateFrom( + static_cast<const MediaEngineFakeVideoSource*>(aSource)); + case MediaSourceEnum::Microphone: + // No main thread members that need to be deep cloned. + return new MediaEngineFakeAudioSource(); + default: + MOZ_ASSERT_UNREACHABLE("Unsupported source type"); + return nullptr; + } +} + } // namespace mozilla diff --git a/dom/media/webrtc/MediaEngineFake.h b/dom/media/webrtc/MediaEngineFake.h @@ -22,6 +22,8 @@ class MediaEngineFake : public MediaEngine { nsTArray<RefPtr<MediaDevice>>*) override; void Shutdown() override {} RefPtr<MediaEngineSource> CreateSource(const MediaDevice* aDevice) override; + RefPtr<MediaEngineSource> CreateSourceFrom( + const MediaEngineSource* aSource, const MediaDevice* aDevice) override; MediaEventSource<void>& DeviceListChangeEvent() override { return mDeviceListChangeEvent; diff --git a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp @@ -203,6 +203,22 @@ MediaEngineRemoteVideoSource::MediaEngineRemoteVideoSource( } } +/*static*/ +already_AddRefed<MediaEngineRemoteVideoSource> +MediaEngineRemoteVideoSource::CreateFrom( + const MediaEngineRemoteVideoSource* aSource, + const MediaDevice* aMediaDevice) { + auto src = MakeRefPtr<MediaEngineRemoteVideoSource>(aMediaDevice); + *static_cast<MediaTrackSettings*>(src->mSettings) = *aSource->mSettings; + *static_cast<MediaTrackCapabilities*>(src->mTrackCapabilities) = + *aSource->mTrackCapabilities; + { + MutexAutoLock lock(aSource->mMutex); + src->mIncomingImageSize = aSource->mIncomingImageSize; + } + return src.forget(); +} + MediaEngineRemoteVideoSource::~MediaEngineRemoteVideoSource() { mFirstFramePromiseHolder.RejectIfExists(NS_ERROR_ABORT, __func__); } @@ -283,8 +299,8 @@ nsresult MediaEngineRemoteVideoSource::Allocate( .mCapabilityWidth = cw ? Some(cw) : Nothing(), .mCapabilityHeight = ch ? Some(ch) : Nothing(), .mCapEngine = mCapEngine, - .mInputWidth = cw, - .mInputHeight = ch, + .mInputWidth = cw ? cw : mIncomingImageSize.width, + .mInputHeight = ch ? ch : mIncomingImageSize.height, .mRotation = 0, }; framerate = input.mCanCropAndScale.valueOr(false) diff --git a/dom/media/webrtc/MediaEngineRemoteVideoSource.h b/dom/media/webrtc/MediaEngineRemoteVideoSource.h @@ -88,6 +88,10 @@ class MediaEngineRemoteVideoSource : public MediaEngineSource, public: explicit MediaEngineRemoteVideoSource(const MediaDevice* aMediaDevice); + static already_AddRefed<MediaEngineRemoteVideoSource> CreateFrom( + const MediaEngineRemoteVideoSource* aSource, + const MediaDevice* aMediaDevice); + // ExternalRenderer /** * Signals that the capture stream has ended @@ -161,7 +165,7 @@ class MediaEngineRemoteVideoSource : public MediaEngineSource, // mMutex protects certain members on 3 threads: // MediaManager, Cameras IPC and MediaTrackGraph. - Mutex mMutex MOZ_UNANNOTATED; + mutable Mutex mMutex MOZ_UNANNOTATED; // Current state of this source. // Set under mMutex on the owning thread. Accessed under one of the two. diff --git a/dom/media/webrtc/MediaEngineWebRTC.cpp b/dom/media/webrtc/MediaEngineWebRTC.cpp @@ -299,6 +299,25 @@ RefPtr<MediaEngineSource> MediaEngineWebRTC::CreateSource( } } +RefPtr<MediaEngineSource> MediaEngineWebRTC::CreateSourceFrom( + const MediaEngineSource* aSource, const MediaDevice* aMediaDevice) { + MOZ_ASSERT(aMediaDevice->mEngine == this); + if (MediaEngineSource::IsVideo(aMediaDevice->mMediaSource)) { + return MediaEngineRemoteVideoSource::CreateFrom( + static_cast<const MediaEngineRemoteVideoSource*>(aSource), + aMediaDevice); + } + switch (aMediaDevice->mMediaSource) { + case MediaSourceEnum::Microphone: + return MediaEngineWebRTCMicrophoneSource::CreateFrom( + static_cast<const MediaEngineWebRTCMicrophoneSource*>(aSource), + aMediaDevice); + default: + MOZ_CRASH("Unsupported source type"); + return nullptr; + } +} + void MediaEngineWebRTC::Shutdown() { AssertIsOnOwningThread(); mCameraListChangeListener.DisconnectIfExists(); diff --git a/dom/media/webrtc/MediaEngineWebRTC.h b/dom/media/webrtc/MediaEngineWebRTC.h @@ -27,6 +27,8 @@ class MediaEngineWebRTC : public MediaEngine { void EnumerateDevices(dom::MediaSourceEnum, MediaSinkEnum, nsTArray<RefPtr<MediaDevice>>*) override; RefPtr<MediaEngineSource> CreateSource(const MediaDevice* aDevice) override; + RefPtr<MediaEngineSource> CreateSourceFrom(const MediaEngineSource* aSource, + const MediaDevice*) override; MediaEventSource<void>& DeviceListChangeEvent() override { return mDeviceListChangeEvent; diff --git a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp @@ -113,6 +113,17 @@ MediaEngineWebRTCMicrophoneSource::MediaEngineWebRTCMicrophoneSource( })); } +/*static*/ already_AddRefed<MediaEngineWebRTCMicrophoneSource> +MediaEngineWebRTCMicrophoneSource::CreateFrom( + const MediaEngineWebRTCMicrophoneSource* aSource, + const MediaDevice* aMediaDevice) { + auto src = MakeRefPtr<MediaEngineWebRTCMicrophoneSource>(aMediaDevice); + *static_cast<dom::MediaTrackSettings*>(src->mSettings) = *aSource->mSettings; + *static_cast<dom::MediaTrackCapabilities*>(src->mCapabilities) = + *aSource->mCapabilities; + return src.forget(); +} + nsresult MediaEngineWebRTCMicrophoneSource::EvaluateSettings( const NormalizedConstraints& aConstraintsUpdate, const MediaEnginePrefs& aInPrefs, MediaEnginePrefs* aOutPrefs, diff --git a/dom/media/webrtc/MediaEngineWebRTCAudio.h b/dom/media/webrtc/MediaEngineWebRTCAudio.h @@ -34,6 +34,10 @@ class MediaEngineWebRTCMicrophoneSource : public MediaEngineSource { public: explicit MediaEngineWebRTCMicrophoneSource(const MediaDevice* aMediaDevice); + static already_AddRefed<MediaEngineWebRTCMicrophoneSource> CreateFrom( + const MediaEngineWebRTCMicrophoneSource* aSource, + const MediaDevice* aMediaDevice); + nsresult Allocate(const dom::MediaTrackConstraints& aConstraints, const MediaEnginePrefs& aPrefs, uint64_t aWindowID, const char** aOutBadConstraint) override;