Bug 1300479. Part 3 - extract RunStateMachine() cases to its own function. draft
authorJW Wang <jwwang@mozilla.com>
Mon, 05 Sep 2016 15:48:37 +0800
changeset 410080 a2590cddffbf76f71453a5c538d30b7639cb03ce
parent 410079 8872eb2df1720504a5386e2a559605a9120880e2
child 410895 ac7974c6096a925c70863c843e6cf3b215b1d6e3
push id28635
push userjwwang@mozilla.com
push dateTue, 06 Sep 2016 05:20:34 +0000
bugs1300479
milestone51.0a1
Bug 1300479. Part 3 - extract RunStateMachine() cases to its own function. MozReview-Commit-ID: LNLu7X8VD3s
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2270,127 +2270,140 @@ MediaDecoderStateMachine::FinishShutdown
 void
 MediaDecoderStateMachine::RunStateMachine()
 {
   MOZ_ASSERT(OnTaskQueue());
 
   mDelayedScheduler.Reset(); // Must happen on state machine task queue.
   mDispatchedStateMachine = false;
 
-  MediaResource* resource = mResource;
-  NS_ENSURE_TRUE_VOID(resource);
-
   switch (mState) {
-    case DECODER_STATE_DECODING: {
-      if (mPlayState != MediaDecoder::PLAY_STATE_PLAYING && IsPlaying())
-      {
-        // We're playing, but the element/decoder is in paused state. Stop
-        // playing!
-        StopPlayback();
-      }
-
-      // Start playback if necessary so that the clock can be properly queried.
-      MaybeStartPlayback();
-
-      UpdatePlaybackPositionPeriodically();
-      NS_ASSERTION(!IsPlaying() ||
-                   IsStateMachineScheduled(),
-                   "Must have timer scheduled");
-      MaybeStartBuffering();
+    case DECODER_STATE_DECODING:
+      StepDecoding();
+      return;
+    case DECODER_STATE_BUFFERING:
+      StepBuffering();
+      return;
+    case DECODER_STATE_COMPLETED:
+      StepCompleted();
+      return;
+    default:
+      return;
+  }
+}
+
+void
+MediaDecoderStateMachine::StepDecoding()
+{
+  MOZ_ASSERT(OnTaskQueue());
+
+  if (mPlayState != MediaDecoder::PLAY_STATE_PLAYING && IsPlaying()) {
+    // We're playing, but the element/decoder is in paused state. Stop
+    // playing!
+    StopPlayback();
+  }
+
+  // Start playback if necessary so that the clock can be properly queried.
+  MaybeStartPlayback();
+
+  UpdatePlaybackPositionPeriodically();
+
+  NS_ASSERTION(!IsPlaying() ||
+               IsStateMachineScheduled(),
+               "Must have timer scheduled");
+
+  MaybeStartBuffering();
+}
+
+void
+MediaDecoderStateMachine::StepBuffering()
+{
+  MOZ_ASSERT(OnTaskQueue());
+
+  TimeStamp now = TimeStamp::Now();
+  NS_ASSERTION(!mBufferingStart.IsNull(), "Must know buffering start time.");
+
+  // With buffering heuristics we will remain in the buffering state if
+  // we've not decoded enough data to begin playback, or if we've not
+  // downloaded a reasonable amount of data inside our buffering time.
+  if (mReader->UseBufferingHeuristics()) {
+    TimeDuration elapsed = now - mBufferingStart;
+    bool isLiveStream = mResource->IsLiveStream();
+    if ((isLiveStream || !CanPlayThrough()) &&
+        elapsed < TimeDuration::FromSeconds(mBufferingWait * mPlaybackRate) &&
+        (mQuickBuffering ? HasLowDecodedData(mQuickBufferingLowDataThresholdUsecs)
+                         : HasLowUndecodedData(mBufferingWait * USECS_PER_S)) &&
+        mResource->IsExpectingMoreData()) {
+      DECODER_LOG("Buffering: wait %ds, timeout in %.3lfs %s",
+                  mBufferingWait, mBufferingWait - elapsed.ToSeconds(),
+                  (mQuickBuffering ? "(quick exit)" : ""));
+      ScheduleStateMachineIn(USECS_PER_S);
       return;
     }
-
-    case DECODER_STATE_BUFFERING: {
-      TimeStamp now = TimeStamp::Now();
-      NS_ASSERTION(!mBufferingStart.IsNull(), "Must know buffering start time.");
-
-      // With buffering heuristics we will remain in the buffering state if
-      // we've not decoded enough data to begin playback, or if we've not
-      // downloaded a reasonable amount of data inside our buffering time.
-      if (mReader->UseBufferingHeuristics()) {
-        TimeDuration elapsed = now - mBufferingStart;
-        bool isLiveStream = resource->IsLiveStream();
-        if ((isLiveStream || !CanPlayThrough()) &&
-              elapsed < TimeDuration::FromSeconds(mBufferingWait * mPlaybackRate) &&
-              (mQuickBuffering ? HasLowDecodedData(mQuickBufferingLowDataThresholdUsecs)
-                               : HasLowUndecodedData(mBufferingWait * USECS_PER_S)) &&
-              mResource->IsExpectingMoreData())
-        {
-          DECODER_LOG("Buffering: wait %ds, timeout in %.3lfs %s",
-                      mBufferingWait, mBufferingWait - elapsed.ToSeconds(),
-                      (mQuickBuffering ? "(quick exit)" : ""));
-          ScheduleStateMachineIn(USECS_PER_S);
-          return;
-        }
-      } else if (OutOfDecodedAudio() || OutOfDecodedVideo()) {
-        MOZ_ASSERT(mReader->IsWaitForDataSupported(),
-                   "Don't yet have a strategy for non-heuristic + non-WaitForData");
-        DispatchDecodeTasksIfNeeded();
-        MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedAudio(), mReader->IsRequestingAudioData() || mReader->IsWaitingAudioData());
-        MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedVideo(), mReader->IsRequestingVideoData() || mReader->IsWaitingVideoData());
-        DECODER_LOG("In buffering mode, waiting to be notified: outOfAudio: %d, "
-                    "mAudioStatus: %s, outOfVideo: %d, mVideoStatus: %s",
-                    OutOfDecodedAudio(), AudioRequestStatus(),
-                    OutOfDecodedVideo(), VideoRequestStatus());
-        return;
-      }
-
-      DECODER_LOG("Changed state from BUFFERING to DECODING");
-      DECODER_LOG("Buffered for %.3lfs", (now - mBufferingStart).ToSeconds());
-      SetState(DECODER_STATE_DECODING);
-
-      NS_ASSERTION(IsStateMachineScheduled(), "Must have timer scheduled");
-      return;
-    }
-
-    case DECODER_STATE_COMPLETED: {
-      if (mPlayState != MediaDecoder::PLAY_STATE_PLAYING && IsPlaying()) {
-        StopPlayback();
-      }
-      // Play the remaining media. We want to run AdvanceFrame() at least
-      // once to ensure the current playback position is advanced to the
-      // end of the media, and so that we update the readyState.
-      if ((HasVideo() && !mVideoCompleted) ||
-          (HasAudio() && !mAudioCompleted)) {
-        // Start playback if necessary to play the remaining media.
-        MaybeStartPlayback();
-        UpdatePlaybackPositionPeriodically();
-        NS_ASSERTION(!IsPlaying() ||
-                     IsStateMachineScheduled(),
-                     "Must have timer scheduled");
-        return;
-      }
-
-      // StopPlayback in order to reset the IsPlaying() state so audio
-      // is restarted correctly.
-      StopPlayback();
-
-      if (mPlayState == MediaDecoder::PLAY_STATE_PLAYING &&
-          !mSentPlaybackEndedEvent)
-      {
-        int64_t clockTime = std::max(AudioEndTime(), VideoEndTime());
-        clockTime = std::max(int64_t(0), std::max(clockTime, Duration().ToMicroseconds()));
-        UpdatePlaybackPosition(clockTime);
-
-        // Ensure readyState is updated before firing the 'ended' event.
-        UpdateNextFrameStatus();
-
-        mOnPlaybackEvent.Notify(MediaEventType::PlaybackEnded);
-
-        mSentPlaybackEndedEvent = true;
-
-        // MediaSink::GetEndTime() must be called before stopping playback.
-        StopMediaSink();
-      }
-
-      return;
-    }
-
-    default:
-      return;
+  } else if (OutOfDecodedAudio() || OutOfDecodedVideo()) {
+    MOZ_ASSERT(mReader->IsWaitForDataSupported(),
+               "Don't yet have a strategy for non-heuristic + non-WaitForData");
+    DispatchDecodeTasksIfNeeded();
+    MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedAudio(), mReader->IsRequestingAudioData() || mReader->IsWaitingAudioData());
+    MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedVideo(), mReader->IsRequestingVideoData() || mReader->IsWaitingVideoData());
+    DECODER_LOG("In buffering mode, waiting to be notified: outOfAudio: %d, "
+                "mAudioStatus: %s, outOfVideo: %d, mVideoStatus: %s",
+                OutOfDecodedAudio(), AudioRequestStatus(),
+                OutOfDecodedVideo(), VideoRequestStatus());
+    return;
+  }
+
+  DECODER_LOG("Changed state from BUFFERING to DECODING");
+  DECODER_LOG("Buffered for %.3lfs", (now - mBufferingStart).ToSeconds());
+  SetState(DECODER_STATE_DECODING);
+  NS_ASSERTION(IsStateMachineScheduled(), "Must have timer scheduled");
+}
+
+void
+MediaDecoderStateMachine::StepCompleted()
+{
+  MOZ_ASSERT(OnTaskQueue());
+
+  if (mPlayState != MediaDecoder::PLAY_STATE_PLAYING && IsPlaying()) {
+    StopPlayback();
+  }
+
+  // Play the remaining media. We want to run AdvanceFrame() at least
+  // once to ensure the current playback position is advanced to the
+  // end of the media, and so that we update the readyState.
+  if ((HasVideo() && !mVideoCompleted) ||
+      (HasAudio() && !mAudioCompleted)) {
+    // Start playback if necessary to play the remaining media.
+    MaybeStartPlayback();
+    UpdatePlaybackPositionPeriodically();
+    NS_ASSERTION(!IsPlaying() ||
+                 IsStateMachineScheduled(),
+                 "Must have timer scheduled");
+    return;
+  }
+
+  // StopPlayback in order to reset the IsPlaying() state so audio
+  // is restarted correctly.
+  StopPlayback();
+
+  if (mPlayState == MediaDecoder::PLAY_STATE_PLAYING &&
+      !mSentPlaybackEndedEvent) {
+    int64_t clockTime = std::max(AudioEndTime(), VideoEndTime());
+    clockTime = std::max(int64_t(0), std::max(clockTime, Duration().ToMicroseconds()));
+    UpdatePlaybackPosition(clockTime);
+
+    // Ensure readyState is updated before firing the 'ended' event.
+    UpdateNextFrameStatus();
+
+    mOnPlaybackEvent.Notify(MediaEventType::PlaybackEnded);
+
+    mSentPlaybackEndedEvent = true;
+
+    // MediaSink::GetEndTime() must be called before stopping playback.
+    StopMediaSink();
   }
 }
 
 void
 MediaDecoderStateMachine::Reset(TrackSet aTracks)
 {
   MOZ_ASSERT(OnTaskQueue());
   DECODER_LOG("MediaDecoderStateMachine::Reset");
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -551,16 +551,22 @@ protected:
   // Completes the seek operation, moves onto the next appropriate state.
   void SeekCompleted();
 
   // Queries our state to see whether the decode has finished for all streams.
   bool CheckIfDecodeComplete();
 
   // Performs one "cycle" of the state machine.
   void RunStateMachine();
+  // Perform one cycle of the DECODING state.
+  void StepDecoding();
+  // Perform one cycle of the BUFFERING state.
+  void StepBuffering();
+  // Perform one cycle of the COMPLETED state.
+  void StepCompleted();
 
   bool IsStateMachineScheduled() const;
 
   // These return true if the respective stream's decode has not yet reached
   // the end of stream.
   bool IsAudioDecoding();
   bool IsVideoDecoding();