Bug 1294352 - Merge MDSM::InitiateSeek() and MDSM::InitiateDecodeRecoverySeek(). draft
authorJW Wang <jwwang@mozilla.com>
Thu, 11 Aug 2016 15:37:27 +0800
changeset 399490 72457716e9b8347299700b9a4837ffb46b8e0a78
parent 399484 87bc894e1ba0f0f655ca8a3022c1f314a22d8c78
child 399793 0d9fccbd153e6a5b31f21456f556e935ad20af15
child 399794 11c22b7520e46074068c9fdd123bdd108f6a79ec
child 399806 964420a3bfe7eb54512f390634a6bcfbd5b2309e
child 399809 02141d0351fed13066010a4e1a63835946964725
child 400512 3613ed0f14608379df679ee3b68d0ef3ba51539c
child 400548 4a17b1bb7361220a53addd8950158252cf17f80b
push id25854
push userjwwang@mozilla.com
push dateThu, 11 Aug 2016 07:41:50 +0000
bugs1294352
milestone51.0a1
Bug 1294352 - Merge MDSM::InitiateSeek() and MDSM::InitiateDecodeRecoverySeek(). MozReview-Commit-ID: 8wgRY9QHOYg
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -1362,70 +1362,24 @@ void MediaDecoderStateMachine::Visibilit
 
     // If an existing seek is in flight don't bother creating a new
     // one to catch up.
     if (mSeekTask || mQueuedSeek.Exists()) {
       return;
     }
 
     // Start video-only seek to the current time...
-    InitiateDecodeRecoverySeek();
+    SeekJob seekJob;
+    seekJob.mTarget = SeekTarget(GetMediaTime(),
+                                 SeekTarget::Type::AccurateVideoOnly,
+                                 MediaDecoderEventVisibility::Suppressed);
+    InitiateSeek(Move(seekJob));
   }
 }
 
-// InitiateVideoDecodeRecoverySeek is responsible for setting up a video-only
-// seek using the seek task. When suspension of decoding for videos that are in
-// background tabs (ie. invisible) is enabled, the audio keeps playing and when
-// switching back to decoding video, it is highly desirable to not cause the
-// audio to pause as the video is seeked else there be a noticeable audio glitch
-// as the tab becomes visible.
-void
-MediaDecoderStateMachine::InitiateDecodeRecoverySeek()
-{
-  MOZ_ASSERT(OnTaskQueue());
-  DECODER_LOG("InitiateDecodeRecoverySeek");
-
-  SeekJob seekJob;
-  seekJob.mTarget = SeekTarget(GetMediaTime(),
-                               SeekTarget::Type::AccurateVideoOnly,
-                               MediaDecoderEventVisibility::Suppressed);
-
-  SetState(DECODER_STATE_SEEKING);
-
-  // Discard the existing seek task.
-  DiscardSeekTaskIfExist();
-
-  mSeekTaskRequest.DisconnectIfExists();
-
-  // SeekTask will register its callbacks to MediaDecoderReaderWrapper.
-  CancelMediaDecoderReaderWrapperCallback();
-
-  MOZ_ASSERT(!mCurrentSeek.Exists());
-  mCurrentSeek = Move(seekJob);
-  // Create a new SeekTask instance for the incoming seek task.
-  mSeekTask = new AccurateSeekTask(mDecoderID, OwnerThread(),
-                                   mReader.get(), mCurrentSeek.mTarget,
-                                   mInfo, Duration(), GetMediaTime());
-
-  // Reset our state machine and decoding pipeline before seeking.
-  if (mSeekTask->NeedToResetMDSM()) {
-    Reset(TrackInfo::kVideoTrack);
-  }
-
-  // Do the seek.
-  mSeekTaskRequest.Begin(
-    mSeekTask->Seek(Duration())->Then(OwnerThread(), __func__, this,
-                                      &MediaDecoderStateMachine::OnSeekTaskResolved,
-                                      &MediaDecoderStateMachine::OnSeekTaskRejected));
-  // Nobody is listening to this as OnSeekTaskResolved handles what is
-  // required but the promise needs to exist or SeekJob::Exists() will
-  // assert.
-  RefPtr<MediaDecoder::SeekPromise> unused = mCurrentSeek.mPromise.Ensure(__func__);
-}
-
 void MediaDecoderStateMachine::BufferedRangeUpdated()
 {
   MOZ_ASSERT(OnTaskQueue());
 
   // While playing an unseekable stream of unknown duration, mObservedDuration
   // is updated (in AdvanceFrame()) as we play. But if data is being downloaded
   // faster than played, mObserved won't reflect the end of playable data
   // since we haven't played the frame at the end of buffered data. So update
@@ -1598,45 +1552,53 @@ MediaDecoderStateMachine::InitiateSeek(S
   DiscardSeekTaskIfExist();
 
   mSeekTaskRequest.DisconnectIfExists();
 
   // SeekTask will register its callbacks to MediaDecoderReaderWrapper.
   CancelMediaDecoderReaderWrapperCallback();
 
   // Create a new SeekTask instance for the incoming seek task.
-  if (aSeekJob.mTarget.IsAccurate() || aSeekJob.mTarget.IsFast()) {
+  if (aSeekJob.mTarget.IsAccurate() ||
+      aSeekJob.mTarget.IsFast() ||
+      aSeekJob.mTarget.IsVideoOnly()) {
     mSeekTask = new AccurateSeekTask(mDecoderID, OwnerThread(),
                                      mReader.get(), aSeekJob.mTarget,
                                      mInfo, Duration(), GetMediaTime());
   } else if (aSeekJob.mTarget.IsNextFrame()) {
     mSeekTask = new NextFrameSeekTask(mDecoderID, OwnerThread(), mReader.get(),
                                       aSeekJob.mTarget, mInfo, Duration(),
                                       GetMediaTime(), AudioQueue(), VideoQueue());
   } else {
     MOZ_DIAGNOSTIC_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();
+  // Don't stop playback for a video-only seek since audio is playing.
+  if (!aSeekJob.mTarget.IsVideoOnly()) {
+    StopPlayback();
+  }
 
   // aSeekJob.mTarget.mTime might be different from
   // mSeekTask->GetSeekTarget().mTime because the seek task might clamp the seek
   // target to [0, duration]. We want to update the playback position to the
   // clamped value.
   UpdatePlaybackPositionInternal(mSeekTask->GetSeekTarget().GetTime().ToMicroseconds());
 
   if (aSeekJob.mTarget.mEventVisibility == MediaDecoderEventVisibility::Observable) {
     mOnPlaybackEvent.Notify(MediaEventType::SeekStarted);
   }
 
   // Reset our state machine and decoding pipeline before seeking.
-  if (mSeekTask->NeedToResetMDSM()) { Reset(); }
+  if (mSeekTask->NeedToResetMDSM()) {
+    if (aSeekJob.mTarget.IsVideoOnly()) {
+      Reset(TrackInfo::kVideoTrack);
+    } else {
+      Reset();
+    }
+  }
 
   // Do the seek.
   mSeekTaskRequest.Begin(mSeekTask->Seek(Duration())
     ->Then(OwnerThread(), __func__, this,
            &MediaDecoderStateMachine::OnSeekTaskResolved,
            &MediaDecoderStateMachine::OnSeekTaskRejected));
 
   MOZ_ASSERT(!mCurrentSeek.Exists());
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -503,21 +503,16 @@ protected:
   // The decoder monitor must be held.
   void EnqueueLoadedMetadataEvent();
 
   void EnqueueFirstFrameLoadedEvent();
 
   // Clears any previous seeking state and initiates a new seek on the decoder.
   RefPtr<MediaDecoder::SeekPromise> InitiateSeek(SeekJob aSeekJob);
 
-  // Clears any previous seeking state and initiates a video-only seek on the
-  // decoder to catch up the video to the current audio position, when recovering
-  // from video decoding being suspended in background.
-  void InitiateDecodeRecoverySeek();
-
   nsresult DispatchAudioDecodeTaskIfNeeded();
 
   // Ensures a task to decode audio has been dispatched to the decode task queue.
   // If a task to decode has already been dispatched, this does nothing,
   // otherwise this dispatches a task to do the decode.
   // This is called on the state machine or decode threads.
   // The decoder monitor must be held.
   nsresult EnsureAudioDecodeTaskQueued();