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"
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__
20 DDMOZ_LOG(gMediaDecoderLog, LogLevel::Debug, "Decoder=%p " x, mDecoderID, \
22 #define LOGV(x, ...) \
23 DDMOZ_LOG(gMediaDecoderLog, LogLevel::Verbose, "Decoder=%p " x, mDecoderID, \
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, \
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
),
39 /* aSupportsTailDispatch = */ true)),
40 mReader(new ReaderProxy(mTaskQueue
, aReader
)),
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()
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
);
109 void MediaDecoderStateMachineBase::InitializationTask(MediaDecoder
* aDecoder
) {
110 MOZ_ASSERT(OnTaskQueue());
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
);
131 mSecondaryVideoContainer
,
132 &MediaDecoderStateMachineBase::UpdateSecondaryVideoContainer
);
135 RefPtr
<ShutdownPromise
> MediaDecoderStateMachineBase::BeginShutdown() {
136 MOZ_ASSERT(NS_IsMainThread());
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();
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(
173 return mReader
->SetCDMProxy(aProxy
);
177 #undef INIT_CANONICAL
184 } // namespace mozilla