Bug 1308147. Part 3 - add DecodingFirstFrameState::mPendingSeek to store a pending seek job. draft
authorJW Wang <jwwang@mozilla.com>
Wed, 19 Oct 2016 17:56:20 +0800
changeset 428542 6dacb53128be4693604d42b501a172e9ea03ccfb
parent 428541 041d7bf9e8937897b219a77193bc1783b6a78661
child 428543 e0a3f4a5ec1d3fabf5478c42106961233f43629b
push id33335
push userjwwang@mozilla.com
push dateMon, 24 Oct 2016 07:05:42 +0000
bugs1308147
milestone52.0a1
Bug 1308147. Part 3 - add DecodingFirstFrameState::mPendingSeek to store a pending seek job. MozReview-Commit-ID: 4TMwk6q67go
dom/media/MediaDecoderStateMachine.cpp
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -486,17 +486,24 @@ private:
  *   DECODING when the 'loadeddata' event is fired.
  */
 class MediaDecoderStateMachine::DecodingFirstFrameState
   : public MediaDecoderStateMachine::StateObject
 {
 public:
   explicit DecodingFirstFrameState(Master* aPtr) : StateObject(aPtr) {}
 
-  void Enter();
+  void Enter(SeekJob aPendingSeek);
+
+  void Exit() override
+  {
+    // mPendingSeek is either moved before transition to SEEKING or DORMANT,
+    // or should be rejected here before transition to SHUTDOWN.
+    mPendingSeek.RejectIfExists(__func__);
+  }
 
   State GetState() const override
   {
     return DECODER_STATE_DECODING_FIRSTFRAME;
   }
 
   bool HandleAudioDecoded(MediaData* aAudio) override
   {
@@ -532,16 +539,18 @@ public:
     // We never suspend video decoding in this state.
     MOZ_ASSERT(false, "Shouldn't have suspended video decoding.");
   }
 
 private:
   // Notify FirstFrameLoaded if having decoded first frames and
   // transition to SEEKING if there is any pending seek, or DECODING otherwise.
   void MaybeFinishDecodeFirstFrame();
+
+  SeekJob mPendingSeek;
 };
 
 /**
  * Purpose: decode audio/video data for playback.
  *
  * Transition to:
  *   DORMANT if any dormant request.
  *   SEEKING if any seek request.
@@ -1268,17 +1277,17 @@ DecodeMetadataState::OnMetadataRead(Meta
 
   if (waitingForCDM) {
     // Metadata parsing was successful but we're still waiting for CDM caps
     // to become available so that we can build the correct decryptor/decoder.
     SetState<WaitForCDMState>(mPendingDormant);
   } else if (mPendingDormant) {
     SetState<DormantState>(SeekJob{});
   } else {
-    SetState<DecodingFirstFrameState>();
+    SetState<DecodingFirstFrameState>(SeekJob{});
   }
 }
 
 bool
 MediaDecoderStateMachine::
 WaitForCDMState::HandleDormant(bool aDormant)
 {
   mPendingDormant = aDormant;
@@ -1286,94 +1295,93 @@ WaitForCDMState::HandleDormant(bool aDor
 }
 
 bool
 MediaDecoderStateMachine::
 DormantState::HandleDormant(bool aDormant)
 {
   if (!aDormant) {
     MOZ_ASSERT(!Info().IsEncrypted() || mMaster->mCDMProxy);
-    SetState<DecodingFirstFrameState>();
+    SeekJob seekJob = Move(mPendingSeek);
+    SetState<DecodingFirstFrameState>(Move(seekJob));
   }
   return true;
 }
 
 bool
 MediaDecoderStateMachine::
 WaitForCDMState::HandleCDMProxyReady()
 {
+  SeekJob seekJob = Move(mPendingSeek);
   if (mPendingDormant) {
-    SeekJob seekJob = Move(mPendingSeek);
     SetState<DormantState>(Move(seekJob));
   } else {
-    SetState<DecodingFirstFrameState>();
+    SetState<DecodingFirstFrameState>(Move(seekJob));
   }
   return true;
 }
 
 void
 MediaDecoderStateMachine::
-DecodingFirstFrameState::Enter()
+DecodingFirstFrameState::Enter(SeekJob aPendingSeek)
 {
   // Handle pending seek.
-  if (mMaster->mQueuedSeek.Exists() &&
+  if (aPendingSeek.Exists() &&
       (mMaster->mSentFirstFrameLoadedEvent ||
        Reader()->ForceZeroStartTime())) {
-    SetState<SeekingState>(Move(mMaster->mQueuedSeek));
+    SetState<SeekingState>(Move(aPendingSeek));
     return;
   }
 
   // Transition to DECODING if we've decoded first frames.
   if (mMaster->mSentFirstFrameLoadedEvent) {
     SetState<DecodingState>();
     return;
   }
 
   MOZ_ASSERT(!mMaster->mVideoDecodeSuspended);
+  MOZ_ASSERT(!mMaster->mQueuedSeek.Exists());
+
+  mPendingSeek = Move(aPendingSeek);
 
   // Dispatch tasks to decode first frames.
   mMaster->DispatchDecodeTasksIfNeeded();
 }
 
 RefPtr<MediaDecoder::SeekPromise>
 MediaDecoderStateMachine::
 DecodingFirstFrameState::HandleSeek(SeekTarget aTarget)
 {
   // Should've transitioned to DECODING in Enter()
   // if mSentFirstFrameLoadedEvent is true.
   MOZ_ASSERT(!mMaster->mSentFirstFrameLoadedEvent);
 
   if (!Reader()->ForceZeroStartTime()) {
     SLOG("Not Enough Data to seek at this stage, queuing seek");
-    mMaster->mQueuedSeek.RejectIfExists(__func__);
-    mMaster->mQueuedSeek.mTarget = aTarget;
-    return mMaster->mQueuedSeek.mPromise.Ensure(__func__);
+    mPendingSeek.RejectIfExists(__func__);
+    mPendingSeek.mTarget = aTarget;
+    return mPendingSeek.mPromise.Ensure(__func__);
   }
 
   // Since ForceZeroStartTime() is true, we should've transitioned to SEEKING
-  // in Enter() if there is any queued seek.
-  MOZ_ASSERT(!mMaster->mQueuedSeek.Exists());
+  // in Enter() if there is any pending seek.
+  MOZ_ASSERT(!mPendingSeek.Exists());
 
   SLOG("Changed state to SEEKING (to %lld)", aTarget.GetTime().ToMicroseconds());
   SeekJob seekJob;
   seekJob.mTarget = aTarget;
   return SetState<SeekingState>(Move(seekJob));
 }
 
 bool
 MediaDecoderStateMachine::
 DecodingFirstFrameState::HandleDormant(bool aDormant)
 {
   if (aDormant) {
-    // Don't store mQueuedSeek because:
-    // 1. if mQueuedSeek is not empty, respect the latest seek request
-    //    and don't overwrite it.
-    // 2. if mQueuedSeek is empty, there is no need to seek when exiting
-    //    the dormant state for we are at position 0.
-    SeekJob seekJob = Move(mMaster->mQueuedSeek);
+    SeekJob seekJob = Move(mPendingSeek);
     SetState<DormantState>(Move(seekJob));
   }
   return true;
 }
 
 void
 MediaDecoderStateMachine::
 DecodingFirstFrameState::MaybeFinishDecodeFirstFrame()
@@ -1382,18 +1390,19 @@ DecodingFirstFrameState::MaybeFinishDeco
 
   if ((mMaster->IsAudioDecoding() && mMaster->AudioQueue().GetSize() == 0) ||
       (mMaster->IsVideoDecoding() && mMaster->VideoQueue().GetSize() == 0)) {
     return;
   }
 
   mMaster->FinishDecodeFirstFrame();
 
-  if (mMaster->mQueuedSeek.Exists()) {
-    SetState<SeekingState>(Move(mMaster->mQueuedSeek));
+  if (mPendingSeek.Exists()) {
+    SeekJob seekJob = Move(mPendingSeek);
+    SetState<SeekingState>(Move(seekJob));
   } else {
     SetState<DecodingState>();
   }
 }
 
 void
 MediaDecoderStateMachine::
 DecodingState::Enter()