Bug 1280036: don't create video frame before seek target. r=jya
authorAlfredo <ayang@mozilla.com>
Thu, 16 Jun 2016 13:43:52 +0100
changeset 302136 2c64b2476147f216c14e22f997d26722e50b673a
parent 302135 87f4fe4848c26efe073ed77313aac00ffd437060
child 302137 e15474388a5ff4a49fcea922a2e74ae2a0aff0d7
push id78615
push userayang@mozilla.com
push dateTue, 21 Jun 2016 06:48:44 +0000
treeherdermozilla-inbound@2c64b2476147 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1280036
milestone50.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 1280036: don't create video frame before seek target. r=jya MozReview-Commit-ID: G1QTZTWtvmR
dom/media/platforms/wmf/WMFMediaDataDecoder.cpp
dom/media/platforms/wmf/WMFMediaDataDecoder.h
dom/media/platforms/wmf/WMFVideoMFTManager.cpp
--- a/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp
+++ b/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp
@@ -231,9 +231,24 @@ WMFMediaDataDecoder::ConfigurationChange
 void
 WMFMediaDataDecoder::ProcessConfigurationChanged(UniquePtr<TrackInfo>&& aConfig)
 {
   if (mMFTManager) {
     mMFTManager->ConfigurationChanged(*aConfig);
   }
 }
 
+void
+WMFMediaDataDecoder::SetSeekThreshold(const media::TimeUnit& aTime)
+{
+  MOZ_ASSERT(mCallback->OnReaderTaskQueue());
+  MOZ_DIAGNOSTIC_ASSERT(!mIsShutDown);
+
+  RefPtr<WMFMediaDataDecoder> self = this;
+  nsCOMPtr<nsIRunnable> runnable =
+    NS_NewRunnableFunction([self, aTime]() {
+    media::TimeUnit threshold = aTime;
+    self->mMFTManager->SetSeekThreshold(threshold);
+  });
+  mTaskQueue->Dispatch(runnable.forget());
+}
+
 } // namespace mozilla
--- a/dom/media/platforms/wmf/WMFMediaDataDecoder.h
+++ b/dom/media/platforms/wmf/WMFMediaDataDecoder.h
@@ -32,17 +32,20 @@ public:
   // or until no more is able to be produced.
   // Returns S_OK on success, or MF_E_TRANSFORM_NEED_MORE_INPUT if there's not
   // enough data to produce more output. If this returns a failure code other
   // than MF_E_TRANSFORM_NEED_MORE_INPUT, an error will be reported to the
   // MP4Reader.
   virtual HRESULT Output(int64_t aStreamOffset,
                          RefPtr<MediaData>& aOutput) = 0;
 
-  void Flush() { mDecoder->Flush(); }
+  void Flush() {
+    mDecoder->Flush();
+    mSeekTargetThreshold.reset();
+  }
 
   void Drain()
   {
     if (FAILED(mDecoder->SendMFTMessage(MFT_MESSAGE_COMMAND_DRAIN, 0))) {
       NS_WARNING("Failed to send DRAIN command to MFT");
     }
   }
 
@@ -52,19 +55,25 @@ public:
   virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const { return false; }
 
   virtual TrackInfo::TrackType GetType() = 0;
 
   virtual void ConfigurationChanged(const TrackInfo& aConfig) {}
 
   virtual const char* GetDescriptionName() const = 0;
 
+  virtual void SetSeekThreshold(const media::TimeUnit& aTime) {
+    mSeekTargetThreshold = Some(aTime);
+  }
+
 protected:
   // IMFTransform wrapper that performs the decoding.
   RefPtr<MFTDecoder> mDecoder;
+
+  Maybe<media::TimeUnit> mSeekTargetThreshold;
 };
 
 // Decodes audio and video using Windows Media Foundation. Samples are decoded
 // using the MFTDecoder created by the MFTManager. This class implements
 // the higher-level logic that drives mapping the MFT to the async
 // MediaDataDecoder interface. The specifics of decoding the exact stream
 // type are handled by MFTManager and the MFTDecoder it creates.
 class WMFMediaDataDecoder : public MediaDataDecoder {
@@ -88,16 +97,18 @@ public:
 
   nsresult ConfigurationChanged(const TrackInfo& aConfig) override;
 
   const char* GetDescriptionName() const override
   {
     return mMFTManager ? mMFTManager->GetDescriptionName() : "";
   }
 
+  virtual void SetSeekThreshold(const media::TimeUnit& aTime) override;
+
 private:
 
   // Called on the task queue. Inserts the sample into the decoder, and
   // extracts output if available.
   void ProcessDecode(MediaRawData* aSample);
 
   // Called on the task queue. Extracts output if available, and delivers
   // it to the reader. Called after ProcessDecode() and ProcessDrain().
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
@@ -784,16 +784,30 @@ WMFVideoMFTManager::Output(int64_t aStre
         ++mNullOutputCount;
         if (mNullOutputCount > 250) {
           LOG("Excessive Video MFTDecoder returning success but no output; giving up");
           mGotExcessiveNullOutput = true;
           return E_FAIL;
         }
         continue;
       }
+      if (mSeekTargetThreshold.isSome()) {
+        media::TimeUnit pts = GetSampleTime(sample);
+        if (!pts.IsValid()) {
+          return E_FAIL;
+        }
+        if (pts < mSeekTargetThreshold.ref()) {
+          LOG("Dropping video frame which pts is smaller than seek target.");
+          // It is necessary to clear the pointer to release the previous output
+          // buffer.
+          sample = nullptr;
+          continue;
+        }
+        mSeekTargetThreshold.reset();
+      }
       break;
     }
     // Else unexpected error, assert, and bail.
     NS_WARNING("WMFVideoMFTManager::Output() unexpected error");
     return hr;
   }
 
   RefPtr<VideoData> frame;