Bug 1405025: queue seeking event immediately after seeking. r?jwwang
Per spec, the seeking event is to be queued when the seek operation is starting:
reference: https://www.w3.org/TR/2011/WD-html5-20110113/video.html#seeking
"9. Queue a task to fire a simple event named seeking at the element."
MozReview-Commit-ID: A8MOcagrbWm
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -2837,16 +2837,18 @@ HTMLMediaElement::Seek(double aTime,
// event if it changes the playback position as a result of the seek.
LOG(LogLevel::Debug, ("%p SetCurrentTime(%f) starting seek", this, aTime));
nsresult rv = mDecoder->Seek(aTime, aSeekType);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
}
+ DispatchAsyncEvent(NS_LITERAL_STRING("seeking"));
+
// We changed whether we're seeking so we need to AddRemoveSelfReference.
AddRemoveSelfReference();
// Keep the DOM promise.
mSeekDOMPromise = promise;
return promise.forget();
}
@@ -5483,21 +5485,16 @@ void HTMLMediaElement::PlaybackEnded()
// A MediaStream that goes from inactive to active shall be eligible for
// autoplay again according to the mediacapture-main spec.
mAutoplaying = true;
}
DispatchAsyncEvent(NS_LITERAL_STRING("ended"));
}
-void HTMLMediaElement::SeekStarted()
-{
- DispatchAsyncEvent(NS_LITERAL_STRING("seeking"));
-}
-
void HTMLMediaElement::SeekCompleted()
{
mPlayingBeforeSeek = false;
SetPlayedOrSeeked(true);
if (mTextTrackManager) {
mTextTrackManager->DidSeek();
}
FireTimeUpdate(false);
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -191,20 +191,16 @@ public:
// resource load has been cancelled.
virtual void LoadAborted() final override;
// Called by the video decoder object, on the main thread,
// when the video playback has ended.
virtual void PlaybackEnded() final override;
// Called by the video decoder object, on the main thread,
- // when the resource has started seeking.
- virtual void SeekStarted() final override;
-
- // Called by the video decoder object, on the main thread,
// when the resource has completed seeking.
virtual void SeekCompleted() final override;
// Called by the media stream, on the main thread, when the download
// has been suspended by the cache or because the element itself
// asked the decoder to suspend the download.
virtual void DownloadSuspended() final override;
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -503,19 +503,16 @@ MediaDecoder::~MediaDecoder()
void
MediaDecoder::OnPlaybackEvent(MediaEventType aEvent)
{
switch (aEvent) {
case MediaEventType::PlaybackEnded:
PlaybackEnded();
break;
- case MediaEventType::SeekStarted:
- SeekingStarted();
- 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"));
@@ -938,24 +935,16 @@ MediaDecoder::OnSeekRejected()
{
MOZ_ASSERT(NS_IsMainThread());
mSeekRequest.Complete();
mLogicallySeeking = false;
GetOwner()->AsyncRejectSeekDOMPromiseIfExists();
}
void
-MediaDecoder::SeekingStarted()
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
- GetOwner()->SeekStarted();
-}
-
-void
MediaDecoder::ChangeState(PlayState aState)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!IsShutdown(), "SHUTDOWN is the final state.");
AbstractThread::AutoEnter context(AbstractMainThread());
if (mNextState == aState) {
mNextState = PLAY_STATE_PAUSED;
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -321,19 +321,16 @@ private:
// Called when the video has completed playing.
// Call on the main thread only.
void PlaybackEnded();
void OnSeekRejected();
void OnSeekResolved();
- // Seeking has started. Inform the element on the main thread.
- void SeekingStarted();
-
void UpdateLogicalPositionInternal();
void UpdateLogicalPosition()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
// Per spec, offical position remains stable during pause and seek.
if (mPlayState == PLAY_STATE_PAUSED || IsSeeking()) {
return;
--- a/dom/media/MediaDecoderOwner.h
+++ b/dom/media/MediaDecoderOwner.h
@@ -79,20 +79,16 @@ public:
// resource load has been cancelled.
virtual void LoadAborted() = 0;
// Called by the video decoder object, on the main thread,
// when the video playback has ended.
virtual void PlaybackEnded() = 0;
// Called by the video decoder object, on the main thread,
- // when the resource has started seeking.
- virtual void SeekStarted() = 0;
-
- // Called by the video decoder object, on the main thread,
// when the resource has completed seeking.
virtual void SeekCompleted() = 0;
// Called by the media stream, on the main thread, when the download
// has been suspended by the cache or because the element itself
// asked the decoder to suspend the download.
virtual void DownloadSuspended() = 0;
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -863,17 +863,16 @@ public:
// 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.
mMaster->StopPlayback();
mMaster->UpdatePlaybackPositionInternal(mSeekJob.mTarget->GetTime());
- mMaster->mOnPlaybackEvent.Notify(MediaEventType::SeekStarted);
mMaster->UpdateNextFrameStatus(
MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_SEEKING);
}
RefPtr<MediaDecoder::SeekPromise> p = mSeekJob.mPromise.Ensure(__func__);
DoSeek();
--- a/dom/media/gtest/MockMediaDecoderOwner.h
+++ b/dom/media/gtest/MockMediaDecoderOwner.h
@@ -24,17 +24,16 @@ public:
UniquePtr<const MetadataTags> aTags) override
{
}
void NetworkError() override {}
void DecodeError(const MediaResult& aError) override {}
bool HasError() const override { return false; }
void LoadAborted() override {}
void PlaybackEnded() override {}
- void SeekStarted() override {}
void SeekCompleted() override {}
void DownloadProgressed() override {}
void UpdateReadyState() override {}
void FirstFrameLoaded() override {}
void DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
const nsAString& aInitDataType) override {}
bool IsActive() const override { return true; }
bool IsHidden() const override { return false; }