Bug 1532495 - part1 : only skip the 'completed' state during seamless looping mode. r=jya
authoralwu <alwu@mozilla.com>
Thu, 09 May 2019 17:47:52 +0000
changeset 535220 5567ad616234db69e9c4aff10805eca281c839ab
parent 535218 a42caa9f04fc41044437ac56eab6f6086c841d9f
child 535221 126a59b083f619859b308f023bc5c8df49686b3d
push id2082
push userffxbld-merge
push dateMon, 01 Jul 2019 08:34:18 +0000
treeherdermozilla-release@2fb19d0466d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1532495
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1532495 - part1 : only skip the 'completed' state during seamless looping mode. r=jya The normal looping process is that, goes to `completed` state first, notify playback ended, and finally media element would call seek to the start position in order to start looping again. However, if we're in the seamless looping mode, we can stay in `loopingDecoding` state and repeating the looping without going to other states. Otherwise, we should go to `completed` state if decoding has ended. Differential Revision: https://phabricator.services.mozilla.com/D30307
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2155,17 +2155,17 @@ MediaDecoderStateMachine::StateObject::S
     return SetState<NextFrameSeekingState>(std::move(aSeekJob), aVisibility);
   }
 
   MOZ_ASSERT_UNREACHABLE("Unknown SeekTarget::Type.");
   return nullptr;
 }
 
 void MediaDecoderStateMachine::StateObject::SetDecodingState() {
-  if (mMaster->mLooping && mMaster->mSeamlessLoopingAllowed) {
+  if (mMaster->IsInSeamlessLooping()) {
     SetState<LoopingDecodingState>();
     return;
   }
   SetState<DecodingState>();
 }
 
 void MediaDecoderStateMachine::DecodeMetadataState::OnMetadataRead(
     MetadataHolder&& aMetadata) {
@@ -2271,20 +2271,22 @@ void MediaDecoderStateMachine::DecodingS
       !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();
   }
 
-  // If decoding has ended and we are not in looping, we don't need to decode
-  // anything later.
+  // If we're in the normal decoding mode and the decoding has finished, then we
+  // should go to `completed` state because we don't need to decode anything
+  // later. However, if we're in the saemless decoding mode, we will restart
+  // decoding ASAP so we can still stay in `decoding` state.
   if (!mMaster->IsVideoDecoding() && !mMaster->IsAudioDecoding() &&
-      !mMaster->mLooping) {
+      !mMaster->IsInSeamlessLooping()) {
     SetState<CompletedState>();
     return;
   }
 
   mOnAudioPopped =
       AudioQueue().PopFrontEvent().Connect(OwnerThread(), [this]() {
         if (mMaster->IsAudioDecoding() && !mMaster->HaveEnoughDecodedAudio()) {
           EnsureAudioDecodeTaskQueued();
@@ -3932,16 +3934,20 @@ void MediaDecoderStateMachine::CancelSus
 void MediaDecoderStateMachine::AdjustByLooping(media::TimeUnit& aTime) const {
   MOZ_ASSERT(OnTaskQueue());
   if (mAudioDecodedDuration.isSome() &&
       mAudioDecodedDuration.ref().IsPositive()) {
     aTime = aTime % mAudioDecodedDuration.ref();
   }
 }
 
+bool MediaDecoderStateMachine::IsInSeamlessLooping() const {
+  return mLooping && mSeamlessLoopingAllowed;
+}
+
 }  // namespace mozilla
 
 // avoid redefined macro in unified build
 #undef LOG
 #undef LOGV
 #undef LOGW
 #undef LOGE
 #undef SLOGW
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -620,16 +620,18 @@ class MediaDecoderStateMachine
   MozPromiseRequestHolder<WaitForDataPromise> mVideoWaitRequest;
 
   const char* AudioRequestStatus() const;
   const char* VideoRequestStatus() const;
 
   void OnSuspendTimerResolved();
   void CancelSuspendTimer();
 
+  bool IsInSeamlessLooping() const;
+
   bool mCanPlayThrough = false;
 
   bool mIsLiveStream = false;
 
   // True if we shouldn't play our audio (but still write it to any capturing
   // streams). When this is true, the audio thread will never start again after
   // it has stopped.
   bool mAudioCaptured;