Bug 935118 - Allow buffering to be triggered when we're low on decoded audio or video. r=roc

This commit is contained in:
Sotaro Ikeda 2013-11-19 09:01:14 -05:00
parent ad54eee5af
commit 0523044e79
3 changed files with 32 additions and 42 deletions

View File

@ -961,7 +961,7 @@ MediaDecoder::GetStatistics()
double MediaDecoder::ComputePlaybackRate(bool* aReliable)
{
GetReentrantMonitor().AssertCurrentThreadIn();
MOZ_ASSERT(NS_IsMainThread() || OnStateMachineThread());
MOZ_ASSERT(NS_IsMainThread() || OnStateMachineThread() || OnDecodeThread());
int64_t length = mResource ? mResource->GetLength() : -1;
if (mDuration >= 0 && length >= 0) {

View File

@ -1829,52 +1829,44 @@ bool MediaDecoderStateMachine::HasLowDecodedData(int64_t aAudioUsecs) const
AssertCurrentThreadInMonitor();
// 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 only playing video and we're low on video frames, provided
// if we're low on video frames, provided
// we've not decoded to the end of the video stream.
return ((HasAudio() &&
!mReader->AudioQueue().IsFinished() &&
AudioDecodedUsecs() < aAudioUsecs)
||
(!HasAudio() &&
HasVideo() &&
(HasVideo() &&
!mReader->VideoQueue().IsFinished() &&
static_cast<uint32_t>(mReader->VideoQueue().GetSize()) < LOW_VIDEO_FRAMES));
}
bool MediaDecoderStateMachine::HasLowUndecodedData() const
{
return GetUndecodedData() < mLowDataThresholdUsecs;
return HasLowUndecodedData(mLowDataThresholdUsecs);
}
int64_t MediaDecoderStateMachine::GetUndecodedData() const
bool MediaDecoderStateMachine::HasLowUndecodedData(double aUsecs) const
{
AssertCurrentThreadInMonitor();
NS_ASSERTION(mState > DECODER_STATE_DECODING_METADATA,
"Must have loaded metadata for GetBuffered() to work");
TimeRanges buffered;
nsresult res = mDecoder->GetBuffered(&buffered);
NS_ENSURE_SUCCESS(res, 0);
double currentTime = GetCurrentTime();
nsIDOMTimeRanges* r = static_cast<nsIDOMTimeRanges*>(&buffered);
uint32_t length = 0;
res = r->GetLength(&length);
NS_ENSURE_SUCCESS(res, 0);
for (uint32_t index = 0; index < length; ++index) {
double start, end;
res = r->Start(index, &start);
NS_ENSURE_SUCCESS(res, 0);
res = r->End(index, &end);
NS_ENSURE_SUCCESS(res, 0);
if (start <= currentTime && end >= currentTime) {
return static_cast<int64_t>((end - currentTime) * USECS_PER_S);
}
bool reliable;
double bytesPerSecond = mDecoder->ComputePlaybackRate(&reliable);
if (!reliable) {
// Default to assuming we have enough
return false;
}
return 0;
MediaResource* stream = mDecoder->GetResource();
int64_t currentPos = stream->Tell();
int64_t requiredPos = currentPos + int64_t((aUsecs/1000000.0)*bytesPerSecond);
int64_t length = stream->GetLength();
if (length >= 0) {
requiredPos = std::min(requiredPos, length);
}
return stream->GetCachedDataEnd(currentPos) < requiredPos;
}
void MediaDecoderStateMachine::SetFrameBufferLength(uint32_t aLength)
@ -2282,14 +2274,13 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
if ((isLiveStream || !mDecoder->CanPlayThrough()) &&
elapsed < TimeDuration::FromSeconds(mBufferingWait * mPlaybackRate) &&
(mQuickBuffering ? HasLowDecodedData(QUICK_BUFFERING_LOW_DATA_USECS)
: (GetUndecodedData() < mBufferingWait * mPlaybackRate * USECS_PER_S)) &&
: HasLowUndecodedData(mBufferingWait * USECS_PER_S)) &&
!mDecoder->IsDataCachedToEndOfResource() &&
!resource->IsSuspended())
{
LOG(PR_LOG_DEBUG,
("%p Buffering: %.3lfs/%ds, timeout in %.3lfs %s",
("%p Buffering: wait %ds, timeout in %.3lfs %s",
mDecoder.get(),
GetUndecodedData() / static_cast<double>(USECS_PER_S),
mBufferingWait,
mBufferingWait - elapsed.ToSeconds(),
(mQuickBuffering ? "(quick exit)" : "")));
@ -2528,15 +2519,15 @@ void MediaDecoderStateMachine::AdvanceFrame()
mDecoder->GetState() == MediaDecoder::PLAY_STATE_PLAYING &&
HasLowDecodedData(remainingTime + EXHAUSTED_DATA_MARGIN_USECS) &&
!mDecoder->IsDataCachedToEndOfResource() &&
!resource->IsSuspended() &&
(JustExitedQuickBuffering() || HasLowUndecodedData()))
{
if (currentFrame) {
mReader->VideoQueue().PushFront(currentFrame.forget());
!resource->IsSuspended()) {
if (JustExitedQuickBuffering() || HasLowUndecodedData()) {
if (currentFrame) {
mReader->VideoQueue().PushFront(currentFrame.forget());
}
StartBuffering();
ScheduleStateMachine();
return;
}
StartBuffering();
ScheduleStateMachine();
return;
}
// We've got enough data to keep playing until at least the next frame.

View File

@ -394,9 +394,8 @@ private:
// The decoder monitor must be held.
bool HasLowUndecodedData() const;
// Returns the number of microseconds of undecoded data available for
// decoding. The decoder monitor must be held.
int64_t GetUndecodedData() const;
// Returns true if we have less than aUsecs of undecoded data available.
bool HasLowUndecodedData(double aUsecs) const;
// Returns the number of unplayed usecs of audio we've got decoded and/or
// pushed to the hardware waiting to play. This is how much audio we can