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>
Mon, 20 Nov 2017 17:34:25 +0800
changeset 700519 93f9da671e5c9edcd73e716458530bcf18ee4d1c
parent 700518 b86e142963266d1000825f9568c83ebc5b33cf9e
child 740911 4589c996c79ef57fa3576cfcf47c75d4e4fa5017
push id89874
push userbmo:cchang@mozilla.com
push dateMon, 20 Nov 2017 09:34:49 +0000
reviewersjwwang
bugs654787
milestone59.0a1
Bug 654787 - part8: Fire seeking and seeked events when looping back to the beginning; r=jwwang MozReview-Commit-ID: ApLN948bV4M
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,32 +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 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);
-  // Without checking IsPlaying(), the media might be terminated immediately
-  // when the state is just transited from seeking state. At that time,
-  // GetClock() might be smaller than GetMediaTime(), since GetMediaTime() is
-  // updated upon seek is completed while GetClock() will be updated after the
-  // media is started again.
-  if (adjusted < before && mMaster->IsPlaying() && !mMaster->mLooping) {
-    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. Ignore the
+  // check if the media has not been played yet.
+  } else if(!mMaster->mLooping && mMaster->IsPlaying()) {
+    // Without checking IsPlaying(), the media might be terminated immediately
+    // when the state is just transited from seeking state. At that time,
+    // GetClock() might be smaller than GetMediaTime(), since GetMediaTime() is
+    // updated upon seek is completed while GetClock() will be updated after the
+    // media is started again.
+    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,
 };