Bug 654787 - part8: Fire seeking and seeked events when looping back to the beginning; r=jwwang
MozReview-Commit-ID: 2hYJfcCmvam
--- 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,
};