Bug 1274626 part 5 - provide APIs to switch to blank decoders dynamically; r=jya draft
authorKaku Kuo <tkuo@mozilla.com>
Fri, 29 Jul 2016 14:51:18 +0800
changeset 396020 43d69e89e24fdbdf62a89a7a1f4511066f6fee3c
parent 396019 e52b85b0d4925c3a28d2127d6de14ba77f5bc88a
child 396021 bb308422cb06039fdf8b4b971fc4a063c3aeee35
push id24896
push usertkuo@mozilla.com
push dateWed, 03 Aug 2016 07:58:00 +0000
reviewersjya
bugs1274626
milestone51.0a1
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();
@@ -2051,9 +2053,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