Bug 1420608. P1 - don't switch off blank decoder when seeking begins. draft
authorJW Wang <jwwang@mozilla.com>
Thu, 07 Dec 2017 11:38:23 +0800
changeset 711023 52df84c8c26d53de0c3fe24f0e9c8a2529129d3b
parent 711022 86cb52d67b92f93345e72fdfef415cc5cfafb6f3
child 711024 cbf577a8b28a2721b391fbfc560d3994988914f1
push id92980
push userjwwang@mozilla.com
push dateWed, 13 Dec 2017 01:34:00 +0000
bugs1420608
milestone59.0a1
Bug 1420608. P1 - don't switch off blank decoder when seeking begins. When looping videos in a background tab, SeekingState::Enter() will switch off blank decoder and then DecodingState::Enter() will switch it on again. It is a waste of CPU cycles when the tab never goes to the foreground. The overhread is even more significant when looping short files. We should resume video decoding only when necessary that is we check in DecodingState::Enter() to see if mVideoDecodeSuspended matches mVideoDecodeMode. MozReview-Commit-ID: 54vq7mEjWQf
dom/media/MediaDecoderStateMachine.cpp
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -828,25 +828,16 @@ public:
   explicit SeekingState(Master* aPtr) : StateObject(aPtr) { }
 
   RefPtr<MediaDecoder::SeekPromise> Enter(SeekJob&& aSeekJob,
                                           EventVisibility aVisibility)
   {
     mSeekJob = Move(aSeekJob);
     mVisibility = aVisibility;
 
-    // Always switch off the blank decoder otherwise we might become visible
-    // in the middle of seeking and won't have a valid video frame to show
-    // when seek is done.
-    if (mMaster->mVideoDecodeSuspended) {
-      mMaster->mVideoDecodeSuspended = false;
-      mMaster->mOnPlaybackEvent.Notify(MediaPlaybackEvent::ExitVideoSuspend);
-      Reader()->SetVideoBlankDecode(false);
-    }
-
     // Suppressed visibility comes from two cases: (1) leaving dormant state,
     // and (2) resuming suspended video decoder. We want both cases to be
     // transparent to the user. So we only notify the change when the seek
     // request is from the user.
     if (mVisibility == EventVisibility::Observable) {
       // Don't stop playback for a video-only seek since we want to keep playing
       // audio and we don't need to stop playback while leaving dormant for the
       // playback should has been stopped.
@@ -879,18 +870,17 @@ public:
 
   void HandleVideoSuspendTimeout() override
   {
     // Do nothing since we want a valid video frame to show when seek is done.
   }
 
   void HandleResumeVideoDecoding(const TimeUnit&) override
   {
-    // We set mVideoDecodeSuspended to false in Enter().
-    MOZ_ASSERT(false, "Shouldn't have suspended video decoding.");
+    // Do nothing. We will resume video decoding in the decoding state.
   }
 
 protected:
   SeekJob mSeekJob;
   EventVisibility mVisibility;
 
   virtual void DoSeek() = 0;
   // Transition to the next state (defined by the subclass) when seek is completed.
@@ -2111,16 +2101,20 @@ ReportRecoveryTelemetry(const TimeStamp&
 }
 
 void
 MediaDecoderStateMachine::
 StateObject::HandleResumeVideoDecoding(const TimeUnit& aTarget)
 {
   MOZ_ASSERT(mMaster->mVideoDecodeSuspended);
 
+  mMaster->mVideoDecodeSuspended = false;
+  mMaster->mOnPlaybackEvent.Notify(MediaPlaybackEvent::ExitVideoSuspend);
+  Reader()->SetVideoBlankDecode(false);
+
   // Start counting recovery time from right now.
   TimeStamp start = TimeStamp::Now();
 
   // Local reference to mInfo, so that it will be copied in the lambda below.
   auto& info = Info();
   bool hw = Reader()->VideoIsHardwareAccelerated();
 
   // Start video-only seek to the current time.
@@ -2273,16 +2267,22 @@ DecodingFirstFrameState::MaybeFinishDeco
 }
 
 void
 MediaDecoderStateMachine::
 DecodingState::Enter()
 {
   MOZ_ASSERT(mMaster->mSentFirstFrameLoadedEvent);
 
+  if (mMaster->mVideoDecodeSuspended &&
+      mMaster->mVideoDecodeMode == VideoDecodeMode::Normal) {
+    StateObject::HandleResumeVideoDecoding(mMaster->GetMediaTime());
+    return;
+  }
+
   if (mMaster->mVideoDecodeMode == VideoDecodeMode::Suspend &&
       !mMaster->mVideoDecodeSuspendTimer.IsScheduled() &&
       !mMaster->mVideoDecodeSuspended) {
     // If the VideoDecodeMode is Suspend and the timer is not schedule, it means
     // the timer has timed out and we should suspend video decoding now if
     // necessary.
     HandleVideoSuspendTimeout();
   }