Bug 1294352 - Merge MDSM::InitiateSeek() and MDSM::InitiateDecodeRecoverySeek().
MozReview-Commit-ID: 8wgRY9QHOYg
--- 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();