Bug 1346498 part 2 - implement the VideoDecodeMode mechanism in MDSM; r?jwwang draft
authorKaku Kuo <kaku@mozilla.com>
Fri, 10 Mar 2017 16:17:46 +0800
changeset 497401 643d962efd04c425a7879448215b056888dbed3f
parent 497400 fc3f68f4db87e973bc7ab7ec4119324768d3c663
child 497402 ff74c75457f4d2de0df3f062d872fa05d05eae18
push id48888
push userbmo:kaku@mozilla.com
push dateMon, 13 Mar 2017 08:46:01 +0000
reviewersjwwang
bugs1346498
milestone55.0a1
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
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- 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;