Bug 1282722: add seek target threshold for VPX decoder. r?jwwang draft
authorAlfredo Yang <ayang@mozilla.com>
Fri, 24 Jun 2016 15:54:53 +0800
changeset 382207 74250c3b6da6ca029875a59e2bc114011508d146
parent 381812 017843f01210c2c4409d89333487cec116148fc0
child 524125 5f1d7403b3abd7b5994ce637062207c68c4f5a99
push id21649
push userayang@mozilla.com
push dateWed, 29 Jun 2016 06:34:06 +0000
reviewersjwwang
bugs1282722
milestone50.0a1
Bug 1282722: add seek target threshold for VPX decoder. r?jwwang MozReview-Commit-ID: FGLhKRH8j3u
dom/media/platforms/agnostic/VPXDecoder.cpp
dom/media/platforms/agnostic/VPXDecoder.h
--- a/dom/media/platforms/agnostic/VPXDecoder.cpp
+++ b/dom/media/platforms/agnostic/VPXDecoder.cpp
@@ -88,17 +88,17 @@ VPXDecoder::Init()
 }
 
 nsresult
 VPXDecoder::Flush()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   mIsFlushing = true;
   nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([this] () {
-    // nothing to do for now.
+    this->mSeekTargetThreshold.reset();
   });
   SyncRunnable::DispatchToThread(mTaskQueue, r);
   mIsFlushing = false;
   return NS_OK;
 }
 
 int
 VPXDecoder::DoDecode(MediaRawData* aSample)
@@ -125,16 +125,25 @@ VPXDecoder::DoDecode(MediaRawData* aSamp
   vpx_codec_iter_t  iter = nullptr;
   vpx_image_t      *img;
 
   while ((img = vpx_codec_get_frame(&mVPX, &iter))) {
     NS_ASSERTION(img->fmt == VPX_IMG_FMT_I420 ||
                  img->fmt == VPX_IMG_FMT_I444,
                  "WebM image format not I420 or I444");
 
+    if (mSeekTargetThreshold) {
+      if ((aSample->mTime + aSample->mDuration) < mSeekTargetThreshold.ref().ToMicroseconds()) {
+        LOG("VPX Decode drops frame with pts %lld, duration: %lld",
+             aSample->mTime, aSample->mDuration);
+        continue;
+      }
+      mSeekTargetThreshold.reset();
+    }
+
     // Chroma shifts are rounded down as per the decoding examples in the SDK
     VideoData::YCbCrBuffer b;
     b.mPlanes[0].mData = img->planes[0];
     b.mPlanes[0].mStride = img->stride[0];
     b.mPlanes[0].mHeight = img->d_h;
     b.mPlanes[0].mWidth = img->d_w;
     b.mPlanes[0].mOffset = b.mPlanes[0].mSkip = 0;
 
@@ -220,16 +229,27 @@ nsresult
 VPXDecoder::Drain()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   mTaskQueue->Dispatch(NewRunnableMethod(this, &VPXDecoder::ProcessDrain));
 
   return NS_OK;
 }
 
+void
+VPXDecoder::SetSeekThreshold(const media::TimeUnit& aTime)
+{
+  MOZ_ASSERT(mCallback->OnReaderTaskQueue());
+  RefPtr<VPXDecoder> self = this;
+  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aTime] () {
+    self->mSeekTargetThreshold = Some(aTime);
+  });
+  mTaskQueue->Dispatch(r.forget());
+}
+
 /* static */
 bool
 VPXDecoder::IsVPX(const nsACString& aMimeType, uint8_t aCodecMask)
 {
   return ((aCodecMask & VPXDecoder::VP8) &&
           aMimeType.EqualsLiteral("video/webm; codecs=vp8")) ||
          ((aCodecMask & VPXDecoder::VP9) &&
           aMimeType.EqualsLiteral("video/webm; codecs=vp9"));
--- a/dom/media/platforms/agnostic/VPXDecoder.h
+++ b/dom/media/platforms/agnostic/VPXDecoder.h
@@ -32,16 +32,17 @@ public:
   nsresult Input(MediaRawData* aSample) override;
   nsresult Flush() override;
   nsresult Drain() override;
   nsresult Shutdown() override;
   const char* GetDescriptionName() const override
   {
     return "libvpx video decoder";
   }
+  void SetSeekThreshold(const media::TimeUnit& aTime) override;
 
   enum Codec: uint8_t {
     VP8 = 1 << 0,
     VP9 = 1 << 1
   };
 
   // Return true if mimetype is a VPX codec of given types.
   static bool IsVPX(const nsACString& aMimeType, uint8_t aCodecMask=VP8|VP9);
@@ -50,16 +51,18 @@ private:
   void ProcessDecode(MediaRawData* aSample);
   int DoDecode(MediaRawData* aSample);
   void ProcessDrain();
 
   const RefPtr<ImageContainer> mImageContainer;
   const RefPtr<TaskQueue> mTaskQueue;
   MediaDataDecoderCallback* mCallback;
   Atomic<bool> mIsFlushing;
+  // mSeekTargetThreshold is accessed in mTaskQueue.
+  Maybe<media::TimeUnit> mSeekTargetThreshold;
 
   // VPx decoder state
   vpx_codec_ctx_t mVPX;
 
   const VideoInfo& mInfo;
 
   const int mCodec;
 };