Bug 654787 - part8: Fire seeking and seeked events when looping back to the beginning; r=jwwang draft
authorChun-Min Chang <chun.m.chang@gmail.com>
Tue, 21 Nov 2017 18:10:19 +0800
changeset 702948 563a4b2af481f132638e4417e91db270975e0fb3
parent 702947 09e395f88f355d64b4ece8f980540bec03fb80f6
child 741611 76d6e885563094762e1842eea38328c88c64b34a
push id90643
push userbmo:cchang@mozilla.com
push dateFri, 24 Nov 2017 02:29:17 +0000
reviewersjwwang
bugs654787
milestone59.0a1
Bug 654787 - part8: Fire seeking and seeked events when looping back to the beginning; r=jwwang MozReview-Commit-ID: 2hYJfcCmvam
dom/media/MediaDecoder.cpp
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -520,16 +520,20 @@ MediaDecoder::OnPlaybackEvent(MediaEvent
 {
   switch (aEvent) {
     case MediaEventType::PlaybackEnded:
       PlaybackEnded();
       break;
     case MediaEventType::SeekStarted:
       SeekingStarted();
       break;
+    case MediaEventType::Loop:
+      GetOwner()->DispatchAsyncEvent(NS_LITERAL_STRING("seeking"));
+      GetOwner()->DispatchAsyncEvent(NS_LITERAL_STRING("seeked"));
+      break;
     case MediaEventType::Invalidate:
       Invalidate();
       break;
     case MediaEventType::EnterVideoSuspend:
       GetOwner()->DispatchAsyncEvent(NS_LITERAL_STRING("mozentervideosuspend"));
       break;
     case MediaEventType::ExitVideoSuspend:
       GetOwner()->DispatchAsyncEvent(NS_LITERAL_STRING("mozexitvideosuspend"));
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2304,34 +2304,40 @@ DecodingState::Step()
   // Start playback if necessary so that the clock can be properly queried.
   if (!mIsPrerolling) {
     mMaster->MaybeStartPlayback();
   }
 
   TimeUnit before = mMaster->GetMediaTime();
   mMaster->UpdatePlaybackPositionPeriodically();
 
+  // Fire the `seeking` and `seeked` events to meet the HTML spec
+  // when the media is looped back from the end to the beginning.
+  if (before > mMaster->GetMediaTime()) {
+    MOZ_ASSERT(mMaster->mLooping);
+    mMaster->mOnPlaybackEvent.Notify(MediaEventType::Loop);
   // After looping is cancelled, the time won't be corrected, and therefore we
-  // can check it to see if the end of the media track is reached.
-  TimeUnit adjusted = mMaster->GetClock();
-  Reader()->AdjustByLooping(adjusted);
-  // Make sure the media is started before comparing the time, or it's
-  // meaningless. Without checking IsStarted(), the media will be terminated
-  // immediately after seeking forward. When the state is just transited from
-  // seeking state, GetClock() is smaller than GetMediaTime(), since
-  // GetMediaTime() is updated upon seek is completed while GetClock() will be
-  // updated after the media is started again.
-  if (mMaster->mMediaSink->IsStarted() && !mMaster->mLooping &&
-      adjusted < before) {
-    mMaster->StopPlayback();
-    mMaster->mAudioDataRequest.DisconnectIfExists();
-    AudioQueue().Finish();
-    mMaster->mAudioCompleted = true;
-    SetState<CompletedState>();
-    return;
+  // can check it to see if the end of the media track is reached. Make sure
+  // the media is started before comparing the time, or it's meaningless.
+  // Without checking IsStarted(), the media will be terminated immediately
+  // after seeking forward. When the state is just transited from seeking state,
+  // GetClock() is smaller than GetMediaTime(), since GetMediaTime() is updated
+  // upon seek is completed while GetClock() will be updated after the media is
+  // started again.
+  } else if (mMaster->mMediaSink->IsStarted() && !mMaster->mLooping) {
+    TimeUnit adjusted = mMaster->GetClock();
+    Reader()->AdjustByLooping(adjusted);
+    if (adjusted < before) {
+      mMaster->StopPlayback();
+      mMaster->mAudioDataRequest.DisconnectIfExists();
+      AudioQueue().Finish();
+      mMaster->mAudioCompleted = true;
+      SetState<CompletedState>();
+      return;
+    }
   }
 
   MOZ_ASSERT(!mMaster->IsPlaying() || mMaster->IsStateMachineScheduled(),
              "Must have timer scheduled");
 
   MaybeStartBuffering();
 }
 
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -115,16 +115,17 @@ class TaskQueue;
 extern LazyLogModule gMediaDecoderLog;
 
 enum class MediaEventType : int8_t
 {
   PlaybackStarted,
   PlaybackStopped,
   PlaybackEnded,
   SeekStarted,
+  Loop,
   Invalidate,
   EnterVideoSuspend,
   ExitVideoSuspend,
   StartVideoSuspendTimer,
   CancelVideoSuspendTimer,
   VideoOnlySeekBegin,
   VideoOnlySeekCompleted,
 };