Bug 1378631. P1 - move the duration mirror from MediaDecoderReader to MediaDecoderReaderWrapper. r=jya
authorJW Wang <jwwang@mozilla.com>
Thu, 06 Jul 2017 11:45:02 +0800
changeset 368169 8d529f0b6575b7f95111597e060dc3a0538d388d
parent 368168 33f8d1b03767e0f63c2420a9b510372ff98ffe8b
child 368170 d047630ee1fff5792cb0e7e0230ffdeeb4fc0e57
push id32158
push usercbook@mozilla.com
push dateTue, 11 Jul 2017 10:48:59 +0000
treeherdermozilla-central@5e2692f8a367 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1378631
milestone56.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 1378631. P1 - move the duration mirror from MediaDecoderReader to MediaDecoderReaderWrapper. r=jya So we can remove AbstractMediaDecoder::CanonicalDurationOrNull() later. MozReview-Commit-ID: 6zJCFDsCZPC
dom/media/MediaDecoderReader.cpp
dom/media/MediaDecoderReader.h
dom/media/MediaDecoderReaderWrapper.cpp
dom/media/MediaDecoderReaderWrapper.h
dom/media/MediaDecoderStateMachine.cpp
--- a/dom/media/MediaDecoderReader.cpp
+++ b/dom/media/MediaDecoderReader.cpp
@@ -70,53 +70,32 @@ public:
 
 MediaDecoderReader::MediaDecoderReader(const MediaDecoderReaderInit& aInit)
   : mAudioCompactor(mAudioQueue)
   , mDecoder(aInit.mDecoder)
   , mTaskQueue(new TaskQueue(
       GetMediaThreadPool(MediaThreadType::PLAYBACK),
       "MediaDecoderReader::mTaskQueue",
       /* aSupportsTailDispatch = */ true))
-  , mWatchManager(this, mTaskQueue)
   , mBuffered(mTaskQueue, TimeIntervals(), "MediaDecoderReader::mBuffered (Canonical)")
-  , mDuration(mTaskQueue, NullableTimeUnit(), "MediaDecoderReader::mDuration (Mirror)")
   , mIgnoreAudioOutputFormat(false)
   , mHitAudioDecodeError(false)
   , mShutdown(false)
   , mResource(aInit.mResource)
 {
   MOZ_COUNT_CTOR(MediaDecoderReader);
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 nsresult
 MediaDecoderReader::Init()
 {
-  // Dispatch initialization that needs to happen on that task queue.
-  mTaskQueue->Dispatch(
-    NewRunnableMethod("MediaDecoderReader::InitializationTask",
-                      this,
-                      &MediaDecoderReader::InitializationTask));
   return InitInternal();
 }
 
-void
-MediaDecoderReader::InitializationTask()
-{
-  if (!mDecoder) {
-    return;
-  }
-  if (mDecoder->CanonicalDurationOrNull()) {
-    mDuration.Connect(mDecoder->CanonicalDurationOrNull());
-  }
-
-  // Initialize watchers.
-  mWatchManager.Watch(mDuration, &MediaDecoderReader::UpdateBuffered);
-}
-
 MediaDecoderReader::~MediaDecoderReader()
 {
   MOZ_ASSERT(mShutdown);
   MOZ_COUNT_DTOR(MediaDecoderReader);
 }
 
 size_t MediaDecoderReader::SizeOfVideoQueueInBytes() const
 {
@@ -137,16 +116,24 @@ size_t MediaDecoderReader::SizeOfVideoQu
   return mVideoQueue.GetSize();
 }
 
 size_t MediaDecoderReader::SizeOfAudioQueueInFrames()
 {
   return mAudioQueue.GetSize();
 }
 
+void
+MediaDecoderReader::UpdateDuration(const media::TimeUnit& aDuration)
+{
+  MOZ_ASSERT(OnTaskQueue());
+  mDuration = Some(aDuration);
+  UpdateBuffered();
+}
+
 nsresult MediaDecoderReader::ResetDecode(TrackSet aTracks)
 {
   if (aTracks.contains(TrackInfo::kVideoTrack)) {
     VideoQueue().Reset();
     mBaseVideoPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
   }
 
   if (aTracks.contains(TrackInfo::kAudioTrack)) {
@@ -198,23 +185,22 @@ void
 MediaDecoderReader::VisibilityChanged()
 {}
 
 media::TimeIntervals
 MediaDecoderReader::GetBuffered()
 {
   MOZ_ASSERT(OnTaskQueue());
 
-  AutoPinned<MediaResource> stream(mResource);
-
-  if (!mDuration.Ref().isSome()) {
+  if (mDuration.isNothing()) {
     return TimeIntervals();
   }
 
-  return GetEstimatedBufferedTimeRanges(stream, mDuration.Ref().ref().ToMicroseconds());
+  AutoPinned<MediaResource> stream(mResource);
+  return GetEstimatedBufferedTimeRanges(stream, mDuration->ToMicroseconds());
 }
 
 RefPtr<MediaDecoderReader::MetadataPromise>
 MediaDecoderReader::AsyncReadMetadata()
 {
   MOZ_ASSERT(OnTaskQueue());
   DECODER_LOG("MediaDecoderReader::AsyncReadMetadata");
 
@@ -366,20 +352,16 @@ MediaDecoderReader::Shutdown()
 {
   MOZ_ASSERT(OnTaskQueue());
   mShutdown = true;
 
   mBaseAudioPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
   mBaseVideoPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
 
   ReleaseResources();
-  mDuration.DisconnectIfConnected();
   mBuffered.DisconnectAll();
 
-  // Shut down the watch manager before shutting down our task queue.
-  mWatchManager.Shutdown();
-
   mDecoder = nullptr;
 
   return mTaskQueue->BeginShutdown();
 }
 
 } // namespace mozilla
--- a/dom/media/MediaDecoderReader.h
+++ b/dom/media/MediaDecoderReader.h
@@ -127,16 +127,18 @@ public:
   // thread.
   virtual RefPtr<ShutdownPromise> Shutdown();
 
   virtual bool OnTaskQueue() const
   {
     return OwnerThread()->IsCurrentThreadIn();
   }
 
+  void UpdateDuration(const media::TimeUnit& aDuration);
+
   // 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.
   //
   // Normally this call preceedes a Seek() call, or shutdown.
@@ -296,27 +298,23 @@ protected:
   AudioCompactor mAudioCompactor;
 
   // Reference to the owning decoder object.
   AbstractMediaDecoder* mDecoder;
 
   // Decode task queue.
   RefPtr<TaskQueue> mTaskQueue;
 
-  // State-watching manager.
-  WatchManager<MediaDecoderReader> mWatchManager;
-
   // Buffered range.
   Canonical<media::TimeIntervals> mBuffered;
 
   // Stores presentation info required for playback.
   MediaInfo mInfo;
 
-  // Duration, mirrored from the state machine task queue.
-  Mirror<media::NullableTimeUnit> mDuration;
+  media::NullableTimeUnit mDuration;
 
   // 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;
 
   // This is a quick-and-dirty way for DecodeAudioData implementations to
   // communicate the presence of a decoding error to RequestAudioData. We should
@@ -334,22 +332,16 @@ protected:
   // Notify if we are waiting for a decryption key.
   MediaEventProducer<TrackInfo::TrackType> mOnTrackWaitingForKey;
 
   RefPtr<MediaResource> mResource;
 
 private:
   virtual nsresult InitInternal() { return NS_OK; }
 
-  // Does any spinup that needs to happen on this task queue. This runs on a
-  // different thread than Init, and there should not be ordering dependencies
-  // between the two (even though in practice, Init will always run first right
-  // now thanks to the tail dispatcher).
-  void InitializationTask();
-
   // Read header data for all bitstreams in the file. Fills aInfo with
   // the data required to present the media, and optionally fills *aTags
   // with tag metadata from the file.
   // Returns NS_OK on success, or NS_ERROR_FAILURE on failure.
   virtual nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
   {
     MOZ_CRASH();
   }
--- a/dom/media/MediaDecoderReaderWrapper.cpp
+++ b/dom/media/MediaDecoderReaderWrapper.cpp
@@ -8,16 +8,20 @@
 #include "MediaDecoderReaderWrapper.h"
 
 namespace mozilla {
 
 MediaDecoderReaderWrapper::MediaDecoderReaderWrapper(AbstractThread* aOwnerThread,
                                                      MediaDecoderReader* aReader)
   : mOwnerThread(aOwnerThread)
   , mReader(aReader)
+  , mWatchManager(this, aReader->OwnerThread())
+  , mDuration(aReader->OwnerThread(),
+              NullableTimeUnit(),
+              "MediaDecoderReaderWrapper::mDuration (Mirror)")
 {
   // Must support either heuristic buffering or WaitForData().
   MOZ_ASSERT(mReader->UseBufferingHeuristics() ||
              mReader->IsWaitForDataSupported());
 }
 
 MediaDecoderReaderWrapper::~MediaDecoderReaderWrapper()
 {}
@@ -129,18 +133,22 @@ MediaDecoderReaderWrapper::ResetDecode(T
   mReader->OwnerThread()->Dispatch(r.forget());
 }
 
 RefPtr<ShutdownPromise>
 MediaDecoderReaderWrapper::Shutdown()
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   mShutdown = true;
-  return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
-                     &MediaDecoderReader::Shutdown);
+  RefPtr<MediaDecoderReaderWrapper> self = this;
+  return InvokeAsync(mReader->OwnerThread(), __func__, [self]() {
+    self->mDuration.DisconnectIfConnected();
+    self->mWatchManager.Shutdown();
+    return self->mReader->Shutdown();
+  });
 }
 
 RefPtr<MediaDecoderReaderWrapper::MetadataPromise>
 MediaDecoderReaderWrapper::OnMetadataRead(MetadataHolder&& aMetadata)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   if (mShutdown) {
     return MetadataPromise::CreateAndReject(
@@ -166,9 +174,33 @@ MediaDecoderReaderWrapper::SetVideoBlank
   nsCOMPtr<nsIRunnable> r =
     NewRunnableMethod<bool>("MediaDecoderReader::SetVideoNullDecode",
                             mReader,
                             &MediaDecoderReader::SetVideoNullDecode,
                             aIsBlankDecode);
   mReader->OwnerThread()->Dispatch(r.forget());
 }
 
+void
+MediaDecoderReaderWrapper::UpdateDuration()
+{
+  MOZ_ASSERT(mReader->OwnerThread()->IsCurrentThreadIn());
+  mReader->UpdateDuration(mDuration.Ref().ref());
+}
+
+void
+MediaDecoderReaderWrapper::SetCanonicalDuration(
+  AbstractCanonical<media::NullableTimeUnit>* aCanonical)
+{
+  using DurationT = AbstractCanonical<media::NullableTimeUnit>;
+  RefPtr<MediaDecoderReaderWrapper> self = this;
+  RefPtr<DurationT> canonical = aCanonical;
+  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
+    "MediaDecoderReaderWrapper::SetCanonicalDuration",
+    [this, self, canonical]() {
+      mDuration.Connect(canonical);
+      mWatchManager.Watch(mDuration,
+                          &MediaDecoderReaderWrapper::UpdateDuration);
+    });
+  mReader->OwnerThread()->Dispatch(r.forget());
+}
+
 } // namespace mozilla
--- a/dom/media/MediaDecoderReaderWrapper.h
+++ b/dom/media/MediaDecoderReaderWrapper.h
@@ -83,23 +83,33 @@ public:
   AbstractCanonical<media::TimeIntervals>* CanonicalBuffered() {
     return mReader->CanonicalBuffered();
   }
 
   void SetCDMProxy(CDMProxy* aProxy) { mReader->SetCDMProxy(aProxy); }
 
   void SetVideoBlankDecode(bool aIsBlankDecode);
 
+  void SetCanonicalDuration(
+    AbstractCanonical<media::NullableTimeUnit>* aCanonical);
+
 private:
   ~MediaDecoderReaderWrapper();
   RefPtr<MetadataPromise> OnMetadataRead(MetadataHolder&& aMetadata);
   RefPtr<MetadataPromise> OnMetadataNotRead(const MediaResult& aError);
+  void UpdateDuration();
 
   const RefPtr<AbstractThread> mOwnerThread;
   const RefPtr<MediaDecoderReader> mReader;
 
   bool mShutdown = false;
   Maybe<media::TimeUnit> mStartTime;
+
+  // State-watching manager.
+  WatchManager<MediaDecoderReaderWrapper> mWatchManager;
+
+  // Duration, mirrored from the state machine task queue.
+  Mirror<media::NullableTimeUnit> mDuration;
 };
 
 } // namespace mozilla
 
 #endif // MediaDecoderReaderWrapper_h_
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2956,16 +2956,18 @@ nsresult MediaDecoderStateMachine::Init(
     OwnerThread(), __func__, this,
     &MediaDecoderStateMachine::OnCDMProxyReady,
     &MediaDecoderStateMachine::OnCDMProxyNotReady)
   ->Track(mCDMProxyPromise);
 
   nsresult rv = mReader->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
+  mReader->SetCanonicalDuration(&mDuration);
+
   return NS_OK;
 }
 
 void
 MediaDecoderStateMachine::StopPlayback()
 {
   MOZ_ASSERT(OnTaskQueue());
   LOG("StopPlayback()");