Line data Source code
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/. */
6 :
7 : #if !defined(PlatformDecoderModule_h_)
8 : #define PlatformDecoderModule_h_
9 :
10 : #include "GMPCrashHelper.h"
11 : #include "MediaDecoderReader.h"
12 : #include "MediaInfo.h"
13 : #include "MediaResult.h"
14 : #include "mozilla/EnumSet.h"
15 : #include "mozilla/MozPromise.h"
16 : #include "mozilla/RefPtr.h"
17 : #include "mozilla/layers/KnowsCompositor.h"
18 : #include "mozilla/layers/LayersTypes.h"
19 : #include "nsTArray.h"
20 : #include <queue>
21 :
22 : namespace mozilla {
23 : class TrackInfo;
24 : class AudioInfo;
25 : class VideoInfo;
26 : class MediaRawData;
27 : class DecoderDoctorDiagnostics;
28 :
29 : namespace layers {
30 : class ImageContainer;
31 : } // namespace layers
32 :
33 : namespace dom {
34 : class RemoteDecoderModule;
35 : }
36 :
37 : class MediaDataDecoder;
38 : class TaskQueue;
39 : class CDMProxy;
40 :
41 : static LazyLogModule sPDMLog("PlatformDecoderModule");
42 :
43 0 : struct MOZ_STACK_CLASS CreateDecoderParams final
44 : {
45 : explicit CreateDecoderParams(const TrackInfo& aConfig) : mConfig(aConfig) { }
46 :
47 : enum class Option
48 : {
49 : Default,
50 : LowLatency,
51 : };
52 : using OptionSet = EnumSet<Option>;
53 :
54 : template <typename T1, typename... Ts>
55 0 : CreateDecoderParams(const TrackInfo& aConfig, T1&& a1, Ts&&... args)
56 0 : : mConfig(aConfig)
57 : {
58 0 : Set(mozilla::Forward<T1>(a1), mozilla::Forward<Ts>(args)...);
59 0 : }
60 :
61 0 : const VideoInfo& VideoConfig() const
62 : {
63 0 : MOZ_ASSERT(mConfig.IsVideo());
64 0 : return *mConfig.GetAsVideoInfo();
65 : }
66 :
67 0 : const AudioInfo& AudioConfig() const
68 : {
69 0 : MOZ_ASSERT(mConfig.IsAudio());
70 0 : return *mConfig.GetAsAudioInfo();
71 : }
72 :
73 0 : layers::LayersBackend GetLayersBackend() const
74 : {
75 0 : if (mKnowsCompositor) {
76 0 : return mKnowsCompositor->GetCompositorBackendType();
77 : }
78 0 : return layers::LayersBackend::LAYERS_NONE;
79 : }
80 :
81 : const TrackInfo& mConfig;
82 : TaskQueue* mTaskQueue = nullptr;
83 : DecoderDoctorDiagnostics* mDiagnostics = nullptr;
84 : layers::ImageContainer* mImageContainer = nullptr;
85 : MediaResult* mError = nullptr;
86 : RefPtr<layers::KnowsCompositor> mKnowsCompositor;
87 : RefPtr<GMPCrashHelper> mCrashHelper;
88 : bool mUseNullDecoder = false;
89 : TrackInfo::TrackType mType = TrackInfo::kUndefinedTrack;
90 : MediaEventProducer<TrackInfo::TrackType>* mOnWaitingForKeyEvent = nullptr;
91 : OptionSet mOptions = OptionSet(Option::Default);
92 :
93 : private:
94 0 : void Set(TaskQueue* aTaskQueue) { mTaskQueue = aTaskQueue; }
95 0 : void Set(DecoderDoctorDiagnostics* aDiagnostics)
96 : {
97 0 : mDiagnostics = aDiagnostics;
98 0 : }
99 0 : void Set(layers::ImageContainer* aImageContainer)
100 : {
101 0 : mImageContainer = aImageContainer;
102 0 : }
103 0 : void Set(MediaResult* aError) { mError = aError; }
104 0 : void Set(GMPCrashHelper* aCrashHelper) { mCrashHelper = aCrashHelper; }
105 0 : void Set(bool aUseNullDecoder) { mUseNullDecoder = aUseNullDecoder; }
106 0 : void Set(OptionSet aOptions) { mOptions = aOptions; }
107 0 : void Set(layers::KnowsCompositor* aKnowsCompositor)
108 : {
109 0 : mKnowsCompositor = aKnowsCompositor;
110 0 : }
111 0 : void Set(TrackInfo::TrackType aType)
112 : {
113 0 : mType = aType;
114 0 : }
115 0 : void Set(MediaEventProducer<TrackInfo::TrackType>* aOnWaitingForKey)
116 : {
117 0 : mOnWaitingForKeyEvent = aOnWaitingForKey;
118 0 : }
119 : template <typename T1, typename T2, typename... Ts>
120 0 : void Set(T1&& a1, T2&& a2, Ts&&... args)
121 : {
122 0 : Set(mozilla::Forward<T1>(a1));
123 0 : Set(mozilla::Forward<T2>(a2), mozilla::Forward<Ts>(args)...);
124 0 : }
125 : };
126 :
127 : // The PlatformDecoderModule interface is used by the MediaFormatReader to
128 : // abstract access to decoders provided by various
129 : // platforms.
130 : // Each platform (Windows, MacOSX, Linux, B2G etc) must implement a
131 : // PlatformDecoderModule to provide access to its decoders in order to get
132 : // decompressed H.264/AAC from the MediaFormatReader.
133 : //
134 : // Decoding is asynchronous, and should be performed on the task queue
135 : // provided if the underlying platform isn't already exposing an async API.
136 : //
137 : // A cross-platform decoder module that discards input and produces "blank"
138 : // output samples exists for testing, and is created when the pref
139 : // "media.use-blank-decoder" is true.
140 :
141 : class PlatformDecoderModule
142 : {
143 : public:
144 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PlatformDecoderModule)
145 :
146 : // Perform any per-instance initialization.
147 : // This is called on the decode task queue.
148 0 : virtual nsresult Startup() { return NS_OK; }
149 :
150 : // Indicates if the PlatformDecoderModule supports decoding of aMimeType.
151 : virtual bool
152 : SupportsMimeType(const nsACString& aMimeType,
153 : DecoderDoctorDiagnostics* aDiagnostics) const = 0;
154 : virtual bool
155 0 : Supports(const TrackInfo& aTrackInfo,
156 : DecoderDoctorDiagnostics* aDiagnostics) const
157 : {
158 : // By default, fall back to SupportsMimeType with just the MIME string.
159 : // (So PDMs do not need to override this method -- yet.)
160 0 : return SupportsMimeType(aTrackInfo.mMimeType, aDiagnostics);
161 : }
162 :
163 : protected:
164 0 : PlatformDecoderModule() { }
165 0 : virtual ~PlatformDecoderModule() { }
166 :
167 : friend class H264Converter;
168 : friend class PDMFactory;
169 : friend class dom::RemoteDecoderModule;
170 : friend class EMEDecoderModule;
171 :
172 : // Creates a Video decoder. The layers backend is passed in so that
173 : // decoders can determine whether hardware accelerated decoding can be used.
174 : // Asynchronous decoding of video should be done in runnables dispatched
175 : // to aVideoTaskQueue. If the task queue isn't needed, the decoder should
176 : // not hold a reference to it.
177 : // On Windows the task queue's threads in have MSCOM initialized with
178 : // COINIT_MULTITHREADED.
179 : // Returns nullptr if the decoder can't be created.
180 : // It is safe to store a reference to aConfig.
181 : // This is called on the decode task queue.
182 : virtual already_AddRefed<MediaDataDecoder>
183 : CreateVideoDecoder(const CreateDecoderParams& aParams) = 0;
184 :
185 : // Creates an Audio decoder with the specified properties.
186 : // Asynchronous decoding of audio should be done in runnables dispatched to
187 : // aAudioTaskQueue. If the task queue isn't needed, the decoder should
188 : // not hold a reference to it.
189 : // Returns nullptr if the decoder can't be created.
190 : // On Windows the task queue's threads in have MSCOM initialized with
191 : // COINIT_MULTITHREADED.
192 : // It is safe to store a reference to aConfig.
193 : // This is called on the decode task queue.
194 : virtual already_AddRefed<MediaDataDecoder>
195 : CreateAudioDecoder(const CreateDecoderParams& aParams) = 0;
196 : };
197 :
198 : // MediaDataDecoder is the interface exposed by decoders created by the
199 : // PlatformDecoderModule's Create*Decoder() functions. The type of
200 : // media data that the decoder accepts as valid input and produces as
201 : // output is determined when the MediaDataDecoder is created.
202 : //
203 : // Unless otherwise noted, all functions are only called on the decode task
204 : // queue. An exception is the MediaDataDecoder in
205 : // MediaFormatReader::IsVideoAccelerated() for which all calls (Init(),
206 : // IsHardwareAccelerated(), and Shutdown()) are from the main thread.
207 : //
208 : // Don't block inside these functions, unless it's explicitly noted that you
209 : // should (like in Flush()).
210 : //
211 : // Decoding is done asynchronously. Any async work can be done on the
212 : // TaskQueue passed into the PlatformDecoderModules's Create*Decoder()
213 : // function. This may not be necessary for platforms with async APIs
214 : // for decoding.
215 0 : class MediaDataDecoder
216 : {
217 : protected:
218 0 : virtual ~MediaDataDecoder() { }
219 :
220 : public:
221 : typedef TrackInfo::TrackType TrackType;
222 : typedef nsTArray<RefPtr<MediaData>> DecodedData;
223 : typedef MozPromise<TrackType, MediaResult, /* IsExclusive = */ true>
224 : InitPromise;
225 : typedef MozPromise<DecodedData, MediaResult, /* IsExclusive = */ true>
226 : DecodePromise;
227 : typedef MozPromise<bool, MediaResult, /* IsExclusive = */ true> FlushPromise;
228 :
229 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDataDecoder)
230 :
231 : // Initialize the decoder. The decoder should be ready to decode once
232 : // promise resolves. The decoder should do any initialization here, rather
233 : // than in its constructor or PlatformDecoderModule::Create*Decoder(),
234 : // so that if the MediaFormatReader needs to shutdown during initialization,
235 : // it can call Shutdown() to cancel this operation. Any initialization
236 : // that requires blocking the calling thread in this function *must*
237 : // be done here so that it can be canceled by calling Shutdown()!
238 : virtual RefPtr<InitPromise> Init() = 0;
239 :
240 : // Inserts a sample into the decoder's decode pipeline. The DecodePromise will
241 : // be resolved with the decoded MediaData. In case the decoder needs more
242 : // input, the DecodePromise may be resolved with an empty array of samples to
243 : // indicate that Decode should be called again before a MediaData is returned.
244 : virtual RefPtr<DecodePromise> Decode(MediaRawData* aSample) = 0;
245 :
246 : // Causes all complete samples in the pipeline that can be decoded to be
247 : // output. If the decoder can't produce samples from the current output,
248 : // it drops the input samples. The decoder may be holding onto samples
249 : // that are required to decode samples that it expects to get in future.
250 : // This is called when the demuxer reaches end of stream.
251 : // This function is asynchronous.
252 : // The MediaDataDecoder shall resolve the pending DecodePromise with drained
253 : // samples. Drain will be called multiple times until the resolved
254 : // DecodePromise is empty which indicates that there are no more samples to
255 : // drain.
256 : virtual RefPtr<DecodePromise> Drain() = 0;
257 :
258 : // Causes all samples in the decoding pipeline to be discarded. When this
259 : // promise resolves, the decoder must be ready to accept new data for
260 : // decoding. This function is called when the demuxer seeks, before decoding
261 : // resumes after the seek. The current DecodePromise if any shall be rejected
262 : // with NS_ERROR_DOM_MEDIA_CANCELED
263 : virtual RefPtr<FlushPromise> Flush() = 0;
264 :
265 : // Cancels all init/decode/drain operations, and shuts down the decoder. The
266 : // platform decoder should clean up any resources it's using and release
267 : // memory etc. The shutdown promise will be resolved once the decoder has
268 : // completed shutdown. The reader calls Flush() before calling Shutdown(). The
269 : // reader will delete the decoder once the promise is resolved.
270 : // The ShutdownPromise must only ever be resolved.
271 : virtual RefPtr<ShutdownPromise> Shutdown() = 0;
272 :
273 : // Called from the state machine task queue or main thread. Decoder needs to
274 : // decide whether or not hardware acceleration is supported after creating.
275 : // It doesn't need to call Init() before calling this function.
276 0 : virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const
277 : {
278 0 : return false;
279 : }
280 :
281 : // Return the name of the MediaDataDecoder, only used for decoding.
282 : // Only return a static const string, as the information may be accessed
283 : // in a non thread-safe fashion.
284 : virtual const char* GetDescriptionName() const = 0;
285 :
286 : // Set a hint of seek target time to decoder. Decoder will drop any decoded
287 : // data which pts is smaller than this value. This threshold needs to be clear
288 : // after reset decoder.
289 : // Decoder may not honor this value. However, it'd be better that
290 : // video decoder implements this API to improve seek performance.
291 : // Note: it should be called before Input() or after Flush().
292 0 : virtual void SetSeekThreshold(const media::TimeUnit& aTime) { }
293 :
294 : // When playing adaptive playback, recreating an Android video decoder will
295 : // cause the transition not smooth during resolution change.
296 : // Reuse the decoder if the decoder support recycling.
297 : // Currently, only Android video decoder will return true.
298 0 : virtual bool SupportDecoderRecycling() const { return false; }
299 :
300 : enum class ConversionRequired
301 : {
302 : kNeedNone = 0,
303 : kNeedAVCC = 1,
304 : kNeedAnnexB = 2,
305 : };
306 :
307 : // Indicates that the decoder requires a specific format.
308 : // The demuxed data will be converted accordingly before feeding it to
309 : // Decode().
310 0 : virtual ConversionRequired NeedsConversion() const
311 : {
312 0 : return ConversionRequired::kNeedNone;
313 : }
314 : };
315 :
316 : } // namespace mozilla
317 :
318 : #endif
|