Bug 1308147. Part 3 - add DecodingFirstFrameState::mPendingSeek to store a pending seek job.
MozReview-Commit-ID: 4TMwk6q67go
--- 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()