Bug 1885602 - Part 2: Add a MozillaAccountMenuButton composable for the menu redesign...
[gecko.git] / dom / media / MediaDecoderStateMachineBase.cpp
blob38d51dbd8e03793dfe0a8394ff401f0cf0d57753
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "MediaDecoderStateMachineBase.h"
7 #include "MediaDecoder.h"
8 #include "mozilla/ProfilerMarkers.h"
9 #include "mozilla/TaskQueue.h"
10 #include "nsThreadUtils.h"
12 namespace mozilla {
14 #define INIT_MIRROR(name, val) \
15 name(mTaskQueue, val, "MediaDecoderStateMachineBase::" #name " (Mirror)")
16 #define INIT_CANONICAL(name, val) \
17 name(mTaskQueue, val, "MediaDecoderStateMachineBase::" #name " (Canonical)")
18 #define FMT(x, ...) "Decoder=%p " x, mDecoderID, ##__VA_ARGS__
19 #define LOG(x, ...) \
20 DDMOZ_LOG(gMediaDecoderLog, LogLevel::Debug, "Decoder=%p " x, mDecoderID, \
21 ##__VA_ARGS__)
22 #define LOGV(x, ...) \
23 DDMOZ_LOG(gMediaDecoderLog, LogLevel::Verbose, "Decoder=%p " x, mDecoderID, \
24 ##__VA_ARGS__)
25 #define LOGW(x, ...) NS_WARNING(nsPrintfCString(FMT(x, ##__VA_ARGS__)).get())
26 #define LOGE(x, ...) \
27 NS_DebugBreak(NS_DEBUG_WARNING, \
28 nsPrintfCString(FMT(x, ##__VA_ARGS__)).get(), nullptr, \
29 __FILE__, __LINE__)
31 MediaDecoderStateMachineBase::MediaDecoderStateMachineBase(
32 MediaDecoder* aDecoder, MediaFormatReader* aReader)
33 : mDecoderID(aDecoder),
34 mAbstractMainThread(aDecoder->AbstractMainThread()),
35 mFrameStats(&aDecoder->GetFrameStatistics()),
36 mVideoFrameContainer(aDecoder->GetVideoFrameContainer()),
37 mTaskQueue(TaskQueue::Create(GetMediaThreadPool(MediaThreadType::MDSM),
38 "MDSM::mTaskQueue",
39 /* aSupportsTailDispatch = */ true)),
40 mReader(new ReaderProxy(mTaskQueue, aReader)),
41 mPlaybackRate(1.0),
42 INIT_MIRROR(mBuffered, media::TimeIntervals()),
43 INIT_MIRROR(mPlayState, MediaDecoder::PLAY_STATE_LOADING),
44 INIT_MIRROR(mVolume, 1.0),
45 INIT_MIRROR(mPreservesPitch, true),
46 INIT_MIRROR(mLooping, false),
47 INIT_MIRROR(mSecondaryVideoContainer, nullptr),
48 INIT_CANONICAL(mDuration, media::NullableTimeUnit()),
49 INIT_CANONICAL(mCurrentPosition, media::TimeUnit::Zero()),
50 INIT_CANONICAL(mIsAudioDataAudible, false),
51 mMinimizePreroll(aDecoder->GetMinimizePreroll()),
52 mWatchManager(this, mTaskQueue) {}
54 MediaEventSource<void>& MediaDecoderStateMachineBase::OnMediaNotSeekable()
55 const {
56 return mReader->OnMediaNotSeekable();
59 AbstractCanonical<media::TimeIntervals>*
60 MediaDecoderStateMachineBase::CanonicalBuffered() const {
61 return mReader->CanonicalBuffered();
64 void MediaDecoderStateMachineBase::DispatchSetFragmentEndTime(
65 const media::TimeUnit& aEndTime) {
66 OwnerThread()->DispatchStateChange(NewRunnableMethod<media::TimeUnit>(
67 "MediaDecoderStateMachineBase::SetFragmentEndTime", this,
68 &MediaDecoderStateMachineBase::SetFragmentEndTime, aEndTime));
71 void MediaDecoderStateMachineBase::DispatchCanPlayThrough(
72 bool aCanPlayThrough) {
73 OwnerThread()->DispatchStateChange(NewRunnableMethod<bool>(
74 "MediaDecoderStateMachineBase::SetCanPlayThrough", this,
75 &MediaDecoderStateMachineBase::SetCanPlayThrough, aCanPlayThrough));
78 void MediaDecoderStateMachineBase::DispatchIsLiveStream(bool aIsLiveStream) {
79 OwnerThread()->DispatchStateChange(NewRunnableMethod<bool>(
80 "MediaDecoderStateMachineBase::SetIsLiveStream", this,
81 &MediaDecoderStateMachineBase::SetIsLiveStream, aIsLiveStream));
84 void MediaDecoderStateMachineBase::DispatchSetPlaybackRate(
85 double aPlaybackRate) {
86 OwnerThread()->DispatchStateChange(NewRunnableMethod<double>(
87 "MediaDecoderStateMachineBase::SetPlaybackRate", this,
88 &MediaDecoderStateMachineBase::SetPlaybackRate, aPlaybackRate));
91 nsresult MediaDecoderStateMachineBase::Init(MediaDecoder* aDecoder) {
92 MOZ_ASSERT(NS_IsMainThread());
94 // Dispatch initialization that needs to happen on that task queue.
95 nsCOMPtr<nsIRunnable> r = NewRunnableMethod<RefPtr<MediaDecoder>>(
96 "MediaDecoderStateMachineBase::InitializationTask", this,
97 &MediaDecoderStateMachineBase::InitializationTask, aDecoder);
98 mTaskQueue->DispatchStateChange(r.forget());
100 // Connect mirrors.
101 aDecoder->CanonicalPlayState().ConnectMirror(&mPlayState);
102 aDecoder->CanonicalVolume().ConnectMirror(&mVolume);
103 aDecoder->CanonicalPreservesPitch().ConnectMirror(&mPreservesPitch);
104 aDecoder->CanonicalLooping().ConnectMirror(&mLooping);
105 aDecoder->CanonicalSecondaryVideoContainer().ConnectMirror(
106 &mSecondaryVideoContainer);
108 nsresult rv = mReader->Init();
109 NS_ENSURE_SUCCESS(rv, rv);
111 mMetadataManager.Connect(mReader->TimedMetadataEvent(), OwnerThread());
113 return NS_OK;
116 void MediaDecoderStateMachineBase::InitializationTask(MediaDecoder* aDecoder) {
117 MOZ_ASSERT(OnTaskQueue());
119 // Connect mirrors.
120 mBuffered.Connect(mReader->CanonicalBuffered());
121 mReader->SetCanonicalDuration(mDuration);
123 // Initialize watchers.
124 mWatchManager.Watch(mBuffered,
125 &MediaDecoderStateMachineBase::BufferedRangeUpdated);
126 mWatchManager.Watch(mVolume, &MediaDecoderStateMachineBase::VolumeChanged);
127 mWatchManager.Watch(mPreservesPitch,
128 &MediaDecoderStateMachineBase::PreservesPitchChanged);
129 mWatchManager.Watch(mPlayState,
130 &MediaDecoderStateMachineBase::PlayStateChanged);
131 mWatchManager.Watch(mLooping, &MediaDecoderStateMachineBase::LoopingChanged);
132 mWatchManager.Watch(
133 mSecondaryVideoContainer,
134 &MediaDecoderStateMachineBase::UpdateSecondaryVideoContainer);
137 RefPtr<ShutdownPromise> MediaDecoderStateMachineBase::BeginShutdown() {
138 MOZ_ASSERT(NS_IsMainThread());
139 return InvokeAsync(
140 OwnerThread(), __func__,
141 [self = RefPtr<MediaDecoderStateMachineBase>(this), this]() {
142 mWatchManager.Shutdown();
143 mBuffered.DisconnectIfConnected();
144 mPlayState.DisconnectIfConnected();
145 mVolume.DisconnectIfConnected();
146 mPreservesPitch.DisconnectIfConnected();
147 mLooping.DisconnectIfConnected();
148 mSecondaryVideoContainer.DisconnectIfConnected();
149 return Shutdown();
153 RefPtr<MediaDecoder::SeekPromise> MediaDecoderStateMachineBase::InvokeSeek(
154 const SeekTarget& aTarget) {
155 return InvokeAsync(OwnerThread(), __func__,
156 [self = RefPtr<MediaDecoderStateMachineBase>(this),
157 target = aTarget]() { return self->Seek(target); });
160 bool MediaDecoderStateMachineBase::OnTaskQueue() const {
161 return OwnerThread()->IsCurrentThreadIn();
164 void MediaDecoderStateMachineBase::DecodeError(const MediaResult& aError) {
165 MOZ_ASSERT(OnTaskQueue());
166 if (aError != NS_ERROR_DOM_MEDIA_EXTERNAL_ENGINE_NOT_SUPPORTED_ERR) {
167 LOGE("Decode error: %s", aError.Description().get());
169 PROFILER_MARKER_TEXT("MDSMBase::DecodeError", MEDIA_PLAYBACK, {},
170 aError.Description());
171 // Notify the decode error and MediaDecoder will shut down MDSM.
172 mOnPlaybackErrorEvent.Notify(aError);
175 RefPtr<SetCDMPromise> MediaDecoderStateMachineBase::SetCDMProxy(
176 CDMProxy* aProxy) {
177 return mReader->SetCDMProxy(aProxy);
180 #undef INIT_MIRROR
181 #undef INIT_CANONICAL
182 #undef FMT
183 #undef LOG
184 #undef LOGV
185 #undef LOGW
186 #undef LOGE
188 } // namespace mozilla