Bug 623637 - Initiate media buffering when decode hits end of downloaded data, rather than when they're close. r=roc a=roc

This commit is contained in:
Chris Pearce 2011-01-18 13:53:18 +13:00
Родитель 5e9829c7c7
Коммит 84b8ab4f74
7 изменённых файлов: 47 добавлений и 18 удалений

Просмотреть файл

@ -303,6 +303,8 @@ public:
// with the decode monitor held. Called on the state machine thread and
// the main thread.
virtual void StartBuffering() = 0;
virtual void NotifyDataExhausted() = 0;
};
class nsBuiltinDecoder : public nsMediaDecoder
@ -367,6 +369,10 @@ class nsBuiltinDecoder : public nsMediaDecoder
// from the resource.
void NotifyBytesConsumed(PRInt64 aBytes);
void NotifyDataExhausted() {
mDecoderStateMachine->NotifyDataExhausted();
}
// Called when the video file has completed downloading.
// Call on the main thread only.
void ResourceLoaded();

Просмотреть файл

@ -901,7 +901,23 @@ PRBool nsBuiltinDecoderStateMachine::IsDecodeCloseToDownload()
double threshold = (bufferTarget > 0 && length != -1) ?
(length / (bufferTarget)) : LIVE_BUFFER_MARGIN;
return (downloadPos - decodePos) < threshold;
}
}
void nsBuiltinDecoderStateMachine::NotifyDataExhausted()
{
MonitorAutoEnter mon(mDecoder->GetMonitor());
nsMediaStream* stream = mDecoder->GetCurrentStream();
NS_ASSERTION(!stream->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition),
"We shouldn't be notified in this case!");
if (mDecoder->GetState() == nsBuiltinDecoder::PLAY_STATE_PLAYING &&
mState == DECODER_STATE_DECODING &&
!stream->IsSuspended())
{
// Our decode has caught up with the download. Let's buffer to make sure
// we can play a decent amount of video in the future.
StartBuffering();
}
}
nsresult nsBuiltinDecoderStateMachine::Run()
{
@ -991,17 +1007,6 @@ nsresult nsBuiltinDecoderStateMachine::Run()
if (mState != DECODER_STATE_DECODING)
continue;
if (IsDecodeCloseToDownload() &&
mDecoder->GetState() == nsBuiltinDecoder::PLAY_STATE_PLAYING &&
!stream->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) &&
!stream->IsSuspended())
{
// We're low on decoded data, and/or our decode has caught up with
// the download. Let's buffer to make sure we can play a decent
// amount of video in the future.
StartBuffering();
}
}
break;
@ -1107,6 +1112,11 @@ nsresult nsBuiltinDecoderStateMachine::Run()
case DECODER_STATE_BUFFERING:
{
if (IsPlaying()) {
StopPlayback(AUDIO_PAUSE);
mDecoder->GetMonitor().NotifyAll();
}
TimeStamp now = TimeStamp::Now();
if (mBufferingEndOffset == -1) {
// This is the first time we've entered the buffering state.
@ -1479,10 +1489,6 @@ void nsBuiltinDecoderStateMachine::LoadMetadata()
void nsBuiltinDecoderStateMachine::StartBuffering()
{
mDecoder->GetMonitor().AssertCurrentThreadIn();
if (IsPlaying()) {
StopPlayback(AUDIO_PAUSE);
mDecoder->GetMonitor().NotifyAll();
}
// We need to tell the element that buffering has started.
// We can't just directly send an asynchronous runnable that

Просмотреть файл

@ -250,6 +250,8 @@ public:
return mEndTime;
}
void NotifyDataExhausted();
protected:
// Returns PR_TRUE if the decode is withing an estimated one tenth of a

Просмотреть файл

@ -286,6 +286,11 @@ public:
// to buffer, given the current download and playback rates.
PRBool CanPlayThrough();
// Called by the nsMediaStream when a read on the stream by the decoder
// is about to block due to insuffient data. Decoders may want to pause
// playback and go into buffering mode when this is called.
virtual void NotifyDataExhausted() = 0;
protected:
// Start timer to update download progress information.

Просмотреть файл

@ -571,6 +571,15 @@ nsresult nsMediaChannelStream::Read(char* aBuffer,
{
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
PRInt64 pos = Tell();
PRInt64 endOfRead = pos + aCount;
if (endOfRead > mCacheStream.GetCachedDataEnd(pos) &&
!IsDataCachedToEndOfStream(pos)) {
// Our read will almost certainly block waiting for more data to download.
// Notify the decoder, so it can move to buffering state if need be.
mDecoder->NotifyDataExhausted();
}
return mCacheStream.Read(aBuffer, aCount, aBytes);
}

Просмотреть файл

@ -21,8 +21,8 @@ function ended(evt) {
function startTest(test, token) {
var v = document.createElement('video');
v.token = v;
manager.started(v);
v.token = token;
manager.started(v.token);
v.src = test.name;
v._name = test.name;
v._finished = false;

Просмотреть файл

@ -244,6 +244,7 @@ class nsWaveDecoder : public nsMediaDecoder
virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRUint32 aOffset) {}
void NotifyDataExhausted() {}
private:
// Notifies the element that seeking has started.
void SeekingStarted();