@@ -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;
diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h
index 09846c6fe53..b62a2db6da4 100644
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -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'
diff --git a/content/media/nsBuiltinDecoder.cpp b/content/media/nsBuiltinDecoder.cpp
index 6efaa6ed5fd..ac457f85c18 100644
--- a/content/media/nsBuiltinDecoder.cpp
+++ b/content/media/nsBuiltinDecoder.cpp
@@ -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.");
diff --git a/content/media/nsBuiltinDecoder.h b/content/media/nsBuiltinDecoder.h
index 82dd1b41fe7..f3623f43d08 100644
--- a/content/media/nsBuiltinDecoder.h
+++ b/content/media/nsBuiltinDecoder.h
@@ -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() {
diff --git a/content/media/nsBuiltinDecoderStateMachine.cpp b/content/media/nsBuiltinDecoderStateMachine.cpp
index 7b78e8e031a..724d3a5b9a4 100644
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -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,39 @@ 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 event = new ShutdownThreadEvent(mDecoder->mStateMachineThread);
+ NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
+ mDecoder->mStateMachineThread = nsnull;
+
+ return NS_OK;
}
}
}
diff --git a/content/media/nsMediaCache.cpp b/content/media/nsMediaCache.cpp
index ee617109a6b..998c503066d 100644
--- a/content/media/nsMediaCache.cpp
+++ b/content/media/nsMediaCache.cpp
@@ -2067,23 +2067,28 @@ nsMediaCacheStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
return NS_ERROR_FAILURE;
PRInt64 oldOffset = mStreamOffset;
+ PRInt64 newOffset = mStreamOffset;
switch (aWhence) {
case PR_SEEK_END:
if (mStreamLength < 0)
return NS_ERROR_FAILURE;
- mStreamOffset = mStreamLength + aOffset;
+ newOffset = mStreamLength + aOffset;
break;
case PR_SEEK_CUR:
- mStreamOffset += aOffset;
+ newOffset += aOffset;
break;
case PR_SEEK_SET:
- mStreamOffset = aOffset;
+ newOffset = aOffset;
break;
default:
NS_ERROR("Unknown whence");
return NS_ERROR_FAILURE;
}
+ if (newOffset < 0)
+ return NS_ERROR_FAILURE;
+ mStreamOffset = newOffset;
+
LOG(PR_LOG_DEBUG, ("Stream %p Seek to %lld", this, (long long)mStreamOffset));
gMediaCache->NoteSeek(this, oldOffset);