Bug 631058 - Part 2 -Only decode Only decode metadata for preload=metadata. r=cpearce, a=blocking-fennec

This commit is contained in:
Wes Johnston 2011-02-15 16:54:47 -08:00
parent 6979a59264
commit d04cf02a60
7 changed files with 70 additions and 27 deletions

View File

@ -62,7 +62,7 @@ onload = function() {
iframe = document.getElementById('iframe');
iframe.onerror = iframe.onload = iframeNotifyParent;
audio = document.getElementById('audio');
audio.onerror = audio.oncanplay = audioNotifyParent;
audio.onerror = audio.onloadedmetadata = audioNotifyParent;
}
</script>

View File

@ -12,7 +12,7 @@
<iframe id=inner></iframe>
<iframe id=iframe></iframe>
<img id=img onload="gen.send(event);">
<audio id=audio oncanplay="gen.send(event);">
<audio id=audio onloadedmetadata="gen.send(event);">
<input type=file id=fileList>
</p>
<div id="content" style="display: none">
@ -90,11 +90,11 @@ function runTest() {
var fileurl = URL.createObjectURL(file);
audio.src = fileurl;
var e = (yield);
is(e.type, "canplay", "loaded successfully");
is(e.type, "loadedmetadata", "loaded successfully");
// Revoke url and attempt to load a audio in this document
audio.src = "file_mozfiledataurl_audio.ogg";
is((yield).type, "canplay", "successfully reset audio");
is((yield).type, "loadedmetadata", "successfully reset audio");
URL.revokeObjectURL(fileurl);
todo(false, "urls need to act like 404s, not fail to parse");
/* img.src = fileurl;
@ -113,7 +113,7 @@ function runTest() {
yield;
inner.contentWindow.postMessage(JSON.stringify({audio:fileurl}), "*");
var res = (yield);
is(res.type, "canplay", "loaded successfully");
is(res.type, "loadedmetadata", "loaded successfully");
// Attempt to load an audio in a different cross-origin document
inner.src = innerCrossSiteURI;

View File

@ -328,6 +328,19 @@ public:
*/
PRBool GetPlayedOrSeeked() const { return mHasPlayedOrSeeked; }
/**
* The preloading action to perform. These dictate how we react to the
* preload attribute. See mPreloadAction.
*/
enum PreloadAction {
PRELOAD_UNDEFINED = 0, // not determined - used only for initialization
PRELOAD_NONE = 1, // do not preload
PRELOAD_METADATA = 2, // preload only the metadata (and first frame)
PRELOAD_ENOUGH = 3 // preload enough data to allow uninterrupted
// playback
};
PreloadAction GetPreloadAction() const { return mPreloadAction; }
nsresult CopyInnerTo(nsGenericElement* aDest) const;
/**
@ -478,18 +491,6 @@ protected:
PRELOAD_ATTR_AUTO // set to "auto"
};
/**
* The preloading action to perform. These dictate how we react to the
* preload attribute. See mPreloadAction.
*/
enum PreloadAction {
PRELOAD_UNDEFINED = 0, // not determined - used only for initialization
PRELOAD_NONE = 1, // do not preload
PRELOAD_METADATA = 2, // preload only the metadata (and first frame)
PRELOAD_ENOUGH = 3 // preload enough data to allow uninterrupted
// playback
};
/**
* Suspends the load of resource at aURI, so that it can be resumed later
* by ResumeLoad(). This is called when we have a media with a 'preload'

View File

@ -855,6 +855,10 @@ void nsBuiltinDecoder::Resume(PRBool aForceBuffering)
}
}
nsHTMLMediaElement::PreloadAction nsBuiltinDecoder::GetPreloadAction() {
return mElement->GetPreloadAction();
}
void nsBuiltinDecoder::StopProgressUpdates()
{
NS_ASSERTION(IsCurrentThread(mStateMachineThread), "Should be on state machine thread.");

View File

@ -450,6 +450,9 @@ class nsBuiltinDecoder : public nsMediaDecoder
}
public:
// Return the preloadAction
nsHTMLMediaElement::PreloadAction GetPreloadAction();
// Return the current state. Can be called on any thread. If called from
// a non-main thread, the decoder monitor must be held.
PlayState GetState() {

View File

@ -987,11 +987,14 @@ nsresult nsBuiltinDecoderStateMachine::Run()
MonitorAutoExit exitMon(mDecoder->GetMonitor());
RenderVideoFrame(videoData);
}
// Start the decode threads, so that we can pre buffer the streams.
// and calculate the start time in order to determine the duration.
if (NS_FAILED(StartDecodeThreads())) {
continue;
if (mDecoder->GetPreloadAction() == nsHTMLMediaElement::PRELOAD_ENOUGH ||
mDecoder->GetState() == nsBuiltinDecoder::PLAY_STATE_PLAYING)
{
// Start the decode threads, so that we can pre buffer the streams
// and calculate the start time in order to determine the duration.
if (NS_FAILED(StartDecodeThreads())) {
continue;
}
}
NS_ASSERTION(mStartTime != -1, "Must have start time");
@ -1023,12 +1026,41 @@ nsresult nsBuiltinDecoderStateMachine::Run()
if (mState == DECODER_STATE_DECODING_METADATA) {
LOG(PR_LOG_DEBUG, ("%p Changed state from DECODING_METADATA to DECODING", mDecoder));
mState = DECODER_STATE_DECODING;
}
// Start playback.
if (mDecoder->GetState() == nsBuiltinDecoder::PLAY_STATE_PLAYING) {
if (!IsPlaying()) {
StartPlayback();
// Start playback.
if (mDecoder->GetState() == nsBuiltinDecoder::PLAY_STATE_PLAYING) {
if (!IsPlaying()) {
StartPlayback();
}
} else if (mDecoder->GetPreloadAction() != nsHTMLMediaElement::PRELOAD_ENOUGH) {
if (mReader) {
// Clear any frames queued up during FindStartTime() and reset
// to the start of the stream to save memory.
MonitorAutoExit exitMon(mDecoder->GetMonitor());
mReader->ResetDecode();
nsMediaStream* stream = mDecoder->GetCurrentStream();
PRInt64 offset = mReader->GetInfo().mDataOffset;
if (NS_FAILED(stream->Seek(nsISeekableStream::NS_SEEK_SET, offset)))
{
mState = DECODER_STATE_SHUTDOWN;
}
}
// Note state can change when we release the decoder monitor to
// call ResetDecode() above, so we must re-verify the state here.
if (mState != DECODER_STATE_DECODING ||
mDecoder->GetState() == nsBuiltinDecoder::PLAY_STATE_PLAYING)
{
continue;
}
// Shutdown the state machine thread, in order to save
// memory on thread stacks, particuarly on Linux.
nsCOMPtr<nsIRunnable> event = new ShutdownThreadEvent(mDecoder->mStateMachineThread);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
mDecoder->mStateMachineThread = nsnull;
return NS_OK;
}
}
}

View File

@ -2084,6 +2084,9 @@ nsMediaCacheStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
return NS_ERROR_FAILURE;
}
if (mStreamOffset < 0)
return NS_ERROR_FAILURE;
LOG(PR_LOG_DEBUG, ("Stream %p Seek to %lld", this, (long long)mStreamOffset));
gMediaCache->NoteSeek(this, oldOffset);