Bug 468190 - ended reports true when seeking after playback ended; r=chris.double sr=roc

This commit is contained in:
Matthew Gregan 2008-12-14 19:02:54 +01:00
parent 42b6a52e99
commit 908bfe5f7a
7 changed files with 56 additions and 18 deletions

View File

@ -214,9 +214,6 @@ protected:
// Set to false when completed, or not yet started.
PRPackedBool mBegun;
// If truen then the video playback has completed.
PRPackedBool mEnded;
// True when the decoder has loaded enough data to display the
// first frame of the content.
PRPackedBool mLoadedFirstFrame;

View File

@ -112,7 +112,7 @@ NS_IMETHODIMP nsHTMLMediaElement::GetError(nsIDOMHTMLMediaError * *aError)
/* readonly attribute boolean ended; */
NS_IMETHODIMP nsHTMLMediaElement::GetEnded(PRBool *aEnded)
{
*aEnded = mEnded;
*aEnded = mDecoder ? mDecoder->IsEnded() : PR_FALSE;
return NS_OK;
}
@ -191,7 +191,6 @@ nsresult nsHTMLMediaElement::LoadWithChannel(nsIChannel *aChannel,
NS_ENSURE_SUCCESS(rv, rv);
mBegun = PR_TRUE;
mEnded = PR_FALSE;
DispatchAsyncProgressEvent(NS_LITERAL_STRING("loadstart"));
@ -343,7 +342,6 @@ nsHTMLMediaElement::nsHTMLMediaElement(nsINodeInfo *aNodeInfo, PRBool aFromParse
mMutedVolume(0.0),
mMediaSize(-1,-1),
mBegun(PR_FALSE),
mEnded(PR_FALSE),
mLoadedFirstFrame(PR_FALSE),
mAutoplaying(PR_TRUE),
mPaused(PR_TRUE),
@ -374,8 +372,7 @@ nsHTMLMediaElement::Play(void)
NS_ENSURE_SUCCESS(rv, rv);
}
if (mEnded) {
mEnded = PR_FALSE;
if (mDecoder->IsEnded()) {
SetCurrentTime(0);
}
@ -707,7 +704,6 @@ void nsHTMLMediaElement::FirstFrameLoaded()
void nsHTMLMediaElement::ResourceLoaded()
{
mBegun = PR_FALSE;
mEnded = PR_FALSE;
mNetworkState = nsIDOMHTMLMediaElement::LOADED;
ChangeReadyState(nsIDOMHTMLMediaElement::CAN_PLAY_THROUGH);
@ -725,8 +721,8 @@ void nsHTMLMediaElement::NetworkError()
void nsHTMLMediaElement::PlaybackEnded()
{
NS_ASSERTION(mDecoder->IsEnded(), "Decoder fired ended, but not in ended state");
mBegun = PR_FALSE;
mEnded = PR_TRUE;
mPaused = PR_TRUE;
DispatchSimpleEvent(NS_LITERAL_STRING("ended"));
}
@ -871,13 +867,15 @@ PRBool nsHTMLMediaElement::IsActivelyPlaying() const
mReadyState == nsIDOMHTMLMediaElement::CAN_PLAY_THROUGH) &&
!IsPlaybackEnded();
}
PRBool nsHTMLMediaElement::IsPlaybackEnded() const
{
// TODO:
// the current playback position is equal to the effective end of the media resource,
// and the currentLoop attribute is equal to playCount-1.
// See bug 449157.
return mNetworkState >= nsIDOMHTMLMediaElement::LOADED_METADATA && mEnded;
return mNetworkState >= nsIDOMHTMLMediaElement::LOADED_METADATA &&
mDecoder ? mDecoder->IsEnded() : PR_FALSE;
}
nsIPrincipal*

View File

@ -134,6 +134,10 @@ class nsMediaDecoder : public nsIObserver
// seeking in the media resource.
virtual PRBool IsSeeking() const = 0;
// Return PR_TRUE if the decoder has reached the end of playback.
// Call in the main thread only.
virtual PRBool IsEnded() const = 0;
// Return the current number of bytes loaded from the video file.
// This is used for progress events.
virtual PRUint64 GetBytesLoaded() = 0;

View File

@ -339,6 +339,10 @@ class nsOggDecoder : public nsMediaDecoder
// seeking in the media resource.
virtual PRBool IsSeeking() const;
// Return PR_TRUE if the decoder has reached the end of playback.
// Call on the main thread only.
virtual PRBool IsEnded() const;
// Get the size of the media file in bytes. Called on the main thread only.
virtual void SetTotalBytes(PRInt64 aBytes);

View File

@ -173,6 +173,9 @@ class nsWaveDecoder : public nsMediaDecoder
// Report whether the decoder is currently seeking.
virtual PRBool IsSeeking() const;
// Report whether the decoder has reached end of playback.
virtual PRBool IsEnded() const;
// Start downloading the media at the specified URI. The media's metadata
// will be parsed and made available as the load progresses.
virtual nsresult Load(nsIURI* aURI, nsIChannel* aChannel, nsIStreamListener** aStreamListener);
@ -259,11 +262,12 @@ private:
// state machine will validate the offset against the current media.
float mTimeOffset;
// Copy of the current time and duration when the state machine was
// disposed. Used to respond to time and duration queries with sensible
// values after playback has ended.
// Copy of the current time, duration, and ended state when the state
// machine was disposed. Used to respond to time and duration queries
// with sensible values after the state machine is destroyed.
float mEndedCurrentTime;
float mEndedDuration;
PRPackedBool mEnded;
// True if we have registered a shutdown observer.
PRPackedBool mNotifyOnShutdown;

View File

@ -1490,7 +1490,12 @@ void nsOggDecoder::NetworkError()
PRBool nsOggDecoder::IsSeeking() const
{
return mPlayState == PLAY_STATE_SEEKING;
return mPlayState == PLAY_STATE_SEEKING || mNextState == PLAY_STATE_SEEKING;
}
PRBool nsOggDecoder::IsEnded() const
{
return mPlayState == PLAY_STATE_ENDED || mPlayState == PLAY_STATE_SHUTDOWN;
}
void nsOggDecoder::PlaybackEnded()

View File

@ -145,6 +145,9 @@ public:
// Returns true if the state machine is seeking. Threadsafe.
PRBool IsSeeking();
// Returns true if the state machine has reached the end of playback. Threadsafe.
PRBool IsEnded();
// Called by the decoder to indicate that the media stream has closed.
void StreamEnded();
@ -428,7 +431,14 @@ PRBool
nsWaveStateMachine::IsSeeking()
{
nsAutoMonitor monitor(mMonitor);
return mState == STATE_SEEKING;
return mState == STATE_SEEKING || mNextState == STATE_SEEKING;
}
PRBool
nsWaveStateMachine::IsEnded()
{
nsAutoMonitor monitor(mMonitor);
return mState == STATE_ENDED || mState == STATE_SHUTDOWN;
}
void
@ -467,7 +477,9 @@ nsWaveStateMachine::Run()
newState = STATE_ERROR;
}
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
if (event) {
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
}
ChangeState(newState);
}
}
@ -952,6 +964,7 @@ nsWaveDecoder::nsWaveDecoder()
mTimeOffset(0.0),
mEndedCurrentTime(0.0),
mEndedDuration(std::numeric_limits<float>::quiet_NaN()),
mEnded(PR_FALSE),
mNotifyOnShutdown(PR_FALSE),
mSeekable(PR_TRUE)
{
@ -1075,9 +1088,13 @@ nsWaveDecoder::Stop()
}
if (mPlaybackThread) {
mPlaybackThread->Shutdown();
}
if (mPlaybackStateMachine) {
mEndedCurrentTime = mPlaybackStateMachine->GetCurrentTime();
mEndedDuration = mPlaybackStateMachine->GetDuration();
mPlaybackThread->Shutdown();
mEnded = mPlaybackStateMachine->IsEnded();
}
mPlaybackThread = nsnull;
@ -1193,6 +1210,15 @@ nsWaveDecoder::IsSeeking() const
return PR_FALSE;
}
PRBool
nsWaveDecoder::IsEnded() const
{
if (mPlaybackStateMachine) {
return mPlaybackStateMachine->IsEnded();
}
return mEnded;
}
PRUint64
nsWaveDecoder::GetBytesLoaded()
{