--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -189,17 +189,16 @@ public:
virtual void Exit() {}; // Exit action.
virtual void Step() {} // Perform a 'cycle' of this state object.
virtual State GetState() const = 0;
// Event handlers for various events.
virtual void HandleCDMProxyReady() {}
virtual void HandleAudioDecoded(MediaData* aAudio) {}
virtual void HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) {}
- virtual void HandleVideoNotDecoded(const MediaResult& aError);
virtual void HandleAudioWaited(MediaData::Type aType);
virtual void HandleVideoWaited(MediaData::Type aType);
virtual void HandleNotWaited(const WaitForDataRejectValue& aRejection);
virtual void HandleEndOfStream() {}
virtual void HandleWaitingForData() {}
virtual void HandleAudioCaptured() {}
virtual void HandleWaitingForAudio()
@@ -214,16 +213,33 @@ public:
}
virtual void HandleEndOfAudio()
{
AudioQueue().Finish();
HandleEndOfStream();
}
+ virtual void HandleWaitingForVideo()
+ {
+ mMaster->WaitForData(MediaData::VIDEO_DATA);
+ HandleWaitingForData();
+ }
+
+ virtual void HandleVideoCanceled()
+ {
+ mMaster->EnsureVideoDecodeTaskQueued();
+ }
+
+ virtual void HandleEndOfVideo()
+ {
+ VideoQueue().Finish();
+ HandleEndOfStream();
+ }
+
virtual RefPtr<MediaDecoder::SeekPromise> HandleSeek(SeekTarget aTarget);
virtual RefPtr<ShutdownPromise> HandleShutdown();
virtual void HandleVideoSuspendTimeout() = 0;
virtual void HandleResumeVideoDecoding();
@@ -525,17 +541,31 @@ public:
}
void HandleEndOfAudio() override
{
AudioQueue().Finish();
MaybeFinishDecodeFirstFrame();
}
- void HandleVideoNotDecoded(const MediaResult& aError) override;
+ void HandleWaitingForVideo() override
+ {
+ mMaster->WaitForData(MediaData::VIDEO_DATA);
+ }
+
+ void HandleVideoCanceled() override
+ {
+ mMaster->RequestVideoData(false, media::TimeUnit());
+ }
+
+ void HandleEndOfVideo() override
+ {
+ VideoQueue().Finish();
+ MaybeFinishDecodeFirstFrame();
+ }
void HandleAudioWaited(MediaData::Type aType) override
{
mMaster->RequestAudioData();
}
void HandleVideoWaited(MediaData::Type aType) override
{
@@ -845,17 +875,16 @@ public:
State GetState() const override
{
return DECODER_STATE_SEEKING;
}
void HandleAudioDecoded(MediaData* aAudio) override = 0;
void HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) override = 0;
- void HandleVideoNotDecoded(const MediaResult& aError) override = 0;
void HandleAudioWaited(MediaData::Type aType) override = 0;
void HandleVideoWaited(MediaData::Type aType) override = 0;
void HandleNotWaited(const WaitForDataRejectValue& aRejection) override = 0;
void HandleVideoSuspendTimeout() override
{
// Do nothing since we want a valid video frame to show when seek is done.
}
@@ -985,17 +1014,40 @@ public:
if (!mSeekJob.mTarget->IsVideoOnly()) {
MOZ_ASSERT(!mDoneAudioSeeking);
AudioQueue().Finish();
mDoneAudioSeeking = true;
MaybeFinishSeek();
}
}
- void HandleVideoNotDecoded(const MediaResult& aError) override;
+ void HandleWaitingForVideo() override
+ {
+ MOZ_ASSERT(!mDoneVideoSeeking);
+ mMaster->WaitForData(MediaData::VIDEO_DATA);
+ }
+
+ void HandleVideoCanceled() override
+ {
+ MOZ_ASSERT(!mDoneVideoSeeking);
+ RequestVideoData();
+ }
+
+ void HandleEndOfVideo() override
+ {
+ MOZ_ASSERT(!mDoneVideoSeeking);
+ if (mFirstVideoFrameAfterSeek) {
+ // Hit the end of stream. Move mFirstVideoFrameAfterSeek into
+ // mSeekedVideoData so we have something to display after seeking.
+ mMaster->PushVideo(mFirstVideoFrameAfterSeek);
+ }
+ VideoQueue().Finish();
+ mDoneVideoSeeking = true;
+ MaybeFinishSeek();
+ }
void HandleAudioWaited(MediaData::Type aType) override
{
MOZ_ASSERT(!mDoneAudioSeeking || !mDoneVideoSeeking, "Seek shouldn't be finished");
// Ignore pending requests from video-only seek.
if (mSeekJob.mTarget->IsVideoOnly()) {
return;
@@ -1422,17 +1474,37 @@ private:
void HandleEndOfAudio() override
{
MOZ_ASSERT(!mSeekJob.mPromise.IsEmpty(), "Seek shouldn't be finished");
MOZ_ASSERT(NeedMoreVideo());
// We don't care about audio decode errors in this state which will be
// handled by other states after seeking.
}
- void HandleVideoNotDecoded(const MediaResult& aError) override;
+ void HandleWaitingForVideo() override
+ {
+ MOZ_ASSERT(!mSeekJob.mPromise.IsEmpty(), "Seek shouldn't be finished");
+ MOZ_ASSERT(NeedMoreVideo());
+ mMaster->WaitForData(MediaData::VIDEO_DATA);
+ }
+
+ void HandleVideoCanceled() override
+ {
+ MOZ_ASSERT(!mSeekJob.mPromise.IsEmpty(), "Seek shouldn't be finished");
+ MOZ_ASSERT(NeedMoreVideo());
+ RequestVideoData();
+ }
+
+ void HandleEndOfVideo() override
+ {
+ MOZ_ASSERT(!mSeekJob.mPromise.IsEmpty(), "Seek shouldn't be finished");
+ MOZ_ASSERT(NeedMoreVideo());
+ VideoQueue().Finish();
+ FinishSeek();
+ }
void HandleAudioWaited(MediaData::Type aType) override
{
// We don't care about audio in this state.
}
void HandleVideoWaited(MediaData::Type aType) override
{
@@ -1715,18 +1787,16 @@ public:
MOZ_DIAGNOSTIC_ASSERT(false, "Shouldn't escape the SHUTDOWN state.");
}
State GetState() const override
{
return DECODER_STATE_SHUTDOWN;
}
- void HandleVideoNotDecoded(const MediaResult& aError) override {}
-
RefPtr<MediaDecoder::SeekPromise> HandleSeek(SeekTarget aTarget) override
{
MOZ_DIAGNOSTIC_ASSERT(false, "Can't seek in shutdown state.");
return MediaDecoder::SeekPromise::CreateAndReject(true, __func__);
}
RefPtr<ShutdownPromise> HandleShutdown() override
{
@@ -1761,37 +1831,16 @@ StateObject::HandleVideoWaited(MediaData
void
MediaDecoderStateMachine::
StateObject::HandleNotWaited(const WaitForDataRejectValue& aRejection)
{
}
-void
-MediaDecoderStateMachine::
-StateObject::HandleVideoNotDecoded(const MediaResult& aError)
-{
- switch (aError.Code()) {
- case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
- mMaster->WaitForData(MediaData::VIDEO_DATA);
- HandleWaitingForData();
- break;
- case NS_ERROR_DOM_MEDIA_CANCELED:
- mMaster->EnsureVideoDecodeTaskQueued();
- break;
- case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
- VideoQueue().Finish();
- HandleEndOfStream();
- break;
- default:
- mMaster->DecodeError(aError);
- }
-}
-
RefPtr<MediaDecoder::SeekPromise>
MediaDecoderStateMachine::
StateObject::HandleSeek(SeekTarget aTarget)
{
SLOG("Changed state to SEEKING (to %lld)", aTarget.GetTime().ToMicroseconds());
SeekJob seekJob;
seekJob.mTarget = Some(aTarget);
return SetSeekingState(Move(seekJob), EventVisibility::Observable);
@@ -1980,36 +2029,16 @@ DecodingFirstFrameState::Enter()
}
if (mMaster->HasVideo()) {
mMaster->RequestVideoData(false, media::TimeUnit());
}
}
void
MediaDecoderStateMachine::
-DecodingFirstFrameState::HandleVideoNotDecoded(const MediaResult& aError)
-{
- switch (aError.Code()) {
- case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
- mMaster->WaitForData(MediaData::VIDEO_DATA);
- break;
- case NS_ERROR_DOM_MEDIA_CANCELED:
- mMaster->RequestVideoData(false, media::TimeUnit());
- break;
- case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
- VideoQueue().Finish();
- MaybeFinishDecodeFirstFrame();
- break;
- default:
- mMaster->DecodeError(aError);
- }
-}
-
-void
-MediaDecoderStateMachine::
DecodingFirstFrameState::MaybeFinishDecodeFirstFrame()
{
MOZ_ASSERT(!mMaster->mSentFirstFrameLoadedEvent);
if ((mMaster->IsAudioDecoding() && AudioQueue().GetSize() == 0) ||
(mMaster->IsVideoDecoding() && VideoQueue().GetSize() == 0)) {
return;
}
@@ -2179,67 +2208,16 @@ SeekingState::SeekCompleted()
mMaster->mOnPlaybackEvent.Notify(MediaEventType::Invalidate);
}
SetState<DecodingState>();
}
void
MediaDecoderStateMachine::
-AccurateSeekingState::HandleVideoNotDecoded(const MediaResult& aError)
-{
- MOZ_ASSERT(!mDoneVideoSeeking);
- switch (aError.Code()) {
- case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
- mMaster->WaitForData(MediaData::VIDEO_DATA);
- break;
- case NS_ERROR_DOM_MEDIA_CANCELED:
- RequestVideoData();
- break;
- case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
- if (mFirstVideoFrameAfterSeek) {
- // Hit the end of stream. Move mFirstVideoFrameAfterSeek into
- // mSeekedVideoData so we have something to display after seeking.
- mMaster->PushVideo(mFirstVideoFrameAfterSeek);
- }
- VideoQueue().Finish();
- mDoneVideoSeeking = true;
- MaybeFinishSeek();
- break;
- default:
- mMaster->DecodeError(aError);
- }
-}
-
-void
-MediaDecoderStateMachine::
-NextFrameSeekingState::HandleVideoNotDecoded(const MediaResult& aError)
-{
- MOZ_ASSERT(!mSeekJob.mPromise.IsEmpty(), "Seek shouldn't be finished");
- MOZ_ASSERT(NeedMoreVideo());
- // Video seek not finished.
- switch (aError.Code()) {
- case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
- mMaster->WaitForData(MediaData::VIDEO_DATA);
- break;
- case NS_ERROR_DOM_MEDIA_CANCELED:
- RequestVideoData();
- break;
- case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
- VideoQueue().Finish();
- FinishSeek();
- break;
- default:
- // Raise an error since we can't finish video seek anyway.
- mMaster->DecodeError(aError);
- }
-}
-
-void
-MediaDecoderStateMachine::
BufferingState::DispatchDecodeTasksIfNeeded()
{
if (mMaster->IsAudioDecoding() &&
!mMaster->HaveEnoughDecodedAudio()) {
mMaster->EnsureAudioDecodeTaskQueued();
}
if (mMaster->IsVideoDecoding() &&
@@ -3076,17 +3054,29 @@ MediaDecoderStateMachine::RequestVideoDa
// Handle abnormal or negative timestamps.
mDecodedVideoEndTime = std::max(mDecodedVideoEndTime, aVideo->GetEndTime());
SAMPLE_LOG("OnVideoDecoded [%lld,%lld]", aVideo->mTime, aVideo->GetEndTime());
mStateObj->HandleVideoDecoded(aVideo, videoDecodeStartTime);
},
[this] (const MediaResult& aError) {
SAMPLE_LOG("OnVideoNotDecoded aError=%u", aError.Code());
mVideoDataRequest.Complete();
- mStateObj->HandleVideoNotDecoded(aError);
+ switch (aError.Code()) {
+ case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
+ mStateObj->HandleWaitingForVideo();
+ break;
+ case NS_ERROR_DOM_MEDIA_CANCELED:
+ mStateObj->HandleVideoCanceled();
+ break;
+ case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
+ mStateObj->HandleEndOfVideo();
+ break;
+ default:
+ DecodeError(aError);
+ }
})
);
}
void
MediaDecoderStateMachine::WaitForData(MediaData::Type aType)
{
MOZ_ASSERT(OnTaskQueue());