mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 14:55:47 +00:00
Bug 1185972
: P1. Remove DECODER_STATE_DECODING_FIRSTFRAME state. r=jwwang
We want to be able to process the steps following decoding of the first frame independent of a state.
This commit is contained in:
parent
0259a11e37
commit
afb92e8070
@ -217,6 +217,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
||||
mDecodeToSeekTarget(false),
|
||||
mCurrentTimeBeforeSeek(0),
|
||||
mCorruptFrames(30),
|
||||
mDecodingFirstFrame(false),
|
||||
mDisabledHardwareAcceleration(false),
|
||||
mDecodingFrozenAtStateDecoding(false),
|
||||
mSentLoadedMetadataEvent(false),
|
||||
@ -441,7 +442,7 @@ MediaDecoderStateMachine::NeedToDecodeVideo()
|
||||
HaveEnoughDecodedVideo());
|
||||
return IsVideoDecoding() &&
|
||||
((mState == DECODER_STATE_SEEKING && mDecodeToSeekTarget) ||
|
||||
(mState == DECODER_STATE_DECODING_FIRSTFRAME &&
|
||||
(IsDecodingFirstFrame() &&
|
||||
IsVideoDecoding() && VideoQueue().GetSize() == 0) ||
|
||||
(!mMinimizePreroll && !HaveEnoughDecodedVideo()));
|
||||
}
|
||||
@ -451,7 +452,7 @@ MediaDecoderStateMachine::NeedToSkipToNextKeyframe()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
if (mState == DECODER_STATE_DECODING_FIRSTFRAME) {
|
||||
if (IsDecodingFirstFrame()) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(mState == DECODER_STATE_DECODING ||
|
||||
@ -508,7 +509,7 @@ MediaDecoderStateMachine::NeedToDecodeAudio()
|
||||
|
||||
return IsAudioDecoding() &&
|
||||
((mState == DECODER_STATE_SEEKING && mDecodeToSeekTarget) ||
|
||||
(mState == DECODER_STATE_DECODING_FIRSTFRAME &&
|
||||
(IsDecodingFirstFrame() &&
|
||||
IsAudioDecoding() && AudioQueue().GetSize() == 0) ||
|
||||
(!mMinimizePreroll &&
|
||||
!HaveEnoughDecodedAudio(mAmpleAudioThresholdUsecs * mPlaybackRate) &&
|
||||
@ -560,12 +561,6 @@ MediaDecoderStateMachine::OnAudioDecoded(AudioData* aAudioSample)
|
||||
(audio ? audio->mDiscontinuity : 0));
|
||||
|
||||
switch (mState) {
|
||||
case DECODER_STATE_DECODING_FIRSTFRAME: {
|
||||
Push(audio);
|
||||
MaybeFinishDecodeFirstFrame();
|
||||
return;
|
||||
}
|
||||
|
||||
case DECODER_STATE_BUFFERING: {
|
||||
// If we're buffering, this may be the sample we need to stop buffering.
|
||||
// Save it and schedule the state machine.
|
||||
@ -576,6 +571,10 @@ MediaDecoderStateMachine::OnAudioDecoded(AudioData* aAudioSample)
|
||||
|
||||
case DECODER_STATE_DECODING: {
|
||||
Push(audio);
|
||||
if (IsDecodingFirstFrame()) {
|
||||
MaybeFinishDecodeFirstFrame();
|
||||
return;
|
||||
}
|
||||
if (mIsAudioPrerolling && DonePrerollingAudio()) {
|
||||
StopPrerollingAudio();
|
||||
}
|
||||
@ -781,13 +780,12 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
|
||||
StopPrerollingVideo();
|
||||
}
|
||||
switch (mState) {
|
||||
case DECODER_STATE_DECODING_FIRSTFRAME: {
|
||||
MaybeFinishDecodeFirstFrame();
|
||||
return;
|
||||
}
|
||||
|
||||
case DECODER_STATE_BUFFERING:
|
||||
case DECODER_STATE_DECODING: {
|
||||
if (IsDecodingFirstFrame()) {
|
||||
MaybeFinishDecodeFirstFrame();
|
||||
return;
|
||||
}
|
||||
CheckIfDecodeComplete();
|
||||
mDecoder->GetReentrantMonitor().NotifyAll();
|
||||
// Tell AudioSink to wake up for audio queue is finished.
|
||||
@ -852,12 +850,6 @@ MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample)
|
||||
(video ? video->mDiscontinuity : 0));
|
||||
|
||||
switch (mState) {
|
||||
case DECODER_STATE_DECODING_FIRSTFRAME: {
|
||||
Push(video);
|
||||
MaybeFinishDecodeFirstFrame();
|
||||
return;
|
||||
}
|
||||
|
||||
case DECODER_STATE_BUFFERING: {
|
||||
// If we're buffering, this may be the sample we need to stop buffering.
|
||||
// Save it and schedule the state machine.
|
||||
@ -868,6 +860,10 @@ MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample)
|
||||
|
||||
case DECODER_STATE_DECODING: {
|
||||
Push(video);
|
||||
if (IsDecodingFirstFrame()) {
|
||||
MaybeFinishDecodeFirstFrame();
|
||||
return;
|
||||
}
|
||||
if (mIsVideoPrerolling && DonePrerollingVideo()) {
|
||||
StopPrerollingVideo();
|
||||
}
|
||||
@ -1144,7 +1140,6 @@ static const char* const gMachineStateStr[] = {
|
||||
"DECODING_METADATA",
|
||||
"WAIT_FOR_RESOURCES",
|
||||
"WAIT_FOR_CDM",
|
||||
"DECODING_FIRSTFRAME",
|
||||
"DORMANT",
|
||||
"DECODING",
|
||||
"SEEKING",
|
||||
@ -1166,6 +1161,10 @@ void MediaDecoderStateMachine::SetState(State aState)
|
||||
|
||||
mState = aState;
|
||||
|
||||
if (mState != DECODER_STATE_DECODING) {
|
||||
mDecodingFirstFrame = false;
|
||||
}
|
||||
|
||||
mIsShutdown = mState == DECODER_STATE_ERROR || mState == DECODER_STATE_SHUTDOWN;
|
||||
|
||||
// Clear state-scoped state.
|
||||
@ -1319,7 +1318,7 @@ void MediaDecoderStateMachine::StartDecoding()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
if (mState == DECODER_STATE_DECODING) {
|
||||
if (mState == DECODER_STATE_DECODING && !mDecodingFirstFrame) {
|
||||
return;
|
||||
}
|
||||
SetState(DECODER_STATE_DECODING);
|
||||
@ -1353,7 +1352,8 @@ void MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged()
|
||||
ScheduleStateMachine();
|
||||
} else if (mState == DECODER_STATE_WAIT_FOR_CDM &&
|
||||
!mReader->IsWaitingOnCDMResource()) {
|
||||
SetState(DECODER_STATE_DECODING_FIRSTFRAME);
|
||||
SetState(DECODER_STATE_DECODING);
|
||||
mDecodingFirstFrame = true;
|
||||
EnqueueDecodeFirstFrameTask();
|
||||
}
|
||||
}
|
||||
@ -1454,7 +1454,7 @@ MediaDecoderStateMachine::Seek(SeekTarget aTarget)
|
||||
NS_ASSERTION(mState > DECODER_STATE_DECODING_METADATA,
|
||||
"We should have got duration already");
|
||||
|
||||
if (mState < DECODER_STATE_DECODING) {
|
||||
if (mState < DECODER_STATE_DECODING || IsDecodingFirstFrame()) {
|
||||
DECODER_LOG("Seek() Not Enough Data to continue at this stage, queuing seek");
|
||||
mQueuedSeek.RejectIfExists(__func__);
|
||||
mQueuedSeek.mTarget = aTarget;
|
||||
@ -1489,7 +1489,7 @@ MediaDecoderStateMachine::EnqueueDecodeFirstFrameTask()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
MOZ_ASSERT(mState == DECODER_STATE_DECODING_FIRSTFRAME);
|
||||
MOZ_ASSERT(IsDecodingFirstFrame());
|
||||
|
||||
nsCOMPtr<nsIRunnable> task(
|
||||
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::CallDecodeFirstFrame));
|
||||
@ -1504,7 +1504,6 @@ MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
|
||||
AssertCurrentThreadInMonitor();
|
||||
|
||||
if (mState != DECODER_STATE_DECODING &&
|
||||
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
|
||||
mState != DECODER_STATE_BUFFERING &&
|
||||
mState != DECODER_STATE_SEEKING) {
|
||||
return;
|
||||
@ -1653,7 +1652,6 @@ MediaDecoderStateMachine::EnsureAudioDecodeTaskQueued()
|
||||
IsAudioDecoding(), AudioRequestStatus());
|
||||
|
||||
if (mState != DECODER_STATE_DECODING &&
|
||||
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
|
||||
mState != DECODER_STATE_BUFFERING &&
|
||||
mState != DECODER_STATE_SEEKING) {
|
||||
return NS_OK;
|
||||
@ -1725,7 +1723,6 @@ MediaDecoderStateMachine::EnsureVideoDecodeTaskQueued()
|
||||
IsVideoDecoding(), VideoRequestStatus());
|
||||
|
||||
if (mState != DECODER_STATE_DECODING &&
|
||||
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
|
||||
mState != DECODER_STATE_BUFFERING &&
|
||||
mState != DECODER_STATE_SEEKING) {
|
||||
return NS_OK;
|
||||
@ -1862,7 +1859,7 @@ bool MediaDecoderStateMachine::HasLowUndecodedData(int64_t aUsecs)
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
NS_ASSERTION(mState > DECODER_STATE_DECODING_FIRSTFRAME,
|
||||
NS_ASSERTION(mState >= DECODER_STATE_DECODING && !IsDecodingFirstFrame(),
|
||||
"Must have loaded first frame for mBuffered to be valid");
|
||||
|
||||
// If we don't have a duration, mBuffered is probably not going to have
|
||||
@ -1993,7 +1990,8 @@ MediaDecoderStateMachine::OnMetadataRead(MetadataHolder* aMetadata)
|
||||
return;
|
||||
}
|
||||
|
||||
SetState(DECODER_STATE_DECODING_FIRSTFRAME);
|
||||
SetState(DECODER_STATE_DECODING);
|
||||
mDecodingFirstFrame = true;
|
||||
EnqueueDecodeFirstFrameTask();
|
||||
ScheduleStateMachine();
|
||||
}
|
||||
@ -2050,7 +2048,7 @@ MediaDecoderStateMachine::CallDecodeFirstFrame()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
if (mState != DECODER_STATE_DECODING_FIRSTFRAME) {
|
||||
if (!IsDecodingFirstFrame()) {
|
||||
return;
|
||||
}
|
||||
if (NS_FAILED(DecodeFirstFrame())) {
|
||||
@ -2064,7 +2062,7 @@ MediaDecoderStateMachine::DecodeFirstFrame()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
MOZ_ASSERT(mState == DECODER_STATE_DECODING_FIRSTFRAME);
|
||||
MOZ_ASSERT(IsDecodingFirstFrame());
|
||||
DECODER_LOG("DecodeFirstFrame started");
|
||||
|
||||
if (IsRealTime()) {
|
||||
@ -2088,6 +2086,12 @@ MediaDecoderStateMachine::DecodeFirstFrame()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
MediaDecoderStateMachine::IsDecodingFirstFrame()
|
||||
{
|
||||
return mState == DECODER_STATE_DECODING && mDecodingFirstFrame;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaDecoderStateMachine::FinishDecodeFirstFrame()
|
||||
{
|
||||
@ -2137,11 +2141,13 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
|
||||
mPendingSeek.Steal(mQueuedSeek);
|
||||
SetState(DECODER_STATE_SEEKING);
|
||||
ScheduleStateMachine();
|
||||
} else if (mState == DECODER_STATE_DECODING_FIRSTFRAME) {
|
||||
} else if (IsDecodingFirstFrame()) {
|
||||
// StartDecoding() will also check if decode is completed.
|
||||
StartDecoding();
|
||||
}
|
||||
|
||||
mDecodingFirstFrame = false;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2338,12 +2344,11 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
case DECODER_STATE_DECODING_FIRSTFRAME: {
|
||||
// DECODER_STATE_DECODING_FIRSTFRAME will be started by OnMetadataRead.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
case DECODER_STATE_DECODING: {
|
||||
if (IsDecodingFirstFrame()) {
|
||||
// DECODER_STATE_DECODING will be started by OnMetadataRead.
|
||||
return NS_OK;
|
||||
}
|
||||
if (mPlayState != MediaDecoder::PLAY_STATE_PLAYING && IsPlaying())
|
||||
{
|
||||
// We're playing, but the element/decoder is in paused state. Stop
|
||||
@ -2890,7 +2895,7 @@ void MediaDecoderStateMachine::UpdateNextFrameStatus()
|
||||
|
||||
MediaDecoderOwner::NextFrameStatus status;
|
||||
const char* statusString;
|
||||
if (mState <= DECODER_STATE_DECODING_FIRSTFRAME) {
|
||||
if (mState <= DECODER_STATE_WAIT_FOR_CDM || IsDecodingFirstFrame()) {
|
||||
status = MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
|
||||
statusString = "NEXT_FRAME_UNAVAILABLE";
|
||||
} else if (IsBuffering()) {
|
||||
|
@ -138,7 +138,6 @@ public:
|
||||
DECODER_STATE_DECODING_METADATA,
|
||||
DECODER_STATE_WAIT_FOR_RESOURCES,
|
||||
DECODER_STATE_WAIT_FOR_CDM,
|
||||
DECODER_STATE_DECODING_FIRSTFRAME,
|
||||
DECODER_STATE_DORMANT,
|
||||
DECODER_STATE_DECODING,
|
||||
DECODER_STATE_SEEKING,
|
||||
@ -407,6 +406,7 @@ protected:
|
||||
MediaQueue<AudioData>& AudioQueue() { return mAudioQueue; }
|
||||
MediaQueue<VideoData>& VideoQueue() { return mVideoQueue; }
|
||||
|
||||
bool IsDecodingFirstFrame();
|
||||
nsresult FinishDecodeFirstFrame();
|
||||
|
||||
// True if our buffers of decoded audio are not full, and we should
|
||||
@ -1262,6 +1262,10 @@ private:
|
||||
|
||||
mozilla::RollingMean<uint32_t, uint32_t> mCorruptFrames;
|
||||
|
||||
// True if we need to call FinishDecodeFirstFrame() upon frame decoding
|
||||
// successeeding.
|
||||
bool mDecodingFirstFrame;
|
||||
|
||||
bool mDisabledHardwareAcceleration;
|
||||
|
||||
// mDecodingFrozenAtStateDecoding: turn on/off at
|
||||
|
Loading…
Reference in New Issue
Block a user