Bug 1885959 - part3 : postpone seek while the engine is still in initialization. r=jolin

We will postpone any seek happening before the engine initialization is
finished, and will resolve the seek promise based on the latest seek if
there are multiple seek being requested.

Differential Revision: https://phabricator.services.mozilla.com/D205017
This commit is contained in:
alwu 2024-03-20 22:29:33 +00:00
parent 07febbc907
commit eefde59bed
3 changed files with 65 additions and 1 deletions

View file

@ -365,6 +365,58 @@ bool ExternalEngineStateMachine::IsFormatSupportedByExternalEngine(
#endif
}
RefPtr<MediaDecoder::SeekPromise> ExternalEngineStateMachine::InvokeSeek(
const SeekTarget& aTarget) {
return InvokeAsync(
OwnerThread(), __func__,
[self = RefPtr<ExternalEngineStateMachine>(this), this,
target = aTarget]() -> RefPtr<MediaDecoder::SeekPromise> {
AssertOnTaskQueue();
if (!mEngine || !mEngine->IsInited()) {
LOG("Can't perform seek (%" PRId64 ") now, add a pending seek task",
target.GetTime().ToMicroseconds());
// We haven't added any pending seek before
if (mPendingSeek.mPromise.IsEmpty()) {
mPendingTasks.AppendElement(NS_NewRunnableFunction(
"ExternalEngineStateMachine::InvokeSeek",
[self = RefPtr{this}, this] {
if (!mPendingSeek.Exists()) {
return;
}
Seek(*mPendingSeek.mTarget)
->Then(OwnerThread(), __func__,
[self = RefPtr{this},
this](const MediaDecoder::SeekPromise::
ResolveOrRejectValue& aVal) {
mPendingSeekRequest.Complete();
if (aVal.IsResolve()) {
mPendingSeek.Resolve(__func__);
} else {
mPendingSeek.RejectIfExists(__func__);
}
mPendingSeek = SeekJob();
})
->Track(mPendingSeekRequest);
}));
} else {
// Reject previous pending promise, as we will create a new one
LOG("Replace previous pending seek with a new one");
mPendingSeek.RejectIfExists(__func__);
mPendingSeekRequest.DisconnectIfExists();
}
mPendingSeek.mTarget = Some(target);
return mPendingSeek.mPromise.Ensure(__func__);
}
if (mPendingSeek.Exists()) {
LOG("Discard pending seek because another new seek happens");
mPendingSeek.RejectIfExists(__func__);
mPendingSeek = SeekJob();
mPendingSeekRequest.DisconnectIfExists();
}
return self->Seek(target);
});
}
RefPtr<MediaDecoder::SeekPromise> ExternalEngineStateMachine::Seek(
const SeekTarget& aTarget) {
AssertOnTaskQueue();
@ -571,6 +623,9 @@ RefPtr<ShutdownPromise> ExternalEngineStateMachine::Shutdown() {
mSetCDMProxyPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_ABORT_ERR, __func__);
mSetCDMProxyRequest.DisconnectIfExists();
mPendingSeek.RejectIfExists(__func__);
mPendingSeekRequest.DisconnectIfExists();
mPendingTasks.Clear();
if (mEngine) {

View file

@ -56,6 +56,9 @@ class ExternalEngineStateMachine final
ExternalEngineStateMachine(MediaDecoder* aDecoder,
MediaFormatReader* aReader);
RefPtr<MediaDecoder::SeekPromise> InvokeSeek(
const SeekTarget& aTarget) override;
RefPtr<GenericPromise> InvokeSetSink(
const RefPtr<AudioDeviceInfo>& aSink) override;
@ -309,6 +312,11 @@ class ExternalEngineStateMachine final
MozPromiseHolder<SetCDMPromise> mSetCDMProxyPromise;
MozPromiseRequestHolder<SetCDMPromise> mSetCDMProxyRequest;
// If seek happens while the engine is still initializing, then we would
// postpone the seek until the engine is ready.
SeekJob mPendingSeek;
MozPromiseRequestHolder<MediaDecoder::SeekPromise> mPendingSeekRequest;
// It would be zero for audio-only playback.
gfx::IntSize mVideoDisplay;

View file

@ -85,7 +85,8 @@ class MediaDecoderStateMachineBase {
RefPtr<ShutdownPromise> BeginShutdown();
// Seeks to the decoder to aTarget asynchronously.
RefPtr<MediaDecoder::SeekPromise> InvokeSeek(const SeekTarget& aTarget);
virtual RefPtr<MediaDecoder::SeekPromise> InvokeSeek(
const SeekTarget& aTarget);
virtual size_t SizeOfVideoQueue() const = 0;
virtual size_t SizeOfAudioQueue() const = 0;