bug 1161892 use separate thread pool for platform decoder task queues r=bholley
authorKarl Tomlinson <karlt+@karlt.net>
Thu, 07 May 2015 16:01:43 +1200
changeset 242885 8c1d33d0ad8b8488ae767137a9698cf4b8f45767
parent 242884 18d25adcfce88d7a0cf69c89a8bab6b653f02323
child 242886 9a8248d7999ec8e68a9fcf2051d6c83c780c77fd
push id59535
push userktomlinson@mozilla.com
push dateThu, 07 May 2015 23:54:57 +0000
treeherdermozilla-inbound@7b11fc3efb14 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1161892
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1161892 use separate thread pool for platform decoder task queues r=bholley so that platform decoder tasks will run when their readers wait and block their thread pool.
dom/media/MediaDecoderReader.cpp
dom/media/MediaDecoderStateMachine.cpp
dom/media/VideoUtils.cpp
dom/media/VideoUtils.h
dom/media/fmp4/MP4Reader.cpp
dom/media/fmp4/SharedDecoderManager.cpp
dom/media/mediasource/TrackBuffer.cpp
--- a/dom/media/MediaDecoderReader.cpp
+++ b/dom/media/MediaDecoderReader.cpp
@@ -339,17 +339,17 @@ MediaDecoderReader::RequestAudioData()
   return p;
 }
 
 MediaTaskQueue*
 MediaDecoderReader::EnsureTaskQueue()
 {
   if (!mTaskQueue) {
     MOZ_ASSERT(!mTaskQueueIsBorrowed);
-    RefPtr<SharedThreadPool> pool(GetMediaThreadPool());
+    RefPtr<SharedThreadPool> pool(GetMediaThreadPool(MediaThreadType::PLAYBACK));
     MOZ_DIAGNOSTIC_ASSERT(pool);
     mTaskQueue = new MediaTaskQueue(pool.forget());
   }
 
   return mTaskQueue;
 }
 
 void
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -197,17 +197,18 @@ static const uint32_t MAX_VIDEO_QUEUE_SI
 
 static uint32_t sVideoQueueDefaultSize = MAX_VIDEO_QUEUE_SIZE;
 static uint32_t sVideoQueueHWAccelSize = MIN_VIDEO_QUEUE_SIZE;
 
 MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
                                                    MediaDecoderReader* aReader,
                                                    bool aRealTime) :
   mDecoder(aDecoder),
-  mTaskQueue(new MediaTaskQueue(GetMediaThreadPool(), /* aAssertTailDispatch = */ true)),
+  mTaskQueue(new MediaTaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK),
+                                /* aAssertTailDispatch = */ true)),
   mWatchManager(this, mTaskQueue),
   mRealTime(aRealTime),
   mDispatchedStateMachine(false),
   mDelayedScheduler(this),
   mState(DECODER_STATE_DECODING_NONE, "MediaDecoderStateMachine::mState"),
   mPlayDuration(0),
   mStartTime(-1),
   mEndTime(-1),
--- a/dom/media/VideoUtils.cpp
+++ b/dom/media/VideoUtils.cpp
@@ -192,20 +192,32 @@ IsValidVideoRegion(const nsIntSize& aFra
     aPicture.width * aPicture.height <= MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT &&
     aPicture.width * aPicture.height != 0 &&
     aDisplay.width <= PlanarYCbCrImage::MAX_DIMENSION &&
     aDisplay.height <= PlanarYCbCrImage::MAX_DIMENSION &&
     aDisplay.width * aDisplay.height <= MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT &&
     aDisplay.width * aDisplay.height != 0;
 }
 
-TemporaryRef<SharedThreadPool> GetMediaThreadPool()
+TemporaryRef<SharedThreadPool> GetMediaThreadPool(MediaThreadType aType)
 {
-  return SharedThreadPool::Get(NS_LITERAL_CSTRING("Media Playback"),
-                               Preferences::GetUint("media.num-decode-threads", 25));
+  const char *name;
+  switch (aType) {
+    case MediaThreadType::PLATFORM_DECODER:
+      name = "MediaPDecoder";
+      break;
+    default:
+      MOZ_ASSERT(false);
+    case MediaThreadType::PLAYBACK:
+      name = "MediaPlayback";
+      break;
+  }
+  return SharedThreadPool::
+    Get(nsDependentCString(name),
+        Preferences::GetUint("media.num-decode-threads", 12));
 }
 
 bool
 ExtractH264CodecDetails(const nsAString& aCodec,
                         int16_t& aProfile,
                         int16_t& aLevel)
 {
   // H.264 codecs parameters have a type defined as avcN.PPCCLL, where
@@ -299,27 +311,29 @@ GenerateRandomPathName(nsCString& aOutSa
   aOutSalt.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, '_');
   return NS_OK;
 }
 
 class CreateTaskQueueTask : public nsRunnable {
 public:
   NS_IMETHOD Run() {
     MOZ_ASSERT(NS_IsMainThread());
-    mTaskQueue = new MediaTaskQueue(GetMediaThreadPool());
+    mTaskQueue =
+      new MediaTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
     return NS_OK;
   }
   nsRefPtr<MediaTaskQueue> mTaskQueue;
 };
 
 class CreateFlushableTaskQueueTask : public nsRunnable {
 public:
   NS_IMETHOD Run() {
     MOZ_ASSERT(NS_IsMainThread());
-    mTaskQueue = new FlushableMediaTaskQueue(GetMediaThreadPool());
+    mTaskQueue =
+      new FlushableMediaTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
     return NS_OK;
   }
   nsRefPtr<FlushableMediaTaskQueue> mTaskQueue;
 };
 
 already_AddRefed<MediaTaskQueue>
 CreateMediaDecodeTaskQueue()
 {
--- a/dom/media/VideoUtils.h
+++ b/dom/media/VideoUtils.h
@@ -211,19 +211,32 @@ public:
   }
 private:
   T& mVar;
   const T mValue;
 };
 
 class SharedThreadPool;
 
+// The MediaDataDecoder API blocks, with implementations waiting on platform
+// decoder tasks.  These platform decoder tasks are queued on a separate
+// thread pool to ensure they can run when the MediaDataDecoder clients'
+// thread pool is blocked.  Tasks on the PLATFORM_DECODER thread pool must not
+// wait on tasks in the PLAYBACK thread pool.
+//
+// No new dependencies on this mechanism should be added, as methods are being
+// made async supported by MediaPromise, making this unnecessary and
+// permitting unifying the pool.
+enum class MediaThreadType {
+  PLAYBACK, // MediaDecoderStateMachine and MediaDecoderReader
+  PLATFORM_DECODER
+};
 // Returns the thread pool that is shared amongst all decoder state machines
 // for decoding streams.
-TemporaryRef<SharedThreadPool> GetMediaThreadPool();
+TemporaryRef<SharedThreadPool> GetMediaThreadPool(MediaThreadType aType);
 
 enum H264_PROFILE {
   H264_PROFILE_UNKNOWN                     = 0,
   H264_PROFILE_BASE                        = 0x42,
   H264_PROFILE_MAIN                        = 0x4D,
   H264_PROFILE_EXTENDED                    = 0x58,
   H264_PROFILE_HIGH                        = 0x64,
 };
--- a/dom/media/fmp4/MP4Reader.cpp
+++ b/dom/media/fmp4/MP4Reader.cpp
@@ -284,20 +284,22 @@ nsresult
 MP4Reader::Init(MediaDecoderReader* aCloneDonor)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
   PlatformDecoderModule::Init();
   mStream = new MP4Stream(mDecoder->GetResource());
 
   InitLayersBackendType();
 
-  mAudio.mTaskQueue = new FlushableMediaTaskQueue(GetMediaThreadPool());
+  mAudio.mTaskQueue =
+    new FlushableMediaTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
   NS_ENSURE_TRUE(mAudio.mTaskQueue, NS_ERROR_FAILURE);
 
-  mVideo.mTaskQueue = new FlushableMediaTaskQueue(GetMediaThreadPool());
+  mVideo.mTaskQueue =
+    new FlushableMediaTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
   NS_ENSURE_TRUE(mVideo.mTaskQueue, NS_ERROR_FAILURE);
 
   static bool sSetupPrefCache = false;
   if (!sSetupPrefCache) {
     sSetupPrefCache = true;
     Preferences::AddBoolVarCache(&sIsEMEEnabled, "media.eme.enabled", false);
     Preferences::AddBoolVarCache(&sDemuxSkipToNextKeyframe, "media.fmp4.demux-skip", true);
   }
--- a/dom/media/fmp4/SharedDecoderManager.cpp
+++ b/dom/media/fmp4/SharedDecoderManager.cpp
@@ -72,17 +72,17 @@ private:
     MOZ_DIAGNOSTIC_ASSERT(mManager->mActiveProxy);
 #endif
   }
 
   SharedDecoderManager* mManager;
 };
 
 SharedDecoderManager::SharedDecoderManager()
-  : mTaskQueue(new FlushableMediaTaskQueue(GetMediaThreadPool()))
+  : mTaskQueue(new FlushableMediaTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER)))
   , mActiveProxy(nullptr)
   , mActiveCallback(nullptr)
   , mWaitForInternalDrain(false)
   , mMonitor("SharedDecoderProxy")
   , mDecoderReleasedResources(false)
 {
   MOZ_ASSERT(NS_IsMainThread()); // taskqueue must be created on main thread.
   mCallback = new SharedDecoderCallback(this);
--- a/dom/media/mediasource/TrackBuffer.cpp
+++ b/dom/media/mediasource/TrackBuffer.cpp
@@ -48,17 +48,18 @@ TrackBuffer::TrackBuffer(MediaSourceDeco
   , mLastStartTimestamp(0)
   , mLastTimestampOffset(0)
   , mAdjustedTimestamp(0)
   , mIsWaitingOnCDM(false)
   , mShutdown(false)
 {
   MOZ_COUNT_CTOR(TrackBuffer);
   mParser = ContainerParser::CreateForMIMEType(aType);
-  mTaskQueue = new MediaTaskQueue(GetMediaThreadPool());
+  mTaskQueue =
+    new MediaTaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK));
   aParentDecoder->AddTrackBuffer(this);
   mDecoderPerSegment = Preferences::GetBool("media.mediasource.decoder-per-segment", false);
   MSE_DEBUG("TrackBuffer created for parent decoder %p", aParentDecoder);
 }
 
 TrackBuffer::~TrackBuffer()
 {
   MOZ_COUNT_DTOR(TrackBuffer);