Bug 1443886 - Bounce dispatches to the main thread on another thread. f?pehrsons draft
authorPaul Adenot <paul@paul.cx>
Mon, 12 Mar 2018 14:02:13 +0100
changeset 776654 26d20dfc505f88ebf5844ee979a0ae499f902fe5
parent 776477 d75d996016dcf325c2db2ed8a47af512d07ffacd
child 776655 b148cce2e4fb2c49627704dee6335f55d59fb0a5
push id104937
push userpaul@paul.cx
push dateTue, 03 Apr 2018 14:51:36 +0000
bugs1443886
milestone61.0a1
Bug 1443886 - Bounce dispatches to the main thread on another thread. f?pehrsons MozReview-Commit-ID: Lnujy5kdvo2
dom/media/MediaStreamGraph.cpp
dom/media/MediaStreamGraphImpl.h
dom/media/MediaStreamVideoSink.cpp
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -1481,16 +1481,17 @@ public:
     {
       MonitorAutoLock mon(mGraph->mMonitor);
       mGraph->SetCurrentDriver(nullptr);
     }
 
     // Do not hold on our threadpool, global shutdown will hang otherwise as
     // it waits for all thread pools to shutdown.
     mGraph->mThreadPool = nullptr;
+    mGraph->mDispatchBounceThread = nullptr;
 
     // Safe to access these without the monitor since the graph isn't running.
     // We may be one of several graphs. Drop ticket to eventually unblock shutdown.
     if (mGraph->mShutdownTimer && !mGraph->mForceShutdownTicket) {
       MOZ_ASSERT(false,
         "AudioCallbackDriver took too long to shut down and we let shutdown"
         " continue - freezing and leaking");
 
@@ -1761,17 +1762,17 @@ MediaStreamGraphImpl::EnsureStableStateE
 {
   MOZ_ASSERT(OnGraphThread());
   mMonitor.AssertCurrentThreadOwns();
 
   if (mPostedRunInStableStateEvent)
     return;
   mPostedRunInStableStateEvent = true;
   nsCOMPtr<nsIRunnable> event = new MediaStreamGraphStableStateRunnable(this, true);
-  mAbstractMainThread->Dispatch(event.forget());
+  Dispatch(event.forget());
 }
 
 void
 MediaStreamGraphImpl::SignalMainThreadCleanup()
 {
   MOZ_ASSERT(mDriver->OnThread());
 
   MonitorAutoLock lock(mMonitor);
@@ -1827,17 +1828,46 @@ MediaStreamGraphImpl::AppendMessage(Uniq
 
   mCurrentTaskMessageQueue.AppendElement(Move(aMessage));
   EnsureRunInStableState();
 }
 
 void
 MediaStreamGraphImpl::Dispatch(already_AddRefed<nsIRunnable>&& aRunnable)
 {
-  mAbstractMainThread->Dispatch(Move(aRunnable));
+  if (!mDispatchBounceThread) {
+    mAbstractMainThread->Dispatch(Move(aRunnable));
+    return;
+  }
+
+  class BounceRunnable : public Runnable
+  {
+  public:
+    explicit BounceRunnable(AbstractThread* aThread,
+                            already_AddRefed<nsIRunnable>&& aRunnable)
+    : Runnable("MediaStreamGraphImpl::BounceRunnable")
+    , mMainThread(aThread)
+    , mRunnable(aRunnable)
+    {
+
+    }
+
+    NS_IMETHOD Run() override
+    {
+      return mMainThread->Dispatch(mRunnable.forget());
+    }
+  private:
+    ~BounceRunnable() {}
+
+    RefPtr<AbstractThread> mMainThread;
+    nsCOMPtr<nsIRunnable> mRunnable;
+  };
+
+  nsCOMPtr<nsIRunnable> r = new BounceRunnable(mAbstractMainThread, Move(aRunnable));
+  mDispatchBounceThread->Dispatch(r.forget());
 }
 
 MediaStream::MediaStream()
   : mTracksStartTime(0)
   , mStartBlocking(GRAPH_TIME_MAX)
   , mSuspendedCount(0)
   , mFinished(false)
   , mNotifiedFinished(false)
@@ -3600,29 +3630,35 @@ MediaStreamGraphImpl::MediaStreamGraphIm
   , mDetectedNotRunning(false)
   , mPostedRunInStableState(false)
   , mRealtime(aDriverRequested != OFFLINE_THREAD_DRIVER)
   , mNonRealtimeProcessing(false)
   , mStreamOrderDirty(false)
   , mLatencyLog(AsyncLatencyLogger::Get())
   , mAbstractMainThread(aMainThread)
   , mThreadPool(GetMediaThreadPool(MediaThreadType::MSG_CONTROL))
+  , mDispatchBounceThread(nullptr)
   , mSelfRef(this)
   , mOutputChannels(std::min<uint32_t>(8, CubebUtils::MaxNumberOfChannels()))
 #ifdef DEBUG
   , mCanRunMessagesSynchronously(false)
 #endif
 {
   if (mRealtime) {
     if (aDriverRequested == AUDIO_THREAD_DRIVER) {
       AudioCallbackDriver* driver = new AudioCallbackDriver(this);
       mDriver = driver;
     } else {
       mDriver = new SystemClockDriver(this);
     }
+    nsresult rv = NS_NewNamedThread("MSG Dispatch", getter_AddRefs(mDispatchBounceThread));
+    if (NS_FAILED(rv)) {
+      NS_WARNING("Could not create dispatch bounce thread for the MSG, falling back to direct dispatch");
+      mDispatchBounceThread = nullptr;
+    }
   } else {
     mDriver = new OfflineClockDriver(this, MEDIA_GRAPH_TARGET_PERIOD_MS);
   }
 
   mLastMainThreadUpdate = TimeStamp::Now();
 
   RegisterWeakAsyncMemoryReporter(this);
 }
--- a/dom/media/MediaStreamGraphImpl.h
+++ b/dom/media/MediaStreamGraphImpl.h
@@ -815,16 +815,17 @@ public:
   bool mStreamOrderDirty;
   /**
    * Hold a ref to the Latency logger
    */
   RefPtr<AsyncLatencyLogger> mLatencyLog;
   AudioMixer mMixer;
   const RefPtr<AbstractThread> mAbstractMainThread;
   RefPtr<SharedThreadPool> mThreadPool;
+  RefPtr<nsIThread> mDispatchBounceThread;
 
   // used to limit graph shutdown time
   // Only accessed on the main thread.
   nsCOMPtr<nsITimer> mShutdownTimer;
 
 private:
   virtual ~MediaStreamGraphImpl();
 
--- a/dom/media/MediaStreamVideoSink.cpp
+++ b/dom/media/MediaStreamVideoSink.cpp
@@ -9,13 +9,21 @@
 
 namespace mozilla {
 void
 MediaStreamVideoSink::NotifyRealtimeTrackData(MediaStreamGraph* aGraph,
                                               StreamTime aTrackOffset,
                                               const MediaSegment& aMedia)
 {
   if (aMedia.GetType() == MediaSegment::VIDEO) {
-    SetCurrentFrames(static_cast<const VideoSegment&>(aMedia));
+    RefPtr<MediaStreamVideoSink> self = this;
+    VideoSegment copy;
+    copy.AppendSlice(aMedia, 0, aMedia.GetDuration());
+    static_cast<MediaStreamGraphImpl*>(aGraph)->Dispatch(
+      NewRunnableMethod<StoreCopyPassByRRef<VideoSegment>>(
+        "MediaStreamVideoSink::SetCurrentFrame",
+        this,
+        &MediaStreamVideoSink::SetCurrentFrames,
+        Move(copy)));
   }
 }
 
 } // namespace mozilla