Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #if !defined(MediaDecoder_h_)
8 : #define MediaDecoder_h_
9 :
10 : #include "AbstractMediaDecoder.h"
11 : #include "DecoderDoctorDiagnostics.h"
12 : #include "MediaDecoderOwner.h"
13 : #include "MediaEventSource.h"
14 : #include "MediaMetadataManager.h"
15 : #include "MediaResource.h"
16 : #include "MediaStatistics.h"
17 : #include "MediaStreamGraph.h"
18 : #include "SeekTarget.h"
19 : #include "TimeUnits.h"
20 : #include "mozilla/Atomics.h"
21 : #include "mozilla/CDMProxy.h"
22 : #include "mozilla/MozPromise.h"
23 : #include "mozilla/ReentrantMonitor.h"
24 : #include "mozilla/StateMirroring.h"
25 : #include "mozilla/StateWatching.h"
26 : #include "mozilla/dom/AudioChannelBinding.h"
27 : #include "necko-config.h"
28 : #include "nsAutoPtr.h"
29 : #include "nsCOMPtr.h"
30 : #include "nsIObserver.h"
31 : #include "nsISupports.h"
32 : #include "nsITimer.h"
33 :
34 : class nsIPrincipal;
35 :
36 : namespace mozilla {
37 :
38 : namespace dom {
39 : class HTMLMediaElement;
40 : }
41 :
42 : class AbstractThread;
43 : class VideoFrameContainer;
44 : class MediaDecoderReader;
45 : class MediaDecoderStateMachine;
46 :
47 : enum class MediaEventType : int8_t;
48 : enum class Visibility : uint8_t;
49 :
50 : // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
51 : // GetTickCount() and conflicts with MediaDecoder::GetCurrentTime implementation.
52 : #ifdef GetCurrentTime
53 : #undef GetCurrentTime
54 : #endif
55 :
56 0 : struct MOZ_STACK_CLASS MediaDecoderInit
57 : {
58 : MediaDecoderOwner* const mOwner;
59 : const dom::AudioChannel mAudioChannel;
60 : const double mVolume;
61 : const bool mPreservesPitch;
62 : const double mPlaybackRate;
63 : const bool mMinimizePreroll;
64 : const bool mHasSuspendTaint;
65 : const bool mLooping;
66 : const MediaContainerType mContainerType;
67 :
68 0 : MediaDecoderInit(MediaDecoderOwner* aOwner,
69 : dom::AudioChannel aAudioChannel,
70 : double aVolume,
71 : bool aPreservesPitch,
72 : double aPlaybackRate,
73 : bool aMinimizePreroll,
74 : bool aHasSuspendTaint,
75 : bool aLooping,
76 : const MediaContainerType& aContainerType)
77 0 : : mOwner(aOwner)
78 : , mAudioChannel(aAudioChannel)
79 : , mVolume(aVolume)
80 : , mPreservesPitch(aPreservesPitch)
81 : , mPlaybackRate(aPlaybackRate)
82 : , mMinimizePreroll(aMinimizePreroll)
83 : , mHasSuspendTaint(aHasSuspendTaint)
84 : , mLooping(aLooping)
85 0 : , mContainerType(aContainerType)
86 : {
87 0 : }
88 : };
89 :
90 : class MediaDecoder : public AbstractMediaDecoder
91 : {
92 : public:
93 : typedef MozPromise<bool /* aIgnored */, bool /* aIgnored */,
94 : /* IsExclusive = */ true>
95 : SeekPromise;
96 :
97 : NS_DECL_THREADSAFE_ISUPPORTS
98 :
99 : // Enumeration for the valid play states (see mPlayState)
100 : enum PlayState
101 : {
102 : PLAY_STATE_START,
103 : PLAY_STATE_LOADING,
104 : PLAY_STATE_PAUSED,
105 : PLAY_STATE_PLAYING,
106 : PLAY_STATE_ENDED,
107 : PLAY_STATE_SHUTDOWN
108 : };
109 :
110 : // Must be called exactly once, on the main thread, during startup.
111 : static void InitStatics();
112 :
113 : explicit MediaDecoder(MediaDecoderInit& aInit);
114 :
115 : // Returns the container content type of the resource.
116 : // Safe to call from any thread.
117 0 : const MediaContainerType& ContainerType() const { return mContainerType; }
118 :
119 : // Create a new state machine to run this decoder.
120 : // Subclasses must implement this.
121 : virtual MediaDecoderStateMachine* CreateStateMachine() = 0;
122 :
123 : // Cleanup internal data structures. Must be called on the main
124 : // thread by the owning object before that object disposes of this object.
125 : virtual void Shutdown();
126 :
127 : // Notified by the shutdown manager that XPCOM shutdown has begun.
128 : // The decoder should notify its owner to drop the reference to the decoder
129 : // to prevent further calls into the decoder.
130 : void NotifyXPCOMShutdown();
131 :
132 : // Called if the media file encounters a network error.
133 : void NetworkError();
134 :
135 : // Get the current MediaResource being used.
136 : // Note: The MediaResource is refcounted, but it outlives the MediaDecoder,
137 : // so it's OK to use the reference returned by this function without
138 : // refcounting, *unless* you need to store and use the reference after the
139 : // MediaDecoder has been destroyed. You might need to do this if you're
140 : // wrapping the MediaResource in some kind of byte stream interface to be
141 : // passed to a platform decoder.
142 0 : MediaResource* GetResource() const { return mResource; }
143 :
144 : // Return the principal of the current URI being played or downloaded.
145 : virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
146 :
147 : // Return the time position in the video stream being
148 : // played measured in seconds.
149 : virtual double GetCurrentTime();
150 :
151 : // Seek to the time position in (seconds) from the start of the video.
152 : // If aDoFastSeek is true, we'll seek to the sync point/keyframe preceeding
153 : // the seek target.
154 : virtual nsresult Seek(double aTime, SeekTarget::Type aSeekType);
155 :
156 : // Initialize state machine and schedule it.
157 : nsresult InitializeStateMachine();
158 :
159 : // Start playback of a video. 'Load' must have previously been
160 : // called.
161 : virtual nsresult Play();
162 :
163 : // Notify activity of the decoder owner is changed.
164 : virtual void NotifyOwnerActivityChanged(bool aIsDocumentVisible,
165 : Visibility aElementVisibility,
166 : bool aIsElementInTree);
167 :
168 : // Pause video playback.
169 : virtual void Pause();
170 : // Adjust the speed of the playback, optionally with pitch correction,
171 : void SetVolume(double aVolume);
172 :
173 : void SetPlaybackRate(double aPlaybackRate);
174 : void SetPreservesPitch(bool aPreservesPitch);
175 : void SetLooping(bool aLooping);
176 :
177 0 : bool GetMinimizePreroll() const { return mMinimizePreroll; }
178 :
179 : // All MediaStream-related data is protected by mReentrantMonitor.
180 : // We have at most one DecodedStreamData per MediaDecoder. Its stream
181 : // is used as the input for each ProcessedMediaStream created by calls to
182 : // captureStream(UntilEnded). Seeking creates a new source stream, as does
183 : // replaying after the input as ended. In the latter case, the new source is
184 : // not connected to streams created by captureStreamUntilEnded.
185 :
186 : // Add an output stream. All decoder output will be sent to the stream.
187 : // The stream is initially blocked. The decoder is responsible for unblocking
188 : // it while it is playing back.
189 : virtual void AddOutputStream(ProcessedMediaStream* aStream,
190 : bool aFinishWhenEnded);
191 : // Remove an output stream added with AddOutputStream.
192 : virtual void RemoveOutputStream(MediaStream* aStream);
193 :
194 : // Return the duration of the video in seconds.
195 : virtual double GetDuration();
196 :
197 : // Return true if the stream is infinite (see SetInfinite).
198 : bool IsInfinite() const;
199 :
200 : // Called as data arrives on the stream and is read into the cache. Called
201 : // on the main thread only.
202 : void NotifyDataArrived();
203 :
204 : // Return true if we are currently seeking in the media resource.
205 : // Call on the main thread only.
206 : bool IsSeeking() const;
207 :
208 : // Return true if the decoder has reached the end of playback.
209 : bool IsEnded() const;
210 :
211 : // True if we are playing a MediaSource object.
212 0 : virtual bool IsMSE() const { return false; }
213 :
214 : // Return true if the MediaDecoderOwner's error attribute is not null.
215 : // Must be called before Shutdown().
216 : bool OwnerHasError() const;
217 :
218 : already_AddRefed<GMPCrashHelper> GetCrashHelper() override;
219 :
220 : public:
221 : // Returns true if this media supports random seeking. False for example with
222 : // chained ogg files.
223 : bool IsMediaSeekable();
224 : // Returns true if seeking is supported on a transport level (e.g. the server
225 : // supports range requests, we are playing a file, etc.).
226 : bool IsTransportSeekable();
227 :
228 : // Return the time ranges that can be seeked into.
229 : virtual media::TimeIntervals GetSeekable();
230 :
231 : // Set the end time of the media resource. When playback reaches
232 : // this point the media pauses. aTime is in seconds.
233 : virtual void SetFragmentEndTime(double aTime);
234 :
235 : // Invalidate the frame.
236 : void Invalidate();
237 : void InvalidateWithFlags(uint32_t aFlags);
238 :
239 : // Suspend any media downloads that are in progress. Called by the
240 : // media element when it is sent to the bfcache, or when we need
241 : // to throttle the download. Call on the main thread only. This can
242 : // be called multiple times, there's an internal "suspend count".
243 : virtual void Suspend();
244 :
245 : // Resume any media downloads that have been suspended. Called by the
246 : // media element when it is restored from the bfcache, or when we need
247 : // to stop throttling the download. Call on the main thread only.
248 : // The download will only actually resume once as many Resume calls
249 : // have been made as Suspend calls.
250 : virtual void Resume();
251 :
252 : // Moves any existing channel loads into or out of background. Background
253 : // loads don't block the load event. This is called when we stop or restart
254 : // delaying the load event. This also determines whether any new loads
255 : // initiated (for example to seek) will be in the background. This calls
256 : // SetLoadInBackground() on mResource.
257 : void SetLoadInBackground(bool aLoadInBackground);
258 :
259 : MediaDecoderStateMachine* GetStateMachine() const;
260 : void SetStateMachine(MediaDecoderStateMachine* aStateMachine);
261 :
262 : // Constructs the time ranges representing what segments of the media
263 : // are buffered and playable.
264 : virtual media::TimeIntervals GetBuffered();
265 :
266 : // Returns the size, in bytes, of the heap memory used by the currently
267 : // queued decoded video and audio data.
268 : size_t SizeOfVideoQueue();
269 : size_t SizeOfAudioQueue();
270 :
271 : // Helper struct for accumulating resource sizes that need to be measured
272 : // asynchronously. Once all references are dropped the callback will be
273 : // invoked.
274 : struct ResourceSizes
275 : {
276 : typedef MozPromise<size_t, size_t, true> SizeOfPromise;
277 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ResourceSizes)
278 0 : explicit ResourceSizes(MallocSizeOf aMallocSizeOf)
279 0 : : mMallocSizeOf(aMallocSizeOf)
280 : , mByteSize(0)
281 0 : , mCallback()
282 : {
283 0 : }
284 :
285 : mozilla::MallocSizeOf mMallocSizeOf;
286 : mozilla::Atomic<size_t> mByteSize;
287 :
288 0 : RefPtr<SizeOfPromise> Promise()
289 : {
290 0 : return mCallback.Ensure(__func__);
291 : }
292 :
293 : private:
294 0 : ~ResourceSizes()
295 0 : {
296 0 : mCallback.ResolveIfExists(mByteSize, __func__);
297 0 : }
298 :
299 : MozPromiseHolder<SizeOfPromise> mCallback;
300 : };
301 :
302 : virtual void AddSizeOfResources(ResourceSizes* aSizes);
303 :
304 0 : VideoFrameContainer* GetVideoFrameContainer() final override
305 : {
306 0 : return mVideoFrameContainer;
307 : }
308 : layers::ImageContainer* GetImageContainer() override;
309 :
310 : // Fire timeupdate events if needed according to the time constraints
311 : // outlined in the specification.
312 : void FireTimeUpdate();
313 :
314 : // Something has changed that could affect the computed playback rate,
315 : // so recompute it. The monitor must be held.
316 : virtual void UpdatePlaybackRate();
317 :
318 : // The actual playback rate computation. The monitor must be held.
319 : void ComputePlaybackRate();
320 :
321 : // Returns true if we can play the entire media through without stopping
322 : // to buffer, given the current download and playback rates.
323 : virtual bool CanPlayThrough();
324 :
325 0 : dom::AudioChannel GetAudioChannel() { return mAudioChannel; }
326 :
327 : // Called from HTMLMediaElement when owner document activity changes
328 : virtual void SetElementVisibility(bool aIsDocumentVisible,
329 : Visibility aElementVisibility,
330 : bool aIsElementInTree);
331 :
332 : // Force override the visible state to hidden.
333 : // Called from HTMLMediaElement when testing of video decode suspend from mochitests.
334 : void SetForcedHidden(bool aForcedHidden);
335 :
336 : // Mark the decoder as tainted, meaning suspend-video-decoder is disabled.
337 : void SetSuspendTaint(bool aTaint);
338 :
339 : // Returns true if the decoder can't participate in suspend-video-decoder.
340 : bool HasSuspendTaint() const;
341 :
342 : void UpdateVideoDecodeMode();
343 :
344 : /******
345 : * The following methods must only be called on the main
346 : * thread.
347 : ******/
348 :
349 : // Change to a new play state. This updates the mState variable and
350 : // notifies any thread blocking on this object's monitor of the
351 : // change. Call on the main thread only.
352 : virtual void ChangeState(PlayState aState);
353 :
354 : // Called when the video has completed playing.
355 : // Call on the main thread only.
356 : void PlaybackEnded();
357 :
358 : void OnSeekRejected();
359 : void OnSeekResolved();
360 :
361 0 : void SeekingChanged()
362 : {
363 : // Stop updating the bytes downloaded for progress notifications when
364 : // seeking to prevent wild changes to the progress notification.
365 0 : MOZ_ASSERT(NS_IsMainThread());
366 0 : mIgnoreProgressData = mLogicallySeeking;
367 0 : }
368 :
369 : // Seeking has started. Inform the element on the main thread.
370 : void SeekingStarted();
371 :
372 : void UpdateLogicalPositionInternal();
373 0 : void UpdateLogicalPosition()
374 : {
375 0 : MOZ_ASSERT(NS_IsMainThread());
376 0 : MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
377 : // Per spec, offical position remains stable during pause and seek.
378 0 : if (mPlayState == PLAY_STATE_PAUSED || IsSeeking()) {
379 0 : return;
380 : }
381 0 : UpdateLogicalPositionInternal();
382 : }
383 :
384 : // Find the end of the cached data starting at the current decoder
385 : // position.
386 : int64_t GetDownloadPosition();
387 :
388 : // Notifies the element that decoding has failed.
389 : void DecodeError(const MediaResult& aError);
390 :
391 : // Indicate whether the media is same-origin with the element.
392 : void UpdateSameOriginStatus(bool aSameOrigin);
393 :
394 : MediaDecoderOwner* GetOwner() const override;
395 :
396 0 : AbstractThread* AbstractMainThread() const final override
397 : {
398 0 : return mAbstractMainThread;
399 : }
400 :
401 : typedef MozPromise<RefPtr<CDMProxy>, bool /* aIgnored */,
402 : /* IsExclusive = */ true>
403 : CDMProxyPromise;
404 :
405 : // Resolved when a CDMProxy is available and the capabilities are known or
406 : // rejected when this decoder is about to shut down.
407 : RefPtr<CDMProxyPromise> RequestCDMProxy() const;
408 :
409 : void SetCDMProxy(CDMProxy* aProxy);
410 :
411 : void EnsureTelemetryReported();
412 :
413 : static bool IsOggEnabled();
414 : static bool IsOpusEnabled();
415 : static bool IsWaveEnabled();
416 : static bool IsWebMEnabled();
417 :
418 : #ifdef MOZ_ANDROID_OMX
419 : static bool IsAndroidMediaPluginEnabled();
420 : #endif
421 :
422 : #ifdef MOZ_WMF
423 : static bool IsWMFEnabled();
424 : #endif
425 :
426 : // Return statistics. This is used for progress events and other things.
427 : // This can be called from any thread. It's only a snapshot of the
428 : // current state, since other threads might be changing the state
429 : // at any time.
430 : MediaStatistics GetStatistics();
431 :
432 : // Return the frame decode/paint related statistics.
433 0 : FrameStatistics& GetFrameStatistics() { return *mFrameStats; }
434 :
435 : // Increments the parsed and decoded frame counters by the passed in counts.
436 : // Can be called on any thread.
437 0 : virtual void NotifyDecodedFrames(const FrameStatisticsData& aStats) override
438 : {
439 0 : GetFrameStatistics().NotifyDecodedFrames(aStats);
440 0 : }
441 :
442 0 : void UpdateReadyState()
443 : {
444 0 : MOZ_ASSERT(NS_IsMainThread());
445 0 : MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
446 0 : GetOwner()->UpdateReadyState();
447 0 : }
448 :
449 0 : virtual MediaDecoderOwner::NextFrameStatus NextFrameStatus()
450 : {
451 0 : return mNextFrameStatus;
452 : }
453 : virtual MediaDecoderOwner::NextFrameStatus NextFrameBufferedStatus();
454 :
455 : // Returns a string describing the state of the media player internal
456 : // data. Used for debugging purposes.
457 0 : virtual void GetMozDebugReaderData(nsACString& aString) { }
458 :
459 : virtual void DumpDebugInfo();
460 :
461 : using DebugInfoPromise = MozPromise<nsCString, bool, true>;
462 : RefPtr<DebugInfoPromise> RequestDebugInfo();
463 :
464 : protected:
465 : virtual ~MediaDecoder();
466 :
467 : // Called when the first audio and/or video from the media file has been loaded
468 : // by the state machine. Call on the main thread only.
469 : virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
470 : MediaDecoderEventVisibility aEventVisibility);
471 :
472 : void SetStateMachineParameters();
473 :
474 : bool IsShutdown() const;
475 :
476 : // Called by the state machine to notify the decoder that the duration
477 : // has changed.
478 : void DurationChanged();
479 :
480 : // State-watching manager.
481 : WatchManager<MediaDecoder> mWatchManager;
482 :
483 0 : double ExplicitDuration() { return mExplicitDuration.Ref().ref(); }
484 :
485 0 : void SetExplicitDuration(double aValue)
486 : {
487 0 : MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
488 0 : mExplicitDuration.Set(Some(aValue));
489 :
490 : // We Invoke DurationChanged explicitly, rather than using a watcher, so
491 : // that it takes effect immediately, rather than at the end of the current task.
492 0 : DurationChanged();
493 0 : }
494 :
495 : /******
496 : * The following members should be accessed with the decoder lock held.
497 : ******/
498 :
499 : // The logical playback position of the media resource in units of
500 : // seconds. This corresponds to the "official position" in HTML5. Note that
501 : // we need to store this as a double, rather than an int64_t (like
502 : // mCurrentPosition), so that |v.currentTime = foo; v.currentTime == foo|
503 : // returns true without being affected by rounding errors.
504 : double mLogicalPosition;
505 :
506 : // The current playback position of the underlying playback infrastructure.
507 : // This corresponds to the "current position" in HTML5.
508 : // We allow omx subclasses to substitute an alternative current position for
509 : // usage with the audio offload player.
510 0 : virtual media::TimeUnit CurrentPosition()
511 : {
512 0 : return mCurrentPosition.Ref();
513 : }
514 :
515 : // Official duration of the media resource as observed by script.
516 : double mDuration;
517 :
518 : /******
519 : * The following member variables can be accessed from any thread.
520 : ******/
521 :
522 : // Media data resource.
523 : RefPtr<MediaResource> mResource;
524 :
525 : RefPtr<MediaDecoderReader> mReader;
526 :
527 : // Amount of buffered data ahead of current time required to consider that
528 : // the next frame is available.
529 : // An arbitrary value of 250ms is used.
530 : static constexpr auto DEFAULT_NEXT_FRAME_AVAILABLE_BUFFERED =
531 : media::TimeUnit::FromMicroseconds(250000);
532 :
533 : private:
534 : nsCString GetDebugInfo();
535 :
536 : // Called when the metadata from the media file has been loaded by the
537 : // state machine. Call on the main thread only.
538 : void MetadataLoaded(UniquePtr<MediaInfo> aInfo,
539 : UniquePtr<MetadataTags> aTags,
540 : MediaDecoderEventVisibility aEventVisibility);
541 :
542 : // Called when the owner's activity changed.
543 : void NotifyCompositor();
544 :
545 : MediaEventSource<RefPtr<layers::KnowsCompositor>>*
546 0 : CompositorUpdatedEvent() override { return &mCompositorUpdatedEvent; }
547 :
548 : void OnPlaybackEvent(MediaEventType aEvent);
549 : void OnPlaybackErrorEvent(const MediaResult& aError);
550 :
551 : void OnDecoderDoctorEvent(DecoderDoctorEvent aEvent);
552 :
553 0 : void OnMediaNotSeekable()
554 : {
555 0 : mMediaSeekable = false;
556 0 : }
557 :
558 : void FinishShutdown();
559 :
560 : void ConnectMirrors(MediaDecoderStateMachine* aObject);
561 : void DisconnectMirrors();
562 :
563 : MediaEventProducer<RefPtr<layers::KnowsCompositor>> mCompositorUpdatedEvent;
564 :
565 : // The state machine object for handling the decoding. It is safe to
566 : // call methods of this object from other threads. Its internal data
567 : // is synchronised on a monitor. The lifetime of this object is
568 : // after mPlayState is LOADING and before mPlayState is SHUTDOWN. It
569 : // is safe to access it during this period.
570 : //
571 : // Explicitly prievate to force access via accessors.
572 : RefPtr<MediaDecoderStateMachine> mDecoderStateMachine;
573 :
574 : MozPromiseHolder<CDMProxyPromise> mCDMProxyPromiseHolder;
575 : RefPtr<CDMProxyPromise> mCDMProxyPromise;
576 :
577 : protected:
578 : void NotifyDataArrivedInternal();
579 : void DiscardOngoingSeekIfExists();
580 : virtual void CallSeek(const SeekTarget& aTarget);
581 :
582 : // Called to recompute playback rate and notify 'progress' event.
583 : // Call on the main thread only.
584 : void DownloadProgressed();
585 :
586 : // A media stream is assumed to be infinite if the metadata doesn't
587 : // contain the duration, and range requests are not supported, and
588 : // no headers give a hint of a possible duration (Content-Length,
589 : // Content-Duration, and variants), and we cannot seek in the media
590 : // stream to determine the duration.
591 : //
592 : // When the media stream ends, we can know the duration, thus the stream is
593 : // no longer considered to be infinite.
594 : void SetInfinite(bool aInfinite);
595 :
596 : // Called by MediaResource when the "cache suspended" status changes.
597 : // If MediaResource::IsSuspendedByCache returns true, then the decoder
598 : // should stop buffering or otherwise waiting for download progress and
599 : // start consuming data, if possible, because the cache is full.
600 : void NotifySuspendedStatusChanged();
601 :
602 : // Called by MediaResource when the principal of the resource has
603 : // changed. Called on main thread only.
604 : void NotifyPrincipalChanged();
605 :
606 : // Called by the MediaResource to keep track of the number of bytes read
607 : // from the resource. Called on the main by an event runner dispatched
608 : // by the MediaResource read functions.
609 : void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset);
610 :
611 : // Called by nsChannelToPipeListener or MediaResource when the
612 : // download has ended. Called on the main thread only. aStatus is
613 : // the result from OnStopRequest.
614 : void NotifyDownloadEnded(nsresult aStatus);
615 :
616 : MozPromiseRequestHolder<SeekPromise> mSeekRequest;
617 :
618 : // True when seeking or otherwise moving the play position around in
619 : // such a manner that progress event data is inaccurate. This is set
620 : // during seek and duration operations to prevent the progress indicator
621 : // from jumping around. Read/Write on the main thread only.
622 : bool mIgnoreProgressData;
623 :
624 : // True if the stream is infinite (e.g. a webradio).
625 : bool mInfiniteStream;
626 :
627 : // Ensures our media stream has been pinned.
628 : void PinForSeek();
629 :
630 : // Ensures our media stream has been unpinned.
631 : void UnpinForSeek();
632 :
633 : const char* PlayStateStr();
634 :
635 : void OnMetadataUpdate(TimedMetadata&& aMetadata);
636 :
637 : bool ShouldThrottleDownload();
638 :
639 : // This should only ever be accessed from the main thread.
640 : // It is set in the constructor and cleared in Shutdown when the element goes
641 : // away. The decoder does not add a reference the element.
642 : MediaDecoderOwner* mOwner;
643 :
644 : // The AbstractThread from mOwner.
645 : const RefPtr<AbstractThread> mAbstractMainThread;
646 :
647 : // Counters related to decode and presentation of frames.
648 : const RefPtr<FrameStatistics> mFrameStats;
649 :
650 : RefPtr<VideoFrameContainer> mVideoFrameContainer;
651 :
652 : // Data needed to estimate playback data rate. The timeline used for
653 : // this estimate is "decode time" (where the "current time" is the
654 : // time of the last decoded video frame).
655 : MediaChannelStatistics mPlaybackStatistics;
656 :
657 : // True when our media stream has been pinned. We pin the stream
658 : // while seeking.
659 : bool mPinnedForSeek;
660 :
661 : // Be assigned from media element during the initialization and pass to
662 : // AudioStream Class.
663 : const dom::AudioChannel mAudioChannel;
664 :
665 : // True if the decoder has been directed to minimize its preroll before
666 : // playback starts. After the first time playback starts, we don't attempt
667 : // to minimize preroll, as we assume the user is likely to keep playing,
668 : // or play the media again.
669 : const bool mMinimizePreroll;
670 :
671 : // True if we've already fired metadataloaded.
672 : bool mFiredMetadataLoaded;
673 :
674 : // True if the media is seekable (i.e. supports random access).
675 : bool mMediaSeekable = true;
676 :
677 : // True if the media is only seekable within its buffered ranges
678 : // like WebMs with no cues.
679 : bool mMediaSeekableOnlyInBufferedRanges = false;
680 :
681 : // Stores media info, including info of audio tracks and video tracks, should
682 : // only be accessed from main thread.
683 : nsAutoPtr<MediaInfo> mInfo;
684 :
685 : // Tracks the visibility status of owner element's document.
686 : bool mIsDocumentVisible;
687 :
688 : // Tracks the visibility status of owner element.
689 : Visibility mElementVisibility;
690 :
691 : // Tracks the owner is in-tree or not.
692 : bool mIsElementInTree;
693 :
694 : // If true, forces the decoder to be considered hidden.
695 : bool mForcedHidden;
696 :
697 : // True if the decoder has a suspend taint - meaning suspend-video-decoder is
698 : // disabled.
699 : bool mHasSuspendTaint;
700 :
701 : // A listener to receive metadata updates from MDSM.
702 : MediaEventListener mTimedMetadataListener;
703 :
704 : MediaEventListener mMetadataLoadedListener;
705 : MediaEventListener mFirstFrameLoadedListener;
706 :
707 : MediaEventListener mOnPlaybackEvent;
708 : MediaEventListener mOnPlaybackErrorEvent;
709 : MediaEventListener mOnDecoderDoctorEvent;
710 : MediaEventListener mOnMediaNotSeekable;
711 :
712 : protected:
713 : // PlaybackRate and pitch preservation status we should start at.
714 : double mPlaybackRate;
715 :
716 : // Buffered range, mirrored from the reader.
717 : Mirror<media::TimeIntervals> mBuffered;
718 :
719 : // NextFrameStatus, mirrored from the state machine.
720 : Mirror<MediaDecoderOwner::NextFrameStatus> mNextFrameStatus;
721 :
722 : // NB: Don't use mCurrentPosition directly, but rather CurrentPosition().
723 : Mirror<media::TimeUnit> mCurrentPosition;
724 :
725 : // Duration of the media resource according to the state machine.
726 : Mirror<media::NullableTimeUnit> mStateMachineDuration;
727 :
728 : // Current playback position in the stream. This is (approximately)
729 : // where we're up to playing back the stream. This is not adjusted
730 : // during decoder seek operations, but it's updated at the end when we
731 : // start playing back again.
732 : Mirror<int64_t> mPlaybackPosition;
733 :
734 : // Used to distinguish whether the audio is producing sound.
735 : Mirror<bool> mIsAudioDataAudible;
736 :
737 : // Volume of playback. 0.0 = muted. 1.0 = full volume.
738 : Canonical<double> mVolume;
739 :
740 : Canonical<bool> mPreservesPitch;
741 :
742 : Canonical<bool> mLooping;
743 :
744 : // Media duration set explicitly by JS. At present, this is only ever present
745 : // for MSE.
746 : Canonical<Maybe<double>> mExplicitDuration;
747 :
748 : // Set to one of the valid play states.
749 : // This can only be changed on the main thread while holding the decoder
750 : // monitor. Thus, it can be safely read while holding the decoder monitor
751 : // OR on the main thread.
752 : Canonical<PlayState> mPlayState;
753 :
754 : // This can only be changed on the main thread while holding the decoder
755 : // monitor. Thus, it can be safely read while holding the decoder monitor
756 : // OR on the main thread.
757 : Canonical<PlayState> mNextState;
758 :
759 : // True if the decoder is seeking.
760 : Canonical<bool> mLogicallySeeking;
761 :
762 : // True if the media is same-origin with the element. Data can only be
763 : // passed to MediaStreams when this is true.
764 : Canonical<bool> mSameOriginMedia;
765 :
766 : // An identifier for the principal of the media. Used to track when
767 : // main-thread induced principal changes get reflected on MSG thread.
768 : Canonical<PrincipalHandle> mMediaPrincipalHandle;
769 :
770 : // Estimate of the current playback rate (bytes/second).
771 : Canonical<double> mPlaybackBytesPerSecond;
772 :
773 : // True if mPlaybackBytesPerSecond is a reliable estimate.
774 : Canonical<bool> mPlaybackRateReliable;
775 :
776 : // Current decoding position in the stream. This is where the decoder
777 : // is up to consuming the stream. This is not adjusted during decoder
778 : // seek operations, but it's updated at the end when we start playing
779 : // back again.
780 : Canonical<int64_t> mDecoderPosition;
781 :
782 : public:
783 0 : AbstractCanonical<double>* CanonicalVolume() { return &mVolume; }
784 0 : AbstractCanonical<bool>* CanonicalPreservesPitch()
785 : {
786 0 : return &mPreservesPitch;
787 : }
788 0 : AbstractCanonical<bool>* CanonicalLooping()
789 : {
790 0 : return &mLooping;
791 : }
792 0 : AbstractCanonical<Maybe<double>>* CanonicalExplicitDuration()
793 : {
794 0 : return &mExplicitDuration;
795 : }
796 0 : AbstractCanonical<PlayState>* CanonicalPlayState() { return &mPlayState; }
797 0 : AbstractCanonical<PlayState>* CanonicalNextPlayState() { return &mNextState; }
798 : AbstractCanonical<bool>* CanonicalLogicallySeeking()
799 : {
800 : return &mLogicallySeeking;
801 : }
802 0 : AbstractCanonical<bool>* CanonicalSameOriginMedia()
803 : {
804 0 : return &mSameOriginMedia;
805 : }
806 0 : AbstractCanonical<PrincipalHandle>* CanonicalMediaPrincipalHandle()
807 : {
808 0 : return &mMediaPrincipalHandle;
809 : }
810 0 : AbstractCanonical<double>* CanonicalPlaybackBytesPerSecond()
811 : {
812 0 : return &mPlaybackBytesPerSecond;
813 : }
814 0 : AbstractCanonical<bool>* CanonicalPlaybackRateReliable()
815 : {
816 0 : return &mPlaybackRateReliable;
817 : }
818 0 : AbstractCanonical<int64_t>* CanonicalDecoderPosition()
819 : {
820 0 : return &mDecoderPosition;
821 : }
822 :
823 : private:
824 : // Notify owner when the audible state changed
825 : void NotifyAudibleStateChanged();
826 :
827 : bool mTelemetryReported;
828 :
829 : // Used to debug how mOwner becomes a dangling pointer in bug 1326294.
830 : bool mIsMediaElement;
831 : WeakPtr<dom::HTMLMediaElement> mElement;
832 : const MediaContainerType mContainerType;
833 : };
834 :
835 : } // namespace mozilla
836 :
837 : #endif
|