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
authorChris Double <chris.double@double.co.nz>
Fri, 12 Jun 2009 14:14:28 +1200
changeset 29115 b3c4e464fed7f947dba1ebc720e843bfee457bad
parent 29114 7de9babda96b8a5d8365698ef6d8befe3aa952d5
child 29116 ddad1c32b194926e943eabe1ffd08929a0e6e782
push id7423
push userrocallahan@mozilla.com
push dateFri, 12 Jun 2009 02:16:07 +0000
treeherderautoland@b3c4e464fed7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce, roc
bugs496456
milestone1.9.2a1pre
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
content/media/video/src/nsOggDecoder.cpp
--- 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();