Bug 1235301 part 3 - export HTMLMediaElement::seekToNextFrame(); r=jwwang draft
authorKaku Kuo <tkuo@mozilla.com>
Tue, 24 May 2016 23:05:35 +0800
changeset 372168 bce191db59199d25f79d954c9573512961b57afd
parent 372167 1a205db83a22c9d91f7fac0ddf0d184d0591cba7
child 372169 4beafd27b0de14e3f3da63d8d14f859ed9b1a7f8
child 372171 748fdc001a477ad5544a0102adc1ca8c82136b75
push id19455
push usertkuo@mozilla.com
push dateFri, 27 May 2016 16:28:45 +0000
reviewersjwwang
bugs1235301
milestone49.0a1
Bug 1235301 part 3 - export HTMLMediaElement::seekToNextFrame(); r=jwwang MozReview-Commit-ID: 8WMpwOwfqxz
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
dom/media/MediaDecoderStateMachine.cpp
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1460,16 +1460,22 @@ void
 HTMLMediaElement::FastSeek(double aTime, ErrorResult& aRv)
 {
   LOG(LogLevel::Debug, ("Reporting telemetry VIDEO_FASTSEEK_USED"));
   Telemetry::Accumulate(Telemetry::VIDEO_FASTSEEK_USED, 1);
   Seek(aTime, SeekTarget::PrevSyncPoint, aRv);
 }
 
 void
+HTMLMediaElement::SeekToNextFrame(ErrorResult& aRv)
+{
+  Seek(CurrentTime(), SeekTarget::NextFrame, aRv);
+}
+
+void
 HTMLMediaElement::SetCurrentTime(double aCurrentTime, ErrorResult& aRv)
 {
   Seek(aCurrentTime, SeekTarget::Accurate, aRv);
 }
 
 /**
  * Check if aValue is inside a range of aRanges, and if so sets aIsInRanges
  * to true and put the range index in aIntervalIndex. If aValue is not
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -475,16 +475,18 @@ public:
   bool Seeking() const;
 
   double CurrentTime() const;
 
   void SetCurrentTime(double aCurrentTime, ErrorResult& aRv);
 
   void FastSeek(double aTime, ErrorResult& aRv);
 
+  void SeekToNextFrame(ErrorResult& aRv);
+
   double Duration() const;
 
   bool HasAudio() const
   {
     return mMediaInfo.HasAudio();
   }
 
   bool HasVideo() const
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -42,16 +42,17 @@
 #include "DOMMediaStream.h"
 #include "ImageContainer.h"
 #include "MediaDecoder.h"
 #include "MediaDecoderReader.h"
 #include "MediaDecoderReaderWrapper.h"
 #include "MediaDecoderStateMachine.h"
 #include "MediaShutdownManager.h"
 #include "MediaTimer.h"
+#include "NextFrameSeekTask.h"
 #include "TimeUnits.h"
 #include "VideoSegment.h"
 #include "VideoUtils.h"
 #include "gfxPrefs.h"
 
 namespace mozilla {
 
 using namespace mozilla::dom;
@@ -1463,16 +1464,21 @@ MediaDecoderStateMachine::Seek(SeekTarge
   }
 
   // We need to be able to seek in some way
   if (!mMediaSeekable && !mMediaSeekableOnlyInBufferedRanges) {
     DECODER_WARN("Seek() function should not be called on a non-seekable state machine");
     return MediaDecoder::SeekPromise::CreateAndReject(/* aIgnored = */ true, __func__);
   }
 
+  if (aTarget.IsNextFrame() && !HasVideo()) {
+    DECODER_WARN("Ignore a NextFrameSeekTask on a media file without video track.");
+    return MediaDecoder::SeekPromise::CreateAndReject(/* aIgnored = */ true, __func__);
+  }
+
   MOZ_ASSERT(mState > DECODER_STATE_DECODING_METADATA,
                "We should have got duration already");
 
   if (mState < DECODER_STATE_DECODING ||
       (IsDecodingFirstFrame() && !mReader->ForceZeroStartTime())) {
     DECODER_LOG("Seek() Not Enough Data to continue at this stage, queuing seek");
     mQueuedSeek.RejectIfExists(__func__);
     mQueuedSeek.mTarget = aTarget;
@@ -1575,19 +1581,27 @@ MediaDecoderStateMachine::InitiateSeek(S
   DiscardSeekTaskIfExist();
 
   mSeekTaskRequest.DisconnectIfExists();
 
   // SeekTask will register its callbacks to MediaDecoderReaderWrapper.
   CancelMediaDecoderReaderWrapperCallback();
 
   // Create a new SeekTask instance for the incoming seek task.
-  mSeekTask = new AccurateSeekTask(mDecoderID, OwnerThread(),
-                                   mReader.get(), Move(aSeekJob),
-                                   mInfo, Duration(), GetMediaTime());
+  if (aSeekJob.mTarget.IsAccurate() || aSeekJob.mTarget.IsFast()) {
+    mSeekTask = new AccurateSeekTask(mDecoderID, OwnerThread(),
+                                     mReader.get(), Move(aSeekJob),
+                                     mInfo, Duration(), GetMediaTime());
+  } else if (aSeekJob.mTarget.IsNextFrame()) {
+    mSeekTask = new NextFrameSeekTask(mDecoderID, OwnerThread(), mReader.get(),
+                                      Move(aSeekJob), mInfo, Duration(),
+                                      GetMediaTime(), AudioQueue(), VideoQueue());
+  } else {
+    MOZ_ASSERT(false, "Cannot handle this seek task.");
+  }
 
   // Stop playback now to ensure that while we're outside the monitor
   // dispatching SeekingStarted, playback doesn't advance and mess with
   // mCurrentPosition that we've setting to seekTime here.
   StopPlayback();
   UpdatePlaybackPositionInternal(mSeekTask->GetSeekJob().mTarget.GetTime().ToMicroseconds());
 
   mOnSeekingStart.Notify(mSeekTask->GetSeekJob().mTarget.mEventVisibility);