From 85ded5b9580cb19dbfcf08c847bb57baebf511bd Mon Sep 17 00:00:00 2001 From: Andreas Pehrson Date: Fri, 10 Nov 2017 15:55:42 +0100 Subject: [PATCH] Bug 1299515 - Plumb MediaStreamTrack enabled state to sources. r=jib MozReview-Commit-ID: Eg1g9JtLmOz --HG-- extra : rebase_source : 73057e1093d487736f69addca346b05c48d8d280 --- dom/html/HTMLCanvasElement.cpp | 8 ++ dom/html/HTMLMediaElement.cpp | 24 ++++ dom/media/MediaManager.cpp | 123 ++++++++++++++++++ dom/media/MediaStreamTrack.cpp | 1 + dom/media/MediaStreamTrack.h | 56 +++++++- .../MediaStreamAudioDestinationNode.cpp | 8 ++ .../gtest/mediapipeline_unittest.cpp | 9 ++ .../src/peerconnection/RemoteTrackSource.h | 8 ++ 8 files changed, 236 insertions(+), 1 deletion(-) diff --git a/dom/html/HTMLCanvasElement.cpp b/dom/html/HTMLCanvasElement.cpp index 9afbec1736c7..58bf3d301869 100644 --- a/dom/html/HTMLCanvasElement.cpp +++ b/dom/html/HTMLCanvasElement.cpp @@ -720,6 +720,14 @@ public: mCaptureStream->StopCapture(); } + void Disable() override + { + } + + void Enable() override + { + } + private: virtual ~CanvasCaptureTrackSource() {} diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index e319fbcac73c..76ec0969d9ec 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -3248,6 +3248,22 @@ public: return false; } + /** + * Do not keep the track source on. It is controlled by its associated tracks. + */ + bool Enabled() const override + { + return false; + } + + void Disable() override + { + } + + void Enable() override + { + } + void PrincipalChanged() override { if (!mCapturedTrackSource) { @@ -3341,6 +3357,14 @@ public: // based on MediaStreams during capture. } + void Disable() override + { + } + + void Enable() override + { + } + void NotifyDecoderPrincipalChanged() override { nsCOMPtr newPrincipal = mElement->GetCurrentPrincipal(); diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index 0f319fd9dd69..b61097837e88 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -187,6 +187,19 @@ public: */ void StopTrack(TrackID aTrackID); + /** + * Posts a task to disable the device associated with aTrackID and notifies + * the associated window listener that a track has been disabled. + */ + void DisableTrack(TrackID aTrackID); + + + /** + * Posts a task to enable the device associated with aTrackID and notifies + * the associated window listener that a track has been enabled. + */ + void EnableTrack(TrackID aTrackID); + /** * Stops all screen/app/window/audioCapture sharing, but not camera or * microphone. @@ -1119,6 +1132,20 @@ public: } } + void Disable() override + { + if (mListener) { + mListener->DisableTrack(mTrackID); + } + } + + void Enable() override + { + if (mListener) { + mListener->EnableTrack(mTrackID); + } + } + protected: ~LocalTrackSource() {} @@ -3810,6 +3837,102 @@ SourceListener::StopTrack(TrackID aTrackID) mWindowListener->NotifySourceTrackStopped(); } +void +SourceListener::DisableTrack(TrackID aTrackID) +{ + MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread"); + + if (!Activated()) { + MOZ_ASSERT(false, "No device to disable"); + return; + } + + RefPtr device; + + switch (aTrackID) { + case kAudioTrack: { + LOG(("SourceListener %p disabling audio track %d", this, aTrackID)); + if (!mAudioDevice) { + NS_ASSERTION(false, "Can't disable audio. No device."); + return; + } + if (mAudioStopped) { + // Audio stopped. Disabling is pointless. + return; + } + device = mAudioDevice; + break; + } + case kVideoTrack: { + LOG(("SourceListener %p disabling video track %d", this, aTrackID)); + if (!mVideoDevice) { + NS_ASSERTION(false, "Can't disable video. No device."); + return; + } + if (mVideoStopped) { + // Video stopped. Disabling is pointless. + return; + } + device = mVideoDevice; + break; + } + default: { + MOZ_ASSERT(false, "Unknown track id"); + return; + } + } + + // XXX Later patch +} + +void +SourceListener::EnableTrack(TrackID aTrackID) +{ + MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread"); + + if (!Activated()) { + MOZ_ASSERT(false, "No device to enable"); + return; + } + + RefPtr device; + + switch (aTrackID) { + case kAudioTrack: { + LOG(("SourceListener %p enabling audio track %d", this, aTrackID)); + if (!mAudioDevice) { + NS_ASSERTION(false, "Can't enable audio. No device."); + return; + } + if (mAudioStopped) { + // Audio stopped. Enabling is pointless. + return; + } + device = mAudioDevice; + break; + } + case kVideoTrack: { + LOG(("SourceListener %p enabling video track %d", this, aTrackID)); + if (!mVideoDevice) { + NS_ASSERTION(false, "Can't enable video. No device."); + return; + } + if (mVideoStopped) { + // Video stopped. Enabling is pointless. + return; + } + device = mVideoDevice; + break; + } + default: { + MOZ_ASSERT(false, "Unknown track id"); + return; + } + } + + // XXX Later patch +} + void SourceListener::StopSharing() { diff --git a/dom/media/MediaStreamTrack.cpp b/dom/media/MediaStreamTrack.cpp index 31dd2869f453..495a80e11dd9 100644 --- a/dom/media/MediaStreamTrack.cpp +++ b/dom/media/MediaStreamTrack.cpp @@ -222,6 +222,7 @@ MediaStreamTrack::SetEnabled(bool aEnabled) mEnabled = aEnabled; GetOwnedStream()->SetTrackEnabled(mTrackID, mEnabled ? DisabledTrackMode::ENABLED : DisabledTrackMode::SILENCE_BLACK); + GetSource().SinkEnabledStateChanged(); } void diff --git a/dom/media/MediaStreamTrack.h b/dom/media/MediaStreamTrack.h index ae0f1bd34a79..38b1e13ae044 100644 --- a/dom/media/MediaStreamTrack.h +++ b/dom/media/MediaStreamTrack.h @@ -74,6 +74,21 @@ public: */ virtual bool KeepsSourceAlive() const = 0; + /** + * Return true to ensure that the MediaStreamTrackSource where this Sink is + * registered is kept turned on and active. + * Return false to allow the source to pause, and any underlying devices to + * temporarily stop. + * + * When the underlying enabled state of the sink changes, + * call MediaStreamTrackSource::SinkEnabledStateChanged(). + * + * Typically MediaStreamTrack returns the track's enabled state and other + * Sinks (like HTMLMediaElement::StreamCaptureTrackSource) return false so + * control over device state remains with tracks and their enabled state. + */ + virtual bool Enabled() const = 0; + virtual void PrincipalChanged() = 0; virtual void MutedChanged(bool aNewState) = 0; }; @@ -156,6 +171,33 @@ public: */ virtual void Stop() = 0; + /** + * Called by the source interface when all registered sinks with + * KeepsSourceAlive() == true become disabled. + */ + virtual void Disable() = 0; + + /** + * Called by the source interface when at least one registered sink with + * KeepsSourceAlive() == true become enabled. + */ + virtual void Enable() = 0; + + /** + * Called when a Sink's Enabled() state changed. Will iterate through all + * sinks and notify the source of the aggregated enabled state. + * + * Note that a Sink with KeepsSourceAlive() == false counts as disabled. + */ + void SinkEnabledStateChanged() + { + if (IsEnabled()) { + Enable(); + } else { + Disable(); + } + } + /** * Called by each MediaStreamTrack clone on initialization. */ @@ -205,6 +247,16 @@ protected: return false; } + bool IsEnabled() + { + for (const WeakPtr& sink : mSinks) { + if (sink && sink->KeepsSourceAlive() && sink->Enabled()) { + return true; + } + } + return false; + } + /** * Called by a sub class when the principal has changed. * Notifies all sinks. @@ -272,6 +324,8 @@ public: MediaSourceEnum GetMediaSource() const override { return mMediaSource; } void Stop() override {} + void Disable() override {} + void Enable() override {} protected: ~BasicTrackSource() {} @@ -342,7 +396,7 @@ public: virtual void GetKind(nsAString& aKind) = 0; void GetId(nsAString& aID) const; virtual void GetLabel(nsAString& aLabel, CallerType /* aCallerType */) { GetSource().GetLabel(aLabel); } - bool Enabled() { return mEnabled; } + bool Enabled() const override { return mEnabled; } void SetEnabled(bool aEnabled); bool Muted() { return mMuted; } void Stop(); diff --git a/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp b/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp index 98928f57db40..c72b12683a52 100644 --- a/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp +++ b/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp @@ -49,6 +49,14 @@ public: Destroy(); } + void Disable() override + { + } + + void Enable() override + { + } + private: ~AudioDestinationTrackSource() = default; diff --git a/media/webrtc/signaling/gtest/mediapipeline_unittest.cpp b/media/webrtc/signaling/gtest/mediapipeline_unittest.cpp index 4f37af79e308..4d46387638b6 100644 --- a/media/webrtc/signaling/gtest/mediapipeline_unittest.cpp +++ b/media/webrtc/signaling/gtest/mediapipeline_unittest.cpp @@ -72,6 +72,15 @@ public: return mozilla::dom::MediaSourceEnum::Microphone; } + + virtual void Disable() override + { + } + + virtual void Enable() override + { + } + virtual void Stop() override { } diff --git a/media/webrtc/signaling/src/peerconnection/RemoteTrackSource.h b/media/webrtc/signaling/src/peerconnection/RemoteTrackSource.h index 4eec3f597864..e271cf263785 100644 --- a/media/webrtc/signaling/src/peerconnection/RemoteTrackSource.h +++ b/media/webrtc/signaling/src/peerconnection/RemoteTrackSource.h @@ -40,6 +40,14 @@ public: // clarity in the spec. } + void Disable() override + { + } + + void Enable() override + { + } + void SetPrincipal(nsIPrincipal* aPrincipal) { mPrincipal = aPrincipal;