Bug 1300956. Part 1 - Add declarations of the state objects of MDSM. Also implement DecodeMetadataState. r=kaku
authorJW Wang <jwwang@mozilla.com>
Tue, 06 Sep 2016 11:01:57 +0800
changeset 354469 b867d9ef5e6417e26085eb19654b9e8c7ca0a512
parent 354402 afb8c6617510e7a8a0132e8412ca1aa8c049933a
child 354470 782c54cd404f894cdd1f101fb5a7b1648f29baa9
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskaku
bugs1300956
milestone51.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 1300956. Part 1 - Add declarations of the state objects of MDSM. Also implement DecodeMetadataState. r=kaku MozReview-Commit-ID: BRyi409rmn5
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -199,16 +199,51 @@ static void InitVideoQueuePrefs() {
 // decoding is suspended.
 static TimeDuration
 SuspendBackgroundVideoDelay()
 {
   return TimeDuration::FromMilliseconds(
     MediaPrefs::MDSMSuspendBackgroundVideoDelay());
 }
 
+class MediaDecoderStateMachine::StateObject
+{
+public:
+  virtual ~StateObject() {}
+  virtual void Enter() {}; // Entry action.
+  virtual void Exit() {};  // Exit action.
+  virtual void Step() {}   // Perform a 'cycle' of this state object.
+  virtual State GetState() const = 0;
+
+protected:
+  using Master = MediaDecoderStateMachine;
+  explicit StateObject(Master* aPtr) : mMaster(aPtr) {}
+
+  // Take a raw pointer in order not to change the life cycle of MDSM.
+  // It is guaranteed to be valid by MDSM.
+  Master* mMaster;
+};
+
+class MediaDecoderStateMachine::DecodeMetadataState
+  : public MediaDecoderStateMachine::StateObject
+{
+public:
+  explicit DecodeMetadataState(Master* aPtr) : StateObject(aPtr) {}
+
+  void Enter() override
+  {
+    mMaster->ReadMetadata();
+  }
+
+  State GetState() const override
+  {
+    return DECODER_STATE_DECODING_METADATA;
+  }
+};
+
 #define INIT_WATCHABLE(name, val) \
   name(val, "MediaDecoderStateMachine::" #name)
 #define INIT_MIRROR(name, val) \
   name(mTaskQueue, val, "MediaDecoderStateMachine::" #name " (Mirror)")
 #define INIT_CANONICAL(name, val) \
   name(mTaskQueue, val, "MediaDecoderStateMachine::" #name " (Canonical)")
 
 MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
@@ -218,16 +253,17 @@ MediaDecoderStateMachine::MediaDecoderSt
   mVideoFrameContainer(aDecoder->GetVideoFrameContainer()),
   mAudioChannel(aDecoder->GetAudioChannel()),
   mTaskQueue(new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK),
                            /* aSupportsTailDispatch = */ true)),
   mWatchManager(this, mTaskQueue),
   mDispatchedStateMachine(false),
   mDelayedScheduler(mTaskQueue),
   INIT_WATCHABLE(mState, DECODER_STATE_DECODING_METADATA),
+  mStateObj(new DecodeMetadataState(this)),
   mCurrentFrameID(0),
   INIT_WATCHABLE(mObservedDuration, TimeUnit()),
   mFragmentEndTime(-1),
   mReader(new MediaDecoderReaderWrapper(mTaskQueue, aReader)),
   mDecodedAudioEndTime(0),
   mDecodedVideoEndTime(0),
   mPlaybackRate(1.0),
   mLowAudioThresholdUsecs(detail::LOW_AUDIO_USECS),
@@ -1060,43 +1096,64 @@ MediaDecoderStateMachine::SetState(State
   if (mState == aState) {
     return;
   }
 
   DECODER_LOG("MDSM state: %s -> %s", ToStateStr(), ToStateStr(aState));
 
   ExitState();
   mState = aState;
+
+  switch (mState) {
+    case DECODER_STATE_DECODING_METADATA:
+      mStateObj = MakeUnique<DecodeMetadataState>(this);
+      break;
+    default:
+      mStateObj = nullptr;
+      break;
+  }
+
   EnterState();
 }
 
 void
 MediaDecoderStateMachine::ExitState()
 {
   MOZ_ASSERT(OnTaskQueue());
+
+  if (mStateObj) {
+    MOZ_ASSERT(mState == mStateObj->GetState());
+    mStateObj->Exit();
+    return;
+  }
+
   switch (mState) {
     case DECODER_STATE_COMPLETED:
       mSentPlaybackEndedEvent = false;
       break;
     case DECODER_STATE_SHUTDOWN:
       MOZ_DIAGNOSTIC_ASSERT(false, "Shouldn't escape the SHUTDOWN state.");
       break;
     default:
       break;
   }
 }
 
 void
 MediaDecoderStateMachine::EnterState()
 {
   MOZ_ASSERT(OnTaskQueue());
+
+  if (mStateObj) {
+    MOZ_ASSERT(mState == mStateObj->GetState());
+    mStateObj->Enter();
+    return;
+  }
+
   switch (mState) {
-    case DECODER_STATE_DECODING_METADATA:
-      ReadMetadata();
-      break;
     case DECODER_STATE_DORMANT:
       DiscardSeekTaskIfExist();
       if (IsPlaying()) {
         StopPlayback();
       }
       Reset();
       mReader->ReleaseResources();
       break;
@@ -2258,16 +2315,21 @@ MediaDecoderStateMachine::FinishShutdown
 void
 MediaDecoderStateMachine::RunStateMachine()
 {
   MOZ_ASSERT(OnTaskQueue());
 
   mDelayedScheduler.Reset(); // Must happen on state machine task queue.
   mDispatchedStateMachine = false;
 
+  if (mStateObj) {
+    mStateObj->Step();
+    return;
+  }
+
   switch (mState) {
     case DECODER_STATE_DECODING:
       StepDecoding();
       return;
     case DECODER_STATE_BUFFERING:
       StepBuffering();
       return;
     case DECODER_STATE_COMPLETED:
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -246,16 +246,27 @@ public:
   MediaEventSource<MediaEventType>&
   OnPlaybackEvent() { return mOnPlaybackEvent; }
 
   size_t SizeOfVideoQueue() const;
 
   size_t SizeOfAudioQueue() const;
 
 private:
+  class StateObject;
+  class DecodeMetadataState;
+  class WaitForCDMState;
+  class DormantState;
+  class DecodingFirstFrameState;
+  class DecodingState;
+  class SeekingState;
+  class BufferingState;
+  class CompletedState;
+  class ShutdownState;
+
   static const char* ToStateStr(State aState);
   const char* ToStateStr();
 
   // Functions used by assertions to ensure we're calling things
   // on the appropriate threads.
   bool OnTaskQueue() const;
 
   // Initialization that needs to happen on the task queue. This is the first
@@ -598,16 +609,18 @@ private:
   // Queue of video frames. This queue is threadsafe, and is accessed from
   // the decoder, state machine, and main threads.
   MediaQueue<MediaData> mVideoQueue;
 
   // The decoder monitor must be obtained before modifying this state.
   // Accessed on state machine, audio, main, and AV thread.
   Watchable<State> mState;
 
+  UniquePtr<StateObject> mStateObj;
+
   // Time that buffering started. Used for buffering timeout and only
   // accessed on the state machine thread. This is null while we're not
   // buffering.
   TimeStamp mBufferingStart;
 
   media::TimeUnit Duration() const { MOZ_ASSERT(OnTaskQueue()); return mDuration.Ref().ref(); }
 
   // Recomputes the canonical duration from various sources.