Bug 1109437 - Only switch to buffering mode when the reader is waiting for data. r=cpearce

This commit is contained in:
Bobby Holley 2014-12-22 00:20:31 -08:00
parent 10d012cc54
commit 078237732a
2 changed files with 30 additions and 12 deletions

View File

@ -1963,6 +1963,7 @@ int64_t MediaDecoderStateMachine::AudioDecodedUsecs()
bool MediaDecoderStateMachine::HasLowDecodedData(int64_t aAudioUsecs)
{
AssertCurrentThreadInMonitor();
MOZ_ASSERT(mReader->UseBufferingHeuristics());
// We consider ourselves low on decoded data if we're low on audio,
// provided we've not decoded to the end of the audio stream, or
// if we're low on video frames, provided
@ -2659,12 +2660,6 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
TimeStamp now = TimeStamp::Now();
NS_ASSERTION(!mBufferingStart.IsNull(), "Must know buffering start time.");
// When we enter buffering mode from playback, we push our most recent
// video frame back into the queue. So depending on how we started
// buffering, we may have one dummy frame in the queue. :-(
bool outOfAudio = IsAudioDecoding() && !AudioQueue().IsFinished() && AudioQueue().GetSize() == 0;
bool outOfVideo = IsVideoDecoding() && !VideoQueue().IsFinished() && VideoQueue().GetSize() <= 1;
// With buffering heuristics we will remain in the buffering state if
// we've not decoded enough data to begin playback, or if we've not
// downloaded a reasonable amount of data inside our buffering time.
@ -2683,15 +2678,16 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
ScheduleStateMachine(USECS_PER_S);
return NS_OK;
}
} else if (outOfAudio || outOfVideo) {
} else if (OutOfDecodedAudio() || OutOfDecodedVideo()) {
MOZ_ASSERT(mReader->IsWaitForDataSupported(),
"Don't yet have a strategy for non-heuristic + non-WaitForData");
DispatchDecodeTasksIfNeeded();
MOZ_ASSERT_IF(outOfAudio, mAudioRequestStatus != RequestStatus::Idle);
MOZ_ASSERT_IF(outOfVideo, mVideoRequestStatus != RequestStatus::Idle);
MOZ_ASSERT_IF(OutOfDecodedAudio(), mAudioRequestStatus != RequestStatus::Idle);
MOZ_ASSERT_IF(OutOfDecodedVideo(), mVideoRequestStatus != RequestStatus::Idle);
DECODER_LOG("In buffering mode, waiting to be notified: outOfAudio: %d, "
"mAudioStatus: %d, outOfVideo: %d, mVideoStatus: %d",
outOfAudio, mAudioRequestStatus, outOfVideo, mVideoRequestStatus);
OutOfDecodedAudio(), mAudioRequestStatus,
OutOfDecodedVideo(), mVideoRequestStatus);
return NS_OK;
}
@ -2955,9 +2951,16 @@ void MediaDecoderStateMachine::AdvanceFrame()
// If we don't, switch to buffering mode.
if (mState == DECODER_STATE_DECODING &&
mDecoder->GetState() == MediaDecoder::PLAY_STATE_PLAYING &&
HasLowDecodedData(remainingTime + EXHAUSTED_DATA_MARGIN_USECS) &&
mDecoder->IsExpectingMoreData()) {
if (!mReader->UseBufferingHeuristics() || JustExitedQuickBuffering() || HasLowUndecodedData()) {
bool shouldBuffer;
if (mReader->UseBufferingHeuristics()) {
shouldBuffer = HasLowDecodedData(remainingTime + EXHAUSTED_DATA_MARGIN_USECS) &&
(JustExitedQuickBuffering() || HasLowUndecodedData());
} else {
MOZ_ASSERT(mReader->IsWaitForDataSupported());
shouldBuffer = OutOfDecodedAudio() || OutOfDecodedVideo();
}
if (shouldBuffer) {
if (currentFrame) {
VideoQueue().PushFront(currentFrame);
}

View File

@ -479,8 +479,23 @@ protected:
// Returns true if we've got less than aAudioUsecs microseconds of decoded
// and playable data. The decoder monitor must be held.
//
// May not be invoked when mReader->UseBufferingHeuristics() is false.
bool HasLowDecodedData(int64_t aAudioUsecs);
bool OutOfDecodedAudio()
{
return IsAudioDecoding() && !AudioQueue().IsFinished() && AudioQueue().GetSize() == 0;
}
bool OutOfDecodedVideo()
{
// In buffering mode, we keep the last already-played frame in the queue.
int emptyVideoSize = mState == DECODER_STATE_BUFFERING ? 1 : 0;
return IsVideoDecoding() && !VideoQueue().IsFinished() && VideoQueue().GetSize() <= emptyVideoSize;
}
// Returns true if we're running low on data which is not yet decoded.
// The decoder monitor must be held.
bool HasLowUndecodedData();