Bug 1839170 - Refactor Snap pulling, Add Firefox Snap Core22 and GNOME 42 SDK symbols...
[gecko.git] / dom / media / MediaDecoderStateMachineBase.cpp
blob081ed09e6b6d4b6e64b491d2296fda2c3296a848
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 nsresult rv = mReader->Init();
101 NS_ENSURE_SUCCESS(rv, rv);
103 mMetadataManager.Connect(mReader->TimedMetadataEvent(), OwnerThread());
104 mReader->SetCanonicalDuration(&mDuration);
106 return NS_OK;
109 void MediaDecoderStateMachineBase::InitializationTask(MediaDecoder* aDecoder) {
110 MOZ_ASSERT(OnTaskQueue());
112 // Connect mirrors.
113 mBuffered.Connect(mReader->CanonicalBuffered());
114 mPlayState.Connect(aDecoder->CanonicalPlayState());
115 mVolume.Connect(aDecoder->CanonicalVolume());
116 mPreservesPitch.Connect(aDecoder->CanonicalPreservesPitch());
117 mLooping.Connect(aDecoder->CanonicalLooping());
118 mSecondaryVideoContainer.Connect(
119 aDecoder->CanonicalSecondaryVideoContainer());
121 // Initialize watchers.
122 mWatchManager.Watch(mBuffered,
123 &MediaDecoderStateMachineBase::BufferedRangeUpdated);
124 mWatchManager.Watch(mVolume, &MediaDecoderStateMachineBase::VolumeChanged);
125 mWatchManager.Watch(mPreservesPitch,
126 &MediaDecoderStateMachineBase::PreservesPitchChanged);
127 mWatchManager.Watch(mPlayState,
128 &MediaDecoderStateMachineBase::PlayStateChanged);
129 mWatchManager.Watch(mLooping, &MediaDecoderStateMachineBase::LoopingChanged);
130 mWatchManager.Watch(
131 mSecondaryVideoContainer,
132 &MediaDecoderStateMachineBase::UpdateSecondaryVideoContainer);
135 RefPtr<ShutdownPromise> MediaDecoderStateMachineBase::BeginShutdown() {
136 MOZ_ASSERT(NS_IsMainThread());
137 return InvokeAsync(
138 OwnerThread(), __func__,
139 [self = RefPtr<MediaDecoderStateMachineBase>(this), this]() {
140 mWatchManager.Shutdown();
141 mBuffered.DisconnectIfConnected();
142 mPlayState.DisconnectIfConnected();
143 mVolume.DisconnectIfConnected();
144 mPreservesPitch.DisconnectIfConnected();
145 mLooping.DisconnectIfConnected();
146 mSecondaryVideoContainer.DisconnectIfConnected();
147 return Shutdown();
151 RefPtr<MediaDecoder::SeekPromise> MediaDecoderStateMachineBase::InvokeSeek(
152 const SeekTarget& aTarget) {
153 return InvokeAsync(OwnerThread(), __func__,
154 [self = RefPtr<MediaDecoderStateMachineBase>(this),
155 target = aTarget]() { return self->Seek(target); });
158 bool MediaDecoderStateMachineBase::OnTaskQueue() const {
159 return OwnerThread()->IsCurrentThreadIn();
162 void MediaDecoderStateMachineBase::DecodeError(const MediaResult& aError) {
163 MOZ_ASSERT(OnTaskQueue());
164 LOGE("Decode error: %s", aError.Description().get());
165 PROFILER_MARKER_TEXT("MDSMBase::DecodeError", MEDIA_PLAYBACK, {},
166 aError.Description());
167 // Notify the decode error and MediaDecoder will shut down MDSM.
168 mOnPlaybackErrorEvent.Notify(aError);
171 RefPtr<SetCDMPromise> MediaDecoderStateMachineBase::SetCDMProxy(
172 CDMProxy* aProxy) {
173 return mReader->SetCDMProxy(aProxy);
176 #undef INIT_MIRROR
177 #undef INIT_CANONICAL
178 #undef FMT
179 #undef LOG
180 #undef LOGV
181 #undef LOGW
182 #undef LOGE
184 } // namespace mozilla