Bug 1308147. Part 2 - add DormantState::mPendingSeek to store a pending seek job.
MozReview-Commit-ID: oySkHWuYo3
--- 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__);