Bug 1120017 - Make the DispatchDecodeTasksIfNeeded path handle DECODER_STATE_DECODING_FIRSTFRAME. r=cpearce, a=sledru
authorBobby Holley <bobbyholley@gmail.com>
Fri, 09 Jan 2015 17:20:58 -0800
changeset 242860 aa8cdb057186
parent 242859 201fee3158c1
child 242861 60f6890d84cf
push id4322
push userryanvm@gmail.com
push date2015-01-14 15:18 +0000
treeherdermozilla-beta@82cce51fb174 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce, sledru
bugs1120017
milestone36.0
Bug 1120017 - Make the DispatchDecodeTasksIfNeeded path handle DECODER_STATE_DECODING_FIRSTFRAME. r=cpearce, a=sledru 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
@@ -576,16 +576,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;
@@ -623,16 +626,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;
     }
 
     // We don't want to consider skipping to the next keyframe if we've
@@ -683,16 +687,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;
     }
 
@@ -1734,16 +1739,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");
@@ -1849,17 +1855,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 {
@@ -1894,17 +1900,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 {