Bug 1300956. Part 1 - Add declarations of the state objects of MDSM. Also implement DecodeMetadataState.
MozReview-Commit-ID: BRyi409rmn5
--- 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.