Bug 1306186. Part 5 - add MaybeStopPrerolling() to check if we can stop prerolling. r=kikuo
authorJW Wang <jwwang@mozilla.com>
Mon, 03 Oct 2016 14:04:27 +0800
changeset 316177 0621d50a7455c7200988e13d48ff9a0a0aadece2
parent 316176 b19f904b612736e56b8a02eea687c53b002de811
child 316178 73e1dac8253d1c57cef65bd88f923738b7b84de0
push id30765
push userphilringnalda@gmail.com
push dateTue, 04 Oct 2016 03:06:46 +0000
treeherdermozilla-central@adb484f84dec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskikuo
bugs1306186
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1306186. Part 5 - add MaybeStopPrerolling() to check if we can stop prerolling. r=kikuo MozReview-Commit-ID: 15Y5e4DUr4S
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -1039,20 +1039,17 @@ MediaDecoderStateMachine::OnAudioDecoded
     case DECODER_STATE_DECODING_FIRSTFRAME: {
       Push(audio, MediaData::AUDIO_DATA);
       MaybeFinishDecodeFirstFrame();
       return;
     }
 
     case DECODER_STATE_DECODING: {
       Push(audio, MediaData::AUDIO_DATA);
-      if (mIsPrerolling) {
-        // Schedule next cycle to check if we can stop prerolling.
-        ScheduleStateMachine();
-      }
+      MaybeStopPrerolling();
       return;
     }
 
     default: {
       // Ignore other cases.
       return;
     }
   }
@@ -1118,22 +1115,17 @@ MediaDecoderStateMachine::OnNotDecoded(M
   }
 
   // If the decoder is waiting for data, we tell it to call us back when the
   // data arrives.
   if (aError == NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA) {
     MOZ_ASSERT(mReader->IsWaitForDataSupported(),
                "Readers that send WAITING_FOR_DATA need to implement WaitForData");
     mReader->WaitForData(aType);
-
-    if (mIsPrerolling) {
-      // Schedule next cycle to stop prerolling so we can play the frames we've
-      // decoded so far.
-      ScheduleStateMachine();
-    }
+    MaybeStopPrerolling();
     return;
   }
 
   if (aError == NS_ERROR_DOM_MEDIA_CANCELED) {
     if (isAudio) {
       EnsureAudioDecodeTaskQueued();
     } else {
       EnsureVideoDecodeTaskQueued();
@@ -1150,21 +1142,17 @@ MediaDecoderStateMachine::OnNotDecoded(M
   // This is an EOS. Finish off the queue, and then handle things based on our
   // state.
   if (isAudio) {
     AudioQueue().Finish();
   } else {
     VideoQueue().Finish();
   }
 
-  if (mIsPrerolling) {
-    // No more data to decode. Schedule next cycle to stop prerolling
-    // and start playback.
-    ScheduleStateMachine();
-  }
+  MaybeStopPrerolling();
 
   switch (mState) {
     case DECODER_STATE_DECODING_FIRSTFRAME:
       MaybeFinishDecodeFirstFrame();
       return;
     case DECODER_STATE_BUFFERING:
     case DECODER_STATE_DECODING: {
       if (CheckIfDecodeComplete()) {
@@ -1230,20 +1218,17 @@ MediaDecoderStateMachine::OnVideoDecoded
     case DECODER_STATE_DECODING_FIRSTFRAME: {
       Push(video, MediaData::VIDEO_DATA);
       MaybeFinishDecodeFirstFrame();
       return;
     }
 
     case DECODER_STATE_DECODING: {
       Push(video, MediaData::VIDEO_DATA);
-      if (mIsPrerolling) {
-        // Schedule next cycle to check if we can stop prerolling.
-        ScheduleStateMachine();
-      }
+      MaybeStopPrerolling();
 
       // For non async readers, if the requested video sample was slow to
       // arrive, increase the amount of audio we buffer to ensure that we
       // don't run out of audio. This is unnecessary for async readers,
       // since they decode audio and video on different threads so they
       // are unlikely to run out of decoded audio.
       if (mReader->IsAsync()) {
         return;
@@ -1393,35 +1378,42 @@ void MediaDecoderStateMachine::StopPlayb
   if (IsPlaying()) {
     mMediaSink->SetPlaying(false);
     MOZ_ASSERT(!IsPlaying());
   }
 
   DispatchDecodeTasksIfNeeded();
 }
 
+void
+MediaDecoderStateMachine::MaybeStopPrerolling()
+{
+  MOZ_ASSERT(OnTaskQueue());
+  if (mIsPrerolling &&
+      (DonePrerollingAudio() || mReader->IsWaitingAudioData()) &&
+      (DonePrerollingVideo() || mReader->IsWaitingVideoData())) {
+    mIsPrerolling = false;
+    // Check if we can start playback.
+    ScheduleStateMachine();
+  }
+}
+
 void MediaDecoderStateMachine::MaybeStartPlayback()
 {
   MOZ_ASSERT(OnTaskQueue());
   // Should try to start playback only after decoding first frames.
   MOZ_ASSERT(mSentFirstFrameLoadedEvent);
   MOZ_ASSERT(mState == DECODER_STATE_DECODING ||
              mState == DECODER_STATE_COMPLETED);
 
   if (IsPlaying()) {
     // Logging this case is really spammy - don't do it.
     return;
   }
 
-  if (mIsPrerolling &&
-      (DonePrerollingAudio() || mReader->IsWaitingAudioData()) &&
-      (DonePrerollingVideo() || mReader->IsWaitingVideoData())) {
-    mIsPrerolling = false;
-  }
-
   bool playStatePermits = mPlayState == MediaDecoder::PLAY_STATE_PLAYING;
   if (!playStatePermits || mIsPrerolling || mAudioOffloading) {
     DECODER_LOG("Not starting playback [playStatePermits: %d, "
                 "mIsPrerolling: %d, mAudioOffloading: %d]",
                 playStatePermits, mIsPrerolling, mAudioOffloading);
     return;
   }
 
@@ -2920,20 +2912,17 @@ MediaDecoderStateMachine::SetAudioCaptur
   ScheduleStateMachine();
 
   // Don't buffer as much when audio is captured because we don't need to worry
   // about high latency audio devices.
   mAmpleAudioThresholdUsecs = mAudioCaptured ?
                               detail::AMPLE_AUDIO_USECS / 2 :
                               detail::AMPLE_AUDIO_USECS;
 
-  if (mIsPrerolling) {
-    // Schedule next cycle to check if we can stop prerolling.
-    ScheduleStateMachine();
-  }
+  MaybeStopPrerolling();
 }
 
 uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const
 {
   MOZ_ASSERT(OnTaskQueue());
   return (mReader->IsAsync() && mReader->VideoIsHardwareAccelerated())
     ? std::max<uint32_t>(sVideoQueueHWAccelSize, MIN_VIDEO_QUEUE_SIZE)
     : std::max<uint32_t>(sVideoQueueDefaultSize, MIN_VIDEO_QUEUE_SIZE);
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -725,16 +725,18 @@ private:
   {
     MOZ_ASSERT(OnTaskQueue());
     return !mIsVisible ||
         !IsVideoDecoding() ||
         static_cast<uint32_t>(VideoQueue().GetSize()) >=
             VideoPrerollFrames() * mPlaybackRate + 1;
   }
 
+  void MaybeStopPrerolling();
+
   // When we start decoding (either for the first time, or after a pause)
   // we may be low on decoded data. We don't want our "low data" logic to
   // kick in and decide that we're low on decoded data because the download
   // can't keep up with the decode, and cause us to pause playback. So we
   // have a "preroll" stage, where we ignore the results of our "low data"
   // logic during the first few frames of our decode. This occurs during
   // playback.
   bool mIsPrerolling = false;