Bug 1274626 part 5 - provide APIs to switch to blank decoders dynamically; r=jya
authorKaku Kuo <tkuo@mozilla.com>
Fri, 29 Jul 2016 14:51:18 +0800
changeset 308036 e15f10941eed0808b6de4197918b84979797d566
parent 308035 fd97d47edbb9c3671694dc2446a131e3901f4a41
child 308037 4adc486250b600006b6d7eaedf038c9fdf4cb26e
push id30528
push usercbook@mozilla.com
push dateThu, 04 Aug 2016 13:58:28 +0000
treeherdermozilla-central@0ba72e8027cf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1274626
milestone51.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 1274626 part 5 - provide APIs to switch to blank decoders dynamically; r=jya MozReview-Commit-ID: PyoIsrEf1r
dom/media/MediaDecoderReader.h
dom/media/MediaDecoderReaderWrapper.cpp
dom/media/MediaDecoderReaderWrapper.h
dom/media/MediaFormatReader.cpp
dom/media/MediaFormatReader.h
--- a/dom/media/MediaDecoderReader.h
+++ b/dom/media/MediaDecoderReader.h
@@ -312,16 +312,21 @@ public:
     MOZ_ASSERT(OnTaskQueue());
     mIsSuspended = aState;
   }
 
   AbstractCanonical<bool>* CanonicalIsSuspended() {
     return &mIsSuspended;
   }
 
+  // Switch the video decoder to BlankDecoderModule. It might takes effective
+  // since a few samples later depends on how much demuxed samples are already
+  // queued in the original video decoder.
+  virtual void SetVideoBlankDecode(bool aIsBlankDecode) {}
+
 protected:
   virtual ~MediaDecoderReader();
 
   // Populates aBuffered with the time ranges which are buffered. This may only
   // be called on the decode task queue, and should only be used internally by
   // UpdateBuffered - mBuffered (or mirrors of it) should be used for everything
   // else.
   //
--- a/dom/media/MediaDecoderReaderWrapper.cpp
+++ b/dom/media/MediaDecoderReaderWrapper.cpp
@@ -405,9 +405,19 @@ MediaDecoderReaderWrapper::OnMetadataRea
         self->mReader->DispatchSetStartTime(self->StartTime().ToMicroseconds());
       },
       [] () {
         NS_WARNING("Setting start time on reader failed");
       });
   }
 }
 
+void
+MediaDecoderReaderWrapper::SetVideoBlankDecode(bool aIsBlankDecode)
+{
+  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
+  nsCOMPtr<nsIRunnable> r =
+    NewRunnableMethod<bool>(mReader, &MediaDecoderReader::SetVideoBlankDecode,
+                            aIsBlankDecode);
+  mReader->OwnerThread()->Dispatch(r.forget());
+}
+
 } // namespace mozilla
--- a/dom/media/MediaDecoderReaderWrapper.h
+++ b/dom/media/MediaDecoderReaderWrapper.h
@@ -116,16 +116,18 @@ public:
   AbstractCanonical<bool>* CanonicalIsSuspended() {
     return mReader->CanonicalIsSuspended();
   }
 
 #ifdef MOZ_EME
   void SetCDMProxy(CDMProxy* aProxy) { mReader->SetCDMProxy(aProxy); }
 #endif
 
+  void SetVideoBlankDecode(bool aIsBlankDecode);
+
 private:
   ~MediaDecoderReaderWrapper();
 
   void OnMetadataRead(MetadataHolder* aMetadata);
   void OnMetadataNotRead() {}
   MediaCallbackExc<WaitCallbackData>& WaitCallbackRef(MediaData::Type aType);
   MozPromiseRequestHolder<WaitForDataPromise>& WaitRequestRef(MediaData::Type aType);
 
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -413,31 +413,33 @@ MediaFormatReader::EnsureDecoderCreated(
   MonitorAutoLock mon(decoder.mMonitor);
 
   switch (aTrack) {
     case TrackType::kAudioTrack: {
       decoder.mDecoder = mPlatform->CreateDecoder({
         decoder.mInfo ? *decoder.mInfo->GetAsAudioInfo() : mInfo.mAudio,
         decoder.mTaskQueue,
         decoder.mCallback.get(),
-        mCrashHelper
+        mCrashHelper,
+        decoder.mIsBlankDecode
       });
       break;
     }
 
     case TrackType::kVideoTrack: {
       // Decoders use the layers backend to decide if they can use hardware decoding,
       // so specify LAYERS_NONE if we want to forcibly disable it.
       decoder.mDecoder = mPlatform->CreateDecoder({
         mVideo.mInfo ? *mVideo.mInfo->GetAsVideoInfo() : mInfo.mVideo,
         decoder.mTaskQueue,
         decoder.mCallback.get(),
         mLayersBackendType,
         GetImageContainer(),
-        mCrashHelper
+        mCrashHelper,
+        decoder.mIsBlankDecode
       });
       break;
     }
     default:
       break;
   }
   if (decoder.mDecoder ) {
     decoder.mDescription = decoder.mDecoder->GetDescriptionName();
@@ -2055,9 +2057,37 @@ MediaFormatReader::GetMozDebugReaderData
                               mVideo.mNumSamplesInput, mVideo.mNumSamplesOutput,
                               unsigned(size_t(mVideo.mSizeOfQueue)),
                               unsigned(mVideo.mOutput.Length()),
                               mVideo.mWaitingForData, mVideo.mLastStreamSourceID);
   }
   aString += NS_ConvertUTF8toUTF16(result);
 }
 
+void
+MediaFormatReader::SetVideoBlankDecode(bool aIsBlankDecode)
+{
+  MOZ_ASSERT(OnTaskQueue());
+  return SetBlankDecode(TrackType::kVideoTrack, aIsBlankDecode);
+}
+
+void
+MediaFormatReader::SetBlankDecode(TrackType aTrack, bool aIsBlankDecode)
+{
+  MOZ_ASSERT(OnTaskQueue());
+  auto& decoder = GetDecoderData(aTrack);
+
+  LOG("%s, decoder.mIsBlankDecode = %d => aIsBlankDecode = %d",
+      TrackTypeToStr(aTrack), decoder.mIsBlankDecode, aIsBlankDecode);
+
+  if (decoder.mIsBlankDecode == aIsBlankDecode) {
+    return;
+  }
+
+  decoder.mIsBlankDecode = aIsBlankDecode;
+  decoder.Flush();
+  decoder.ShutdownDecoder();
+  NotifyDecodingRequested(TrackInfo::kVideoTrack); // Calls ScheduleUpdate().
+
+  return;
+}
+
 } // namespace mozilla
--- a/dom/media/MediaFormatReader.h
+++ b/dom/media/MediaFormatReader.h
@@ -96,16 +96,18 @@ public:
 #ifdef MOZ_EME
   void SetCDMProxy(CDMProxy* aProxy) override;
 #endif
 
   // Returns a string describing the state of the decoder data.
   // Used for debugging purposes.
   void GetMozDebugReaderData(nsAString& aString);
 
+  void SetVideoBlankDecode(bool aIsBlankDecode) override;
+
 private:
 
   bool HasVideo() { return mVideo.mTrackDemuxer; }
   bool HasAudio() { return mAudio.mTrackDemuxer; }
 
   bool IsWaitingOnCDMResource();
 
   bool InitDemuxer();
@@ -248,16 +250,17 @@ private:
       , mMaxConsecutiveError(aNumOfMaxError)
       , mNumSamplesInput(0)
       , mNumSamplesOutput(0)
       , mNumSamplesOutputTotal(0)
       , mNumSamplesSkippedTotal(0)
       , mSizeOfQueue(0)
       , mIsHardwareAccelerated(false)
       , mLastStreamSourceID(UINT32_MAX)
+      , mIsBlankDecode(false)
     {}
 
     MediaFormatReader* mOwner;
     // Disambiguate Audio vs Video.
     MediaData::Type mType;
     RefPtr<MediaTrackDemuxer> mTrackDemuxer;
     // TaskQueue on which decoder can choose to decode.
     // Only non-null up until the decoder is created.
@@ -422,16 +425,19 @@ private:
     Atomic<bool> mIsHardwareAccelerated;
     // Sample format monitoring.
     uint32_t mLastStreamSourceID;
     Maybe<uint32_t> mNextStreamSourceID;
     media::TimeIntervals mTimeRanges;
     Maybe<media::TimeUnit> mLastTimeRangesEnd;
     RefPtr<SharedTrackInfo> mInfo;
     Maybe<media::TimeUnit> mFirstDemuxedSampleTime;
+    // Use BlankDecoderModule or not.
+    bool mIsBlankDecode;
+
   };
 
   class DecoderDataWithPromise : public DecoderData {
   public:
     DecoderDataWithPromise(MediaFormatReader* aOwner,
                            MediaData::Type aType,
                            uint32_t aDecodeAhead,
                            uint32_t aNumOfMaxError)
@@ -566,13 +572,15 @@ private:
 
   RefPtr<VideoFrameContainer> mVideoFrameContainer;
   layers::ImageContainer* GetImageContainer();
 
 #ifdef MOZ_EME
   RefPtr<CDMProxy> mCDMProxy;
 #endif
   RefPtr<GMPCrashHelper> mCrashHelper;
+
+  void SetBlankDecode(TrackType aTrack, bool aIsBlankDecode);
 };
 
 } // namespace mozilla
 
 #endif