Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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 : #if !defined(MediaDecoderReader_h_)
7 : #define MediaDecoderReader_h_
8 :
9 : #include "AbstractMediaDecoder.h"
10 : #include "AudioCompactor.h"
11 : #include "Intervals.h"
12 : #include "MediaData.h"
13 : #include "MediaInfo.h"
14 : #include "MediaMetadataManager.h"
15 : #include "MediaQueue.h"
16 : #include "MediaResult.h"
17 : #include "MediaTimer.h"
18 : #include "SeekTarget.h"
19 : #include "TimeUnits.h"
20 : #include "mozilla/EnumSet.h"
21 : #include "mozilla/MozPromise.h"
22 : #include "nsAutoPtr.h"
23 :
24 : namespace mozilla {
25 :
26 : class CDMProxy;
27 : class MediaDecoderReader;
28 : class TaskQueue;
29 : class VideoFrameContainer;
30 :
31 : struct WaitForDataRejectValue
32 : {
33 : enum Reason
34 : {
35 : SHUTDOWN,
36 : CANCELED
37 : };
38 :
39 0 : WaitForDataRejectValue(MediaData::Type aType, Reason aReason)
40 0 : :mType(aType), mReason(aReason)
41 : {
42 0 : }
43 : MediaData::Type mType;
44 : Reason mReason;
45 : };
46 :
47 0 : struct SeekRejectValue
48 : {
49 : MOZ_IMPLICIT SeekRejectValue(const MediaResult& aError)
50 : : mType(MediaData::NULL_DATA), mError(aError) { }
51 0 : MOZ_IMPLICIT SeekRejectValue(nsresult aResult)
52 0 : : mType(MediaData::NULL_DATA), mError(aResult) { }
53 0 : SeekRejectValue(MediaData::Type aType, const MediaResult& aError)
54 0 : : mType(aType), mError(aError) { }
55 : MediaData::Type mType;
56 : MediaResult mError;
57 : };
58 :
59 0 : struct MetadataHolder
60 : {
61 : UniquePtr<MediaInfo> mInfo;
62 : UniquePtr<MetadataTags> mTags;
63 : };
64 :
65 : struct MOZ_STACK_CLASS MediaDecoderReaderInit
66 : {
67 : AbstractMediaDecoder* const mDecoder;
68 : MediaResource* mResource = nullptr;
69 : VideoFrameContainer* mVideoFrameContainer = nullptr;
70 :
71 0 : explicit MediaDecoderReaderInit(AbstractMediaDecoder* aDecoder)
72 0 : : mDecoder(aDecoder)
73 : {
74 0 : }
75 : };
76 :
77 : // Encapsulates the decoding and reading of media data. Reading can either
78 : // synchronous and done on the calling "decode" thread, or asynchronous and
79 : // performed on a background thread, with the result being returned by
80 : // callback.
81 : // Unless otherwise specified, methods and fields of this class can only
82 : // be accessed on the decode task queue.
83 : class MediaDecoderReader
84 : {
85 : friend class ReRequestVideoWithSkipTask;
86 : friend class ReRequestAudioTask;
87 :
88 : static const bool IsExclusive = true;
89 :
90 : public:
91 : using TrackSet = EnumSet<TrackInfo::TrackType>;
92 :
93 : using MetadataPromise = MozPromise<MetadataHolder, MediaResult, IsExclusive>;
94 :
95 : template <typename Type>
96 : using DataPromise = MozPromise<RefPtr<Type>, MediaResult, IsExclusive>;
97 : using AudioDataPromise = DataPromise<AudioData>;
98 : using VideoDataPromise = DataPromise<VideoData>;
99 :
100 : using SeekPromise = MozPromise<media::TimeUnit, SeekRejectValue, IsExclusive>;
101 :
102 : // Note that, conceptually, WaitForData makes sense in a non-exclusive sense.
103 : // But in the current architecture it's only ever used exclusively (by MDSM),
104 : // so we mark it that way to verify our assumptions. If you have a use-case
105 : // for multiple WaitForData consumers, feel free to flip the exclusivity here.
106 : using WaitForDataPromise =
107 : MozPromise<MediaData::Type, WaitForDataRejectValue, IsExclusive>;
108 :
109 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderReader)
110 :
111 : // The caller must ensure that Shutdown() is called before aDecoder is
112 : // destroyed.
113 : explicit MediaDecoderReader(const MediaDecoderReaderInit& aInit);
114 :
115 : // Initializes the reader, returns NS_OK on success, or NS_ERROR_FAILURE
116 : // on failure.
117 : nsresult Init();
118 :
119 : // Called by MDSM in dormant state to release resources allocated by this
120 : // reader. The reader can resume decoding by calling Seek() to a specific
121 : // position.
122 0 : virtual void ReleaseResources() { }
123 :
124 : // Destroys the decoding state. The reader cannot be made usable again.
125 : // This is different from ReleaseMediaResources() as it is irreversable,
126 : // whereas ReleaseMediaResources() is. Must be called on the decode
127 : // thread.
128 : virtual RefPtr<ShutdownPromise> Shutdown();
129 :
130 0 : virtual bool OnTaskQueue() const
131 : {
132 0 : return OwnerThread()->IsCurrentThreadIn();
133 : }
134 :
135 : void UpdateDuration(const media::TimeUnit& aDuration);
136 :
137 : // Resets all state related to decoding, emptying all buffers etc.
138 : // Cancels all pending Request*Data() request callbacks, rejects any
139 : // outstanding seek promises, and flushes the decode pipeline. The
140 : // decoder must not call any of the callbacks for outstanding
141 : // Request*Data() calls after this is called. Calls to Request*Data()
142 : // made after this should be processed as usual.
143 : //
144 : // Normally this call preceedes a Seek() call, or shutdown.
145 : //
146 : // aParam is a set of TrackInfo::TrackType enums specifying which
147 : // queues need to be reset, defaulting to both audio and video tracks.
148 : virtual nsresult ResetDecode(
149 : TrackSet aTracks = TrackSet(TrackInfo::kAudioTrack,
150 : TrackInfo::kVideoTrack));
151 :
152 : // Requests one audio sample from the reader.
153 : //
154 : // The decode should be performed asynchronously, and the promise should
155 : // be resolved when it is complete.
156 : virtual RefPtr<AudioDataPromise> RequestAudioData();
157 :
158 : // Requests one video sample from the reader.
159 : virtual RefPtr<VideoDataPromise>
160 : RequestVideoData(const media::TimeUnit& aTimeThreshold);
161 :
162 : // By default, the state machine polls the reader once per second when it's
163 : // in buffering mode. Some readers support a promise-based mechanism by which
164 : // they notify the state machine when the data arrives.
165 0 : virtual bool IsWaitForDataSupported() const { return false; }
166 :
167 0 : virtual RefPtr<WaitForDataPromise> WaitForData(MediaData::Type aType)
168 : {
169 0 : MOZ_CRASH();
170 : }
171 :
172 : // The default implementation of AsyncReadMetadata is implemented in terms of
173 : // synchronous ReadMetadata() calls. Implementations may also
174 : // override AsyncReadMetadata to create a more proper async implementation.
175 : virtual RefPtr<MetadataPromise> AsyncReadMetadata();
176 :
177 : // Fills aInfo with the latest cached data required to present the media,
178 : // ReadUpdatedMetadata will always be called once ReadMetadata has succeeded.
179 0 : virtual void ReadUpdatedMetadata(MediaInfo* aInfo) {}
180 :
181 : // Moves the decode head to aTime microseconds.
182 : virtual RefPtr<SeekPromise> Seek(const SeekTarget& aTarget) = 0;
183 :
184 0 : virtual void SetCDMProxy(CDMProxy* aProxy) {}
185 :
186 : // Tell the reader that the data decoded are not for direct playback, so it
187 : // can accept more files, in particular those which have more channels than
188 : // available in the audio output.
189 0 : void SetIgnoreAudioOutputFormat()
190 : {
191 0 : mIgnoreAudioOutputFormat = true;
192 0 : }
193 :
194 : // The MediaDecoderStateMachine uses various heuristics that assume that
195 : // raw media data is arriving sequentially from a network channel. This
196 : // makes sense in the <video src="foo"> case, but not for more advanced use
197 : // cases like MSE.
198 0 : virtual bool UseBufferingHeuristics() const { return true; }
199 :
200 : // Returns the number of bytes of memory allocated by structures/frames in
201 : // the video queue.
202 : size_t SizeOfVideoQueueInBytes() const;
203 :
204 : // Returns the number of bytes of memory allocated by structures/frames in
205 : // the audio queue.
206 : size_t SizeOfAudioQueueInBytes() const;
207 :
208 : virtual size_t SizeOfVideoQueueInFrames();
209 : virtual size_t SizeOfAudioQueueInFrames();
210 :
211 : // Called once new data has been cached by the MediaResource.
212 : // mBuffered should be recalculated and updated accordingly.
213 0 : virtual void NotifyDataArrived()
214 : {
215 0 : MOZ_ASSERT(OnTaskQueue());
216 0 : NS_ENSURE_TRUE_VOID(!mShutdown);
217 0 : UpdateBuffered();
218 : }
219 :
220 0 : virtual MediaQueue<AudioData>& AudioQueue() { return mAudioQueue; }
221 0 : virtual MediaQueue<VideoData>& VideoQueue() { return mVideoQueue; }
222 :
223 0 : AbstractCanonical<media::TimeIntervals>* CanonicalBuffered()
224 : {
225 0 : return &mBuffered;
226 : }
227 :
228 0 : TaskQueue* OwnerThread() const
229 : {
230 0 : return mTaskQueue;
231 : }
232 :
233 : // Returns true if the reader implements RequestAudioData()
234 : // and RequestVideoData() asynchronously, rather than using the
235 : // implementation in this class to adapt the old synchronous to
236 : // the newer async model.
237 0 : virtual bool IsAsync() const { return false; }
238 :
239 : // Returns true if this decoder reader uses hardware accelerated video
240 : // decoding.
241 0 : virtual bool VideoIsHardwareAccelerated() const { return false; }
242 :
243 0 : TimedMetadataEventSource& TimedMetadataEvent()
244 : {
245 0 : return mTimedMetadataEvent;
246 : }
247 :
248 : // Notified by the OggDemuxer during playback when chained ogg is detected.
249 0 : MediaEventSource<void>& OnMediaNotSeekable() { return mOnMediaNotSeekable; }
250 :
251 0 : TimedMetadataEventProducer& TimedMetadataProducer()
252 : {
253 0 : return mTimedMetadataEvent;
254 : }
255 :
256 0 : MediaEventProducer<void>& MediaNotSeekableProducer()
257 : {
258 0 : return mOnMediaNotSeekable;
259 : }
260 :
261 : // Notified if the reader can't decode a sample due to a missing decryption
262 : // key.
263 0 : MediaEventSource<TrackInfo::TrackType>& OnTrackWaitingForKey()
264 : {
265 0 : return mOnTrackWaitingForKey;
266 : }
267 :
268 0 : MediaEventProducer<TrackInfo::TrackType>& OnTrackWaitingForKeyProducer()
269 : {
270 0 : return mOnTrackWaitingForKey;
271 : }
272 :
273 : // Switch the video decoder to NullDecoderModule. It might takes effective
274 : // since a few samples later depends on how much demuxed samples are already
275 : // queued in the original video decoder.
276 0 : virtual void SetVideoNullDecode(bool aIsNullDecode) { }
277 :
278 : protected:
279 : virtual ~MediaDecoderReader();
280 :
281 : // Recomputes mBuffered.
282 : virtual void UpdateBuffered();
283 :
284 : RefPtr<VideoDataPromise> DecodeToFirstVideoData();
285 :
286 : // Queue of audio frames. This queue is threadsafe, and is accessed from
287 : // the audio, decoder, state machine, and main threads.
288 : MediaQueue<AudioData> mAudioQueue;
289 :
290 : // Queue of video frames. This queue is threadsafe, and is accessed from
291 : // the decoder, state machine, and main threads.
292 : MediaQueue<VideoData> mVideoQueue;
293 :
294 : // An adapter to the audio queue which first copies data to buffers with
295 : // minimal allocation slop and then pushes them to the queue. This is
296 : // useful for decoders working with formats that give awkward numbers of
297 : // frames such as mp3.
298 : AudioCompactor mAudioCompactor;
299 :
300 : // Reference to the owning decoder object.
301 : AbstractMediaDecoder* mDecoder;
302 :
303 : // Decode task queue.
304 : RefPtr<TaskQueue> mTaskQueue;
305 :
306 : // Buffered range.
307 : Canonical<media::TimeIntervals> mBuffered;
308 :
309 : // Stores presentation info required for playback.
310 : MediaInfo mInfo;
311 :
312 : media::NullableTimeUnit mDuration;
313 :
314 : // Whether we should accept media that we know we can't play
315 : // directly, because they have a number of channel higher than
316 : // what we support.
317 : bool mIgnoreAudioOutputFormat;
318 :
319 : // This is a quick-and-dirty way for DecodeAudioData implementations to
320 : // communicate the presence of a decoding error to RequestAudioData. We should
321 : // replace this with a promise-y mechanism as we make this stuff properly
322 : // async.
323 : bool mHitAudioDecodeError;
324 : bool mShutdown;
325 :
326 : // Used to send TimedMetadata to the listener.
327 : TimedMetadataEventProducer mTimedMetadataEvent;
328 :
329 : // Notify if this media is not seekable.
330 : MediaEventProducer<void> mOnMediaNotSeekable;
331 :
332 : // Notify if we are waiting for a decryption key.
333 : MediaEventProducer<TrackInfo::TrackType> mOnTrackWaitingForKey;
334 :
335 : RefPtr<MediaResource> mResource;
336 :
337 : private:
338 0 : virtual nsresult InitInternal() { return NS_OK; }
339 :
340 : // Read header data for all bitstreams in the file. Fills aInfo with
341 : // the data required to present the media, and optionally fills *aTags
342 : // with tag metadata from the file.
343 : // Returns NS_OK on success, or NS_ERROR_FAILURE on failure.
344 0 : virtual nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
345 : {
346 0 : MOZ_CRASH();
347 : }
348 :
349 : virtual void VisibilityChanged();
350 :
351 : // Overrides of this function should decodes an unspecified amount of
352 : // audio data, enqueuing the audio data in mAudioQueue. Returns true
353 : // when there's more audio to decode, false if the audio is finished,
354 : // end of file has been reached, or an un-recoverable read error has
355 : // occured. This function blocks until the decode is complete.
356 0 : virtual bool DecodeAudioData()
357 : {
358 0 : return false;
359 : }
360 :
361 : // Overrides of this function should read and decodes one video frame.
362 : // Packets with a timestamp less than aTimeThreshold will be decoded
363 : // (unless they're not keyframes and aKeyframeSkip is true), but will
364 : // not be added to the queue. This function blocks until the decode
365 : // is complete.
366 0 : virtual bool DecodeVideoFrame(bool& aKeyframeSkip,
367 : const media::TimeUnit& aTimeThreshold)
368 : {
369 0 : return false;
370 : }
371 :
372 : // GetBuffered estimates the time ranges buffered by interpolating the cached
373 : // byte ranges with the duration of the media. Reader subclasses should
374 : // override this method if they can quickly calculate the buffered ranges more
375 : // accurately.
376 : //
377 : // The primary advantage of this implementation in the reader base class is
378 : // that it's a fast approximation, which does not perform any I/O.
379 : media::TimeIntervals GetBuffered();
380 :
381 : // Promises used only for the base-class (sync->async adapter) implementation
382 : // of Request{Audio,Video}Data.
383 : MozPromiseHolder<AudioDataPromise> mBaseAudioPromise;
384 : MozPromiseHolder<VideoDataPromise> mBaseVideoPromise;
385 : };
386 :
387 : } // namespace mozilla
388 :
389 : #endif
|