Bug 1311901 - document the internal states of MDSM.
MozReview-Commit-ID: 4fNJcjk6aMI
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -263,16 +263,25 @@ public:
}
protected:
// Take a raw pointer in order not to change the life cycle of MDSM.
// It is guaranteed to be valid by MDSM.
Master* mMaster;
};
+/**
+ * Purpose: decode metadata like duration and dimensions of the media resource.
+ *
+ * Transition to other states when decoding metadata is done:
+ * SHUTDOWN if failing to decode metadata.
+ * WAIT_FOR_CDM if the media is encrypted and CDM is not available.
+ * DORMANT if any pending dormant request.
+ * DECODING_FIRSTFRAME otherwise.
+ */
class MediaDecoderStateMachine::DecodeMetadataState
: public MediaDecoderStateMachine::StateObject
{
public:
explicit DecodeMetadataState(Master* aPtr) : StateObject(aPtr) {}
void Enter()
{
@@ -341,16 +350,23 @@ private:
MozPromiseRequestHolder<MediaDecoderReader::MetadataPromise> mMetadataRequest;
// True if we need to enter dormant state after reading metadata. Note that
// we can't enter dormant state until reading metadata is done for some
// limitations of the reader.
bool mPendingDormant = false;
};
+/**
+ * Purpose: wait for the CDM to start decoding.
+ *
+ * Transition to other states when CDM is ready:
+ * DORMANT if any pending dormant request.
+ * DECODING_FIRSTFRAME otherwise.
+ */
class MediaDecoderStateMachine::WaitForCDMState
: public MediaDecoderStateMachine::StateObject
{
public:
explicit WaitForCDMState(Master* aPtr) : StateObject(aPtr) {}
void Enter(bool aPendingDormant)
{
@@ -385,16 +401,22 @@ public:
// We never suspend video decoding in this state.
MOZ_ASSERT(false, "Shouldn't have suspended video decoding.");
}
private:
bool mPendingDormant = false;
};
+/**
+ * Purpose: release decoder resources to save memory and hardware resources.
+ *
+ * Transition to:
+ * DECODING_FIRSTFRAME when being asked to exit dormant.
+ */
class MediaDecoderStateMachine::DormantState
: public MediaDecoderStateMachine::StateObject
{
public:
explicit DormantState(Master* aPtr) : StateObject(aPtr) {}
void Enter()
{
@@ -426,16 +448,25 @@ public:
}
void HandleResumeVideoDecoding() override
{
// Do nothing since we won't resume decoding until exiting dormant.
}
};
+/**
+ * Purpose: decode the 1st audio and video frames to fire the 'loadeddata' event.
+ *
+ * Transition to:
+ * DORMANT if any dormant request.
+ * SHUTDOWN if any decode error.
+ * SEEKING if any pending seek and seek is possible.
+ * DECODING when the 'loadeddata' event is fired.
+ */
class MediaDecoderStateMachine::DecodingFirstFrameState
: public MediaDecoderStateMachine::StateObject
{
public:
explicit DecodingFirstFrameState(Master* aPtr) : StateObject(aPtr) {}
void Enter();
@@ -480,16 +511,26 @@ public:
}
private:
// Notify FirstFrameLoaded if having decoded first frames and
// transition to SEEKING if there is any pending seek, or DECODING otherwise.
void MaybeFinishDecodeFirstFrame();
};
+/**
+ * Purpose: decode audio/video data for playback.
+ *
+ * Transition to:
+ * DORMANT if any dormant request.
+ * SEEKING if any seek request.
+ * SHUTDOWN if any decode error.
+ * BUFFERING if playback can't continue due to lack of decoded data.
+ * COMPLETED when having decoded all audio/video data.
+ */
class MediaDecoderStateMachine::DecodingState
: public MediaDecoderStateMachine::StateObject
{
public:
explicit DecodingState(Master* aPtr) : StateObject(aPtr) {}
void Enter();
@@ -643,16 +684,26 @@ private:
// 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 = true;
};
+/**
+ * Purpose: seek to a particular new playback position.
+ *
+ * Transition to:
+ * DORMANT if any dormant request.
+ * SEEKING if any new seek request.
+ * SHUTDOWN if seek failed.
+ * COMPLETED if the new playback position is the end of the media resource.
+ * DECODING otherwise.
+ */
class MediaDecoderStateMachine::SeekingState
: public MediaDecoderStateMachine::StateObject
{
public:
explicit SeekingState(Master* aPtr) : StateObject(aPtr) {}
RefPtr<MediaDecoder::SeekPromise> Enter(SeekJob aSeekJob)
{
@@ -812,16 +863,26 @@ private:
void SeekCompleted();
SeekJob mSeekJob;
MozPromiseRequestHolder<SeekTask::SeekTaskPromise> mSeekTaskRequest;
RefPtr<SeekTask> mSeekTask;
};
+/**
+ * Purpose: stop playback until enough data is decoded to continue playback.
+ *
+ * Transition to:
+ * DORMANT if any dormant request.
+ * SEEKING if any seek request.
+ * SHUTDOWN if any decode error.
+ * COMPLETED when having decoded all audio/video data.
+ * DECODING when having decoded enough data to continue playback.
+ */
class MediaDecoderStateMachine::BufferingState
: public MediaDecoderStateMachine::StateObject
{
public:
explicit BufferingState(Master* aPtr) : StateObject(aPtr) {}
void Enter()
{
@@ -880,16 +941,23 @@ public:
private:
TimeStamp mBufferingStart;
// The maximum number of second we spend buffering when we are short on
// unbuffered data.
const uint32_t mBufferingWait = 15;
};
+/**
+ * Purpose: play all the decoded data and fire the 'ended' event.
+ *
+ * Transition to:
+ * DORMANT if any dormant request.
+ * SEEKING if any seek request.
+ */
class MediaDecoderStateMachine::CompletedState
: public MediaDecoderStateMachine::StateObject
{
public:
explicit CompletedState(Master* aPtr) : StateObject(aPtr) {}
void Enter()
{
@@ -962,16 +1030,25 @@ public:
{
// Do nothing since no decoding is going on.
}
private:
bool mSentPlaybackEndedEvent = false;
};
+/**
+ * Purpose: release all resources allocated by MDSM.
+ *
+ * Transition to:
+ * None since this is the final state.
+ *
+ * Transition from:
+ * Any states other than SHUTDOWN.
+ */
class MediaDecoderStateMachine::ShutdownState
: public MediaDecoderStateMachine::StateObject
{
public:
explicit ShutdownState(Master* aPtr) : StateObject(aPtr) {}
RefPtr<ShutdownPromise> Enter();