Bug 1233650. Part 2 - make OutputStreamManager ref-counted so it can be shared between MDSM and DecodedStream. r=roc. draft
authorJW Wang <jwwang@mozilla.com>
Thu, 24 Dec 2015 10:14:16 +0800
changeset 317474 891c023f4f2fd3b9da4e07de97cc9378a7f742eb
parent 317473 5cb857abfd6dcc6023d7b5884dbd0fc9654910b4
child 317475 faa4bd48d91c0163bb1b799589974edab7527f47
push id8701
push userjwwang@mozilla.com
push dateThu, 24 Dec 2015 02:14:36 +0000
reviewersroc
bugs1233650
milestone46.0a1
Bug 1233650. Part 2 - make OutputStreamManager ref-counted so it can be shared between MDSM and DecodedStream. r=roc.
dom/media/mediasink/DecodedStream.cpp
dom/media/mediasink/DecodedStream.h
dom/media/mediasink/OutputStreamManager.h
--- a/dom/media/mediasink/DecodedStream.cpp
+++ b/dom/media/mediasink/DecodedStream.cpp
@@ -7,16 +7,17 @@
 #include "mozilla/CheckedInt.h"
 #include "mozilla/gfx/Point.h"
 
 #include "AudioSegment.h"
 #include "DecodedStream.h"
 #include "MediaData.h"
 #include "MediaQueue.h"
 #include "MediaStreamGraph.h"
+#include "OutputStreamManager.h"
 #include "SharedBuffer.h"
 #include "VideoSegment.h"
 #include "VideoUtils.h"
 
 namespace mozilla {
 
 class DecodedStreamGraphListener : public MediaStreamListener {
   typedef MediaStreamListener::MediaStreamGraphEvent MediaStreamGraphEvent;
@@ -183,16 +184,17 @@ DecodedStreamData::SetPlaying(bool aPlay
     UpdateStreamSuspended(mStream, !mPlaying);
   }
 }
 
 DecodedStream::DecodedStream(AbstractThread* aOwnerThread,
                              MediaQueue<MediaData>& aAudioQueue,
                              MediaQueue<MediaData>& aVideoQueue)
   : mOwnerThread(aOwnerThread)
+  , mOutputStreamManager(new OutputStreamManager())
   , mPlaying(false)
   , mSameOrigin(false)
   , mAudioQueue(aAudioQueue)
   , mVideoQueue(aVideoQueue)
 {
 }
 
 DecodedStream::~DecodedStream()
@@ -304,38 +306,38 @@ DecodedStream::DestroyData(UniquePtr<Dec
 
   if (!aData) {
     return;
   }
 
   DecodedStreamData* data = aData.release();
   RefPtr<DecodedStream> self = this;
   nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
-    self->mOutputStreamManager.Disconnect();
+    self->mOutputStreamManager->Disconnect();
     delete data;
   });
   AbstractThread::MainThread()->Dispatch(r.forget());
 }
 
 void
 DecodedStream::CreateData(MozPromiseHolder<GenericPromise>&& aPromise)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // No need to create a source stream when there are no output streams. This
   // happens when RemoveOutput() is called immediately after StartPlayback().
-  if (!mOutputStreamManager.Graph()) {
+  if (!mOutputStreamManager->Graph()) {
     // Resolve the promise to indicate the end of playback.
     aPromise.Resolve(true, __func__);
     return;
   }
 
-  auto source = mOutputStreamManager.Graph()->CreateSourceStream(nullptr);
+  auto source = mOutputStreamManager->Graph()->CreateSourceStream(nullptr);
   auto data = new DecodedStreamData(source, Move(aPromise));
-  mOutputStreamManager.Connect(data->mStream);
+  mOutputStreamManager->Connect(data->mStream);
 
   class R : public nsRunnable {
     typedef void(DecodedStream::*Method)(UniquePtr<DecodedStreamData>);
   public:
     R(DecodedStream* aThis, Method aMethod, DecodedStreamData* aData)
       : mThis(aThis), mMethod(aMethod), mData(aData) {}
     NS_IMETHOD Run() override
     {
@@ -347,17 +349,17 @@ DecodedStream::CreateData(MozPromiseHold
     {
       // mData is not transferred when dispatch fails and Run() is not called.
       // We need to dispatch a task to ensure DecodedStreamData is destroyed
       // properly on the main thread.
       if (mData) {
         DecodedStreamData* data = mData.release();
         RefPtr<DecodedStream> self = mThis.forget();
         nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
-          self->mOutputStreamManager.Disconnect();
+          self->mOutputStreamManager->Disconnect();
           delete data;
         });
         // We are in tail dispatching phase. Don't call
         // AbstractThread::MainThread()->Dispatch() to avoid reentrant
         // AutoTaskDispatcher.
         NS_DispatchToMainThread(r.forget());
       }
     }
@@ -370,17 +372,17 @@ DecodedStream::CreateData(MozPromiseHold
   // Note this could fail when MDSM begin to shut down the worker thread.
   nsCOMPtr<nsIRunnable> r = new R(this, &DecodedStream::OnDataCreated, data);
   mOwnerThread->Dispatch(r.forget(), AbstractThread::DontAssertDispatchSuccess);
 }
 
 bool
 DecodedStream::HasConsumers() const
 {
-  return !mOutputStreamManager.IsEmpty();
+  return !mOutputStreamManager->IsEmpty();
 }
 
 void
 DecodedStream::OnDataCreated(UniquePtr<DecodedStreamData> aData)
 {
   AssertOwnerThread();
   MOZ_ASSERT(!mData, "Already created.");
 
@@ -394,23 +396,23 @@ DecodedStream::OnDataCreated(UniquePtr<D
 
   // Playback has ended. Destroy aData which is not needed anymore.
   DestroyData(Move(aData));
 }
 
 void
 DecodedStream::AddOutput(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
 {
-  mOutputStreamManager.Add(aStream, aFinishWhenEnded);
+  mOutputStreamManager->Add(aStream, aFinishWhenEnded);
 }
 
 void
 DecodedStream::RemoveOutput(MediaStream* aStream)
 {
-  mOutputStreamManager.Remove(aStream);
+  mOutputStreamManager->Remove(aStream);
 }
 
 void
 DecodedStream::SetPlaying(bool aPlaying)
 {
   AssertOwnerThread();
 
   // Resume/pause matters only when playback started.
--- a/dom/media/mediasink/DecodedStream.h
+++ b/dom/media/mediasink/DecodedStream.h
@@ -5,29 +5,29 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef DecodedStream_h_
 #define DecodedStream_h_
 
 #include "MediaEventSource.h"
 #include "MediaInfo.h"
 #include "MediaSink.h"
-#include "OutputStreamManager.h"
 
 #include "mozilla/AbstractThread.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/MozPromise.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
 
 namespace mozilla {
 
 class DecodedStreamData;
 class MediaData;
 class MediaStream;
+class OutputStreamManager;
 class ProcessedMediaStream;
 class TimeStamp;
 
 template <class T> class MediaQueue;
 
 class DecodedStream : public media::MediaSink {
   using media::MediaSink::PlaybackParams;
 
@@ -86,17 +86,17 @@ private:
   void DisconnectListener();
 
   const RefPtr<AbstractThread> mOwnerThread;
 
   /*
    * Main thread only members.
    */
   // Data about MediaStreams that are being fed by the decoder.
-  OutputStreamManager mOutputStreamManager;
+  const RefPtr<OutputStreamManager> mOutputStreamManager;
 
   /*
    * Worker thread only members.
    */
   UniquePtr<DecodedStreamData> mData;
   RefPtr<GenericPromise> mFinishPromise;
 
   bool mPlaying;
--- a/dom/media/mediasink/OutputStreamManager.h
+++ b/dom/media/mediasink/OutputStreamManager.h
@@ -37,16 +37,18 @@ public:
 private:
   OutputStreamManager* mOwner;
   RefPtr<ProcessedMediaStream> mStream;
   // mPort connects our mStream to an input stream.
   RefPtr<MediaInputPort> mPort;
 };
 
 class OutputStreamManager {
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OutputStreamManager);
+
 public:
   // Add the output stream to the collection.
   void Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
   // Remove the output stream from the collection.
   void Remove(MediaStream* aStream);
   // Return true if the collection empty.
   bool IsEmpty() const
   {
@@ -60,16 +62,17 @@ public:
   // Return the graph these streams belong to or null if empty.
   MediaStreamGraph* Graph() const
   {
     MOZ_ASSERT(NS_IsMainThread());
     return !IsEmpty() ? mStreams[0].Graph() : nullptr;
   }
 
 private:
+  ~OutputStreamManager() {}
   // Keep the input stream so we can connect the output streams that
   // are added after Connect().
   RefPtr<MediaStream> mInputStream;
   nsTArray<OutputStreamData> mStreams;
 };
 
 } // namespace mozilla