Bug 1257107: set video seek thresohld on mac PDM. r=jya draft
authorAlfredo Yang <ayang@mozilla.com>
Tue, 31 May 2016 15:55:33 +0800
changeset 373164 1f35d4565cb1b8c3ff57ebaa12bd1ffff4db6be2
parent 373163 ed6171eda1a3a661e722790f4e3c000248aec4a9
child 522336 8bf7cf192f042990b9f3eb9e5a44c3fbbda9fb72
push id19691
push userayang@mozilla.com
push dateTue, 31 May 2016 07:59:56 +0000
reviewersjya
bugs1257107
milestone49.0a1
Bug 1257107: set video seek thresohld on mac PDM. r=jya MozReview-Commit-ID: F1xZJInK8E0
dom/media/platforms/apple/AppleVDADecoder.cpp
dom/media/platforms/apple/AppleVDADecoder.h
dom/media/platforms/apple/ReorderQueue.h
--- a/dom/media/platforms/apple/AppleVDADecoder.cpp
+++ b/dom/media/platforms/apple/AppleVDADecoder.cpp
@@ -148,16 +148,19 @@ AppleVDADecoder::Flush()
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   mIsFlushing = true;
   nsCOMPtr<nsIRunnable> runnable =
     NewRunnableMethod(this, &AppleVDADecoder::ProcessFlush);
   SyncRunnable::DispatchToThread(mTaskQueue, runnable);
   mIsFlushing = false;
   // All ProcessDecode() tasks should be done.
   MOZ_ASSERT(mInputIncoming == 0);
+
+  mSeekTargetThreshold.reset();
+
   return NS_OK;
 }
 
 nsresult
 AppleVDADecoder::Drain()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   nsCOMPtr<nsIRunnable> runnable =
@@ -285,16 +288,23 @@ AppleVDADecoder::ClearReorderedFrames()
 {
   MonitorAutoLock mon(mMonitor);
   while (!mReorderQueue.IsEmpty()) {
     mReorderQueue.Pop();
   }
   mQueuedSamples = 0;
 }
 
+void
+AppleVDADecoder::SetSeekThreshold(const media::TimeUnit& aTime)
+{
+  LOG("SetSeekThreshold %lld", aTime.ToMicroseconds());
+  mSeekTargetThreshold = Some(aTime);
+}
+
 // Copy and return a decoded frame.
 nsresult
 AppleVDADecoder::OutputFrame(CVPixelBufferRef aImage,
                              AppleVDADecoder::AppleFrameRef aFrameRef)
 {
   if (mIsShutDown || mIsFlushing) {
     // We are in the process of flushing or shutting down; ignore frame.
     return NS_OK;
@@ -316,27 +326,40 @@ AppleVDADecoder::OutputFrame(CVPixelBuff
   MOZ_ASSERT(mQueuedSamples);
   mQueuedSamples--;
 
   if (!aImage) {
     // Image was dropped by decoder.
     return NS_OK;
   }
 
+  bool useNullSample = false;
+  if (mSeekTargetThreshold.isSome()) {
+    if ((aFrameRef.composition_timestamp + aFrameRef.duration) < mSeekTargetThreshold.ref()) {
+      useNullSample = true;
+    } else {
+      mSeekTargetThreshold.reset();
+    }
+  }
+
   // Where our resulting image will end up.
-  RefPtr<VideoData> data;
+  RefPtr<MediaData> data;
   // Bounds.
   VideoInfo info;
   info.mDisplay = nsIntSize(mDisplayWidth, mDisplayHeight);
   gfx::IntRect visible = gfx::IntRect(0,
                                       0,
                                       mPictureWidth,
                                       mPictureHeight);
 
-  if (mUseSoftwareImages) {
+  if (useNullSample) {
+    data = new NullData(aFrameRef.byte_offset,
+                        aFrameRef.composition_timestamp.ToMicroseconds(),
+                        aFrameRef.duration.ToMicroseconds());
+  } else if (mUseSoftwareImages) {
     size_t width = CVPixelBufferGetWidth(aImage);
     size_t height = CVPixelBufferGetHeight(aImage);
     DebugOnly<size_t> planes = CVPixelBufferGetPlaneCount(aImage);
     MOZ_ASSERT(planes == 2, "Likely not NV12 format and it must be.");
 
     VideoData::YCbCrBuffer buffer;
 
     // Lock the returned image data.
--- a/dom/media/platforms/apple/AppleVDADecoder.h
+++ b/dom/media/platforms/apple/AppleVDADecoder.h
@@ -82,16 +82,18 @@ private:
     return true;
   }
 
   const char* GetDescriptionName() const override
   {
     return "apple VDA decoder";
   }
 
+  void SetSeekThreshold(const media::TimeUnit& aTime) override;
+
 protected:
   AppleVDADecoder(const VideoInfo& aConfig,
                   TaskQueue* aTaskQueue,
                   MediaDataDecoderCallback* aCallback,
                   layers::ImageContainer* aImageContainer);
   virtual ~AppleVDADecoder();
 
   void AssertOnTaskQueueThread()
@@ -135,16 +137,20 @@ private:
 
   // Protects mReorderQueue.
   Monitor mMonitor;
   // Set on reader/decode thread calling Flush() to indicate that output is
   // not required and so input samples on mTaskQueue need not be processed.
   // Cleared on mTaskQueue in ProcessDrain().
   Atomic<bool> mIsFlushing;
   ReorderQueue mReorderQueue;
+  // Decoded frame will be dropped if its pts is smaller than this
+  // value. It shold be initialized before Input() or after Flush(). So it is
+  // safe to access it in OutputFrame without protecting.
+  Maybe<media::TimeUnit> mSeekTargetThreshold;
 
   // Method to set up the decompression session.
   nsresult InitializeSession();
 
   // Method to pass a frame to VideoToolbox for decoding.
   nsresult ProcessDecode(MediaRawData* aSample);
   virtual nsresult DoDecode(MediaRawData* aSample);
   CFDictionaryRef CreateDecoderSpecification();
--- a/dom/media/platforms/apple/ReorderQueue.h
+++ b/dom/media/platforms/apple/ReorderQueue.h
@@ -11,19 +11,19 @@
 
 #include <MediaData.h>
 #include <nsTPriorityQueue.h>
 
 namespace mozilla {
 
 struct ReorderQueueComparator
 {
-  bool LessThan(VideoData* const& a, VideoData* const& b) const
+  bool LessThan(MediaData* const& a, MediaData* const& b) const
   {
     return a->mTime < b->mTime;
   }
 };
 
-typedef nsTPriorityQueue<RefPtr<VideoData>, ReorderQueueComparator> ReorderQueue;
+typedef nsTPriorityQueue<RefPtr<MediaData>, ReorderQueueComparator> ReorderQueue;
 
 } // namespace mozilla
 
 #endif // mozilla_ReorderQueue_h