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/. */
7 #if !defined(MediaDecoder_h_)
8 # define MediaDecoder_h_
10 # include "BackgroundVideoDecodingPermissionObserver.h"
11 # include "DecoderDoctorDiagnostics.h"
12 # include "MediaContainerType.h"
13 # include "MediaDecoderOwner.h"
14 # include "MediaEventSource.h"
15 # include "MediaMetadataManager.h"
16 # include "MediaPromiseDefs.h"
17 # include "MediaResource.h"
18 # include "MediaStatistics.h"
19 # include "SeekTarget.h"
20 # include "TelemetryProbesReporter.h"
21 # include "TimeUnits.h"
22 # include "mozilla/Atomics.h"
23 # include "mozilla/CDMProxy.h"
24 # include "mozilla/MozPromise.h"
25 # include "mozilla/ReentrantMonitor.h"
26 # include "mozilla/StateMirroring.h"
27 # include "mozilla/StateWatching.h"
28 # include "mozilla/dom/MediaDebugInfoBinding.h"
29 # include "nsCOMPtr.h"
30 # include "nsIObserver.h"
31 # include "nsISupports.h"
32 # include "nsITimer.h"
34 class AudioDeviceInfo
;
41 class DecoderBenchmark
;
42 class ProcessedMediaTrack
;
43 class FrameStatistics
;
44 class VideoFrameContainer
;
45 class MediaFormatReader
;
46 class MediaDecoderStateMachineBase
;
47 struct MediaPlaybackEvent
;
48 struct SharedDummyTrack
;
51 struct DurationToType
{
52 double operator()(double aDouble
);
53 double operator()(const media::TimeUnit
& aTimeUnit
);
57 struct DurationToType
<double> {
58 double operator()(double aDouble
) { return aDouble
; }
59 double operator()(const media::TimeUnit
& aTimeUnit
) {
60 if (aTimeUnit
.IsValid()) {
61 if (aTimeUnit
.IsPosInf()) {
62 return std::numeric_limits
<double>::infinity();
64 if (aTimeUnit
.IsNegInf()) {
65 return -std::numeric_limits
<double>::infinity();
67 return aTimeUnit
.ToSeconds();
69 return std::numeric_limits
<double>::quiet_NaN();
73 using DurationToDouble
= DurationToType
<double>;
76 struct DurationToType
<media::TimeUnit
> {
77 media::TimeUnit
operator()(double aDouble
) {
78 return media::TimeUnit::FromSeconds(aDouble
);
80 media::TimeUnit
operator()(const media::TimeUnit
& aTimeUnit
) {
85 using DurationToTimeUnit
= DurationToType
<media::TimeUnit
>;
87 struct MOZ_STACK_CLASS MediaDecoderInit
{
88 MediaDecoderOwner
* const mOwner
;
89 TelemetryProbesReporterOwner
* const mReporterOwner
;
91 const bool mPreservesPitch
;
92 const double mPlaybackRate
;
93 const bool mMinimizePreroll
;
94 const bool mHasSuspendTaint
;
96 const MediaContainerType mContainerType
;
97 const nsAutoString mStreamName
;
99 MediaDecoderInit(MediaDecoderOwner
* aOwner
,
100 TelemetryProbesReporterOwner
* aReporterOwner
, double aVolume
,
101 bool aPreservesPitch
, double aPlaybackRate
,
102 bool aMinimizePreroll
, bool aHasSuspendTaint
, bool aLooping
,
103 const MediaContainerType
& aContainerType
)
105 mReporterOwner(aReporterOwner
),
107 mPreservesPitch(aPreservesPitch
),
108 mPlaybackRate(aPlaybackRate
),
109 mMinimizePreroll(aMinimizePreroll
),
110 mHasSuspendTaint(aHasSuspendTaint
),
112 mContainerType(aContainerType
) {}
115 DDLoggedTypeDeclName(MediaDecoder
);
117 class MediaDecoder
: public DecoderDoctorLifeLogger
<MediaDecoder
> {
119 typedef MozPromise
<bool /* aIgnored */, bool /* aIgnored */,
120 /* IsExclusive = */ true>
123 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoder
)
125 // Enumeration for the valid play states (see mPlayState)
134 // Must be called exactly once, on the main thread, during startup.
135 static void InitStatics();
137 explicit MediaDecoder(MediaDecoderInit
& aInit
);
139 // Returns the container content type of the resource.
140 // Safe to call from any thread.
141 const MediaContainerType
& ContainerType() const { return mContainerType
; }
143 // Cleanup internal data structures. Must be called on the main
144 // thread by the owning object before that object disposes of this object.
145 virtual void Shutdown();
147 // Notified by the shutdown manager that XPCOM shutdown has begun.
148 // The decoder should notify its owner to drop the reference to the decoder
149 // to prevent further calls into the decoder.
150 void NotifyXPCOMShutdown();
152 // Called if the media file encounters a network error.
153 void NetworkError(const MediaResult
& aError
);
155 // Return the principal of the current URI being played or downloaded.
156 virtual already_AddRefed
<nsIPrincipal
> GetCurrentPrincipal() = 0;
158 // Return true if the loading of this resource required cross-origin
160 virtual bool HadCrossOriginRedirects() = 0;
162 // Return the time position in the video stream being
163 // played measured in seconds.
164 virtual double GetCurrentTime();
166 // Seek to the time position in (seconds) from the start of the video.
167 // If aDoFastSeek is true, we'll seek to the sync point/keyframe preceeding
169 void Seek(double aTime
, SeekTarget::Type aSeekType
);
171 // Start playback of a video. 'Load' must have previously been
175 // Notify activity of the decoder owner is changed.
176 virtual void NotifyOwnerActivityChanged(bool aIsOwnerInvisible
,
177 bool aIsOwnerConnected
);
179 // Pause video playback.
180 virtual void Pause();
181 // Adjust the speed of the playback, optionally with pitch correction,
182 void SetVolume(double aVolume
);
184 void SetPlaybackRate(double aPlaybackRate
);
185 void SetPreservesPitch(bool aPreservesPitch
);
186 void SetLooping(bool aLooping
);
187 void SetStreamName(const nsAutoString
& aStreamName
);
189 // Set the given device as the output device.
190 RefPtr
<GenericPromise
> SetSink(AudioDeviceInfo
* aSinkDevice
);
192 bool GetMinimizePreroll() const { return mMinimizePreroll
; }
194 // When we enable delay seek mode, media decoder won't actually ask MDSM to do
195 // seeking. During this period, we would store the latest seeking target and
196 // perform the seek to that target when we leave the mode. If we have any
197 // delayed seeks stored `IsSeeking()` will return true. E.g. During delay
198 // seeking mode, if we get seek target to 5s, 10s, 7s. When we stop delaying
199 // seeking, we would only seek to 7s.
200 void SetDelaySeekMode(bool aShouldDelaySeek
);
202 // All MediaStream-related data is protected by mReentrantMonitor.
203 // We have at most one DecodedStreamData per MediaDecoder. Its stream
204 // is used as the input for each ProcessedMediaTrack created by calls to
205 // captureStream(UntilEnded). Seeking creates a new source stream, as does
206 // replaying after the input as ended. In the latter case, the new source is
207 // not connected to streams created by captureStreamUntilEnded.
209 enum class OutputCaptureState
{ Capture
, Halt
, None
};
210 // Set the output capture state of this decoder.
211 // @param aState Capture: Output is captured into output tracks, and
212 // aDummyTrack must be provided.
213 // Halt: A capturing media sink is used, but capture is
215 // None: Output is not captured.
216 // @param aDummyTrack A SharedDummyTrack the capturing media sink can use to
217 // access a MediaTrackGraph, so it can create tracks even
218 // when there are no output tracks available.
219 void SetOutputCaptureState(OutputCaptureState aState
,
220 SharedDummyTrack
* aDummyTrack
= nullptr);
221 // Add an output track. All decoder output for the track's media type will be
222 // sent to the track.
223 // Note that only one audio track and one video track is supported by
224 // MediaDecoder at this time. Passing in more of one type, or passing in a
225 // type that metadata says we are not decoding, is an error.
226 void AddOutputTrack(RefPtr
<ProcessedMediaTrack
> aTrack
);
227 // Remove an output track added with AddOutputTrack.
228 void RemoveOutputTrack(const RefPtr
<ProcessedMediaTrack
>& aTrack
);
229 // Update the principal for any output tracks.
230 void SetOutputTracksPrincipal(const RefPtr
<nsIPrincipal
>& aPrincipal
);
232 // Return the duration of the video in seconds.
233 virtual double GetDuration();
235 // Return true if the stream is infinite.
236 bool IsInfinite() const;
238 // Return true if we are currently seeking in the media resource.
239 // Call on the main thread only.
240 bool IsSeeking() const;
242 // Return true if the decoder has reached the end of playback.
243 bool IsEnded() const;
245 // True if we are playing a MediaSource object.
246 virtual bool IsMSE() const { return false; }
248 // Return true if the MediaDecoderOwner's error attribute is not null.
249 // Must be called before Shutdown().
250 bool OwnerHasError() const;
252 // Returns true if this media supports random seeking. False for example with
253 // chained ogg files.
254 bool IsMediaSeekable();
255 // Returns true if seeking is supported on a transport level (e.g. the server
256 // supports range requests, we are playing a file, etc.).
257 virtual bool IsTransportSeekable() = 0;
259 // Return the time ranges that can be seeked into, in TimeUnits.
260 virtual media::TimeIntervals
GetSeekable();
261 // Return the time ranges that can be seeked into, in seconds, double
263 virtual media::TimeRanges
GetSeekableTimeRanges();
265 template <typename T
>
268 // Set the end time of the media resource. When playback reaches
269 // this point the media pauses. aTime is in seconds.
270 virtual void SetFragmentEndTime(double aTime
);
272 // Invalidate the frame.
274 void InvalidateWithFlags(uint32_t aFlags
);
276 // Suspend any media downloads that are in progress. Called by the
277 // media element when it is sent to the bfcache, or when we need
278 // to throttle the download. Call on the main thread only. This can
279 // be called multiple times, there's an internal "suspend count".
280 // When it is called the internal system audio resource are cleaned up.
281 virtual void Suspend();
283 // Resume any media downloads that have been suspended. Called by the
284 // media element when it is restored from the bfcache, or when we need
285 // to stop throttling the download. Call on the main thread only.
286 // The download will only actually resume once as many Resume calls
287 // have been made as Suspend calls.
288 virtual void Resume();
290 // Moves any existing channel loads into or out of background. Background
291 // loads don't block the load event. This is called when we stop or restart
292 // delaying the load event. This also determines whether any new loads
293 // initiated (for example to seek) will be in the background. This calls
294 // SetLoadInBackground() on mResource.
295 virtual void SetLoadInBackground(bool aLoadInBackground
) {}
297 MediaDecoderStateMachineBase
* GetStateMachine() const;
298 void SetStateMachine(MediaDecoderStateMachineBase
* aStateMachine
);
300 // Constructs the time ranges representing what segments of the media
301 // are buffered and playable.
302 virtual media::TimeIntervals
GetBuffered();
304 // Returns the size, in bytes, of the heap memory used by the currently
305 // queued decoded video and audio data.
306 size_t SizeOfVideoQueue();
307 size_t SizeOfAudioQueue();
309 // Helper struct for accumulating resource sizes that need to be measured
310 // asynchronously. Once all references are dropped the callback will be
312 struct ResourceSizes
{
313 typedef MozPromise
<size_t, size_t, true> SizeOfPromise
;
314 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ResourceSizes
)
315 explicit ResourceSizes(MallocSizeOf aMallocSizeOf
)
316 : mMallocSizeOf(aMallocSizeOf
), mByteSize(0), mCallback() {}
318 mozilla::MallocSizeOf mMallocSizeOf
;
319 mozilla::Atomic
<size_t> mByteSize
;
321 RefPtr
<SizeOfPromise
> Promise() { return mCallback
.Ensure(__func__
); }
324 ~ResourceSizes() { mCallback
.ResolveIfExists(mByteSize
, __func__
); }
326 MozPromiseHolder
<SizeOfPromise
> mCallback
;
329 virtual void AddSizeOfResources(ResourceSizes
* aSizes
) = 0;
331 VideoFrameContainer
* GetVideoFrameContainer() { return mVideoFrameContainer
; }
333 layers::ImageContainer
* GetImageContainer();
335 // Returns true if we can play the entire media through without stopping
336 // to buffer, given the current download and playback rates.
337 bool CanPlayThrough();
339 // Called from HTMLMediaElement when owner document activity changes
340 virtual void SetElementVisibility(bool aIsOwnerInvisible
,
341 bool aIsOwnerConnected
);
343 // Force override the visible state to hidden.
344 // Called from HTMLMediaElement when testing of video decode suspend from
346 void SetForcedHidden(bool aForcedHidden
);
348 // Mark the decoder as tainted, meaning suspend-video-decoder is disabled.
349 void SetSuspendTaint(bool aTaint
);
351 // Returns true if the decoder can't participate in suspend-video-decoder.
352 bool HasSuspendTaint() const;
354 void UpdateVideoDecodeMode();
356 void SetSecondaryVideoContainer(
357 const RefPtr
<VideoFrameContainer
>& aSecondaryVideoContainer
);
359 void SetIsBackgroundVideoDecodingAllowed(bool aAllowed
);
361 bool IsVideoDecodingSuspended() const;
363 // The MediaDecoderOwner of this decoder wants to resist fingerprinting.
364 bool ShouldResistFingerprinting() const {
365 return mShouldResistFingerprinting
;
369 * The following methods must only be called on the main
373 // Change to a new play state. This updates the mState variable and
374 // notifies any thread blocking on this object's monitor of the
375 // change. Call on the main thread only.
376 virtual void ChangeState(PlayState aState
);
378 // Called when the video has completed playing.
379 // Call on the main thread only.
380 void PlaybackEnded();
382 void OnSeekRejected();
383 void OnSeekResolved();
385 // Seeking has started. Inform the element on the main thread.
386 void SeekingStarted();
388 void UpdateLogicalPositionInternal();
389 void UpdateLogicalPosition() {
390 MOZ_ASSERT(NS_IsMainThread());
391 MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
392 // Per spec, offical position remains stable during pause and seek.
393 if (mPlayState
== PLAY_STATE_PAUSED
|| IsSeeking()) {
396 UpdateLogicalPositionInternal();
399 // Find the end of the cached data starting at the current decoder
401 int64_t GetDownloadPosition();
403 // Notifies the element that decoding has failed.
404 void DecodeError(const MediaResult
& aError
);
406 // Indicate whether the media is same-origin with the element.
407 void UpdateSameOriginStatus(bool aSameOrigin
);
409 MediaDecoderOwner
* GetOwner() const;
411 AbstractThread
* AbstractMainThread() const { return mAbstractMainThread
; }
413 RefPtr
<SetCDMPromise
> SetCDMProxy(CDMProxy
* aProxy
);
415 void EnsureTelemetryReported();
417 static bool IsOggEnabled();
418 static bool IsOpusEnabled();
419 static bool IsWaveEnabled();
420 static bool IsWebMEnabled();
422 // Return the frame decode/paint related statistics.
423 FrameStatistics
& GetFrameStatistics() { return *mFrameStats
; }
425 void UpdateReadyState() {
426 MOZ_ASSERT(NS_IsMainThread());
427 MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
428 GetOwner()->UpdateReadyState();
431 MediaDecoderOwner::NextFrameStatus
NextFrameStatus() const {
432 return mNextFrameStatus
;
435 virtual MediaDecoderOwner::NextFrameStatus
NextFrameBufferedStatus();
437 RefPtr
<GenericPromise
> RequestDebugInfo(dom::MediaDecoderDebugInfo
& aInfo
);
439 void GetDebugInfo(dom::MediaDecoderDebugInfo
& aInfo
);
442 virtual ~MediaDecoder();
444 // Called when the first audio and/or video from the media file has been
445 // loaded by the state machine. Call on the main thread only.
446 virtual void FirstFrameLoaded(UniquePtr
<MediaInfo
> aInfo
,
447 MediaDecoderEventVisibility aEventVisibility
);
449 // Return error if fail to init the state machine.
450 nsresult
CreateAndInitStateMachine(bool aIsLiveStream
,
451 bool aDisableExternalEngine
= false);
453 // Always return a state machine. If the decoder supports using external
454 // engine, `aDisableExternalEngine` can disable the external engine if needed.
455 virtual MediaDecoderStateMachineBase
* CreateStateMachine(
456 bool aDisableExternalEngine
) MOZ_NONNULL_RETURN
= 0;
458 void SetStateMachineParameters();
460 // Disconnect any events before shutting down the state machine.
461 void DisconnectEvents();
462 RefPtr
<ShutdownPromise
> ShutdownStateMachine();
464 // Called when MediaDecoder shutdown is finished. Subclasses use this to clean
465 // up internal structures, and unregister potential shutdown blockers when
467 virtual void ShutdownInternal();
469 bool IsShutdown() const;
471 // Called to notify the decoder that the duration has changed.
472 virtual void DurationChanged();
474 // State-watching manager.
475 WatchManager
<MediaDecoder
> mWatchManager
;
477 double ExplicitDuration() { return mExplicitDuration
.ref(); }
479 void SetExplicitDuration(double aValue
) {
480 MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
481 mExplicitDuration
= Some(aValue
);
483 // We Invoke DurationChanged explicitly, rather than using a watcher, so
484 // that it takes effect immediately, rather than at the end of the current
489 virtual void OnPlaybackEvent(MediaPlaybackEvent
&& aEvent
);
491 // Called when the metadata from the media file has been loaded by the
492 // state machine. Call on the main thread only.
493 virtual void MetadataLoaded(UniquePtr
<MediaInfo
> aInfo
,
494 UniquePtr
<MetadataTags
> aTags
,
495 MediaDecoderEventVisibility aEventVisibility
);
497 void SetLogicalPosition(const media::TimeUnit
& aNewPosition
);
500 * The following members should be accessed with the decoder lock held.
503 // The logical playback position of the media resource in units of
504 // seconds. This corresponds to the "official position" in HTML5. Note that
505 // we need to store this as a double, rather than an int64_t (like
506 // mCurrentPosition), so that |v.currentTime = foo; v.currentTime == foo|
507 // returns true without being affected by rounding errors.
508 double mLogicalPosition
;
510 // The current playback position of the underlying playback infrastructure.
511 // This corresponds to the "current position" in HTML5.
512 // We allow omx subclasses to substitute an alternative current position for
513 // usage with the audio offload player.
514 virtual media::TimeUnit
CurrentPosition() { return mCurrentPosition
.Ref(); }
516 already_AddRefed
<layers::KnowsCompositor
> GetCompositor();
518 // Official duration of the media resource as observed by script.
519 // This can be a TimeUnit representing the exact duration found by demuxing,
520 // as a TimeUnit. This can also be a duration set explicitly by script, as a
522 Variant
<media::TimeUnit
, double> mDuration
;
525 * The following member variables can be accessed from any thread.
528 RefPtr
<MediaFormatReader
> mReader
;
530 // Amount of buffered data ahead of current time required to consider that
531 // the next frame is available.
532 // An arbitrary value of 250ms is used.
533 static constexpr auto DEFAULT_NEXT_FRAME_AVAILABLE_BUFFERED
=
534 media::TimeUnit::FromMicroseconds(250000);
537 // Called when the owner's activity changed.
538 void NotifyCompositor();
540 void OnPlaybackErrorEvent(const MediaResult
& aError
);
542 void OnDecoderDoctorEvent(DecoderDoctorEvent aEvent
);
544 void OnMediaNotSeekable() { mMediaSeekable
= false; }
546 void OnNextFrameStatus(MediaDecoderOwner::NextFrameStatus
);
548 void OnTrackInfoUpdated(const VideoInfo
& aVideoInfo
,
549 const AudioInfo
& aAudioInfo
);
551 void OnSecondaryVideoContainerInstalled(
552 const RefPtr
<VideoFrameContainer
>& aSecondaryVideoContainer
);
554 void OnStoreDecoderBenchmark(const VideoInfo
& aInfo
);
556 void FinishShutdown();
558 void ConnectMirrors(MediaDecoderStateMachineBase
* aObject
);
559 void DisconnectMirrors();
561 virtual bool CanPlayThroughImpl() = 0;
563 // The state machine object for handling the decoding. It is safe to
564 // call methods of this object from other threads. Its internal data
565 // is synchronised on a monitor. The lifetime of this object is
566 // after mPlayState is LOADING and before mPlayState is SHUTDOWN. It
567 // is safe to access it during this period.
569 // Explicitly prievate to force access via accessors.
570 RefPtr
<MediaDecoderStateMachineBase
> mDecoderStateMachine
;
573 void NotifyReaderDataArrived();
574 void DiscardOngoingSeekIfExists();
575 void CallSeek(const SeekTarget
& aTarget
);
577 // Called by MediaResource when the principal of the resource has
578 // changed. Called on main thread only.
579 virtual void NotifyPrincipalChanged();
581 MozPromiseRequestHolder
<SeekPromise
> mSeekRequest
;
583 const char* PlayStateStr();
585 void OnMetadataUpdate(TimedMetadata
&& aMetadata
);
587 // This should only ever be accessed from the main thread.
588 // It is set in the constructor and cleared in Shutdown when the element goes
589 // away. The decoder does not add a reference the element.
590 MediaDecoderOwner
* mOwner
;
592 // The AbstractThread from mOwner.
593 const RefPtr
<AbstractThread
> mAbstractMainThread
;
595 // Counters related to decode and presentation of frames.
596 const RefPtr
<FrameStatistics
> mFrameStats
;
598 // Store a benchmark of the decoder based on FrameStatistics.
599 RefPtr
<DecoderBenchmark
> mDecoderBenchmark
;
601 RefPtr
<VideoFrameContainer
> mVideoFrameContainer
;
603 // True if the decoder has been directed to minimize its preroll before
604 // playback starts. After the first time playback starts, we don't attempt
605 // to minimize preroll, as we assume the user is likely to keep playing,
606 // or play the media again.
607 const bool mMinimizePreroll
;
609 // True if we've already fired metadataloaded.
610 bool mFiredMetadataLoaded
;
612 // True if the media is seekable (i.e. supports random access).
613 bool mMediaSeekable
= true;
615 // True if the media is only seekable within its buffered ranges
616 // like WebMs with no cues.
617 bool mMediaSeekableOnlyInBufferedRanges
= false;
619 // Stores media info, including info of audio tracks and video tracks, should
620 // only be accessed from main thread.
621 UniquePtr
<MediaInfo
> mInfo
;
623 // True if the owner element is actually visible to users.
624 bool mIsOwnerInvisible
;
626 // True if the owner element is connected to a document tree.
627 // https://dom.spec.whatwg.org/#connected
628 bool mIsOwnerConnected
;
630 // If true, forces the decoder to be considered hidden.
633 // True if the decoder has a suspend taint - meaning suspend-video-decoder is
635 bool mHasSuspendTaint
;
637 // If true, the decoder should resist fingerprinting.
638 const bool mShouldResistFingerprinting
;
640 MediaDecoderOwner::NextFrameStatus mNextFrameStatus
=
641 MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE
;
643 // A listener to receive metadata updates from MDSM.
644 MediaEventListener mTimedMetadataListener
;
646 MediaEventListener mMetadataLoadedListener
;
647 MediaEventListener mFirstFrameLoadedListener
;
649 MediaEventListener mOnPlaybackEvent
;
650 MediaEventListener mOnPlaybackErrorEvent
;
651 MediaEventListener mOnDecoderDoctorEvent
;
652 MediaEventListener mOnMediaNotSeekable
;
653 MediaEventListener mOnEncrypted
;
654 MediaEventListener mOnWaitingForKey
;
655 MediaEventListener mOnDecodeWarning
;
656 MediaEventListener mOnNextFrameStatus
;
657 MediaEventListener mOnTrackInfoUpdated
;
658 MediaEventListener mOnSecondaryVideoContainerInstalled
;
659 MediaEventListener mOnStoreDecoderBenchmark
;
661 // True if we have suspended video decoding.
662 bool mIsVideoDecodingSuspended
= false;
665 // PlaybackRate and pitch preservation status we should start at.
666 double mPlaybackRate
;
668 // True if the decoder is seeking.
669 Watchable
<bool> mLogicallySeeking
;
671 // Buffered range, mirrored from the reader.
672 Mirror
<media::TimeIntervals
> mBuffered
;
674 // NB: Don't use mCurrentPosition directly, but rather CurrentPosition().
675 Mirror
<media::TimeUnit
> mCurrentPosition
;
677 // Duration of the media resource according to the state machine.
678 Mirror
<media::NullableTimeUnit
> mStateMachineDuration
;
680 // Used to distinguish whether the audio is producing sound.
681 Mirror
<bool> mIsAudioDataAudible
;
683 // Volume of playback. 0.0 = muted. 1.0 = full volume.
684 Canonical
<double> mVolume
;
686 Canonical
<bool> mPreservesPitch
;
688 Canonical
<bool> mLooping
;
690 Canonical
<nsAutoString
> mStreamName
;
692 // The device used with SetSink, or nullptr if no explicit device has been
694 Canonical
<RefPtr
<AudioDeviceInfo
>> mSinkDevice
;
696 // Set if the decoder is sending video to a secondary container. While set we
697 // should not suspend the decoder.
698 Canonical
<RefPtr
<VideoFrameContainer
>> mSecondaryVideoContainer
;
700 // Whether this MediaDecoder's output is captured, halted or not captured.
701 // When captured, all decoded data must be played out through mOutputTracks.
702 Canonical
<OutputCaptureState
> mOutputCaptureState
;
704 // A dummy track used to access the right MediaTrackGraph instance. Needed
705 // since there's no guarantee that output tracks are present.
706 Canonical
<nsMainThreadPtrHandle
<SharedDummyTrack
>> mOutputDummyTrack
;
708 // Tracks that, if set, will get data routed through them.
709 Canonical
<CopyableTArray
<RefPtr
<ProcessedMediaTrack
>>> mOutputTracks
;
711 // PrincipalHandle to be used when feeding data into mOutputTracks.
712 Canonical
<PrincipalHandle
> mOutputPrincipal
;
714 // Media duration set explicitly by JS. At present, this is only ever present
716 Maybe
<double> mExplicitDuration
;
718 // Set to one of the valid play states.
719 // This can only be changed on the main thread while holding the decoder
720 // monitor. Thus, it can be safely read while holding the decoder monitor
721 // OR on the main thread.
722 Canonical
<PlayState
> mPlayState
;
724 // This can only be changed on the main thread.
725 PlayState mNextState
= PLAY_STATE_PAUSED
;
727 // True if the media is same-origin with the element. Data can only be
728 // passed to MediaStreams when this is true.
729 bool mSameOriginMedia
;
731 // We can allow video decoding in background when we match some special
732 // conditions, eg. when the cursor is hovering over the tab. This observer is
733 // used to listen the related events.
734 RefPtr
<BackgroundVideoDecodingPermissionObserver
> mVideoDecodingOberver
;
736 // True if we want to resume video decoding even the media element is in the
738 bool mIsBackgroundVideoDecodingAllowed
;
740 // True if we want to delay seeking, and and save the latest seeking target to
741 // resume to when we stop delaying seeking.
742 bool mShouldDelaySeek
= false;
743 Maybe
<SeekTarget
> mDelayedSeekTarget
;
746 Canonical
<double>& CanonicalVolume() { return mVolume
; }
747 Canonical
<bool>& CanonicalPreservesPitch() { return mPreservesPitch
; }
748 Canonical
<bool>& CanonicalLooping() { return mLooping
; }
749 Canonical
<nsAutoString
>& CanonicalStreamName() { return mStreamName
; }
750 Canonical
<RefPtr
<AudioDeviceInfo
>>& CanonicalSinkDevice() {
753 Canonical
<RefPtr
<VideoFrameContainer
>>& CanonicalSecondaryVideoContainer() {
754 return mSecondaryVideoContainer
;
756 Canonical
<OutputCaptureState
>& CanonicalOutputCaptureState() {
757 return mOutputCaptureState
;
759 Canonical
<nsMainThreadPtrHandle
<SharedDummyTrack
>>&
760 CanonicalOutputDummyTrack() {
761 return mOutputDummyTrack
;
763 Canonical
<CopyableTArray
<RefPtr
<ProcessedMediaTrack
>>>&
764 CanonicalOutputTracks() {
765 return mOutputTracks
;
767 Canonical
<PrincipalHandle
>& CanonicalOutputPrincipal() {
768 return mOutputPrincipal
;
770 Canonical
<PlayState
>& CanonicalPlayState() { return mPlayState
; }
772 void UpdateTelemetryHelperBasedOnPlayState(PlayState aState
) const;
774 TelemetryProbesReporter::Visibility
OwnerVisibility() const;
776 // Those methods exist to report telemetry related metrics.
777 double GetTotalVideoPlayTimeInSeconds() const;
778 double GetTotalVideoHDRPlayTimeInSeconds() const;
779 double GetVisibleVideoPlayTimeInSeconds() const;
780 double GetInvisibleVideoPlayTimeInSeconds() const;
781 double GetVideoDecodeSuspendedTimeInSeconds() const;
782 double GetTotalAudioPlayTimeInSeconds() const;
783 double GetAudiblePlayTimeInSeconds() const;
784 double GetInaudiblePlayTimeInSeconds() const;
785 double GetMutedPlayTimeInSeconds() const;
789 * This enum describes the reason why we need to update the logical position.
790 * ePeriodicUpdate : the position grows periodically during playback
791 * eSeamlessLoopingSeeking : the position changes due to demuxer level seek.
792 * eOther : due to normal seeking or other attributes changes, eg. playstate
794 enum class PositionUpdate
{
796 eSeamlessLoopingSeeking
,
799 PositionUpdate
GetPositionUpdateReason(double aPrevPos
,
800 const media::TimeUnit
& aCurPos
) const;
802 // Notify owner when the audible state changed
803 void NotifyAudibleStateChanged();
805 void NotifyVolumeChanged();
807 bool mTelemetryReported
;
808 const MediaContainerType mContainerType
;
809 bool mCanPlayThrough
= false;
811 UniquePtr
<TelemetryProbesReporter
> mTelemetryProbesReporter
;
813 # ifdef MOZ_WMF_MEDIA_ENGINE
814 // True when we need to update the newly created MDSM's status to make it
815 // consistent with the previous destroyed one.
816 bool mPendingStatusUpdateForNewlyCreatedStateMachine
= false;
820 } // namespace mozilla