diff --git a/dom/media/MediaDecoder.h b/dom/media/MediaDecoder.h index 5b72e8bf1113..9e2813bc07cb 100644 --- a/dom/media/MediaDecoder.h +++ b/dom/media/MediaDecoder.h @@ -242,6 +242,9 @@ public: // Return true if the decoder has reached the end of playback. bool IsEnded() const; + // True if we are playing a MediaSource object. + virtual bool IsMSE() const { return false; } + // Return true if the MediaDecoderOwner's error attribute is not null. // Must be called before Shutdown(). bool OwnerHasError() const; diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index 2f1d4555c925..1f5e0814927d 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -521,6 +521,13 @@ public: void Enter(); + void Exit() override + { + // mPendingSeek is either moved in MaybeFinishDecodeFirstFrame() + // or should be rejected here before transition to SHUTDOWN. + mPendingSeek.RejectIfExists(__func__); + } + State GetState() const override { return DECODER_STATE_DECODING_FIRSTFRAME; @@ -592,10 +599,24 @@ public: MOZ_ASSERT(false, "Shouldn't have suspended video decoding."); } + RefPtr HandleSeek(SeekTarget aTarget) override + { + if (mMaster->mIsMSE) { + return StateObject::HandleSeek(aTarget); + } + // Delay seek request until decoding first frames for non-MSE media. + SLOG("Not Enough Data to seek at this stage, queuing seek"); + mPendingSeek.RejectIfExists(__func__); + mPendingSeek.mTarget.emplace(aTarget); + return mPendingSeek.mPromise.Ensure(__func__); + } + private: // Notify FirstFrameLoaded if having decoded first frames and // transition to SEEKING if there is any pending seek, or DECODING otherwise. void MaybeFinishDecodeFirstFrame(); + + SeekJob mPendingSeek; }; /** @@ -2099,7 +2120,11 @@ DecodingFirstFrameState::MaybeFinishDecodeFirstFrame() } mMaster->FinishDecodeFirstFrame(); - SetState(); + if (mPendingSeek.Exists()) { + SetSeekingState(Move(mPendingSeek), EventVisibility::Observable); + } else { + SetState(); + } } void @@ -2547,6 +2572,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder, mVideoDecodeSuspendTimer(mTaskQueue), mOutputStreamManager(new OutputStreamManager()), mResource(aDecoder->GetResource()), + mIsMSE(aDecoder->IsMSE()), INIT_MIRROR(mBuffered, TimeIntervals()), INIT_MIRROR(mEstimatedDuration, NullableTimeUnit()), INIT_MIRROR(mExplicitDuration, Maybe()), diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h index 7dd0c4e0b141..46b4d2a1af14 100644 --- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -693,6 +693,8 @@ private: RefPtr mCDMProxy; MozPromiseRequestHolder mCDMProxyPromise; + const bool mIsMSE; + private: // The buffered range. Mirrored from the decoder thread. Mirror mBuffered; diff --git a/dom/media/mediasource/MediaSourceDecoder.h b/dom/media/mediasource/MediaSourceDecoder.h index 420f7208010f..8139d35989f0 100644 --- a/dom/media/mediasource/MediaSourceDecoder.h +++ b/dom/media/mediasource/MediaSourceDecoder.h @@ -76,6 +76,8 @@ public: MediaEventSource* WaitingForKeyEvent() override; + bool IsMSE() const override { return true; } + private: void DoSetMediaSourceDuration(double aDuration); media::TimeInterval ClampIntervalToEnd(const media::TimeInterval& aInterval);