Backed out 7 changesets (bug 1839993) for causing build bustages on DecoderTemplate...
[gecko.git] / dom / media / webcodecs / DecoderTemplate.h
blobfe0cb5baeea2eb856e33b8cf36be152d91098975
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_DecoderTemplate_h
8 #define mozilla_dom_DecoderTemplate_h
10 #include <queue>
12 #include "mozilla/DOMEventTargetHelper.h"
13 #include "mozilla/DecoderAgent.h"
14 #include "mozilla/MozPromise.h"
15 #include "mozilla/RefPtr.h"
16 #include "mozilla/Result.h"
17 #include "mozilla/UniquePtr.h"
18 #include "mozilla/dom/WorkerRef.h"
19 #include "mozilla/media/MediaUtils.h"
20 #include "nsStringFwd.h"
21 #include "WebCodecsUtils.h"
23 namespace mozilla {
25 class TrackInfo;
27 namespace dom {
29 class WebCodecsErrorCallback;
30 class Promise;
31 enum class CodecState : uint8_t;
33 template <typename DecoderType>
34 class DecoderTemplate : public DOMEventTargetHelper {
35 using Self = DecoderTemplate<DecoderType>;
36 using ConfigType = typename DecoderType::ConfigType;
37 using ConfigTypeInternal = typename DecoderType::ConfigTypeInternal;
38 using InputType = typename DecoderType::InputType;
39 using InputTypeInternal = typename DecoderType::InputTypeInternal;
40 using OutputType = typename DecoderType::OutputType;
41 using OutputCallbackType = typename DecoderType::OutputCallbackType;
43 /* ControlMessage classes */
44 protected:
45 class ConfigureMessage;
46 class DecodeMessage;
47 class FlushMessage;
49 class ControlMessage {
50 public:
51 explicit ControlMessage(const nsACString& aTitle);
52 virtual ~ControlMessage() = default;
53 virtual void Cancel() = 0;
54 virtual bool IsProcessing() = 0;
56 virtual const nsCString& ToString() const { return mTitle; }
57 virtual ConfigureMessage* AsConfigureMessage() { return nullptr; }
58 virtual DecodeMessage* AsDecodeMessage() { return nullptr; }
59 virtual FlushMessage* AsFlushMessage() { return nullptr; }
61 const nsCString mTitle; // Used to identify the message in the logs.
64 class ConfigureMessage final
65 : public ControlMessage,
66 public MessageRequestHolder<DecoderAgent::ConfigurePromise> {
67 public:
68 using Id = DecoderAgent::Id;
69 static constexpr Id NoId = 0;
70 static ConfigureMessage* Create(UniquePtr<ConfigTypeInternal>&& aConfig);
72 ~ConfigureMessage() = default;
73 virtual void Cancel() override { Disconnect(); }
74 virtual bool IsProcessing() override { return Exists(); };
75 virtual ConfigureMessage* AsConfigureMessage() override { return this; }
76 const ConfigTypeInternal& Config() { return *mConfig; }
77 UniquePtr<ConfigTypeInternal> TakeConfig() { return std::move(mConfig); }
79 const Id mId; // A unique id shown in log.
81 private:
82 ConfigureMessage(Id aId, UniquePtr<ConfigTypeInternal>&& aConfig);
84 UniquePtr<ConfigTypeInternal> mConfig;
87 class DecodeMessage final
88 : public ControlMessage,
89 public MessageRequestHolder<DecoderAgent::DecodePromise> {
90 public:
91 using Id = size_t;
92 using ConfigId = typename Self::ConfigureMessage::Id;
93 DecodeMessage(Id aId, ConfigId aConfigId,
94 UniquePtr<InputTypeInternal>&& aData);
95 ~DecodeMessage() = default;
96 virtual void Cancel() override { Disconnect(); }
97 virtual bool IsProcessing() override { return Exists(); };
98 virtual DecodeMessage* AsDecodeMessage() override { return this; }
99 const Id mId; // A unique id shown in log.
101 UniquePtr<InputTypeInternal> mData;
104 class FlushMessage final
105 : public ControlMessage,
106 public MessageRequestHolder<DecoderAgent::DecodePromise> {
107 public:
108 using Id = size_t;
109 using ConfigId = typename Self::ConfigureMessage::Id;
110 FlushMessage(Id aId, ConfigId aConfigId, Promise* aPromise);
111 ~FlushMessage() = default;
112 virtual void Cancel() override { Disconnect(); }
113 virtual bool IsProcessing() override { return Exists(); };
114 virtual FlushMessage* AsFlushMessage() override { return this; }
115 already_AddRefed<Promise> TakePromise() { return mPromise.forget(); }
116 void RejectPromiseIfAny(const nsresult& aReason);
118 const Id mId; // A unique id shown in log.
120 private:
121 RefPtr<Promise> mPromise;
124 protected:
125 DecoderTemplate(nsIGlobalObject* aGlobalObject,
126 RefPtr<WebCodecsErrorCallback>&& aErrorCallback,
127 RefPtr<OutputCallbackType>&& aOutputCallback);
129 virtual ~DecoderTemplate() = default;
131 /* WebCodecs interfaces */
132 public:
133 IMPL_EVENT_HANDLER(dequeue)
135 CodecState State() const { return mState; };
137 uint32_t DecodeQueueSize() const { return mDecodeQueueSize; };
139 void Configure(const ConfigType& aConfig, ErrorResult& aRv);
141 void Decode(InputType& aInput, ErrorResult& aRv);
143 already_AddRefed<Promise> Flush(ErrorResult& aRv);
145 void Reset(ErrorResult& aRv);
147 void Close(ErrorResult& aRv);
149 /* Type conversion functions for the Decoder implementation */
150 protected:
151 virtual already_AddRefed<MediaRawData> InputDataToMediaRawData(
152 UniquePtr<InputTypeInternal>&& aData, TrackInfo& aInfo,
153 const ConfigTypeInternal& aConfig) = 0;
154 virtual nsTArray<RefPtr<OutputType>> DecodedDataToOutputType(
155 nsIGlobalObject* aGlobalObject, const nsTArray<RefPtr<MediaData>>&& aData,
156 ConfigTypeInternal& aConfig) = 0;
158 protected:
159 // DecoderTemplate can run on either main thread or worker thread.
160 void AssertIsOnOwningThread() const {
161 NS_ASSERT_OWNINGTHREAD(DecoderTemplate);
164 Result<Ok, nsresult> ResetInternal(const nsresult& aResult);
165 // Calling this method calls the error callback synchronously.
166 MOZ_CAN_RUN_SCRIPT
167 void CloseInternal(const nsresult& aResult);
168 // Calling this method doesn't call the error calback.
169 Result<Ok, nsresult> CloseInternalWithAbort();
171 MOZ_CAN_RUN_SCRIPT void ReportError(const nsresult& aResult);
172 MOZ_CAN_RUN_SCRIPT void OutputDecodedData(
173 const nsTArray<RefPtr<MediaData>>&& aData);
175 void ScheduleDequeueEventIfNeeded();
176 nsresult FireEvent(nsAtom* aTypeWithOn, const nsAString& aEventType);
178 void ProcessControlMessageQueue();
179 void CancelPendingControlMessages(const nsresult& aResult);
181 // Queue a task to the control thread. This is to be used when a task needs to
182 // perform multiple steps.
183 template <typename Func>
184 void QueueATask(const char* aName, Func&& aSteps);
186 MessageProcessedResult ProcessConfigureMessage(
187 UniquePtr<ControlMessage>& aMessage);
189 MessageProcessedResult ProcessDecodeMessage(
190 UniquePtr<ControlMessage>& aMessage);
192 MessageProcessedResult ProcessFlushMessage(
193 UniquePtr<ControlMessage>& aMessage);
195 // Returns true when mAgent can be created.
196 bool CreateDecoderAgent(DecoderAgent::Id aId,
197 UniquePtr<ConfigTypeInternal>&& aConfig,
198 UniquePtr<TrackInfo>&& aInfo);
199 void DestroyDecoderAgentIfAny();
201 // Constant in practice, only set in ctor.
202 RefPtr<WebCodecsErrorCallback> mErrorCallback;
203 RefPtr<OutputCallbackType> mOutputCallback;
205 CodecState mState;
206 bool mKeyChunkRequired;
208 bool mMessageQueueBlocked;
209 std::queue<UniquePtr<ControlMessage>> mControlMessageQueue;
210 UniquePtr<ControlMessage> mProcessingMessage;
212 uint32_t mDecodeQueueSize;
213 bool mDequeueEventScheduled;
215 // A unique id tracking the ConfigureMessage and will be used as the
216 // DecoderAgent's Id.
217 uint32_t mLatestConfigureId;
218 // Tracking how many decode data has been enqueued and this number will be
219 // used as the DecodeMessage's Id.
220 size_t mDecodeCounter;
221 // Tracking how many flush request has been enqueued and this number will be
222 // used as the FlushMessage's Id.
223 size_t mFlushCounter;
225 // DecoderAgent will be created every time "configure" is being processed, and
226 // will be destroyed when "reset" or another "configure" is called (spec
227 // allows calling two "configure" without a "reset" in between).
228 RefPtr<DecoderAgent> mAgent;
229 UniquePtr<ConfigTypeInternal> mActiveConfig;
231 // Used to add a nsIAsyncShutdownBlocker on main thread to block
232 // xpcom-shutdown before the underlying MediaDataDecoder is created. The
233 // blocker will be held until the underlying MediaDataDecoder has been shut
234 // down. This blocker guarantees RemoteDecoderManagerChild's thread, where the
235 // underlying RemoteMediaDataDecoder is on, outlives the
236 // RemoteMediaDataDecoder, since the thread releasing, which happens on main
237 // thread when getting a xpcom-shutdown signal, is blocked by the added
238 // blocker. As a result, RemoteMediaDataDecoder can safely work on worker
239 // thread with a holding blocker (otherwise, if RemoteDecoderManagerChild
240 // releases its thread on main thread before RemoteMediaDataDecoder's
241 // Shutdown() task run on worker thread, RemoteMediaDataDecoder has no thread
242 // to run).
243 UniquePtr<media::ShutdownBlockingTicket> mShutdownBlocker;
245 // Held to make sure the dispatched tasks can be done before worker is going
246 // away. As long as this worker-ref is held somewhere, the tasks dispatched to
247 // the worker can be executed (otherwise the tasks would be canceled). This
248 // ref should be activated as long as the underlying MediaDataDecoder is
249 // alive, and should keep alive until mShutdownBlocker is dropped, so all
250 // MediaDataDecoder's tasks and mShutdownBlocker-releasing task can be
251 // executed.
252 // TODO: Use StrongWorkerRef instead if this is always used in the same
253 // thread?
254 RefPtr<ThreadSafeWorkerRef> mWorkerRef;
257 } // namespace dom
258 } // namespace mozilla
260 #endif // mozilla_dom_DecoderTemplate_h