summaryrefslogtreecommitdiffstats
path: root/dom/media/ExternalEngineStateMachine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/ExternalEngineStateMachine.cpp')
-rw-r--r--dom/media/ExternalEngineStateMachine.cpp153
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__);