Bug 496456. When we seek to the end, we should only fire end stuff if we're not playing, otherwise playing should be responsible for ending. Set the current frame time at the end of the stream to the duration, if it's longer than our end time estimate, because the duration can include more than one frame-time's worth of audio. Also, don't replicate a frame of audio in DecodeToFrame when seeking. r=cpearce,sr=roc
Bug 496456. When we seek to the end, we should only fire end stuff if we're not playing, otherwise playing should be responsible for ending. Set the current frame time at the end of the stream to the duration, if it's longer than our end time estimate, because the duration can include more than one frame-time's worth of audio. Also, don't replicate a frame of audio in DecodeToFrame when seeking. r=cpearce,sr=roc
--- a/content/media/video/src/nsOggDecoder.cpp
+++ b/content/media/video/src/nsOggDecoder.cpp
@@ -1327,16 +1327,21 @@ void nsOggDecodeStateMachine::DecodeToFr
OggPlayErrorCode r;
mLastFrameTime = 0;
// Some of the audio data from previous frames actually belongs
// to this frame and later frames. So rescue that data and stuff
// it into the first frame.
float audioTime = 0;
nsTArray<float> audioData;
do {
+ if (frame) {
+ audioData.AppendElements(frame->mAudioData);
+ audioTime += frame->mAudioData.Length() /
+ (float)mAudioRate / (float)mAudioChannels;
+ }
do {
aMonitor.Exit();
r = DecodeFrame();
aMonitor.Enter();
} while (mState != DECODER_STATE_SHUTDOWN && r == E_OGGPLAY_TIMEOUT);
HandleDecodeErrors(r);
@@ -1344,20 +1349,16 @@ void nsOggDecodeStateMachine::DecodeToFr
break;
FrameData* nextFrame = NextFrame();
if (!nextFrame)
break;
delete frame;
frame = nextFrame;
-
- audioData.AppendElements(frame->mAudioData);
- audioTime += frame->mAudioData.Length() /
- (float)mAudioRate / (float)mAudioChannels;
} while (frame->mDecodedFrameTime < target);
if (mState == DECODER_STATE_SHUTDOWN) {
delete frame;
return;
}
NS_ASSERTION(frame != nsnull, "No frame after decode!");
@@ -1732,16 +1733,19 @@ nsresult nsOggDecodeStateMachine::Run()
StopPlayback();
if (mState != DECODER_STATE_COMPLETED)
continue;
}
// Set the right current time
mCurrentFrameTime += mCallbackPeriod;
+ if (mDuration >= 0) {
+ mCurrentFrameTime = PR_MAX(mCurrentFrameTime, mDuration / 1000.0);
+ }
mon.Exit();
nsCOMPtr<nsIRunnable> event =
NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, PlaybackEnded);
NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
mon.Enter();
while (mState == DECODER_STATE_COMPLETED) {
@@ -2377,18 +2381,18 @@ void nsOggDecoder::SeekingStoppedAtEnd()
{
nsAutoMonitor mon(mMonitor);
// An additional seek was requested while the current seek was
// in operation.
if (mRequestedSeekTime >= 0.0) {
ChangeState(PLAY_STATE_SEEKING);
} else {
- ChangeState(PLAY_STATE_ENDED);
- fireEnded = PR_TRUE;
+ fireEnded = mNextState != PLAY_STATE_PLAYING;
+ ChangeState(fireEnded ? PLAY_STATE_ENDED : mNextState);
}
}
if (mElement) {
UpdateReadyStateForData();
mElement->SeekCompleted();
if (fireEnded) {
mElement->PlaybackEnded();