Bug 1346498 part 2 - implement the VideoDecodeMode mechanism in MDSM; r?jwwang
The MDSM::mVideoDecodeMode and MDSM::SetVideoDecodeMode() are merely a renaming of MDSM::mIsVisible and MDSM::VisibilityChanged().
However, the renaming explicitly reflects that MDSM provides mechanism only without participating in the policy decision.
Will reremove the MDSM::mIsVisible and MDSM::VisibilityChanged() in following patches.
MozReview-Commit-ID: JdMKQTgVCf3
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2606,16 +2606,17 @@ MediaDecoderStateMachine::MediaDecoderSt
mAudioCaptured(false),
mMinimizePreroll(aDecoder->GetMinimizePreroll()),
mSentLoadedMetadataEvent(false),
mSentFirstFrameLoadedEvent(false),
mVideoDecodeSuspended(false),
mVideoDecodeSuspendTimer(mTaskQueue),
mOutputStreamManager(new OutputStreamManager()),
mResource(aDecoder->GetResource()),
+ mVideoDecodeMode(VideoDecodeMode::Normal),
mIsMSE(aDecoder->IsMSE()),
INIT_MIRROR(mBuffered, TimeIntervals()),
INIT_MIRROR(mEstimatedDuration, NullableTimeUnit()),
INIT_MIRROR(mExplicitDuration, Maybe<double>()),
INIT_MIRROR(mPlayState, MediaDecoder::PLAY_STATE_LOADING),
INIT_MIRROR(mNextPlayState, MediaDecoder::PLAY_STATE_PAUSED),
INIT_MIRROR(mVolume, 1.0),
INIT_MIRROR(mPreservesPitch, true),
@@ -3063,16 +3064,66 @@ void MediaDecoderStateMachine::SuspendTa
CancelSuspendTimer();
// Resume from suspended decoding.
if (mVideoDecodeSuspended) {
mStateObj->HandleResumeVideoDecoding();
}
}
+void MediaDecoderStateMachine::SetVideoDecodeMode(VideoDecodeMode aMode)
+{
+ nsCOMPtr<nsIRunnable> r =
+ NewRunnableMethod<VideoDecodeMode>(this,
+ &MediaDecoderStateMachine::SetVideoDecodeModeInternal,
+ aMode);
+ OwnerThread()->DispatchStateChange(r.forget());
+}
+
+void MediaDecoderStateMachine::SetVideoDecodeModeInternal(VideoDecodeMode aMode)
+{
+ MOZ_ASSERT(OnTaskQueue());
+ DECODER_LOG("VideoDecodeModeChanged: VideoDecodeMode=(%s->%s), mVideoDecodeSuspended=%c",
+ mVideoDecodeMode == VideoDecodeMode::Normal ? "Normal" : "Suspend",
+ aMode == VideoDecodeMode::Normal ? "Normal" : "Suspend",
+ mVideoDecodeSuspended ? 'T' : 'F');
+
+ if (!MediaPrefs::MDSMSuspendBackgroundVideoEnabled()) {
+ return;
+ }
+
+ if (aMode == mVideoDecodeMode) {
+ return;
+ }
+
+ // Set new video decode mode.
+ mVideoDecodeMode = aMode;
+
+ // Start timer to trigger suspended video decoding.
+ if (mVideoDecodeMode == VideoDecodeMode::Suspend) {
+ TimeStamp target = TimeStamp::Now() + SuspendBackgroundVideoDelay();
+
+ RefPtr<MediaDecoderStateMachine> self = this;
+ mVideoDecodeSuspendTimer.Ensure(target,
+ [=]() { self->OnSuspendTimerResolved(); },
+ [] () { MOZ_DIAGNOSTIC_ASSERT(false); });
+ mOnPlaybackEvent.Notify(MediaEventType::StartVideoSuspendTimer);
+ return;
+ }
+
+ // Resuming from suspended decoding
+
+ // If suspend timer exists, destroy it.
+ CancelSuspendTimer();
+
+ if (mVideoDecodeSuspended) {
+ mStateObj->HandleResumeVideoDecoding();
+ }
+}
+
void MediaDecoderStateMachine::BufferedRangeUpdated()
{
MOZ_ASSERT(OnTaskQueue());
// While playing an unseekable stream of unknown duration, mObservedDuration
// is updated (in AdvanceFrame()) as we play. But if data is being downloaded
// faster than played, mObserved won't reflect the end of playable data
// since we haven't played the frame at the end of buffered data. So update
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -122,16 +122,22 @@ enum class MediaEventType : int8_t
SeekStarted,
Invalidate,
EnterVideoSuspend,
ExitVideoSuspend,
StartVideoSuspendTimer,
CancelVideoSuspendTimer
};
+enum class VideoDecodeMode : uint8_t
+{
+ Normal,
+ Suspend
+};
+
/*
The state machine class. This manages the decoding and seeking in the
MediaDecoderReader on the decode task queue, and A/V sync on the shared
state machine thread, and controls the audio "push" thread.
All internal state is synchronised via the decoder monitor. State changes
are propagated by scheduling the state machine to run another cycle on the
shared state machine thread.
@@ -221,16 +227,19 @@ public:
MediaEventSource<DecoderDoctorEvent>&
OnDecoderDoctorEvent() { return mOnDecoderDoctorEvent; }
size_t SizeOfVideoQueue() const;
size_t SizeOfAudioQueue() const;
+ // Sets the video decode mode. Used by the suspend-video-decoder feature.
+ void SetVideoDecodeMode(VideoDecodeMode aMode);
+
private:
class StateObject;
class DecodeMetadataState;
class WaitForCDMState;
class DormantState;
class DecodingFirstFrameState;
class DecodingState;
class SeekingState;
@@ -302,16 +311,18 @@ private:
// Sets mMediaSeekable to false.
void SetMediaNotSeekable();
// Resets all states related to decoding and aborts all pending requests
// to the decoders.
void ResetDecode(TrackSet aTracks = TrackSet(TrackInfo::kAudioTrack,
TrackInfo::kVideoTrack));
+ void SetVideoDecodeModeInternal(VideoDecodeMode aMode);
+
protected:
virtual ~MediaDecoderStateMachine();
void BufferedRangeUpdated();
void ReaderSuspendedChanged();
// Inserts MediaData* samples into their respective MediaQueues.
@@ -671,16 +682,19 @@ private:
DelayedScheduler mVideoDecodeSuspendTimer;
// Data about MediaStreams that are being fed by the decoder.
const RefPtr<OutputStreamManager> mOutputStreamManager;
// Media data resource from the decoder.
RefPtr<MediaResource> mResource;
+ // Track the current video decode mode.
+ VideoDecodeMode mVideoDecodeMode;
+
// Track the complete & error for audio/video separately
MozPromiseRequestHolder<GenericPromise> mMediaSinkAudioPromise;
MozPromiseRequestHolder<GenericPromise> mMediaSinkVideoPromise;
MediaEventListener mAudioQueueListener;
MediaEventListener mVideoQueueListener;
MediaEventListener mAudibleListener;
MediaEventListener mOnMediaNotSeekable;