Bug 909187: Part 2 - Allow DOM MediaStreams to intercept SetTrackEnabled calls r=roc a=akeybl
authorRandell Jesup <rjesup@jesup.org>
Mon, 26 Aug 2013 02:07:19 -0400
changeset 153985 e203add2f0eba319bffe56b74e7079ff217a78b3
parent 153984 b558ce6a721755730d8df2c7fc557462159fee68
child 153986 5e3bf07e920d2d330e67eeccc082c8c212d21dbb
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, akeybl
bugs909187
milestone25.0a2
Bug 909187: Part 2 - Allow DOM MediaStreams to intercept SetTrackEnabled calls r=roc a=akeybl
content/media/DOMMediaStream.cpp
content/media/DOMMediaStream.h
content/media/MediaStreamGraph.h
content/media/MediaStreamTrack.cpp
content/media/TrackUnionStream.h
dom/media/MediaManager.cpp
--- a/content/media/DOMMediaStream.cpp
+++ b/content/media/DOMMediaStream.cpp
@@ -235,16 +235,24 @@ DOMMediaStream::CreateSourceStream(nsIDO
 already_AddRefed<DOMMediaStream>
 DOMMediaStream::CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents)
 {
   nsRefPtr<DOMMediaStream> stream = new DOMMediaStream();
   stream->InitTrackUnionStream(aWindow, aHintContents);
   return stream.forget();
 }
 
+void
+DOMMediaStream::SetTrackEnabled(TrackID aTrackID, bool aEnabled)
+{
+  if (mStream) {
+    mStream->SetTrackEnabled(aTrackID, aEnabled);
+  }
+}
+
 bool
 DOMMediaStream::CombineWithPrincipal(nsIPrincipal* aPrincipal)
 {
   return nsContentUtils::CombineResourcePrincipals(&mPrincipal, aPrincipal);
 }
 
 MediaStreamTrack*
 DOMMediaStream::CreateDOMTrack(TrackID aTrackID, MediaSegment::Type aType)
--- a/content/media/DOMMediaStream.h
+++ b/content/media/DOMMediaStream.h
@@ -79,16 +79,22 @@ public:
   /**
    * Overridden in DOMLocalMediaStreams to allow getUserMedia to pass
    * data directly to RTCPeerConnection without going through graph queuing.
    * Returns a bool to let us know if direct data will be delivered.
    */
   virtual bool AddDirectListener(MediaStreamDirectListener *aListener) { return false; }
   virtual void RemoveDirectListener(MediaStreamDirectListener *aListener) {}
 
+  /**
+   * Overridden in DOMLocalMediaStreams to allow getUserMedia to disable
+   * media at the SourceMediaStream.
+   */
+  virtual void SetTrackEnabled(TrackID aTrackID, bool aEnabled);
+
   bool IsFinished();
   /**
    * Returns a principal indicating who may access this stream. The stream contents
    * can only be accessed by principals subsuming this principal.
    */
   nsIPrincipal* GetPrincipal() { return mPrincipal; }
 
   /**
--- a/content/media/MediaStreamGraph.h
+++ b/content/media/MediaStreamGraph.h
@@ -926,16 +926,21 @@ public:
    * Also, we've produced output for all streams up to this one. If this stream
    * is not in a cycle, then all its source streams have produced data.
    * Generate output up to mStateComputedTime.
    * This is called only on streams that have not finished.
    */
   virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo) = 0;
   void SetAutofinishImpl(bool aAutofinish) { mAutofinish = aAutofinish; }
 
+  /**
+   * Forward SetTrackEnabled() to the input MediaStream(s) and translate the ID
+   */
+  virtual void ForwardTrackEnabled(TrackID aOutputID, bool aEnabled) {};
+
 protected:
   // This state is all accessed only on the media graph thread.
 
   // The list of all inputs that are currently enabled or waiting to be enabled.
   nsTArray<MediaInputPort*> mInputs;
   bool mAutofinish;
   // True if and only if this stream is in a cycle.
   // Updated by MediaStreamGraphImpl::UpdateStreamOrder.
--- a/content/media/MediaStreamTrack.cpp
+++ b/content/media/MediaStreamTrack.cpp
@@ -47,16 +47,13 @@ MediaStreamTrack::GetId(nsAString& aID)
   mID.ToProvidedString(chars);
   aID = NS_ConvertASCIItoUTF16(chars);
 }
 
 void
 MediaStreamTrack::SetEnabled(bool aEnabled)
 {
   mEnabled = aEnabled;
-  MediaStream* stream = mStream->GetStream();
-  if (stream) {
-    stream->SetTrackEnabled(mTrackID, aEnabled);
-  }
+  mStream->SetTrackEnabled(mTrackID, aEnabled);
 }
 
 }
 }
--- a/content/media/TrackUnionStream.h
+++ b/content/media/TrackUnionStream.h
@@ -110,16 +110,27 @@ public:
 
   // Consumers may specify a filtering callback to apply to every input track.
   // Returns true to allow the track to act as an input; false to reject it entirely.
   typedef bool (*TrackIDFilterCallback)(StreamBuffer::Track*);
   void SetTrackIDFilter(TrackIDFilterCallback aCallback) {
     mFilterCallback = aCallback;
   }
 
+  // Forward SetTrackEnabled(output_track_id, enabled) to the Source MediaStream,
+  // translating the output track ID into the correct ID in the source.
+  virtual void ForwardTrackEnabled(TrackID aOutputID, bool aEnabled) {
+    for (int32_t i = mTrackMap.Length() - 1; i >= 0; --i) {
+      if (mTrackMap[i].mOutputTrackID == aOutputID) {
+        mTrackMap[i].mInputPort->GetSource()->
+          SetTrackEnabled(mTrackMap[i].mInputTrackID, aEnabled);
+      }
+    }
+  }
+
 protected:
   TrackIDFilterCallback mFilterCallback;
 
   // Only non-ended tracks are allowed to persist in this map.
   struct TrackMapEntry {
     // mEndOfConsumedInputTicks is the end of the input ticks that we've consumed.
     // 0 if we haven't consumed any yet.
     TrackTicks mEndOfConsumedInputTicks;
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -305,16 +305,27 @@ public:
 
   virtual void RemoveDirectListener(MediaStreamDirectListener *aListener) MOZ_OVERRIDE
   {
     if (mSourceStream) {
       mSourceStream->RemoveDirectListener(aListener);
     }
   }
 
+  // let us intervene for direct listeners when someone does track.enabled = false
+  virtual void SetTrackEnabled(TrackID aID, bool aEnabled) MOZ_OVERRIDE
+  {
+    // We encapsulate the SourceMediaStream and TrackUnion into one entity, so
+    // we can handle the disabling at the SourceMediaStream
+
+    // We need to find the input track ID for output ID aID, so we let the TrackUnion
+    // forward the request to the source and translate the ID
+    GetStream()->AsProcessedStream()->ForwardTrackEnabled(aID, aEnabled);
+  }
+
   // The actual MediaStream is a TrackUnionStream. But these resources need to be
   // explicitly destroyed too.
   nsRefPtr<SourceMediaStream> mSourceStream;
   nsRefPtr<MediaInputPort> mPort;
 };
 
 /**
  * Creates a MediaStream, attaches a listener and fires off a success callback