Bug 1306813 - Don't puslish events to mOnOutput after DecodedStream::Stop() is called. draft
authorJW Wang <jwwang@mozilla.com>
Tue, 04 Oct 2016 14:54:23 +0800
changeset 420636 9506a65a2db70c08242f44bac0ac1df6018ce3f5
parent 420441 eb9201bf47dec53715cddc4d45cb9a7f5349f1dc
child 532849 88dad4c0756b27c56b219a7ce55da768aaf6b2ed
push id31242
push userjwwang@mozilla.com
push dateTue, 04 Oct 2016 09:52:50 +0000
bugs1306813
milestone52.0a1
Bug 1306813 - Don't puslish events to mOnOutput after DecodedStream::Stop() is called. Because the TaskQueue of MDSM will shut down soon and TaskQueue::Dispatch() will fail (via mOnOutput.Notify()). We reset mStream in Forget() on the TaskQueue thread of MDSM so NotifyOutput() can check it and ensure mOnOutput.Notify() always happen before DecodedStream::Stop(). MozReview-Commit-ID: 4sCXk1KAfCC
dom/media/mediasink/DecodedStream.cpp
--- a/dom/media/mediasink/DecodedStream.cpp
+++ b/dom/media/mediasink/DecodedStream.cpp
@@ -56,23 +56,26 @@ public:
       nsCOMPtr<nsIRunnable> event =
         NewRunnableMethod(this, &DecodedStreamGraphListener::DoNotifyFinished);
       aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
     }
   }
 
   void DoNotifyFinished()
   {
+    MOZ_ASSERT(NS_IsMainThread());
     mFinishPromise.ResolveIfExists(true, __func__);
   }
 
   void Forget()
   {
-    MOZ_ASSERT(NS_IsMainThread());
-    mFinishPromise.ResolveIfExists(true, __func__);
+    AbstractThread::MainThread()->Dispatch(NS_NewRunnableFunction([this] () {
+      MOZ_ASSERT(NS_IsMainThread());
+      mFinishPromise.ResolveIfExists(true, __func__);
+    }));
     MutexAutoLock lock(mMutex);
     mStream = nullptr;
   }
 
   MediaEventSource<int64_t>& OnOutput()
   {
     return mOnOutput;
   }
@@ -118,16 +121,17 @@ UpdateStreamSuspended(MediaStream* aStre
 class DecodedStreamData {
 public:
   DecodedStreamData(OutputStreamManager* aOutputStreamManager,
                     PlaybackInfoInit&& aInit,
                     MozPromiseHolder<GenericPromise>&& aPromise);
   ~DecodedStreamData();
   void SetPlaying(bool aPlaying);
   MediaEventSource<int64_t>& OnOutput();
+  void Forget();
 
   /* The following group of fields are protected by the decoder's monitor
    * and can be read or written on any thread.
    */
   // Count of audio frames written to the stream
   int64_t mAudioFramesWritten;
   // mNextVideoTime is the end timestamp for the last packet sent to the stream.
   // Therefore video packets starting at or after this time need to be copied
@@ -183,17 +187,16 @@ DecodedStreamData::DecodedStreamData(Out
   if (aInit.mInfo.HasVideo()) {
     mStream->AddTrack(aInit.mInfo.mVideo.mTrackId, 0, new VideoSegment());
   }
 }
 
 DecodedStreamData::~DecodedStreamData()
 {
   mOutputStreamManager->Disconnect();
-  mListener->Forget();
   mStream->Destroy();
 }
 
 MediaEventSource<int64_t>&
 DecodedStreamData::OnOutput()
 {
   return mListener->OnOutput();
 }
@@ -202,16 +205,22 @@ void
 DecodedStreamData::SetPlaying(bool aPlaying)
 {
   if (mPlaying != aPlaying) {
     mPlaying = aPlaying;
     UpdateStreamSuspended(mStream, !mPlaying);
   }
 }
 
+void
+DecodedStreamData::Forget()
+{
+  mListener->Forget();
+}
+
 DecodedStream::DecodedStream(AbstractThread* aOwnerThread,
                              MediaQueue<MediaData>& aAudioQueue,
                              MediaQueue<MediaData>& aVideoQueue,
                              OutputStreamManager* aOutputStreamManager,
                              const bool& aSameOrigin,
                              const PrincipalHandle& aPrincipalHandle)
   : mOwnerThread(aOwnerThread)
   , mOutputStreamManager(aOutputStreamManager)
@@ -358,16 +367,17 @@ DecodedStream::DestroyData(UniquePtr<Dec
 
   if (!aData) {
     return;
   }
 
   mOutputListener.Disconnect();
 
   DecodedStreamData* data = aData.release();
+  data->Forget();
   nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
     delete data;
   });
   AbstractThread::MainThread()->Dispatch(r.forget());
 }
 
 void
 DecodedStream::SetPlaying(bool aPlaying)