Bug 1173001 - Initialize reader task queue in the constructor. r=jww
authorBobby Holley <bobbyholley@gmail.com>
Mon, 08 Jun 2015 17:16:42 -0700
changeset 248173 e7b684137f229a40241bb0f2ad2c834103a2166a
parent 248172 6289cdbce7b7b3950706d5e5bef4daf29c604f55
child 248174 0e722555cc6dcb49b6b833419f9670b99207c311
push id28893
push userkwierso@gmail.com
push dateFri, 12 Jun 2015 00:02:58 +0000
treeherdermozilla-central@8cf9d3e497f9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjww
bugs1173001
milestone41.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 1173001 - Initialize reader task queue in the constructor. r=jww This is a necessary step towards having mirrored/canonical values, since those need to know the task queue in their constructor.
dom/media/MediaDecoderReader.cpp
dom/media/MediaDecoderReader.h
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaFormatReader.cpp
dom/media/MediaFormatReader.h
dom/media/fmp4/MP4Reader.cpp
dom/media/fmp4/MP4Reader.h
dom/media/gtest/TestMP4Reader.cpp
dom/media/mediasource/MediaSourceReader.cpp
dom/media/webaudio/MediaBufferDecoder.cpp
dom/media/webm/WebMReader.cpp
dom/media/webm/WebMReader.h
--- a/dom/media/MediaDecoderReader.cpp
+++ b/dom/media/MediaDecoderReader.cpp
@@ -55,24 +55,26 @@ public:
     const AudioData* audioData = static_cast<const AudioData*>(aObject);
     mSize += audioData->SizeOfIncludingThis(MallocSizeOf);
     return nullptr;
   }
 
   size_t mSize;
 };
 
-MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder)
+MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder,
+                                       MediaTaskQueue* aBorrowedTaskQueue)
   : mAudioCompactor(mAudioQueue)
   , mDecoder(aDecoder)
+  , mTaskQueue(aBorrowedTaskQueue ? aBorrowedTaskQueue : new MediaTaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK)))
   , mIgnoreAudioOutputFormat(false)
   , mStartTime(-1)
   , mHitAudioDecodeError(false)
   , mShutdown(false)
-  , mTaskQueueIsBorrowed(false)
+  , mTaskQueueIsBorrowed(!!aBorrowedTaskQueue)
   , mAudioDiscontinuity(false)
   , mVideoDiscontinuity(false)
 {
   MOZ_COUNT_CTOR(MediaDecoderReader);
 }
 
 MediaDecoderReader::~MediaDecoderReader()
 {
@@ -326,29 +328,16 @@ MediaDecoderReader::RequestAudioData()
     mHitAudioDecodeError = false;
   } else {
     MOZ_ASSERT(false, "Dropping this promise on the floor");
   }
 
   return p;
 }
 
-MediaTaskQueue*
-MediaDecoderReader::EnsureTaskQueue()
-{
-  if (!mTaskQueue) {
-    MOZ_ASSERT(!mTaskQueueIsBorrowed);
-    RefPtr<SharedThreadPool> pool(GetMediaThreadPool(MediaThreadType::PLAYBACK));
-    MOZ_DIAGNOSTIC_ASSERT(pool);
-    mTaskQueue = new MediaTaskQueue(pool.forget());
-  }
-
-  return mTaskQueue;
-}
-
 void
 MediaDecoderReader::BreakCycles()
 {
   mTaskQueue = nullptr;
 }
 
 nsRefPtr<ShutdownPromise>
 MediaDecoderReader::Shutdown()
--- a/dom/media/MediaDecoderReader.h
+++ b/dom/media/MediaDecoderReader.h
@@ -74,17 +74,17 @@ public:
   // so we mark it that way to verify our assumptions. If you have a use-case
   // for multiple WaitForData consumers, feel free to flip the exclusivity here.
   typedef MediaPromise<MediaData::Type, WaitForDataRejectValue, /* IsExclusive = */ true> WaitForDataPromise;
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderReader)
 
   // The caller must ensure that Shutdown() is called before aDecoder is
   // destroyed.
-  explicit MediaDecoderReader(AbstractMediaDecoder* aDecoder);
+  explicit MediaDecoderReader(AbstractMediaDecoder* aDecoder, MediaTaskQueue* aBorrowedTaskQueue = nullptr);
 
   // Initializes the reader, returns NS_OK on success, or NS_ERROR_FAILURE
   // on failure.
   virtual nsresult Init(MediaDecoderReader* aCloneDonor) = 0;
 
   // True if this reader is waiting media resource allocation
   virtual bool IsWaitingMediaResources() { return false; }
   // True if this reader is waiting for a Content Decryption Module to become
@@ -102,28 +102,19 @@ public:
   virtual void BreakCycles();
 
   // Destroys the decoding state. The reader cannot be made usable again.
   // This is different from ReleaseMediaResources() as it is irreversable,
   // whereas ReleaseMediaResources() is.  Must be called on the decode
   // thread.
   virtual nsRefPtr<ShutdownPromise> Shutdown();
 
-  MediaTaskQueue* EnsureTaskQueue();
-
   virtual bool OnTaskQueue()
   {
-    return !GetTaskQueue() || GetTaskQueue()->IsCurrentThreadIn();
-  }
-
-  void SetBorrowedTaskQueue(MediaTaskQueue* aTaskQueue)
-  {
-    MOZ_ASSERT(!mTaskQueue && aTaskQueue);
-    mTaskQueue = aTaskQueue;
-    mTaskQueueIsBorrowed = true;
+    return GetTaskQueue()->IsCurrentThreadIn();
   }
 
   // Resets all state related to decoding, emptying all buffers etc.
   // Cancels all pending Request*Data() request callbacks, rejects any
   // outstanding seek promises, and flushes the decode pipeline. The
   // decoder must not call any of the callbacks for outstanding
   // Request*Data() calls after this is called. Calls to Request*Data()
   // made after this should be processed as usual.
@@ -315,16 +306,19 @@ protected:
   // minimal allocation slop and then pushes them to the queue.  This is
   // useful for decoders working with formats that give awkward numbers of
   // frames such as mp3.
   AudioCompactor mAudioCompactor;
 
   // Reference to the owning decoder object.
   AbstractMediaDecoder* mDecoder;
 
+  // Decode task queue.
+  nsRefPtr<MediaTaskQueue> mTaskQueue;
+
   // Stores presentation info required for playback.
   MediaInfo mInfo;
 
   // Whether we should accept media that we know we can't play
   // directly, because they have a number of channel higher than
   // what we support.
   bool mIgnoreAudioOutputFormat;
 
@@ -342,17 +336,16 @@ protected:
   bool mShutdown;
 
 private:
   // Promises used only for the base-class (sync->async adapter) implementation
   // of Request{Audio,Video}Data.
   MediaPromiseHolder<AudioDataPromise> mBaseAudioPromise;
   MediaPromiseHolder<VideoDataPromise> mBaseVideoPromise;
 
-  nsRefPtr<MediaTaskQueue> mTaskQueue;
   bool mTaskQueueIsBorrowed;
 
   // Flags whether a the next audio/video sample comes after a "gap" or
   // "discontinuity" in the stream. For example after a seek.
   bool mAudioDiscontinuity;
   bool mVideoDiscontinuity;
 };
 
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -1253,20 +1253,16 @@ bool MediaDecoderStateMachine::IsPlaying
   AssertCurrentThreadInMonitor();
   return !mPlayStartTime.IsNull();
 }
 
 nsresult MediaDecoderStateMachine::Init(MediaDecoderStateMachine* aCloneDonor)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  if (NS_WARN_IF(!mReader->EnsureTaskQueue())) {
-    return NS_ERROR_FAILURE;
-  }
-
   MediaDecoderReader* cloneReader = nullptr;
   if (aCloneDonor) {
     cloneReader = aCloneDonor->mReader;
   }
 
   nsresult rv = mReader->Init(cloneReader);
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -56,18 +56,19 @@ TrackTypeToStr(TrackInfo::TrackType aTra
   case TrackInfo::kTextTrack:
     return "Text";
   default:
     return "Unknown";
   }
 }
 
 MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder,
-                                       MediaDataDemuxer* aDemuxer)
-  : MediaDecoderReader(aDecoder)
+                                     MediaDataDemuxer* aDemuxer,
+                                     MediaTaskQueue* aBorrowedTaskQueue)
+  : MediaDecoderReader(aDecoder, aBorrowedTaskQueue)
   , mDemuxer(aDemuxer)
   , mAudio(this, MediaData::AUDIO_DATA, Preferences::GetUint("media.audio-decode-ahead", 2))
   , mVideo(this, MediaData::VIDEO_DATA, Preferences::GetUint("media.video-decode-ahead", 2))
   , mLastReportedNumDecodedFrames(0)
   , mLayersBackendType(layers::LayersBackend::LAYERS_NONE)
   , mInitDone(false)
   , mSeekable(false)
   , mIsEncrypted(false)
--- a/dom/media/MediaFormatReader.h
+++ b/dom/media/MediaFormatReader.h
@@ -25,17 +25,18 @@ namespace mozilla {
 
 class MediaFormatReader final : public MediaDecoderReader
 {
   typedef TrackInfo::TrackType TrackType;
   typedef media::Interval<int64_t> ByteInterval;
 
 public:
   explicit MediaFormatReader(AbstractMediaDecoder* aDecoder,
-                              MediaDataDemuxer* aDemuxer);
+                             MediaDataDemuxer* aDemuxer,
+                             MediaTaskQueue* aBorrowedTaskQueue = nullptr);
 
   virtual ~MediaFormatReader();
 
   virtual nsresult Init(MediaDecoderReader* aCloneDonor) override;
 
   virtual size_t SizeOfVideoQueueInFrames() override;
   virtual size_t SizeOfAudioQueueInFrames() override;
 
--- a/dom/media/fmp4/MP4Reader.cpp
+++ b/dom/media/fmp4/MP4Reader.cpp
@@ -139,18 +139,18 @@ InvokeAndRetry(ThisType* aThisVal, Retur
 
     prevFailure = failure;
     if (NS_WARN_IF(!stream->BlockingReadIntoCache(failure.mOffset, failure.mCount, aMonitor))) {
       return result;
     }
   }
 }
 
-MP4Reader::MP4Reader(AbstractMediaDecoder* aDecoder)
-  : MediaDecoderReader(aDecoder)
+MP4Reader::MP4Reader(AbstractMediaDecoder* aDecoder, MediaTaskQueue* aBorrowedTaskQueue)
+  : MediaDecoderReader(aDecoder, aBorrowedTaskQueue)
   , mAudio(MediaData::AUDIO_DATA, Preferences::GetUint("media.mp4-audio-decode-ahead", 2))
   , mVideo(MediaData::VIDEO_DATA, Preferences::GetUint("media.mp4-video-decode-ahead", 2))
   , mLastReportedNumDecodedFrames(0)
   , mLayersBackendType(layers::LayersBackend::LAYERS_NONE)
   , mDemuxerInitialized(false)
   , mFoundSPSForTelemetry(false)
   , mIsEncrypted(false)
   , mIndexReady(false)
--- a/dom/media/fmp4/MP4Reader.h
+++ b/dom/media/fmp4/MP4Reader.h
@@ -29,17 +29,17 @@ class MP4Stream;
 #undef MP4_READER_DORMANT_HEURISTIC
 #endif
 
 class MP4Reader final : public MediaDecoderReader
 {
   typedef TrackInfo::TrackType TrackType;
 
 public:
-  explicit MP4Reader(AbstractMediaDecoder* aDecoder);
+  explicit MP4Reader(AbstractMediaDecoder* aDecoder, MediaTaskQueue* aBorrowedTaskQueue = nullptr);
 
   virtual ~MP4Reader();
 
   virtual nsresult Init(MediaDecoderReader* aCloneDonor) override;
 
   virtual size_t SizeOfVideoQueueInFrames() override;
   virtual size_t SizeOfAudioQueueInFrames() override;
 
--- a/dom/media/gtest/TestMP4Reader.cpp
+++ b/dom/media/gtest/TestMP4Reader.cpp
@@ -31,17 +31,16 @@ public:
   {
     EXPECT_EQ(NS_OK, Preferences::SetBool(
                        "media.fragmented-mp4.use-blank-decoder", true));
 
     EXPECT_EQ(NS_OK, resource->Open(nullptr));
     decoder->SetResource(resource);
 
     reader->Init(nullptr);
-    reader->EnsureTaskQueue();
     {
       // This needs to be done before invoking GetBuffered. This is normally
       // done by MediaDecoderStateMachine.
       ReentrantMonitorAutoEnter mon(decoder->GetReentrantMonitor());
       reader->SetStartTime(0);
     }
   }
 
--- a/dom/media/mediasource/MediaSourceReader.cpp
+++ b/dom/media/mediasource/MediaSourceReader.cpp
@@ -673,75 +673,74 @@ MediaSourceReader::ReleaseMediaResources
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   if (GetVideoReader()) {
     GetVideoReader()->ReleaseMediaResources();
   }
 }
 
 MediaDecoderReader*
-CreateReaderForType(const nsACString& aType, AbstractMediaDecoder* aDecoder)
+CreateReaderForType(const nsACString& aType, AbstractMediaDecoder* aDecoder,
+                    MediaTaskQueue* aBorrowedTaskQueue)
 {
 #ifdef MOZ_FMP4
   // The MP4Reader that supports fragmented MP4 and uses
   // PlatformDecoderModules is hidden behind prefs for regular video
   // elements, but we always want to use it for MSE, so instantiate it
   // directly here.
   if ((aType.LowerCaseEqualsLiteral("video/mp4") ||
        aType.LowerCaseEqualsLiteral("audio/mp4")) &&
       MP4Decoder::IsEnabled() && aDecoder) {
     bool useFormatDecoder =
       Preferences::GetBool("media.mediasource.format-reader.mp4", true);
     MediaDecoderReader* reader = useFormatDecoder ?
-      static_cast<MediaDecoderReader*>(new MediaFormatReader(aDecoder, new MP4Demuxer(aDecoder->GetResource()))) :
-      static_cast<MediaDecoderReader*>(new MP4Reader(aDecoder));
+      static_cast<MediaDecoderReader*>(new MediaFormatReader(aDecoder, new MP4Demuxer(aDecoder->GetResource()), aBorrowedTaskQueue)) :
+      static_cast<MediaDecoderReader*>(new MP4Reader(aDecoder, aBorrowedTaskQueue));
     return reader;
   }
 #endif
 
 #ifdef MOZ_WEBM
   if (DecoderTraits::IsWebMType(aType)) {
-    return new WebMReader(aDecoder);
+    return new WebMReader(aDecoder, aBorrowedTaskQueue);
   }
 #endif
 
   return nullptr;
 }
 
 already_AddRefed<SourceBufferDecoder>
 MediaSourceReader::CreateSubDecoder(const nsACString& aType, int64_t aTimestampOffset)
 {
   if (IsShutdown()) {
     return nullptr;
   }
-  MOZ_ASSERT(GetTaskQueue());
+
+  // The task queue borrowing is icky. It would be nicer to just give each subreader
+  // its own task queue. Unfortunately though, Request{Audio,Video}Data implementations
+  // currently assert that they're on "the decode thread", and so having
+  // separate task queues makes MediaSource stuff unnecessarily cumbersome. We
+  // should remove the need for these assertions (which probably involves making
+  // all Request*Data implementations fully async), and then get rid of the
+  // borrowing.
   nsRefPtr<SourceBufferDecoder> decoder =
     new SourceBufferDecoder(new SourceBufferResource(aType), mDecoder, aTimestampOffset);
-  nsRefPtr<MediaDecoderReader> reader(CreateReaderForType(aType, decoder));
+  nsRefPtr<MediaDecoderReader> reader(CreateReaderForType(aType, decoder, GetTaskQueue()));
   if (!reader) {
     return nullptr;
   }
 
   // MSE uses a start time of 0 everywhere. Set that immediately on the
   // subreader to make sure that it's always in a state where we can invoke
   // GetBuffered on it.
   {
     ReentrantMonitorAutoEnter mon(decoder->GetReentrantMonitor());
     reader->SetStartTime(0);
   }
 
-  // This part is icky. It would be nicer to just give each subreader its own
-  // task queue. Unfortunately though, Request{Audio,Video}Data implementations
-  // currently assert that they're on "the decode thread", and so having
-  // separate task queues makes MediaSource stuff unnecessarily cumbersome. We
-  // should remove the need for these assertions (which probably involves making
-  // all Request*Data implementations fully async), and then get rid of the
-  // borrowing.
-  reader->SetBorrowedTaskQueue(GetTaskQueue());
-
 #ifdef MOZ_FMP4
   reader->SetSharedDecoderManager(mSharedDecoderManager);
 #endif
   reader->Init(nullptr);
 
   MSE_DEBUG("subdecoder %p subreader %p",
             decoder.get(), reader.get());
   decoder->SetReader(reader);
--- a/dom/media/webaudio/MediaBufferDecoder.cpp
+++ b/dom/media/webaudio/MediaBufferDecoder.cpp
@@ -206,20 +206,16 @@ MediaDecodeTask::CreateReader()
     return false;
   }
 
   nsresult rv = mDecoderReader->Init(nullptr);
   if (NS_FAILED(rv)) {
     return false;
   }
 
-  if (!mDecoderReader->EnsureTaskQueue()) {
-    return false;
-  }
-
   return true;
 }
 
 class AutoResampler final
 {
 public:
   AutoResampler()
     : mResampler(nullptr)
--- a/dom/media/webm/WebMReader.cpp
+++ b/dom/media/webm/WebMReader.cpp
@@ -156,18 +156,18 @@ ogg_packet InitOggPacket(const unsigned 
   packet.packetno = aPacketNo;
   return packet;
 }
 
 #if defined(MOZ_PDM_VPX)
 static bool sIsIntelDecoderEnabled = false;
 #endif
 
-WebMReader::WebMReader(AbstractMediaDecoder* aDecoder)
-  : MediaDecoderReader(aDecoder)
+WebMReader::WebMReader(AbstractMediaDecoder* aDecoder, MediaTaskQueue* aBorrowedTaskQueue)
+  : MediaDecoderReader(aDecoder, aBorrowedTaskQueue)
   , mContext(nullptr)
   , mPacketCount(0)
   , mOpusDecoder(nullptr)
   , mSkip(0)
   , mSeekPreroll(0)
   , mVideoTrack(0)
   , mAudioTrack(0)
   , mAudioStartUsec(-1)
--- a/dom/media/webm/WebMReader.h
+++ b/dom/media/webm/WebMReader.h
@@ -136,17 +136,17 @@ public:
                                 int64_t aTimeThreshold) = 0;
   WebMVideoDecoder() {}
   virtual ~WebMVideoDecoder() {}
 };
 
 class WebMReader : public MediaDecoderReader
 {
 public:
-  explicit WebMReader(AbstractMediaDecoder* aDecoder);
+  explicit WebMReader(AbstractMediaDecoder* aDecoder, MediaTaskQueue* aBorrowedTaskQueue = nullptr);
 
 protected:
   ~WebMReader();
 
 public:
   virtual nsRefPtr<ShutdownPromise> Shutdown() override;
   virtual nsresult Init(MediaDecoderReader* aCloneDonor) override;
   virtual nsresult ResetDecode() override;