diff --git a/content/media/MediaResource.cpp b/content/media/MediaResource.cpp index b2f5469e023..edcd1f0fb6e 100644 --- a/content/media/MediaResource.cpp +++ b/content/media/MediaResource.cpp @@ -41,7 +41,8 @@ ChannelMediaResource::ChannelMediaResource(nsMediaDecoder* aDecoder, mReopenOnError(false), mIgnoreClose(false), mCacheStream(this), mLock("ChannelMediaResource.mLock"), - mIgnoreResume(false) + mIgnoreResume(false), + mSeekingForMetadata(false) { } @@ -261,7 +262,12 @@ ChannelMediaResource::OnStartRequest(nsIRequest* aRequest) } mReopenOnError = false; - mIgnoreClose = false; + // If we are seeking to get metadata, because we are playing an OGG file, + // ignore if the channel gets closed without us suspending it explicitly. We + // don't want to tell the element that the download has finished whereas we + // just happended to have reached the end of the media while seeking. + mIgnoreClose = mSeekingForMetadata; + if (mSuspendCount > 0) { // Re-suspend the channel if it needs to be suspended // No need to call PossiblySuspend here since the channel is @@ -590,6 +596,16 @@ nsresult ChannelMediaResource::Seek(PRInt32 aWhence, PRInt64 aOffset) return mCacheStream.Seek(aWhence, aOffset); } +void ChannelMediaResource::StartSeekingForMetadata() +{ + mSeekingForMetadata = true; +} + +void ChannelMediaResource::EndSeekingForMetadata() +{ + mSeekingForMetadata = false; +} + PRInt64 ChannelMediaResource::Tell() { NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread"); @@ -926,6 +942,8 @@ public: virtual void SetPlaybackRate(PRUint32 aBytesPerSecond) {} virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes); virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset); + virtual void StartSeekingForMetadata() {}; + virtual void EndSeekingForMetadata() {}; virtual PRInt64 Tell(); // Any thread diff --git a/content/media/MediaResource.h b/content/media/MediaResource.h index 018f4fae85e..91f54b28475 100644 --- a/content/media/MediaResource.h +++ b/content/media/MediaResource.h @@ -212,6 +212,8 @@ public: // The file strategy doesn't block for any great length of time so // is fine for a no-op cancel. virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset) = 0; + virtual void StartSeekingForMetadata() = 0; + virtual void EndSeekingForMetadata() = 0; // Report the current offset in bytes from the start of the stream. virtual PRInt64 Tell() = 0; // Moves any existing channel loads into the background, so that they don't @@ -378,6 +380,8 @@ public: virtual void SetPlaybackRate(PRUint32 aBytesPerSecond); virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes); virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset); + virtual void StartSeekingForMetadata(); + virtual void EndSeekingForMetadata(); virtual PRInt64 Tell(); // Any thread @@ -473,6 +477,9 @@ protected: // to resume later. This is usually due to the channel not being in the // isPending state at the time of the suspend request. bool mIgnoreResume; + + // True if we are seeking to get the real duration of the file. + bool mSeekingForMetadata; }; } diff --git a/content/media/ogg/nsOggReader.cpp b/content/media/ogg/nsOggReader.cpp index a942c691b04..052d25ffcc1 100644 --- a/content/media/ogg/nsOggReader.cpp +++ b/content/media/ogg/nsOggReader.cpp @@ -359,7 +359,9 @@ nsresult nsOggReader::ReadMetadata(nsVideoInfo* aInfo, { // We didn't get a duration from the index or a Content-Duration header. // Seek to the end of file to find the end time. + mDecoder->GetResource()->StartSeekingForMetadata(); PRInt64 length = resource->GetLength(); + NS_ASSERTION(length > 0, "Must have a content length to get end time"); PRInt64 endTime = 0; @@ -371,6 +373,7 @@ nsresult nsOggReader::ReadMetadata(nsVideoInfo* aInfo, mDecoder->GetStateMachine()->SetEndTime(endTime); LOG(PR_LOG_DEBUG, ("Got Ogg duration from seeking to end %lld", endTime)); } + mDecoder->GetResource()->EndSeekingForMetadata(); } } else { return NS_ERROR_FAILURE;