diff options
Diffstat (limited to 'dom/media/ExternalEngineStateMachine.cpp')
-rw-r--r-- | dom/media/ExternalEngineStateMachine.cpp | 153 |
1 files changed, 102 insertions, 51 deletions
diff --git a/dom/media/ExternalEngineStateMachine.cpp b/dom/media/ExternalEngineStateMachine.cpp index acfc1f5fa2..1728728dc6 100644 --- a/dom/media/ExternalEngineStateMachine.cpp +++ b/dom/media/ExternalEngineStateMachine.cpp @@ -164,11 +164,11 @@ void ExternalEngineStateMachine::ChangeStateTo(State aNextState) { LOG("Change state : '%s' -> '%s' (play-state=%d)", StateToStr(mState.mName), StateToStr(aNextState), mPlayState.Ref()); // Assert the possible state transitions. - MOZ_ASSERT_IF(mState.IsInitEngine(), aNextState == State::ReadingMetadata || + MOZ_ASSERT_IF( + mState.IsReadingMetadata(), + aNextState == State::InitEngine || aNextState == State::ShutdownEngine); + MOZ_ASSERT_IF(mState.IsInitEngine(), aNextState == State::RunningEngine || aNextState == State::ShutdownEngine); - MOZ_ASSERT_IF(mState.IsReadingMetadata(), - aNextState == State::RunningEngine || - aNextState == State::ShutdownEngine); MOZ_ASSERT_IF(mState.IsRunningEngine(), aNextState == State::SeekingData || aNextState == State::ShutdownEngine || @@ -183,8 +183,8 @@ void ExternalEngineStateMachine::ChangeStateTo(State aNextState) { aNextState == State::SeekingData || aNextState == State::ShutdownEngine); if (aNextState == State::SeekingData) { mState = StateObject({StateObject::SeekingData()}); - } else if (aNextState == State::ReadingMetadata) { - mState = StateObject({StateObject::ReadingMetadata()}); + } else if (aNextState == State::InitEngine) { + mState = StateObject({StateObject::InitEngine()}); } else if (aNextState == State::RunningEngine) { mState = StateObject({StateObject::RunningEngine()}); } else if (aNextState == State::ShutdownEngine) { @@ -200,8 +200,8 @@ ExternalEngineStateMachine::ExternalEngineStateMachine( MediaDecoder* aDecoder, MediaFormatReader* aReader) : MediaDecoderStateMachineBase(aDecoder, aReader) { LOG("Created ExternalEngineStateMachine"); - MOZ_ASSERT(mState.IsInitEngine()); - InitEngine(); + MOZ_ASSERT(mState.IsReadingMetadata()); + ReadMetadata(); } ExternalEngineStateMachine::~ExternalEngineStateMachine() { @@ -214,8 +214,9 @@ void ExternalEngineStateMachine::InitEngine() { mEngine.reset(new MFMediaEngineWrapper(this, mFrameStats)); #endif if (mEngine) { + MOZ_ASSERT(mInfo); auto* state = mState.AsInitEngine(); - state->mInitPromise = mEngine->Init(!mMinimizePreroll); + state->mInitPromise = mEngine->Init(*mInfo, !mMinimizePreroll); state->mInitPromise ->Then(OwnerThread(), __func__, this, &ExternalEngineStateMachine::OnEngineInitSuccess, @@ -235,14 +236,10 @@ void ExternalEngineStateMachine::OnEngineInitSuccess() { mReader->UpdateMediaEngineId(mEngine->Id()); state->mInitPromise = nullptr; if (mState.IsInitEngine()) { - ChangeStateTo(State::ReadingMetadata); - ReadMetadata(); + StartRunningEngine(); return; } - // We just recovered from CDM process crash, so we need to update the media - // info to the new CDM process. - MOZ_ASSERT(mInfo); - mEngine->SetMediaInfo(*mInfo); + // We just recovered from CDM process crash, seek to previous position. SeekTarget target(mCurrentPosition.Ref(), SeekTarget::Type::Accurate); Seek(target); } @@ -260,13 +257,17 @@ void ExternalEngineStateMachine::OnEngineInitFailure() { } void ExternalEngineStateMachine::ReadMetadata() { - AssertOnTaskQueue(); + MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mState.IsReadingMetadata()); - mReader->ReadMetadata() - ->Then(OwnerThread(), __func__, this, - &ExternalEngineStateMachine::OnMetadataRead, - &ExternalEngineStateMachine::OnMetadataNotRead) - ->Track(mState.AsReadingMetadata()->mMetadataRequest); + Unused << OwnerThread()->Dispatch(NS_NewRunnableFunction( + "ExternalEngineStateMachine::ReadMetadata", + [self = RefPtr<ExternalEngineStateMachine>{this}, this] { + mReader->ReadMetadata() + ->Then(OwnerThread(), __func__, this, + &ExternalEngineStateMachine::OnMetadataRead, + &ExternalEngineStateMachine::OnMetadataNotRead) + ->Track(mState.AsReadingMetadata()->mMetadataRequest); + })); } void ExternalEngineStateMachine::OnMetadataRead(MetadataHolder&& aMetadata) { @@ -303,8 +304,6 @@ void ExternalEngineStateMachine::OnMetadataRead(MetadataHolder&& aMetadata) { } #endif - mEngine->SetMediaInfo(*mInfo); - if (Info().mMetadataDuration.isSome()) { mDuration = Info().mMetadataDuration; } else if (Info().mUnadjustedMetadataEndTime.isSome()) { @@ -333,7 +332,8 @@ void ExternalEngineStateMachine::OnMetadataRead(MetadataHolder&& aMetadata) { mMetadataLoadedEvent.Notify(std::move(aMetadata.mInfo), std::move(aMetadata.mTags), MediaDecoderEventVisibility::Observable); - StartRunningEngine(); + ChangeStateTo(State::InitEngine); + InitEngine(); } void ExternalEngineStateMachine::OnMetadataNotRead(const MediaResult& aError) { @@ -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(); @@ -570,11 +622,15 @@ RefPtr<ShutdownPromise> ExternalEngineStateMachine::Shutdown() { mSetCDMProxyPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_ABORT_ERR, __func__); mSetCDMProxyRequest.DisconnectIfExists(); - mInitEngineForCDMRequest.DisconnectIfExists(); + + mPendingSeek.RejectIfExists(__func__); + mPendingSeekRequest.DisconnectIfExists(); mPendingTasks.Clear(); - mEngine->Shutdown(); + if (mEngine) { + mEngine->Shutdown(); + } auto* state = mState.AsShutdownEngine(); state->mShutdown = mReader->Shutdown()->Then( @@ -622,8 +678,7 @@ void ExternalEngineStateMachine::BufferedRangeUpdated() { return; \ } \ /* Initialzation is not done yet, postpone the operation */ \ - if ((mState.IsInitEngine() || mState.IsRecoverEngine()) && \ - mState.AsInitEngine()->mInitPromise) { \ + if (!mEngine || !mEngine->IsInited()) { \ LOG("%s is called before init", __func__); \ mPendingTasks.AppendElement(NewRunnableMethod( \ __func__, this, &ExternalEngineStateMachine::Func)); \ @@ -1213,30 +1268,25 @@ RefPtr<SetCDMPromise> ExternalEngineStateMachine::SetCDMProxy( return SetCDMPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); } - if (mState.IsInitEngine() && mState.AsInitEngine()->mInitPromise) { + if (!mEngine || !mEngine->IsInited()) { LOG("SetCDMProxy is called before init"); - mState.AsInitEngine() - ->mInitPromise - ->Then( - OwnerThread(), __func__, - [self = RefPtr{this}, proxy = RefPtr{aProxy}, this]( - const GenericNonExclusivePromise::ResolveOrRejectValue& aVal) { - mInitEngineForCDMRequest.Complete(); - SetCDMProxy(proxy) - ->Then(OwnerThread(), __func__, - [self = RefPtr{this}, this]( - const SetCDMPromise::ResolveOrRejectValue& aVal) { - mSetCDMProxyRequest.Complete(); - if (aVal.IsResolve()) { - mSetCDMProxyPromise.Resolve(true, __func__); - } else { - mSetCDMProxyPromise.Reject( - NS_ERROR_DOM_MEDIA_CDM_ERR, __func__); - } - }) - ->Track(mSetCDMProxyRequest); - }) - ->Track(mInitEngineForCDMRequest); + mPendingTasks.AppendElement(NS_NewRunnableFunction( + "ExternalEngineStateMachine::SetCDMProxy", + [self = RefPtr{this}, proxy = RefPtr{aProxy}, this] { + SetCDMProxy(proxy) + ->Then(OwnerThread(), __func__, + [self = RefPtr{this}, + this](const SetCDMPromise::ResolveOrRejectValue& aVal) { + mSetCDMProxyRequest.Complete(); + if (aVal.IsResolve()) { + mSetCDMProxyPromise.Resolve(true, __func__); + } else { + mSetCDMProxyPromise.Reject(NS_ERROR_DOM_MEDIA_CDM_ERR, + __func__); + } + }) + ->Track(mSetCDMProxyRequest); + })); return mSetCDMProxyPromise.Ensure(__func__); } @@ -1244,6 +1294,7 @@ RefPtr<SetCDMPromise> ExternalEngineStateMachine::SetCDMProxy( mKeySystem = NS_ConvertUTF16toUTF8(aProxy->KeySystem()); LOG("SetCDMProxy=%p (key-system=%s)", aProxy, mKeySystem.get()); MOZ_DIAGNOSTIC_ASSERT(mEngine); + // TODO : we should check the result of setting CDM proxy in the MFCDM process if (!mEngine->SetCDMProxy(aProxy)) { LOG("Failed to set CDM proxy on the engine"); return SetCDMPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CDM_ERR, __func__); |