|
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 |