Bug 634747 - Set MediaQueue's to Finished() when we reach end of stream while decoding after seeking and while finding first frame. r=kinetik
authorChris Pearce <cpearce@mozilla.com>
Tue, 25 Feb 2014 18:45:03 +1300
changeset 170677 63efb2b87c921f5897a8e7e5d802dd66124e9d21
parent 170676 4d1674345259f9bbbe30d19dab47eb06e657412e
child 170678 ac32ace7a22e09be970836e581b2c67f9263d655
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewerskinetik
bugs634747
milestone30.0a1
Bug 634747 - Set MediaQueue's to Finished() when we reach end of stream while decoding after seeking and while finding first frame. r=kinetik
content/media/MediaDecoderReader.cpp
content/media/MediaDecoderStateMachine.cpp
content/media/test/test_bug495300.html
--- a/content/media/MediaDecoderReader.cpp
+++ b/content/media/MediaDecoderReader.cpp
@@ -76,32 +76,38 @@ VideoData* MediaDecoderReader::DecodeToF
       ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
       if (mDecoder->IsShutdown()) {
         return nullptr;
       }
     }
     bool keyframeSkip = false;
     eof = !DecodeVideoFrame(keyframeSkip, 0);
   }
+  if (eof) {
+    VideoQueue().Finish();
+  }
   VideoData* d = nullptr;
   return (d = VideoQueue().PeekFront()) ? d : nullptr;
 }
 
 AudioData* MediaDecoderReader::DecodeToFirstAudioData()
 {
   bool eof = false;
   while (!eof && AudioQueue().GetSize() == 0) {
     {
       ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
       if (mDecoder->IsShutdown()) {
         return nullptr;
       }
     }
     eof = !DecodeAudioData();
   }
+  if (eof) {
+    AudioQueue().Finish();
+  }
   AudioData* d = nullptr;
   return (d = AudioQueue().PeekFront()) ? d : nullptr;
 }
 
 VideoData* MediaDecoderReader::FindStartTime(int64_t& aOutStartTime)
 {
   NS_ASSERTION(mDecoder->OnStateMachineThread() || mDecoder->OnDecodeThread(),
                "Should be on state machine or decode thread.");
@@ -150,21 +156,22 @@ nsresult MediaDecoderReader::DecodeToTar
         eof = !DecodeVideoFrame(skip, 0);
         {
           ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
           if (mDecoder->IsShutdown()) {
             return NS_ERROR_FAILURE;
           }
         }
       }
-      if (VideoQueue().GetSize() == 0) {
+      if (eof) {
         // Hit end of file, we want to display the last frame of the video.
         if (video) {
           VideoQueue().PushFront(video.forget());
         }
+        VideoQueue().Finish();
         break;
       }
       video = VideoQueue().PeekFront();
       // If the frame end time is less than the seek target, we won't want
       // to display this frame after the seek, so discard it.
       if (video && video->GetEndTime() <= aTarget) {
         if (startTime == -1) {
           startTime = video->mTime;
@@ -193,18 +200,20 @@ nsresult MediaDecoderReader::DecodeToTar
         {
           ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
           if (mDecoder->IsShutdown()) {
             return NS_ERROR_FAILURE;
           }
         }
       }
       const AudioData* audio = AudioQueue().PeekFront();
-      if (!audio)
+      if (!audio || eof) {
+        AudioQueue().Finish();
         break;
+      }
       CheckedInt64 startFrame = UsecsToFrames(audio->mTime, mInfo.mAudio.mRate);
       CheckedInt64 targetFrame = UsecsToFrames(aTarget, mInfo.mAudio.mRate);
       if (!startFrame.isValid() || !targetFrame.isValid()) {
         return NS_ERROR_FAILURE;
       }
       if (startFrame.value() + audio->mFrames <= targetFrame.value()) {
         // Our seek target lies after the frames in this AudioData. Pop it
         // off the queue, and keep decoding forwards.
--- a/content/media/MediaDecoderStateMachine.cpp
+++ b/content/media/MediaDecoderStateMachine.cpp
@@ -1794,27 +1794,29 @@ void MediaDecoderStateMachine::DecodeSee
       // while we seek, since the seek reads, which could block on I/O.
       res = mReader->Seek(seekTime,
                           mStartTime,
                           mEndTime,
                           mediaTime);
     }
     if (NS_SUCCEEDED(res)) {
       AudioData* audio = HasAudio() ? mReader->AudioQueue().PeekFront() : nullptr;
-      NS_ASSERTION(!audio || (audio->mTime <= seekTime &&
-                              seekTime <= audio->mTime + audio->mDuration),
-                    "Seek target should lie inside the first audio block after seek");
+      MOZ_ASSERT(!audio ||
+                 (audio->mTime <= seekTime &&
+                  seekTime <= audio->mTime + audio->mDuration) ||
+                 mReader->AudioQueue().IsFinished(),
+                 "Seek target should lie inside the first audio block after seek");
       int64_t startTime = (audio && audio->mTime < seekTime) ? audio->mTime : seekTime;
       mAudioStartTime = startTime;
       mPlayDuration = startTime - mStartTime;
       if (HasVideo()) {
         VideoData* video = mReader->VideoQueue().PeekFront();
         if (video) {
-          NS_ASSERTION((video->mTime <= seekTime && seekTime <= video->GetEndTime()) ||
-                        mReader->VideoQueue().IsFinished(),
+          MOZ_ASSERT((video->mTime <= seekTime && seekTime <= video->GetEndTime()) ||
+                     mReader->VideoQueue().IsFinished(),
             "Seek target should lie inside the first frame after seek, unless it's the last frame.");
           {
             ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
             RenderVideoFrame(video, TimeStamp::Now());
           }
           nsCOMPtr<nsIRunnable> event =
             NS_NewRunnableMethod(mDecoder, &MediaDecoder::Invalidate);
           NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
--- a/content/media/test/test_bug495300.html
+++ b/content/media/test/test_bug495300.html
@@ -10,21 +10,16 @@ https://bugzilla.mozilla.org/show_bug.cg
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <script type="text/javascript" src="manifest.js"></script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=495300">Mozilla Bug 495300</a>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
-if (!navigator.platform.startsWith("Mac")) {
-  // not Mac
-  SimpleTest.expectAssertions(0, 2);
-}
-
 var manager = new MediaTestManager;
 
 function filename(uri) {
   return uri.substr(uri.lastIndexOf("/")+1);
 }
 
 function mediaEnded(event) {
   ok(true, "Got expected 'ended' event: " + filename(event.target.currentSrc));