Files
tubestation/dom/media/MediaDecoderStateMachineBase.cpp
alwu 73dbbe7442 Bug 1820650 - part1 : add another layer for setting CDM proxy. r=jolin
For media engine playback, we would like to let ExternalStateMachine
being aware of the CDM proxy, so that it can pass the the Id of MFCDM
actor to the remote media engine via MFMediaEngineChild in following
patches.

Differential Revision: https://phabricator.services.mozilla.com/D171800
2023-03-13 21:16:59 +00:00

185 lines
7.2 KiB
C++

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MediaDecoderStateMachineBase.h"
#include "MediaDecoder.h"
#include "mozilla/ProfilerMarkers.h"
#include "mozilla/TaskQueue.h"
#include "nsThreadUtils.h"
namespace mozilla {
#define INIT_MIRROR(name, val) \
name(mTaskQueue, val, "MediaDecoderStateMachineBase::" #name " (Mirror)")
#define INIT_CANONICAL(name, val) \
name(mTaskQueue, val, "MediaDecoderStateMachineBase::" #name " (Canonical)")
#define FMT(x, ...) "Decoder=%p " x, mDecoderID, ##__VA_ARGS__
#define LOG(x, ...) \
DDMOZ_LOG(gMediaDecoderLog, LogLevel::Debug, "Decoder=%p " x, mDecoderID, \
##__VA_ARGS__)
#define LOGV(x, ...) \
DDMOZ_LOG(gMediaDecoderLog, LogLevel::Verbose, "Decoder=%p " x, mDecoderID, \
##__VA_ARGS__)
#define LOGW(x, ...) NS_WARNING(nsPrintfCString(FMT(x, ##__VA_ARGS__)).get())
#define LOGE(x, ...) \
NS_DebugBreak(NS_DEBUG_WARNING, \
nsPrintfCString(FMT(x, ##__VA_ARGS__)).get(), nullptr, \
__FILE__, __LINE__)
MediaDecoderStateMachineBase::MediaDecoderStateMachineBase(
MediaDecoder* aDecoder, MediaFormatReader* aReader)
: mDecoderID(aDecoder),
mAbstractMainThread(aDecoder->AbstractMainThread()),
mFrameStats(&aDecoder->GetFrameStatistics()),
mVideoFrameContainer(aDecoder->GetVideoFrameContainer()),
mTaskQueue(TaskQueue::Create(GetMediaThreadPool(MediaThreadType::MDSM),
"MDSM::mTaskQueue",
/* aSupportsTailDispatch = */ true)),
mReader(new ReaderProxy(mTaskQueue, aReader)),
mPlaybackRate(1.0),
INIT_MIRROR(mBuffered, media::TimeIntervals()),
INIT_MIRROR(mPlayState, MediaDecoder::PLAY_STATE_LOADING),
INIT_MIRROR(mVolume, 1.0),
INIT_MIRROR(mPreservesPitch, true),
INIT_MIRROR(mLooping, false),
INIT_MIRROR(mSecondaryVideoContainer, nullptr),
INIT_CANONICAL(mDuration, media::NullableTimeUnit()),
INIT_CANONICAL(mCurrentPosition, media::TimeUnit::Zero()),
INIT_CANONICAL(mIsAudioDataAudible, false),
mMinimizePreroll(aDecoder->GetMinimizePreroll()),
mWatchManager(this, mTaskQueue) {}
MediaEventSource<void>& MediaDecoderStateMachineBase::OnMediaNotSeekable()
const {
return mReader->OnMediaNotSeekable();
}
AbstractCanonical<media::TimeIntervals>*
MediaDecoderStateMachineBase::CanonicalBuffered() const {
return mReader->CanonicalBuffered();
}
void MediaDecoderStateMachineBase::DispatchSetFragmentEndTime(
const media::TimeUnit& aEndTime) {
OwnerThread()->DispatchStateChange(NewRunnableMethod<media::TimeUnit>(
"MediaDecoderStateMachineBase::SetFragmentEndTime", this,
&MediaDecoderStateMachineBase::SetFragmentEndTime, aEndTime));
}
void MediaDecoderStateMachineBase::DispatchCanPlayThrough(
bool aCanPlayThrough) {
OwnerThread()->DispatchStateChange(NewRunnableMethod<bool>(
"MediaDecoderStateMachineBase::SetCanPlayThrough", this,
&MediaDecoderStateMachineBase::SetCanPlayThrough, aCanPlayThrough));
}
void MediaDecoderStateMachineBase::DispatchIsLiveStream(bool aIsLiveStream) {
OwnerThread()->DispatchStateChange(NewRunnableMethod<bool>(
"MediaDecoderStateMachineBase::SetIsLiveStream", this,
&MediaDecoderStateMachineBase::SetIsLiveStream, aIsLiveStream));
}
void MediaDecoderStateMachineBase::DispatchSetPlaybackRate(
double aPlaybackRate) {
OwnerThread()->DispatchStateChange(NewRunnableMethod<double>(
"MediaDecoderStateMachineBase::SetPlaybackRate", this,
&MediaDecoderStateMachineBase::SetPlaybackRate, aPlaybackRate));
}
nsresult MediaDecoderStateMachineBase::Init(MediaDecoder* aDecoder) {
MOZ_ASSERT(NS_IsMainThread());
// Dispatch initialization that needs to happen on that task queue.
nsCOMPtr<nsIRunnable> r = NewRunnableMethod<RefPtr<MediaDecoder>>(
"MediaDecoderStateMachineBase::InitializationTask", this,
&MediaDecoderStateMachineBase::InitializationTask, aDecoder);
mTaskQueue->DispatchStateChange(r.forget());
;
nsresult rv = mReader->Init();
NS_ENSURE_SUCCESS(rv, rv);
mMetadataManager.Connect(mReader->TimedMetadataEvent(), OwnerThread());
mReader->SetCanonicalDuration(&mDuration);
return NS_OK;
}
void MediaDecoderStateMachineBase::InitializationTask(MediaDecoder* aDecoder) {
MOZ_ASSERT(OnTaskQueue());
// Connect mirrors.
mBuffered.Connect(mReader->CanonicalBuffered());
mPlayState.Connect(aDecoder->CanonicalPlayState());
mVolume.Connect(aDecoder->CanonicalVolume());
mPreservesPitch.Connect(aDecoder->CanonicalPreservesPitch());
mLooping.Connect(aDecoder->CanonicalLooping());
mSecondaryVideoContainer.Connect(
aDecoder->CanonicalSecondaryVideoContainer());
// Initialize watchers.
mWatchManager.Watch(mBuffered,
&MediaDecoderStateMachineBase::BufferedRangeUpdated);
mWatchManager.Watch(mVolume, &MediaDecoderStateMachineBase::VolumeChanged);
mWatchManager.Watch(mPreservesPitch,
&MediaDecoderStateMachineBase::PreservesPitchChanged);
mWatchManager.Watch(mPlayState,
&MediaDecoderStateMachineBase::PlayStateChanged);
mWatchManager.Watch(mLooping, &MediaDecoderStateMachineBase::LoopingChanged);
mWatchManager.Watch(
mSecondaryVideoContainer,
&MediaDecoderStateMachineBase::UpdateSecondaryVideoContainer);
}
RefPtr<ShutdownPromise> MediaDecoderStateMachineBase::BeginShutdown() {
MOZ_ASSERT(NS_IsMainThread());
return InvokeAsync(
OwnerThread(), __func__,
[self = RefPtr<MediaDecoderStateMachineBase>(this), this]() {
mWatchManager.Shutdown();
mBuffered.DisconnectIfConnected();
mPlayState.DisconnectIfConnected();
mVolume.DisconnectIfConnected();
mPreservesPitch.DisconnectIfConnected();
mLooping.DisconnectIfConnected();
mSecondaryVideoContainer.DisconnectIfConnected();
return Shutdown();
});
}
RefPtr<MediaDecoder::SeekPromise> MediaDecoderStateMachineBase::InvokeSeek(
const SeekTarget& aTarget) {
return InvokeAsync(OwnerThread(), __func__,
[self = RefPtr<MediaDecoderStateMachineBase>(this),
target = aTarget]() { return self->Seek(target); });
}
bool MediaDecoderStateMachineBase::OnTaskQueue() const {
return OwnerThread()->IsCurrentThreadIn();
}
void MediaDecoderStateMachineBase::DecodeError(const MediaResult& aError) {
MOZ_ASSERT(OnTaskQueue());
LOGE("Decode error: %s", aError.Description().get());
PROFILER_MARKER_TEXT("MDSMBase::DecodeError", MEDIA_PLAYBACK, {},
aError.Description());
// Notify the decode error and MediaDecoder will shut down MDSM.
mOnPlaybackErrorEvent.Notify(aError);
}
RefPtr<SetCDMPromise> MediaDecoderStateMachineBase::SetCDMProxy(
CDMProxy* aProxy) {
return mReader->SetCDMProxy(aProxy);
}
#undef INIT_MIRROR
#undef INIT_CANONICAL
#undef FMT
#undef LOG
#undef LOGV
#undef LOGW
#undef LOGE
} // namespace mozilla