Bug 1308147. Part 2 - add DormantState::mPendingSeek to store a pending seek job. r=kikuo
authorJW Wang <jwwang@mozilla.com>
Wed, 19 Oct 2016 15:35:29 +0800
changeset 319086 736157befbd0d732db5e3994d1c9b1f06cad7ec5
parent 319085 03952d7927577081fa9d10ccf9d4117afd101b13
child 319087 3bd04c577eedea74e6e5ebeb579144cf8f3c9c32
push id30861
push usercbook@mozilla.com
push dateMon, 24 Oct 2016 14:54:01 +0000
treeherdermozilla-central@08efaee1d568 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskikuo
bugs1308147
milestone52.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 1308147. Part 2 - add DormantState::mPendingSeek to store a pending seek job. r=kikuo MozReview-Commit-ID: oySkHWuYo3
dom/media/MediaDecoderStateMachine.cpp
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -425,49 +425,60 @@ private:
  *   DECODING_FIRSTFRAME when being asked to exit dormant.
  */
 class MediaDecoderStateMachine::DormantState
   : public MediaDecoderStateMachine::StateObject
 {
 public:
   explicit DormantState(Master* aPtr) : StateObject(aPtr) {}
 
-  void Enter()
+  void Enter(SeekJob aPendingSeek)
   {
+    MOZ_ASSERT(!mMaster->mQueuedSeek.Exists());
+    mPendingSeek = Move(aPendingSeek);
     if (mMaster->IsPlaying()) {
       mMaster->StopPlayback();
     }
     mMaster->Reset();
     mMaster->mReader->ReleaseResources();
   }
 
+  void Exit() override
+  {
+    // Transfer the seek job so it is available to the next state.
+    mMaster->mQueuedSeek = Move(mPendingSeek);
+  }
+
   State GetState() const override
   {
     return DECODER_STATE_DORMANT;
   }
 
   bool HandleDormant(bool aDormant) override;
 
   RefPtr<MediaDecoder::SeekPromise> HandleSeek(SeekTarget aTarget) override
   {
     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__);
   }
 
   void HandleVideoSuspendTimeout() override
   {
     // Do nothing since we've released decoders in Enter().
   }
 
   void HandleResumeVideoDecoding() override
   {
     // Do nothing since we won't resume decoding until exiting dormant.
   }
+
+private:
+  SeekJob mPendingSeek;
 };
 
 /**
  * Purpose: decode the 1st audio and video frames to fire the 'loadeddata' event.
  *
  * Transition to:
  *   DORMANT if any dormant request.
  *   SHUTDOWN if any decode error.
@@ -1104,25 +1115,28 @@ public:
 
 bool
 MediaDecoderStateMachine::
 StateObject::HandleDormant(bool aDormant)
 {
   if (!aDormant) {
     return true;
   }
-  mMaster->mQueuedSeek.mTarget =
-    SeekTarget(mMaster->mCurrentPosition,
-               SeekTarget::Accurate,
-               MediaDecoderEventVisibility::Suppressed);
+  // This member function is inherited by DecodingState, BufferingState and
+  // CompletedState which can handle seek immediately without queuing a seek.
+  // Therefore mQueuedSeek must be empty here.
+  MOZ_ASSERT(!mMaster->mQueuedSeek.Exists());
+  SeekJob seekJob;
+  seekJob.mTarget = SeekTarget(mMaster->mCurrentPosition,
+                               SeekTarget::Accurate,
+                               MediaDecoderEventVisibility::Suppressed);
   // SeekJob asserts |mTarget.IsValid() == !mPromise.IsEmpty()| so we
   // need to create the promise even it is not used at all.
-  RefPtr<MediaDecoder::SeekPromise> unused =
-    mMaster->mQueuedSeek.mPromise.Ensure(__func__);
-  SetState<DormantState>();
+  RefPtr<MediaDecoder::SeekPromise> unused = seekJob.mPromise.Ensure(__func__);
+  SetState<DormantState>(Move(seekJob));
   return true;
 }
 
 RefPtr<ShutdownPromise>
 MediaDecoderStateMachine::
 StateObject::HandleShutdown()
 {
   return SetState<ShutdownState>();
@@ -1252,17 +1266,17 @@ DecodeMetadataState::OnMetadataRead(Meta
     mMaster->EnqueueLoadedMetadataEvent();
   }
 
   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>();
+    SetState<DormantState>(SeekJob{});
   } else {
     SetState<DecodingFirstFrameState>();
   }
 }
 
 bool
 MediaDecoderStateMachine::
 WaitForCDMState::HandleDormant(bool aDormant)
@@ -1282,17 +1296,18 @@ DormantState::HandleDormant(bool aDorman
   return true;
 }
 
 bool
 MediaDecoderStateMachine::
 WaitForCDMState::HandleCDMProxyReady()
 {
   if (mPendingDormant) {
-    SetState<DormantState>();
+    SeekJob seekJob = Move(mPendingSeek);
+    SetState<DormantState>(Move(seekJob));
   } else {
     SetState<DecodingFirstFrameState>();
   }
   return true;
 }
 
 void
 MediaDecoderStateMachine::
@@ -1348,17 +1363,18 @@ 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.
-    SetState<DormantState>();
+    SeekJob seekJob = Move(mMaster->mQueuedSeek);
+    SetState<DormantState>(Move(seekJob));
   }
   return true;
 }
 
 void
 MediaDecoderStateMachine::
 DecodingFirstFrameState::MaybeFinishDecodeFirstFrame()
 {
@@ -1482,18 +1498,18 @@ SeekingState::HandleDormant(bool aDorman
   // Because both audio and video decoders are going to be reset in this
   // method later, we treat a VideoOnly seek task as a normal Accurate
   // seek task so that while it is resumed, both audio and video playback
   // are handled.
   if (mSeekJob.mTarget.IsVideoOnly()) {
     mSeekJob.mTarget.SetType(SeekTarget::Accurate);
     mSeekJob.mTarget.SetVideoOnly(false);
   }
-  mMaster->mQueuedSeek = Move(mSeekJob);
-  SetState<DormantState>();
+  SeekJob seekJob = Move(mSeekJob);
+  SetState<DormantState>(Move(seekJob));
   return true;
 }
 
 RefPtr<MediaDecoder::SeekPromise>
 MediaDecoderStateMachine::
 SeekingState::HandleSeek(SeekTarget aTarget)
 {
   mMaster->mQueuedSeek.RejectIfExists(__func__);