diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index 7e65d3c7f46f..711add05a2d5 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -699,6 +699,7 @@ MediaDecoderStateMachine::OnAudioPopped(const nsRefPtr& aSample) mPlaybackOffset = std::max(mPlaybackOffset.Ref(), aSample->mOffset); UpdateNextFrameStatus(); DispatchAudioDecodeTaskIfNeeded(); + MaybeStartBuffering(); } void @@ -709,6 +710,7 @@ MediaDecoderStateMachine::OnVideoPopped(const nsRefPtr& aSample) mPlaybackOffset = std::max(mPlaybackOffset.Ref(), aSample->mOffset); UpdateNextFrameStatus(); DispatchVideoDecodeTaskIfNeeded(); + MaybeStartBuffering(); } void @@ -1097,6 +1099,34 @@ void MediaDecoderStateMachine::MaybeStartPlayback() DispatchDecodeTasksIfNeeded(); } +void +MediaDecoderStateMachine::MaybeStartBuffering() +{ + MOZ_ASSERT(OnTaskQueue()); + AssertCurrentThreadInMonitor(); + + if (mState == DECODER_STATE_DECODING && + mPlayState == MediaDecoder::PLAY_STATE_PLAYING && + mResource->IsExpectingMoreData()) { + bool shouldBuffer; + if (mReader->UseBufferingHeuristics()) { + shouldBuffer = HasLowDecodedData(EXHAUSTED_DATA_MARGIN_USECS) && + (JustExitedQuickBuffering() || HasLowUndecodedData()); + } else { + MOZ_ASSERT(mReader->IsWaitForDataSupported()); + shouldBuffer = (OutOfDecodedAudio() && mAudioWaitRequest.Exists()) || + (OutOfDecodedVideo() && mVideoWaitRequest.Exists()); + } + if (shouldBuffer) { + StartBuffering(); + // Don't go straight back to the state machine loop since that might + // cause us to start decoding again and we could flip-flop between + // decoding and quick-buffering. + ScheduleStateMachineIn(USECS_PER_S); + } + } +} + void MediaDecoderStateMachine::UpdatePlaybackPositionInternal(int64_t aTime) { MOZ_ASSERT(OnTaskQueue()); @@ -2612,30 +2642,6 @@ void MediaDecoderStateMachine::UpdateRenderedVideoFrames() RenderVideoFrames(sVideoQueueSendToCompositorSize, clockTime, nowTime); - // Check to see if we don't have enough data to play up to the next frame. - // If we don't, switch to buffering mode. - if (mState == DECODER_STATE_DECODING && - mPlayState == MediaDecoder::PLAY_STATE_PLAYING && - mResource->IsExpectingMoreData()) { - bool shouldBuffer; - if (mReader->UseBufferingHeuristics()) { - shouldBuffer = HasLowDecodedData(EXHAUSTED_DATA_MARGIN_USECS) && - (JustExitedQuickBuffering() || HasLowUndecodedData()); - } else { - MOZ_ASSERT(mReader->IsWaitForDataSupported()); - shouldBuffer = (OutOfDecodedAudio() && mAudioWaitRequest.Exists()) || - (OutOfDecodedVideo() && mVideoWaitRequest.Exists()); - } - if (shouldBuffer) { - StartBuffering(); - // Don't go straight back to the state machine loop since that might - // cause us to start decoding again and we could flip-flop between - // decoding and quick-buffering. - ScheduleStateMachineIn(USECS_PER_S); - return; - } - } - // Cap the current time to the larger of the audio and video end time. // This ensures that if we're running off the system clock, we don't // advance the clock to after the media end time. diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h index dd1b951f1b6d..772af393487e 100644 --- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -522,6 +522,10 @@ protected: // Must be called with the decode monitor held. void MaybeStartPlayback(); + // Check to see if we don't have enough data to play up to the next frame. + // If we don't, switch to buffering mode. + void MaybeStartBuffering(); + // Moves the decoder into decoding state. Called on the state machine // thread. The decoder monitor must be held. void StartDecoding();