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;