content/media/MediaDecoder.h

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:2648899e52fd
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 Each video element based on MediaDecoder has a state machine to manage
8 its play state and keep the current frame up to date. All state machines
9 share time in a single shared thread. Each decoder also has one thread
10 dedicated to decoding audio and video data. This thread is shutdown when
11 playback is paused. Each decoder also has a thread to push decoded audio
12 to the hardware. This thread is not created until playback starts, but
13 currently is not destroyed when paused, only when playback ends.
14
15 The decoder owns the resources for downloading the media file, and the
16 high level state. It holds an owning reference to the state machine that
17 owns all the resources related to decoding data, and manages the low level
18 decoding operations and A/V sync.
19
20 Each state machine runs on the shared state machine thread. Every time some
21 action is required for a state machine, it is scheduled to run on the shared
22 the state machine thread. The state machine runs one "cycle" on the state
23 machine thread, and then returns. If necessary, it will schedule itself to
24 run again in future. While running this cycle, it must not block the
25 thread, as other state machines' events may need to run. State shared
26 between a state machine's threads is synchronised via the monitor owned
27 by its MediaDecoder object.
28
29 The Main thread controls the decode state machine by setting the value
30 of a mPlayState variable and notifying on the monitor based on the
31 high level player actions required (Seek, Pause, Play, etc).
32
33 The player states are the states requested by the client through the
34 DOM API. They represent the desired state of the player, while the
35 decoder's state represents the actual state of the decoder.
36
37 The high level state of the player is maintained via a PlayState value.
38 It can have the following states:
39
40 START
41 The decoder has been initialized but has no resource loaded.
42 PAUSED
43 A request via the API has been received to pause playback.
44 LOADING
45 A request via the API has been received to load a resource.
46 PLAYING
47 A request via the API has been received to start playback.
48 SEEKING
49 A request via the API has been received to start seeking.
50 COMPLETED
51 Playback has completed.
52 SHUTDOWN
53 The decoder is about to be destroyed.
54
55 State transition occurs when the Media Element calls the Play, Seek,
56 etc methods on the MediaDecoder object. When the transition
57 occurs MediaDecoder then calls the methods on the decoder state
58 machine object to cause it to behave as required by the play state.
59 State transitions will likely schedule the state machine to run to
60 affect the change.
61
62 An implementation of the MediaDecoderStateMachine class is the event
63 that gets dispatched to the state machine thread. Each time the event is run,
64 the state machine must cycle the state machine once, and then return.
65
66 The state machine has the following states:
67
68 DECODING_METADATA
69 The media headers are being loaded, and things like framerate, etc are
70 being determined, and the first frame of audio/video data is being decoded.
71 DECODING
72 The decode has started. If the PlayState is PLAYING, the decode thread
73 should be alive and decoding video and audio frame, the audio thread
74 should be playing audio, and the state machine should run periodically
75 to update the video frames being displayed.
76 SEEKING
77 A seek operation is in progress. The decode thread should be seeking.
78 BUFFERING
79 Decoding is paused while data is buffered for smooth playback. If playback
80 is paused (PlayState transitions to PAUSED) we'll destory the decode thread.
81 COMPLETED
82 The resource has completed decoding, but possibly not finished playback.
83 The decode thread will be destroyed. Once playback finished, the audio
84 thread will also be destroyed.
85 SHUTDOWN
86 The decoder object and its state machine are about to be destroyed.
87 Once the last state machine has been destroyed, the shared state machine
88 thread will also be destroyed. It will be recreated later if needed.
89
90 The following result in state transitions.
91
92 Shutdown()
93 Clean up any resources the MediaDecoderStateMachine owns.
94 Play()
95 Start decoding and playback of media data.
96 Buffer
97 This is not user initiated. It occurs when the
98 available data in the stream drops below a certain point.
99 Complete
100 This is not user initiated. It occurs when the
101 stream is completely decoded.
102 Seek(double)
103 Seek to the time position given in the resource.
104
105 A state transition diagram:
106
107 DECODING_METADATA
108 | |
109 v | Shutdown()
110 | |
111 v -->-------------------->--------------------------|
112 |---------------->----->------------------------| v
113 DECODING | | | | |
114 ^ v Seek(t) | | | |
115 | Play() | v | | |
116 ^-----------<----SEEKING | v Complete v v
117 | | | | | |
118 | | | COMPLETED SHUTDOWN-<-|
119 ^ ^ | |Shutdown() |
120 | | | >-------->-----^
121 | Play() |Seek(t) |Buffer() |
122 -----------<--------<-------BUFFERING |
123 | ^
124 v Shutdown() |
125 | |
126 ------------>-----|
127
128 The following represents the states that the MediaDecoder object
129 can be in, and the valid states the MediaDecoderStateMachine can be in at that
130 time:
131
132 player LOADING decoder DECODING_METADATA
133 player PLAYING decoder DECODING, BUFFERING, SEEKING, COMPLETED
134 player PAUSED decoder DECODING, BUFFERING, SEEKING, COMPLETED
135 player SEEKING decoder SEEKING
136 player COMPLETED decoder SHUTDOWN
137 player SHUTDOWN decoder SHUTDOWN
138
139 The general sequence of events is:
140
141 1) The video element calls Load on MediaDecoder. This creates the
142 state machine and starts the channel for downloading the
143 file. It instantiates and schedules the MediaDecoderStateMachine. The
144 high level LOADING state is entered, which results in the decode
145 thread being created and starting to decode metadata. These are
146 the headers that give the video size, framerate, etc. Load() returns
147 immediately to the calling video element.
148
149 2) When the metadata has been loaded by the decode thread, the state machine
150 will call a method on the video element object to inform it that this
151 step is done, so it can do the things required by the video specification
152 at this stage. The decode thread then continues to decode the first frame
153 of data.
154
155 3) When the first frame of data has been successfully decoded the state
156 machine calls a method on the video element object to inform it that
157 this step has been done, once again so it can do the required things
158 by the video specification at this stage.
159
160 This results in the high level state changing to PLAYING or PAUSED
161 depending on any user action that may have occurred.
162
163 While the play state is PLAYING, the decode thread will decode
164 data, and the audio thread will push audio data to the hardware to
165 be played. The state machine will run periodically on the shared
166 state machine thread to ensure video frames are played at the
167 correct time; i.e. the state machine manages A/V sync.
168
169 The Shutdown method on MediaDecoder closes the download channel, and
170 signals to the state machine that it should shutdown. The state machine
171 shuts down asynchronously, and will release the owning reference to the
172 state machine once its threads are shutdown.
173
174 The owning object of a MediaDecoder object *MUST* call Shutdown when
175 destroying the MediaDecoder object.
176
177 */
178 #if !defined(MediaDecoder_h_)
179 #define MediaDecoder_h_
180
181 #include "nsISupports.h"
182 #include "nsCOMPtr.h"
183 #include "nsIObserver.h"
184 #include "nsAutoPtr.h"
185 #include "MediaResource.h"
186 #include "mozilla/dom/AudioChannelBinding.h"
187 #include "mozilla/gfx/Rect.h"
188 #include "mozilla/ReentrantMonitor.h"
189 #include "mozilla/TimeStamp.h"
190 #include "MediaStreamGraph.h"
191 #include "AbstractMediaDecoder.h"
192 #include "necko-config.h"
193
194 class nsIStreamListener;
195 class nsIPrincipal;
196 class nsITimer;
197
198 namespace mozilla {
199 namespace dom {
200 class TimeRanges;
201 }
202 }
203
204 namespace mozilla {
205 namespace layers {
206 class Image;
207 } //namespace layers
208
209 class VideoFrameContainer;
210 class MediaDecoderStateMachine;
211 class MediaDecoderOwner;
212
213 // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
214 // GetTickCount() and conflicts with MediaDecoder::GetCurrentTime implementation.
215 #ifdef GetCurrentTime
216 #undef GetCurrentTime
217 #endif
218
219 // Stores the seek target; the time to seek to, and whether an Accurate,
220 // or "Fast" (nearest keyframe) seek was requested.
221 struct SeekTarget {
222 enum Type {
223 Invalid,
224 PrevSyncPoint,
225 Accurate
226 };
227 SeekTarget()
228 : mTime(-1.0)
229 , mType(SeekTarget::Invalid)
230 {
231 }
232 SeekTarget(int64_t aTimeUsecs, Type aType)
233 : mTime(aTimeUsecs)
234 , mType(aType)
235 {
236 }
237 bool IsValid() const {
238 return mType != SeekTarget::Invalid;
239 }
240 void Reset() {
241 mTime = -1;
242 mType = SeekTarget::Invalid;
243 }
244 // Seek target time in microseconds.
245 int64_t mTime;
246 // Whether we should seek "Fast", or "Accurate".
247 // "Fast" seeks to the seek point preceeding mTime, whereas
248 // "Accurate" seeks as close as possible to mTime.
249 Type mType;
250 };
251
252 class MediaDecoder : public nsIObserver,
253 public AbstractMediaDecoder
254 {
255 public:
256 class DecodedStreamGraphListener;
257
258 NS_DECL_THREADSAFE_ISUPPORTS
259 NS_DECL_NSIOBSERVER
260
261 // Enumeration for the valid play states (see mPlayState)
262 enum PlayState {
263 PLAY_STATE_START,
264 PLAY_STATE_LOADING,
265 PLAY_STATE_PAUSED,
266 PLAY_STATE_PLAYING,
267 PLAY_STATE_SEEKING,
268 PLAY_STATE_ENDED,
269 PLAY_STATE_SHUTDOWN
270 };
271
272 MediaDecoder();
273 virtual ~MediaDecoder();
274
275 // Reset the decoder and notify the media element that
276 // server connection is closed.
277 virtual void ResetConnectionState();
278 // Create a new decoder of the same type as this one.
279 // Subclasses must implement this.
280 virtual MediaDecoder* Clone() = 0;
281 // Create a new state machine to run this decoder.
282 // Subclasses must implement this.
283 virtual MediaDecoderStateMachine* CreateStateMachine() = 0;
284
285 // Call on the main thread only.
286 // Perform any initialization required for the decoder.
287 // Return true on successful initialisation, false
288 // on failure.
289 virtual bool Init(MediaDecoderOwner* aOwner);
290
291 // Cleanup internal data structures. Must be called on the main
292 // thread by the owning object before that object disposes of this object.
293 virtual void Shutdown();
294
295 // Start downloading the media. Decode the downloaded data up to the
296 // point of the first frame of data.
297 // This is called at most once per decoder, after Init().
298 virtual nsresult Load(nsIStreamListener** aListener,
299 MediaDecoder* aCloneDonor);
300
301 // Called in |Load| to open mResource.
302 nsresult OpenResource(nsIStreamListener** aStreamListener);
303
304 // Called when the video file has completed downloading.
305 virtual void ResourceLoaded();
306
307 // Called if the media file encounters a network error.
308 virtual void NetworkError();
309
310 // Get the current MediaResource being used. Its URI will be returned
311 // by currentSrc. Returns what was passed to Load(), if Load() has been called.
312 // Note: The MediaResource is refcounted, but it outlives the MediaDecoder,
313 // so it's OK to use the reference returned by this function without
314 // refcounting, *unless* you need to store and use the reference after the
315 // MediaDecoder has been destroyed. You might need to do this if you're
316 // wrapping the MediaResource in some kind of byte stream interface to be
317 // passed to a platform decoder.
318 MediaResource* GetResource() const MOZ_FINAL MOZ_OVERRIDE
319 {
320 return mResource;
321 }
322 void SetResource(MediaResource* aResource)
323 {
324 NS_ASSERTION(NS_IsMainThread(), "Should only be called on main thread");
325 mResource = aResource;
326 }
327
328 // Return the principal of the current URI being played or downloaded.
329 virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
330
331 // Return the time position in the video stream being
332 // played measured in seconds.
333 virtual double GetCurrentTime();
334
335 // Seek to the time position in (seconds) from the start of the video.
336 // If aDoFastSeek is true, we'll seek to the sync point/keyframe preceeding
337 // the seek target.
338 virtual nsresult Seek(double aTime, SeekTarget::Type aSeekType);
339
340 // Enables decoders to supply an enclosing byte range for a seek offset.
341 // E.g. used by ChannelMediaResource to download a whole cluster for
342 // DASH-WebM.
343 virtual nsresult GetByteRangeForSeek(int64_t const aOffset,
344 MediaByteRange &aByteRange) {
345 return NS_ERROR_NOT_AVAILABLE;
346 }
347
348 // Initialize state machine and schedule it.
349 nsresult InitializeStateMachine(MediaDecoder* aCloneDonor);
350
351 // Start playback of a video. 'Load' must have previously been
352 // called.
353 virtual nsresult Play();
354
355 // Set/Unset dormant state if necessary.
356 // Dormant state is a state to free all scarce media resources
357 // (like hw video codec), did not decoding and stay dormant.
358 // It is used to share scarece media resources in system.
359 virtual void SetDormantIfNecessary(bool aDormant);
360
361 // Pause video playback.
362 virtual void Pause();
363 // Adjust the speed of the playback, optionally with pitch correction,
364 virtual void SetVolume(double aVolume);
365 // Sets whether audio is being captured. If it is, we won't play any
366 // of our audio.
367 virtual void SetAudioCaptured(bool aCaptured);
368
369 virtual void NotifyWaitingForResourcesStatusChanged() MOZ_OVERRIDE;
370
371 virtual void SetPlaybackRate(double aPlaybackRate);
372 void SetPreservesPitch(bool aPreservesPitch);
373
374 // Directs the decoder to not preroll extra samples until the media is
375 // played. This reduces the memory overhead of media elements that may
376 // not be played. Note that seeking also doesn't cause us start prerolling.
377 void SetMinimizePrerollUntilPlaybackStarts();
378
379 // All MediaStream-related data is protected by mReentrantMonitor.
380 // We have at most one DecodedStreamData per MediaDecoder. Its stream
381 // is used as the input for each ProcessedMediaStream created by calls to
382 // captureStream(UntilEnded). Seeking creates a new source stream, as does
383 // replaying after the input as ended. In the latter case, the new source is
384 // not connected to streams created by captureStreamUntilEnded.
385
386 struct DecodedStreamData {
387 typedef gfx::IntSize IntSize;
388
389 DecodedStreamData(MediaDecoder* aDecoder,
390 int64_t aInitialTime, SourceMediaStream* aStream);
391 ~DecodedStreamData();
392
393 StreamTime GetLastOutputTime() { return mListener->GetLastOutputTime(); }
394 bool IsFinished() { return mListener->IsFinishedOnMainThread(); }
395
396 // The following group of fields are protected by the decoder's monitor
397 // and can be read or written on any thread.
398 int64_t mLastAudioPacketTime; // microseconds
399 int64_t mLastAudioPacketEndTime; // microseconds
400 // Count of audio frames written to the stream
401 int64_t mAudioFramesWritten;
402 // Saved value of aInitialTime. Timestamp of the first audio and/or
403 // video packet written.
404 int64_t mInitialTime; // microseconds
405 // mNextVideoTime is the end timestamp for the last packet sent to the stream.
406 // Therefore video packets starting at or after this time need to be copied
407 // to the output stream.
408 int64_t mNextVideoTime; // microseconds
409 MediaDecoder* mDecoder;
410 // The last video image sent to the stream. Useful if we need to replicate
411 // the image.
412 nsRefPtr<layers::Image> mLastVideoImage;
413 IntSize mLastVideoImageDisplaySize;
414 // This is set to true when the stream is initialized (audio and
415 // video tracks added).
416 bool mStreamInitialized;
417 bool mHaveSentFinish;
418 bool mHaveSentFinishAudio;
419 bool mHaveSentFinishVideo;
420
421 // The decoder is responsible for calling Destroy() on this stream.
422 // Can be read from any thread.
423 const nsRefPtr<SourceMediaStream> mStream;
424 // Can be read from any thread.
425 nsRefPtr<DecodedStreamGraphListener> mListener;
426 // True when we've explicitly blocked this stream because we're
427 // not in PLAY_STATE_PLAYING. Used on the main thread only.
428 bool mHaveBlockedForPlayState;
429 // We also have an explicit blocker on the stream when
430 // mDecoderStateMachine is non-null and MediaDecoderStateMachine is false.
431 bool mHaveBlockedForStateMachineNotPlaying;
432 };
433
434 class DecodedStreamGraphListener : public MediaStreamListener {
435 public:
436 DecodedStreamGraphListener(MediaStream* aStream, DecodedStreamData* aData);
437 virtual void NotifyOutput(MediaStreamGraph* aGraph, GraphTime aCurrentTime) MOZ_OVERRIDE;
438 virtual void NotifyFinished(MediaStreamGraph* aGraph) MOZ_OVERRIDE;
439
440 void DoNotifyFinished();
441
442 StreamTime GetLastOutputTime()
443 {
444 MutexAutoLock lock(mMutex);
445 return mLastOutputTime;
446 }
447 void Forget()
448 {
449 NS_ASSERTION(NS_IsMainThread(), "Main thread only");
450 mData = nullptr;
451
452 MutexAutoLock lock(mMutex);
453 mStream = nullptr;
454 }
455 bool SetFinishedOnMainThread(bool aFinished)
456 {
457 MutexAutoLock lock(mMutex);
458 bool result = !mStreamFinishedOnMainThread;
459 mStreamFinishedOnMainThread = aFinished;
460 return result;
461 }
462 bool IsFinishedOnMainThread()
463 {
464 MutexAutoLock lock(mMutex);
465 return mStreamFinishedOnMainThread;
466 }
467 private:
468 // Main thread only
469 DecodedStreamData* mData;
470
471 Mutex mMutex;
472 // Protected by mMutex
473 nsRefPtr<MediaStream> mStream;
474 // Protected by mMutex
475 StreamTime mLastOutputTime;
476 // Protected by mMutex
477 bool mStreamFinishedOnMainThread;
478 };
479
480 struct OutputStreamData {
481 void Init(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
482 {
483 mStream = aStream;
484 mFinishWhenEnded = aFinishWhenEnded;
485 }
486 nsRefPtr<ProcessedMediaStream> mStream;
487 // mPort connects mDecodedStream->mStream to our mStream.
488 nsRefPtr<MediaInputPort> mPort;
489 bool mFinishWhenEnded;
490 };
491 /**
492 * Connects mDecodedStream->mStream to aStream->mStream.
493 */
494 void ConnectDecodedStreamToOutputStream(OutputStreamData* aStream);
495 /**
496 * Disconnects mDecodedStream->mStream from all outputs and clears
497 * mDecodedStream.
498 */
499 void DestroyDecodedStream();
500 /**
501 * Recreates mDecodedStream. Call this to create mDecodedStream at first,
502 * and when seeking, to ensure a new stream is set up with fresh buffers.
503 * aStartTimeUSecs is relative to the state machine's mStartTime.
504 * Decoder monitor must be held.
505 */
506 void RecreateDecodedStream(int64_t aStartTimeUSecs);
507 /**
508 * Call this when mDecoderStateMachine or mDecoderStateMachine->IsPlaying() changes.
509 * Decoder monitor must be held.
510 */
511 void UpdateStreamBlockingForStateMachinePlaying();
512 nsTArray<OutputStreamData>& OutputStreams()
513 {
514 GetReentrantMonitor().AssertCurrentThreadIn();
515 return mOutputStreams;
516 }
517 DecodedStreamData* GetDecodedStream()
518 {
519 GetReentrantMonitor().AssertCurrentThreadIn();
520 return mDecodedStream;
521 }
522
523 // Add an output stream. All decoder output will be sent to the stream.
524 // The stream is initially blocked. The decoder is responsible for unblocking
525 // it while it is playing back.
526 virtual void AddOutputStream(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
527
528 // Return the duration of the video in seconds.
529 virtual double GetDuration();
530
531 // Return the duration of the video in seconds.
532 int64_t GetMediaDuration() MOZ_FINAL MOZ_OVERRIDE;
533
534 // A media stream is assumed to be infinite if the metadata doesn't
535 // contain the duration, and range requests are not supported, and
536 // no headers give a hint of a possible duration (Content-Length,
537 // Content-Duration, and variants), and we cannot seek in the media
538 // stream to determine the duration.
539 //
540 // When the media stream ends, we can know the duration, thus the stream is
541 // no longer considered to be infinite.
542 virtual void SetInfinite(bool aInfinite);
543
544 // Return true if the stream is infinite (see SetInfinite).
545 virtual bool IsInfinite();
546
547 // Called by MediaResource when the "cache suspended" status changes.
548 // If MediaResource::IsSuspendedByCache returns true, then the decoder
549 // should stop buffering or otherwise waiting for download progress and
550 // start consuming data, if possible, because the cache is full.
551 virtual void NotifySuspendedStatusChanged();
552
553 // Called by MediaResource when some data has been received.
554 // Call on the main thread only.
555 virtual void NotifyBytesDownloaded();
556
557 // Called by nsChannelToPipeListener or MediaResource when the
558 // download has ended. Called on the main thread only. aStatus is
559 // the result from OnStopRequest.
560 virtual void NotifyDownloadEnded(nsresult aStatus);
561
562 // Called as data arrives on the stream and is read into the cache. Called
563 // on the main thread only.
564 virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset);
565
566 // Called by MediaResource when the principal of the resource has
567 // changed. Called on main thread only.
568 virtual void NotifyPrincipalChanged();
569
570 // Called by the MediaResource to keep track of the number of bytes read
571 // from the resource. Called on the main by an event runner dispatched
572 // by the MediaResource read functions.
573 void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
574
575 int64_t GetEndMediaTime() const MOZ_FINAL MOZ_OVERRIDE;
576
577 // Return true if we are currently seeking in the media resource.
578 // Call on the main thread only.
579 virtual bool IsSeeking() const;
580
581 // Return true if the decoder has reached the end of playback.
582 // Call on the main thread only.
583 virtual bool IsEnded() const;
584
585 // Set the duration of the media resource in units of seconds.
586 // This is called via a channel listener if it can pick up the duration
587 // from a content header. Must be called from the main thread only.
588 virtual void SetDuration(double aDuration);
589
590 // Sets the initial duration of the media. Called while the media metadata
591 // is being read and the decode is being setup.
592 void SetMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
593 // Updates the media duration. This is called while the media is being
594 // played, calls before the media has reached loaded metadata are ignored.
595 // The duration is assumed to be an estimate, and so a degree of
596 // instability is expected; if the incoming duration is not significantly
597 // different from the existing duration, the change request is ignored.
598 // If the incoming duration is significantly different, the duration is
599 // changed, this causes a durationchanged event to fire to the media
600 // element.
601 void UpdateEstimatedMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
602
603 // Set a flag indicating whether seeking is supported
604 virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_OVERRIDE;
605 virtual void SetTransportSeekable(bool aTransportSeekable) MOZ_FINAL MOZ_OVERRIDE;
606 // Returns true if this media supports seeking. False for example for WebM
607 // files without an index and chained ogg files.
608 virtual bool IsMediaSeekable() MOZ_FINAL MOZ_OVERRIDE;
609 // Returns true if seeking is supported on a transport level (e.g. the server
610 // supports range requests, we are playing a file, etc.).
611 virtual bool IsTransportSeekable();
612
613 // Return the time ranges that can be seeked into.
614 virtual nsresult GetSeekable(dom::TimeRanges* aSeekable);
615
616 // Set the end time of the media resource. When playback reaches
617 // this point the media pauses. aTime is in seconds.
618 virtual void SetFragmentEndTime(double aTime);
619
620 // Set the end time of the media. aTime is in microseconds.
621 void SetMediaEndTime(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
622
623 // Invalidate the frame.
624 void Invalidate();
625 void InvalidateWithFlags(uint32_t aFlags);
626
627 // Suspend any media downloads that are in progress. Called by the
628 // media element when it is sent to the bfcache, or when we need
629 // to throttle the download. Call on the main thread only. This can
630 // be called multiple times, there's an internal "suspend count".
631 virtual void Suspend();
632
633 // Resume any media downloads that have been suspended. Called by the
634 // media element when it is restored from the bfcache, or when we need
635 // to stop throttling the download. Call on the main thread only.
636 // The download will only actually resume once as many Resume calls
637 // have been made as Suspend calls. When aForceBuffering is true,
638 // we force the decoder to go into buffering state before resuming
639 // playback.
640 virtual void Resume(bool aForceBuffering);
641
642 // Moves any existing channel loads into the background, so that they don't
643 // block the load event. This is called when we stop delaying the load
644 // event. Any new loads initiated (for example to seek) will also be in the
645 // background. Implementations of this must call MoveLoadsToBackground() on
646 // their MediaResource.
647 virtual void MoveLoadsToBackground();
648
649 // Returns a weak reference to the media decoder owner.
650 MediaDecoderOwner* GetMediaOwner() const;
651
652 // Called by the state machine to notify the decoder that the duration
653 // has changed.
654 void DurationChanged();
655
656 bool OnStateMachineThread() const MOZ_OVERRIDE;
657
658 bool OnDecodeThread() const MOZ_OVERRIDE;
659
660 // Returns the monitor for other threads to synchronise access to
661 // state.
662 ReentrantMonitor& GetReentrantMonitor() MOZ_OVERRIDE;
663
664 // Returns true if the decoder is shut down
665 bool IsShutdown() const MOZ_FINAL MOZ_OVERRIDE;
666
667 // Constructs the time ranges representing what segments of the media
668 // are buffered and playable.
669 virtual nsresult GetBuffered(dom::TimeRanges* aBuffered);
670
671 // Returns the size, in bytes, of the heap memory used by the currently
672 // queued decoded video and audio data.
673 size_t SizeOfVideoQueue();
674 size_t SizeOfAudioQueue();
675
676 VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE
677 {
678 return mVideoFrameContainer;
679 }
680 layers::ImageContainer* GetImageContainer() MOZ_OVERRIDE;
681
682 // Return the current state. Can be called on any thread. If called from
683 // a non-main thread, the decoder monitor must be held.
684 PlayState GetState() {
685 return mPlayState;
686 }
687
688 // Fire progress events if needed according to the time and byte
689 // constraints outlined in the specification. aTimer is true
690 // if the method is called as a result of the progress timer rather
691 // than the result of downloaded data.
692 void Progress(bool aTimer);
693
694 // Fire timeupdate events if needed according to the time constraints
695 // outlined in the specification.
696 void FireTimeUpdate();
697
698 // Stop updating the bytes downloaded for progress notifications. Called
699 // when seeking to prevent wild changes to the progress notification.
700 // Must be called with the decoder monitor held.
701 virtual void StopProgressUpdates();
702
703 // Allow updating the bytes downloaded for progress notifications. Must
704 // be called with the decoder monitor held.
705 virtual void StartProgressUpdates();
706
707 // Something has changed that could affect the computed playback rate,
708 // so recompute it. The monitor must be held.
709 virtual void UpdatePlaybackRate();
710
711 // Used to estimate rates of data passing through the decoder's channel.
712 // Records activity stopping on the channel. The monitor must be held.
713 virtual void NotifyPlaybackStarted() {
714 GetReentrantMonitor().AssertCurrentThreadIn();
715 mPlaybackStatistics.Start();
716 }
717
718 // Used to estimate rates of data passing through the decoder's channel.
719 // Records activity stopping on the channel. The monitor must be held.
720 virtual void NotifyPlaybackStopped() {
721 GetReentrantMonitor().AssertCurrentThreadIn();
722 mPlaybackStatistics.Stop();
723 }
724
725 // The actual playback rate computation. The monitor must be held.
726 virtual double ComputePlaybackRate(bool* aReliable);
727
728 // Return true when the media is same-origin with the element. The monitor
729 // must be held.
730 bool IsSameOriginMedia();
731
732 // Returns true if we can play the entire media through without stopping
733 // to buffer, given the current download and playback rates.
734 bool CanPlayThrough();
735
736 // Make the decoder state machine update the playback position. Called by
737 // the reader on the decoder thread (Assertions for this checked by
738 // mDecoderStateMachine). This must be called with the decode monitor
739 // held.
740 void UpdatePlaybackPosition(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
741
742 void SetAudioChannel(dom::AudioChannel aChannel) { mAudioChannel = aChannel; }
743 dom::AudioChannel GetAudioChannel() { return mAudioChannel; }
744
745 // Send a new set of metadata to the state machine, to be dispatched to the
746 // main thread to be presented when the |currentTime| of the media is greater
747 // or equal to aPublishTime.
748 void QueueMetadata(int64_t aPublishTime,
749 int aChannels,
750 int aRate,
751 bool aHasAudio,
752 bool aHasVideo,
753 MetadataTags* aTags);
754
755 /******
756 * The following methods must only be called on the main
757 * thread.
758 ******/
759
760 // Change to a new play state. This updates the mState variable and
761 // notifies any thread blocking on this object's monitor of the
762 // change. Call on the main thread only.
763 virtual void ChangeState(PlayState aState);
764
765 // Called by |ChangeState|, to update the state machine.
766 // Call on the main thread only and the lock must be obtained.
767 virtual void ApplyStateToStateMachine(PlayState aState);
768
769 // May be called by the reader to notify this decoder that the metadata from
770 // the media file has been read. Call on the decode thread only.
771 void OnReadMetadataCompleted() MOZ_OVERRIDE { }
772
773 // Called when the metadata from the media file has been loaded by the
774 // state machine. Call on the main thread only.
775 virtual void MetadataLoaded(int aChannels,
776 int aRate,
777 bool aHasAudio,
778 bool aHasVideo,
779 MetadataTags* aTags);
780
781 // Called when the first frame has been loaded.
782 // Call on the main thread only.
783 void FirstFrameLoaded();
784
785 // Returns true if the resource has been loaded. Acquires the monitor.
786 // Call from any thread.
787 virtual bool IsDataCachedToEndOfResource();
788
789 // Called when the video has completed playing.
790 // Call on the main thread only.
791 void PlaybackEnded();
792
793 // Seeking has stopped. Inform the element on the main
794 // thread.
795 void SeekingStopped();
796
797 // Seeking has stopped at the end of the resource. Inform the element on the main
798 // thread.
799 void SeekingStoppedAtEnd();
800
801 // Seeking has started. Inform the element on the main
802 // thread.
803 void SeekingStarted();
804
805 // Called when the backend has changed the current playback
806 // position. It dispatches a timeupdate event and invalidates the frame.
807 // This must be called on the main thread only.
808 void PlaybackPositionChanged();
809
810 // Calls mElement->UpdateReadyStateForData, telling it whether we have
811 // data for the next frame and if we're buffering. Main thread only.
812 virtual void UpdateReadyStateForData();
813
814 // Find the end of the cached data starting at the current decoder
815 // position.
816 int64_t GetDownloadPosition();
817
818 // Updates the approximate byte offset which playback has reached. This is
819 // used to calculate the readyState transitions.
820 void UpdatePlaybackOffset(int64_t aOffset);
821
822 // Provide access to the state machine object
823 MediaDecoderStateMachine* GetStateMachine() const;
824
825 // Drop reference to state machine. Only called during shutdown dance.
826 virtual void ReleaseStateMachine();
827
828 // Notifies the element that decoding has failed.
829 virtual void DecodeError();
830
831 // Indicate whether the media is same-origin with the element.
832 void UpdateSameOriginStatus(bool aSameOrigin);
833
834 MediaDecoderOwner* GetOwner() MOZ_OVERRIDE;
835
836 // Returns true if we're logically playing, that is, if the Play() has
837 // been called and Pause() has not or we have not yet reached the end
838 // of media. This is irrespective of the seeking state; if the owner
839 // calls Play() and then Seek(), we still count as logically playing.
840 // The decoder monitor must be held.
841 bool IsLogicallyPlaying();
842
843 #ifdef MOZ_RAW
844 static bool IsRawEnabled();
845 #endif
846
847 static bool IsOggEnabled();
848 static bool IsOpusEnabled();
849
850 #ifdef MOZ_WAVE
851 static bool IsWaveEnabled();
852 #endif
853
854 #ifdef MOZ_WEBM
855 static bool IsWebMEnabled();
856 #endif
857 #ifdef NECKO_PROTOCOL_rtsp
858 static bool IsRtspEnabled();
859 #endif
860
861 #ifdef MOZ_GSTREAMER
862 static bool IsGStreamerEnabled();
863 #endif
864
865 #ifdef MOZ_OMX_DECODER
866 static bool IsOmxEnabled();
867 #endif
868
869 #ifdef MOZ_MEDIA_PLUGINS
870 static bool IsMediaPluginsEnabled();
871 #endif
872
873 #ifdef MOZ_WMF
874 static bool IsWMFEnabled();
875 #endif
876
877 #ifdef MOZ_APPLEMEDIA
878 static bool IsAppleMP3Enabled();
879 #endif
880
881 // Schedules the state machine to run one cycle on the shared state
882 // machine thread. Main thread only.
883 nsresult ScheduleStateMachineThread();
884
885 struct Statistics {
886 // Estimate of the current playback rate (bytes/second).
887 double mPlaybackRate;
888 // Estimate of the current download rate (bytes/second). This
889 // ignores time that the channel was paused by Gecko.
890 double mDownloadRate;
891 // Total length of media stream in bytes; -1 if not known
892 int64_t mTotalBytes;
893 // Current position of the download, in bytes. This is the offset of
894 // the first uncached byte after the decoder position.
895 int64_t mDownloadPosition;
896 // Current position of decoding, in bytes (how much of the stream
897 // has been consumed)
898 int64_t mDecoderPosition;
899 // Current position of playback, in bytes
900 int64_t mPlaybackPosition;
901 // If false, then mDownloadRate cannot be considered a reliable
902 // estimate (probably because the download has only been running
903 // a short time).
904 bool mDownloadRateReliable;
905 // If false, then mPlaybackRate cannot be considered a reliable
906 // estimate (probably because playback has only been running
907 // a short time).
908 bool mPlaybackRateReliable;
909 };
910
911 // Return statistics. This is used for progress events and other things.
912 // This can be called from any thread. It's only a snapshot of the
913 // current state, since other threads might be changing the state
914 // at any time.
915 virtual Statistics GetStatistics();
916
917 // Frame decoding/painting related performance counters.
918 // Threadsafe.
919 class FrameStatistics {
920 public:
921
922 FrameStatistics() :
923 mReentrantMonitor("MediaDecoder::FrameStats"),
924 mParsedFrames(0),
925 mDecodedFrames(0),
926 mPresentedFrames(0) {}
927
928 // Returns number of frames which have been parsed from the media.
929 // Can be called on any thread.
930 uint32_t GetParsedFrames() {
931 ReentrantMonitorAutoEnter mon(mReentrantMonitor);
932 return mParsedFrames;
933 }
934
935 // Returns the number of parsed frames which have been decoded.
936 // Can be called on any thread.
937 uint32_t GetDecodedFrames() {
938 ReentrantMonitorAutoEnter mon(mReentrantMonitor);
939 return mDecodedFrames;
940 }
941
942 // Returns the number of decoded frames which have been sent to the rendering
943 // pipeline for painting ("presented").
944 // Can be called on any thread.
945 uint32_t GetPresentedFrames() {
946 ReentrantMonitorAutoEnter mon(mReentrantMonitor);
947 return mPresentedFrames;
948 }
949
950 // Increments the parsed and decoded frame counters by the passed in counts.
951 // Can be called on any thread.
952 void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) {
953 if (aParsed == 0 && aDecoded == 0)
954 return;
955 ReentrantMonitorAutoEnter mon(mReentrantMonitor);
956 mParsedFrames += aParsed;
957 mDecodedFrames += aDecoded;
958 }
959
960 // Increments the presented frame counters.
961 // Can be called on any thread.
962 void NotifyPresentedFrame() {
963 ReentrantMonitorAutoEnter mon(mReentrantMonitor);
964 ++mPresentedFrames;
965 }
966
967 private:
968
969 // ReentrantMonitor to protect access of playback statistics.
970 ReentrantMonitor mReentrantMonitor;
971
972 // Number of frames parsed and demuxed from media.
973 // Access protected by mReentrantMonitor.
974 uint32_t mParsedFrames;
975
976 // Number of parsed frames which were actually decoded.
977 // Access protected by mReentrantMonitor.
978 uint32_t mDecodedFrames;
979
980 // Number of decoded frames which were actually sent down the rendering
981 // pipeline to be painted ("presented"). Access protected by mReentrantMonitor.
982 uint32_t mPresentedFrames;
983 };
984
985 // Return the frame decode/paint related statistics.
986 FrameStatistics& GetFrameStatistics() { return mFrameStats; }
987
988 // Increments the parsed and decoded frame counters by the passed in counts.
989 // Can be called on any thread.
990 virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_OVERRIDE
991 {
992 GetFrameStatistics().NotifyDecodedFrames(aParsed, aDecoded);
993 }
994
995 protected:
996 /******
997 * The following members should be accessed with the decoder lock held.
998 ******/
999
1000 // Current decoding position in the stream. This is where the decoder
1001 // is up to consuming the stream. This is not adjusted during decoder
1002 // seek operations, but it's updated at the end when we start playing
1003 // back again.
1004 int64_t mDecoderPosition;
1005 // Current playback position in the stream. This is (approximately)
1006 // where we're up to playing back the stream. This is not adjusted
1007 // during decoder seek operations, but it's updated at the end when we
1008 // start playing back again.
1009 int64_t mPlaybackPosition;
1010
1011 // The current playback position of the media resource in units of
1012 // seconds. This is updated approximately at the framerate of the
1013 // video (if it is a video) or the callback period of the audio.
1014 // It is read and written from the main thread only.
1015 double mCurrentTime;
1016
1017 // Volume that playback should start at. 0.0 = muted. 1.0 = full
1018 // volume. Readable/Writeable from the main thread.
1019 double mInitialVolume;
1020
1021 // PlaybackRate and pitch preservation status we should start at.
1022 // Readable/Writeable from the main thread.
1023 double mInitialPlaybackRate;
1024 bool mInitialPreservesPitch;
1025
1026 // Duration of the media resource. Set to -1 if unknown.
1027 // Set when the metadata is loaded. Accessed on the main thread
1028 // only.
1029 int64_t mDuration;
1030
1031 // True when playback should start with audio captured (not playing).
1032 bool mInitialAudioCaptured;
1033
1034 // True if the resource is seekable at a transport level (server supports byte
1035 // range requests, local file, etc.).
1036 bool mTransportSeekable;
1037
1038 // True if the media is seekable (i.e. supports random access).
1039 bool mMediaSeekable;
1040
1041 // True if the media is same-origin with the element. Data can only be
1042 // passed to MediaStreams when this is true.
1043 bool mSameOriginMedia;
1044
1045 /******
1046 * The following member variables can be accessed from any thread.
1047 ******/
1048
1049 // The state machine object for handling the decoding. It is safe to
1050 // call methods of this object from other threads. Its internal data
1051 // is synchronised on a monitor. The lifetime of this object is
1052 // after mPlayState is LOADING and before mPlayState is SHUTDOWN. It
1053 // is safe to access it during this period.
1054 nsRefPtr<MediaDecoderStateMachine> mDecoderStateMachine;
1055
1056 // Media data resource.
1057 nsRefPtr<MediaResource> mResource;
1058
1059 // |ReentrantMonitor| for detecting when the video play state changes. A call
1060 // to |Wait| on this monitor will block the thread until the next state
1061 // change.
1062 // Using a wrapper class to restrict direct access to the |ReentrantMonitor|
1063 // object. Subclasses may override |MediaDecoder|::|GetReentrantMonitor|
1064 // e.g. |DASHRepDecoder|::|GetReentrantMonitor| returns the monitor in the
1065 // main |DASHDecoder| object. In this case, directly accessing the
1066 // member variable mReentrantMonitor in |DASHRepDecoder| is wrong.
1067 // The wrapper |RestrictedAccessMonitor| restricts use to the getter
1068 // function rather than the object itself.
1069 private:
1070 class RestrictedAccessMonitor
1071 {
1072 public:
1073 RestrictedAccessMonitor(const char* aName) :
1074 mReentrantMonitor(aName)
1075 {
1076 MOZ_COUNT_CTOR(RestrictedAccessMonitor);
1077 }
1078 ~RestrictedAccessMonitor()
1079 {
1080 MOZ_COUNT_DTOR(RestrictedAccessMonitor);
1081 }
1082
1083 // Returns a ref to the reentrant monitor
1084 ReentrantMonitor& GetReentrantMonitor() {
1085 return mReentrantMonitor;
1086 }
1087 private:
1088 ReentrantMonitor mReentrantMonitor;
1089 };
1090
1091 // The |RestrictedAccessMonitor| member object.
1092 RestrictedAccessMonitor mReentrantMonitor;
1093
1094 protected:
1095 // Data about MediaStreams that are being fed by this decoder.
1096 nsTArray<OutputStreamData> mOutputStreams;
1097 // The SourceMediaStream we are using to feed the mOutputStreams. This stream
1098 // is never exposed outside the decoder.
1099 // Only written on the main thread while holding the monitor. Therefore it
1100 // can be read on any thread while holding the monitor, or on the main thread
1101 // without holding the monitor.
1102 nsAutoPtr<DecodedStreamData> mDecodedStream;
1103
1104 // True if this decoder is in dormant state.
1105 // Should be true only when PlayState is PLAY_STATE_LOADING.
1106 bool mIsDormant;
1107
1108 // True if this decoder is exiting from dormant state.
1109 // Should be true only when PlayState is PLAY_STATE_LOADING.
1110 bool mIsExitingDormant;
1111
1112 // Set to one of the valid play states.
1113 // This can only be changed on the main thread while holding the decoder
1114 // monitor. Thus, it can be safely read while holding the decoder monitor
1115 // OR on the main thread.
1116 // Any change to the state on the main thread must call NotifyAll on the
1117 // monitor so the decode thread can wake up.
1118 PlayState mPlayState;
1119
1120 // The state to change to after a seek or load operation.
1121 // This can only be changed on the main thread while holding the decoder
1122 // monitor. Thus, it can be safely read while holding the decoder monitor
1123 // OR on the main thread.
1124 // Any change to the state must call NotifyAll on the monitor.
1125 // This can only be PLAY_STATE_PAUSED or PLAY_STATE_PLAYING.
1126 PlayState mNextState;
1127
1128 // Position to seek to when the seek notification is received by the
1129 // decode thread.
1130 // This can only be changed on the main thread while holding the decoder
1131 // monitor. Thus, it can be safely read while holding the decoder monitor
1132 // OR on the main thread.
1133 // If the SeekTarget's IsValid() accessor returns false, then no seek has
1134 // been requested. When a seek is started this is reset to invalid.
1135 SeekTarget mRequestedSeekTarget;
1136
1137 // True when we have fully loaded the resource and reported that
1138 // to the element (i.e. reached NETWORK_LOADED state).
1139 // Accessed on the main thread only.
1140 bool mCalledResourceLoaded;
1141
1142 // True when seeking or otherwise moving the play position around in
1143 // such a manner that progress event data is inaccurate. This is set
1144 // during seek and duration operations to prevent the progress indicator
1145 // from jumping around. Read/Write from any thread. Must have decode monitor
1146 // locked before accessing.
1147 bool mIgnoreProgressData;
1148
1149 // True if the stream is infinite (e.g. a webradio).
1150 bool mInfiniteStream;
1151
1152 // Start timer to update download progress information.
1153 nsresult StartProgress();
1154
1155 // Stop progress information timer.
1156 nsresult StopProgress();
1157
1158 // Ensures our media stream has been pinned.
1159 void PinForSeek();
1160
1161 // Ensures our media stream has been unpinned.
1162 void UnpinForSeek();
1163
1164 // Timer used for updating progress events
1165 nsCOMPtr<nsITimer> mProgressTimer;
1166
1167 // This should only ever be accessed from the main thread.
1168 // It is set in Init and cleared in Shutdown when the element goes away.
1169 // The decoder does not add a reference the element.
1170 MediaDecoderOwner* mOwner;
1171
1172 // Counters related to decode and presentation of frames.
1173 FrameStatistics mFrameStats;
1174
1175 nsRefPtr<VideoFrameContainer> mVideoFrameContainer;
1176
1177 // Time that the last progress event was fired. Read/Write from the
1178 // main thread only.
1179 TimeStamp mProgressTime;
1180
1181 // Time that data was last read from the media resource. Used for
1182 // computing if the download has stalled and to rate limit progress events
1183 // when data is arriving slower than PROGRESS_MS. A value of null indicates
1184 // that a stall event has already fired and not to fire another one until
1185 // more data is received. Read/Write from the main thread only.
1186 TimeStamp mDataTime;
1187
1188 // Data needed to estimate playback data rate. The timeline used for
1189 // this estimate is "decode time" (where the "current time" is the
1190 // time of the last decoded video frame).
1191 MediaChannelStatistics mPlaybackStatistics;
1192
1193 // True when our media stream has been pinned. We pin the stream
1194 // while seeking.
1195 bool mPinnedForSeek;
1196
1197 // True if the decoder is being shutdown. At this point all events that
1198 // are currently queued need to return immediately to prevent javascript
1199 // being run that operates on the element and decoder during shutdown.
1200 // Read/Write from the main thread only.
1201 bool mShuttingDown;
1202
1203 // True if the playback is paused because the playback rate member is 0.0.
1204 bool mPausedForPlaybackRateNull;
1205
1206 // Be assigned from media element during the initialization and pass to
1207 // AudioStream Class.
1208 dom::AudioChannel mAudioChannel;
1209
1210 // True if the decoder has been directed to minimize its preroll before
1211 // playback starts. After the first time playback starts, we don't attempt
1212 // to minimize preroll, as we assume the user is likely to keep playing,
1213 // or play the media again.
1214 bool mMinimizePreroll;
1215 };
1216
1217 } // namespace mozilla
1218
1219 #endif

mercurial