Bug 1120017 - Make the DispatchDecodeTasksIfNeeded path handle DECODER_STATE_DECODING_FIRSTFRAME. r=cpearce
authorBobby Holley <bobbyholley@gmail.com>
Fri, 09 Jan 2015 17:20:58 -0800
changeset 223157 02ab5234c39e95266c536a9129ca56e87f9ea03e
parent 223156 84c65d67215fbd78274d13a07167cd069b1ab9ef
child 223158 203e26771e770b3d072e2e3f2e5bb7ca2ca93555
push id10769
push usercbook@mozilla.com
push dateMon, 12 Jan 2015 14:15:52 +0000
treeherderfx-team@0e9765732906 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1120017
milestone37.0a1
Bug 1120017 - Make the DispatchDecodeTasksIfNeeded path handle DECODER_STATE_DECODING_FIRSTFRAME. r=cpearce Once we make MP4Reader reject with WAITING_FOR_DATA, we end up with the following scenario: DecodeFirstFrame requests audio data, and then it gets rejected with WAITING_FOR_DATA. So OnAudioNotDecided does WaitForData, which eventually causes us to be called back in MediaDecoderStateMachine::WaitForDataResolved. That does DispatchDecodeTasksIfNeeded, which currently bails out of our state is DECODER_STATE_DECODING_FIRSTFRAME. The other way to do this would be to add a separate specialized path through all this asynchronicity for DECODER_STATE_DECODING_FIRSTFRAME. But it's not clear to me what that buys us.
dom/media/MediaDecoderStateMachine.cpp
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -571,16 +571,19 @@ MediaDecoderStateMachine::NeedToDecodeVi
          ((mState == DECODER_STATE_SEEKING && mDecodeToSeekTarget) ||
           (!mMinimizePreroll && !HaveEnoughDecodedVideo()));
 }
 
 bool
 MediaDecoderStateMachine::NeedToSkipToNextKeyframe()
 {
   AssertCurrentThreadInMonitor();
+  if (mState == DECODER_STATE_DECODING_FIRSTFRAME) {
+    return false;
+  }
   MOZ_ASSERT(mState == DECODER_STATE_DECODING ||
              mState == DECODER_STATE_BUFFERING ||
              mState == DECODER_STATE_SEEKING);
 
   // We are in seeking or buffering states, don't skip frame.
   if (!IsVideoDecoding() || mState == DECODER_STATE_BUFFERING ||
       mState == DECODER_STATE_SEEKING) {
     return false;
@@ -618,16 +621,17 @@ MediaDecoderStateMachine::DecodeVideo()
 {
   int64_t currentTime = 0;
   bool skipToNextKeyFrame = false;
   {
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
     NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
 
     if (mState != DECODER_STATE_DECODING &&
+        mState != DECODER_STATE_DECODING_FIRSTFRAME &&
         mState != DECODER_STATE_BUFFERING &&
         mState != DECODER_STATE_SEEKING) {
       mVideoRequestStatus = RequestStatus::Idle;
       DispatchDecodeTasksIfNeeded();
       return;
     }
 
     skipToNextKeyFrame = NeedToSkipToNextKeyframe();
@@ -667,16 +671,17 @@ MediaDecoderStateMachine::NeedToDecodeAu
 void
 MediaDecoderStateMachine::DecodeAudio()
 {
   {
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
     NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
 
     if (mState != DECODER_STATE_DECODING &&
+        mState != DECODER_STATE_DECODING_FIRSTFRAME &&
         mState != DECODER_STATE_BUFFERING &&
         mState != DECODER_STATE_SEEKING) {
       mAudioRequestStatus = RequestStatus::Idle;
       DispatchDecodeTasksIfNeeded();
       mon.NotifyAll();
       return;
     }
   }
@@ -1772,16 +1777,17 @@ MediaDecoderStateMachine::SetReaderIdle(
 }
 
 void
 MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
 {
   AssertCurrentThreadInMonitor();
 
   if (mState != DECODER_STATE_DECODING &&
+      mState != DECODER_STATE_DECODING_FIRSTFRAME &&
       mState != DECODER_STATE_BUFFERING &&
       mState != DECODER_STATE_SEEKING) {
     return;
   }
 
   if (mState == DECODER_STATE_DECODING && mDecodingFrozenAtStateDecoding) {
     DECODER_LOG("DispatchDecodeTasksIfNeeded return due to "
                 "mFreezeDecodingAtStateDecoding");
@@ -1887,17 +1893,17 @@ MediaDecoderStateMachine::EnsureAudioDec
 
   SAMPLE_LOG("EnsureAudioDecodeTaskQueued isDecoding=%d status=%d",
               IsAudioDecoding(), mAudioRequestStatus);
 
   if (mState >= DECODER_STATE_COMPLETED) {
     return NS_OK;
   }
 
-  MOZ_ASSERT(mState > DECODER_STATE_DECODING_FIRSTFRAME);
+  MOZ_ASSERT(mState >= DECODER_STATE_DECODING_FIRSTFRAME);
 
   if (IsAudioDecoding() && mAudioRequestStatus == RequestStatus::Idle && !mWaitingForDecoderSeek) {
     RefPtr<nsIRunnable> task(
       NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DecodeAudio));
     nsresult rv = DecodeTaskQueue()->Dispatch(task);
     if (NS_SUCCEEDED(rv)) {
       mAudioRequestStatus = RequestStatus::Pending;
     } else {
@@ -1932,17 +1938,17 @@ MediaDecoderStateMachine::EnsureVideoDec
 
   NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(),
                "Should be on state machine or decode thread.");
 
   if (mState >= DECODER_STATE_COMPLETED) {
     return NS_OK;
   }
 
-  MOZ_ASSERT(mState > DECODER_STATE_DECODING_FIRSTFRAME);
+  MOZ_ASSERT(mState >= DECODER_STATE_DECODING_FIRSTFRAME);
 
   if (IsVideoDecoding() && mVideoRequestStatus == RequestStatus::Idle && !mWaitingForDecoderSeek) {
     RefPtr<nsIRunnable> task(
       NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DecodeVideo));
     nsresult rv = DecodeTaskQueue()->Dispatch(task);
     if (NS_SUCCEEDED(rv)) {
       mVideoRequestStatus = RequestStatus::Pending;
     } else {