MediaDecoder.h (30537B)
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 "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 "SeekTarget.h" 19 # include "TelemetryProbesReporter.h" 20 # include "TimeUnits.h" 21 # include "mozilla/Atomics.h" 22 # include "mozilla/CDMProxy.h" 23 # include "mozilla/DefineEnum.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" 33 34 class AudioDeviceInfo; 35 class nsIPrincipal; 36 37 namespace mozilla { 38 39 class AbstractThread; 40 class DOMMediaStream; 41 class ProcessedMediaTrack; 42 class FrameStatistics; 43 class VideoFrameContainer; 44 class MediaFormatReader; 45 class MediaDecoderStateMachineBase; 46 struct MediaPlaybackEvent; 47 struct SharedDummyTrack; 48 49 template <typename T> 50 struct DurationToType { 51 double operator()(double aDouble); 52 double operator()(const media::TimeUnit& aTimeUnit); 53 }; 54 55 template <> 56 struct DurationToType<double> { 57 double operator()(double aDouble) { return aDouble; } 58 double operator()(const media::TimeUnit& aTimeUnit) { 59 if (aTimeUnit.IsValid()) { 60 if (aTimeUnit.IsPosInf()) { 61 return std::numeric_limits<double>::infinity(); 62 } 63 if (aTimeUnit.IsNegInf()) { 64 return -std::numeric_limits<double>::infinity(); 65 } 66 return aTimeUnit.ToSeconds(); 67 } 68 return std::numeric_limits<double>::quiet_NaN(); 69 } 70 }; 71 72 using DurationToDouble = DurationToType<double>; 73 74 template <> 75 struct DurationToType<media::TimeUnit> { 76 media::TimeUnit operator()(double aDouble) { 77 return media::TimeUnit::FromSeconds(aDouble); 78 } 79 media::TimeUnit operator()(const media::TimeUnit& aTimeUnit) { 80 return aTimeUnit; 81 } 82 }; 83 84 using DurationToTimeUnit = DurationToType<media::TimeUnit>; 85 86 struct MOZ_STACK_CLASS MediaDecoderInit { 87 MediaDecoderOwner* const mOwner; 88 TelemetryProbesReporterOwner* const mReporterOwner; 89 const double mVolume; 90 const bool mPreservesPitch; 91 const double mPlaybackRate; 92 const bool mMinimizePreroll; 93 const bool mHasSuspendTaint; 94 const bool mLooping; 95 const MediaContainerType mContainerType; 96 const nsAutoString mStreamName; 97 98 MediaDecoderInit(MediaDecoderOwner* aOwner, 99 TelemetryProbesReporterOwner* aReporterOwner, double aVolume, 100 bool aPreservesPitch, double aPlaybackRate, 101 bool aMinimizePreroll, bool aHasSuspendTaint, bool aLooping, 102 const MediaContainerType& aContainerType) 103 : mOwner(aOwner), 104 mReporterOwner(aReporterOwner), 105 mVolume(aVolume), 106 mPreservesPitch(aPreservesPitch), 107 mPlaybackRate(aPlaybackRate), 108 mMinimizePreroll(aMinimizePreroll), 109 mHasSuspendTaint(aHasSuspendTaint), 110 mLooping(aLooping), 111 mContainerType(aContainerType) {} 112 }; 113 114 DDLoggedTypeDeclName(MediaDecoder); 115 116 class MediaDecoder : public DecoderDoctorLifeLogger<MediaDecoder> { 117 public: 118 typedef MozPromise<bool /* aIgnored */, bool /* aIgnored */, 119 /* IsExclusive = */ true> 120 SeekPromise; 121 122 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoder) 123 124 // Enumeration for the valid play states (see mPlayState) 125 MOZ_DEFINE_ENUM_WITH_TOSTRING_AT_CLASS_SCOPE( 126 PlayState, (PLAY_STATE_LOADING, PLAY_STATE_PAUSED, PLAY_STATE_PLAYING, 127 PLAY_STATE_ENDED, PLAY_STATE_SHUTDOWN)); 128 129 // Must be called exactly once, on the main thread, during startup. 130 static void InitStatics(); 131 132 explicit MediaDecoder(MediaDecoderInit& aInit); 133 134 // Returns the container content type of the resource. 135 // Safe to call from any thread. 136 const MediaContainerType& ContainerType() const { return mContainerType; } 137 138 // Cleanup internal data structures. Must be called on the main 139 // thread by the owning object before that object disposes of this object. 140 virtual void Shutdown(); 141 142 // Notified by the shutdown manager that XPCOM shutdown has begun. 143 // The decoder should notify its owner to drop the reference to the decoder 144 // to prevent further calls into the decoder. 145 void NotifyXPCOMShutdown(); 146 147 // Called if the media file encounters a network error. 148 void NetworkError(const MediaResult& aError); 149 150 // Return the principal of the current URI being played or downloaded. 151 virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal() = 0; 152 153 // Return true if the loading of this resource required cross-origin 154 // redirects. 155 virtual bool HadCrossOriginRedirects() = 0; 156 157 // Return the time position in the video stream being 158 // played measured in seconds. 159 virtual double GetCurrentTime(); 160 161 // Seek to the time position in (seconds) from the start of the video. 162 // If aDoFastSeek is true, we'll seek to the sync point/keyframe preceeding 163 // the seek target. 164 void Seek(double aTime, SeekTarget::Type aSeekType); 165 166 // Start playback of a video. 'Load' must have previously been 167 // called. 168 virtual void Play(); 169 170 // Notify activity of the decoder owner is changed. 171 void NotifyOwnerActivityChanged(bool aIsOwnerInvisible, 172 bool aIsOwnerConnected, 173 bool aIsOwnerInBackground, 174 bool aHasOwnerPendingCallbacks); 175 176 // Pause video playback. 177 virtual void Pause(); 178 // Adjust the speed of the playback, optionally with pitch correction, 179 void SetVolume(double aVolume); 180 181 void SetPlaybackRate(double aPlaybackRate); 182 void SetPreservesPitch(bool aPreservesPitch); 183 void SetLooping(bool aLooping); 184 void SetStreamName(const nsAutoString& aStreamName); 185 186 // Set the given device as the output device. 187 RefPtr<GenericPromise> SetSink(AudioDeviceInfo* aSinkDevice); 188 189 bool GetMinimizePreroll() const { return mMinimizePreroll; } 190 191 // When we enable delay seek mode, media decoder won't actually ask MDSM to do 192 // seeking. During this period, we would store the latest seeking target and 193 // perform the seek to that target when we leave the mode. If we have any 194 // delayed seeks stored `IsSeeking()` will return true. E.g. During delay 195 // seeking mode, if we get seek target to 5s, 10s, 7s. When we stop delaying 196 // seeking, we would only seek to 7s. 197 void SetDelaySeekMode(bool aShouldDelaySeek); 198 199 // All MediaStream-related data is protected by mReentrantMonitor. 200 // We have at most one DecodedStreamData per MediaDecoder. Its stream 201 // is used as the input for each ProcessedMediaTrack created by calls to 202 // captureStream(UntilEnded). Seeking creates a new source stream, as does 203 // replaying after the input as ended. In the latter case, the new source is 204 // not connected to streams created by captureStreamUntilEnded. 205 206 MOZ_DEFINE_ENUM_CLASS_WITH_TOSTRING_AT_CLASS_SCOPE(OutputCaptureState, 207 (Capture, Halt, None)); 208 209 // Set the output capture state of this decoder. 210 // @param aState Capture: Output is captured into output tracks, and 211 // aDummyTrack must be provided. 212 // Halt: A capturing media sink is used, but capture is 213 // halted. 214 // None: Output is not captured. 215 // @param aDummyTrack A SharedDummyTrack the capturing media sink can use to 216 // access a MediaTrackGraph, so it can create tracks even 217 // when there are no output tracks available. 218 void SetOutputCaptureState(OutputCaptureState aState, 219 SharedDummyTrack* aDummyTrack = nullptr); 220 // Add an output track. All decoder output for the track's media type will be 221 // sent to the track. 222 // Note that only one audio track and one video track is supported by 223 // MediaDecoder at this time. Passing in more of one type, or passing in a 224 // type that metadata says we are not decoding, is an error. 225 void AddOutputTrack(RefPtr<ProcessedMediaTrack> aTrack); 226 // Remove an output track added with AddOutputTrack. 227 void RemoveOutputTrack(const RefPtr<ProcessedMediaTrack>& aTrack); 228 // Update the principal for any output tracks. 229 void SetOutputTracksPrincipal(const RefPtr<nsIPrincipal>& aPrincipal); 230 231 // Return the duration of the video in seconds. 232 virtual double GetDuration(); 233 234 // Return true if the stream is infinite. 235 bool IsInfinite() const; 236 237 // Return true if we are currently seeking in the media resource. 238 // Call on the main thread only. 239 bool IsSeeking() const; 240 241 // Return true if the decoder has reached the end of playback. 242 bool IsEnded() const; 243 244 // True if we are playing a MediaSource object. 245 virtual bool IsMSE() const { return false; } 246 247 // Return true if the MediaDecoderOwner's error attribute is not null. 248 // Must be called before Shutdown(). 249 bool OwnerHasError() const; 250 251 // Returns true if this media supports random seeking. False for example with 252 // chained ogg files. 253 bool IsMediaSeekable(); 254 // Returns true if seeking is supported on a transport level (e.g. the server 255 // supports range requests, we are playing a file, etc.). 256 virtual bool IsTransportSeekable() = 0; 257 258 // Return the time ranges that can be seeked into, in TimeUnits. 259 virtual media::TimeIntervals GetSeekable(); 260 // Return the time ranges that can be seeked into, in seconds, double 261 // precision. 262 virtual media::TimeRanges GetSeekableTimeRanges(); 263 264 template <typename T> 265 T GetSeekableImpl(); 266 267 // Set the end time of the media resource. When playback reaches 268 // this point the media pauses. aTime is in seconds. 269 virtual void SetFragmentEndTime(double aTime); 270 271 // Invalidate the frame. 272 void Invalidate(); 273 void InvalidateWithFlags(uint32_t aFlags); 274 275 // Suspend any media downloads that are in progress. Called by the 276 // media element when it is sent to the bfcache, or when we need 277 // to throttle the download. Call on the main thread only. This can 278 // be called multiple times, there's an internal "suspend count". 279 // When it is called the internal system audio resource are cleaned up. 280 virtual void Suspend(); 281 282 // Resume any media downloads that have been suspended. Called by the 283 // media element when it is restored from the bfcache, or when we need 284 // to stop throttling the download. Call on the main thread only. 285 // The download will only actually resume once as many Resume calls 286 // have been made as Suspend calls. 287 virtual void Resume(); 288 289 // Moves any existing channel loads into or out of background. Background 290 // loads don't block the load event. This is called when we stop or restart 291 // delaying the load event. This also determines whether any new loads 292 // initiated (for example to seek) will be in the background. This calls 293 // SetLoadInBackground() on mResource. 294 virtual void SetLoadInBackground(bool aLoadInBackground) {} 295 296 MediaDecoderStateMachineBase* GetStateMachine() const; 297 void SetStateMachine(MediaDecoderStateMachineBase* aStateMachine); 298 299 // Constructs the time ranges representing what segments of the media 300 // are buffered and playable. 301 virtual media::TimeIntervals GetBuffered(); 302 303 // Returns the size, in bytes, of the heap memory used by the currently 304 // queued decoded video and audio data. 305 size_t SizeOfVideoQueue(); 306 size_t SizeOfAudioQueue(); 307 308 // Helper struct for accumulating resource sizes that need to be measured 309 // asynchronously. Once all references are dropped the callback will be 310 // invoked. 311 struct ResourceSizes { 312 typedef MozPromise<size_t, size_t, true> SizeOfPromise; 313 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ResourceSizes) 314 explicit ResourceSizes(MallocSizeOf aMallocSizeOf) 315 : mMallocSizeOf(aMallocSizeOf), mByteSize(0), mCallback() {} 316 317 mozilla::MallocSizeOf mMallocSizeOf; 318 mozilla::Atomic<size_t> mByteSize; 319 320 RefPtr<SizeOfPromise> Promise() { return mCallback.Ensure(__func__); } 321 322 private: 323 ~ResourceSizes() { mCallback.ResolveIfExists(mByteSize, __func__); } 324 325 MozPromiseHolder<SizeOfPromise> mCallback; 326 }; 327 328 virtual void AddSizeOfResources(ResourceSizes* aSizes) = 0; 329 330 VideoFrameContainer* GetVideoFrameContainer() { return mVideoFrameContainer; } 331 332 layers::ImageContainer* GetImageContainer(); 333 334 // Returns true if we can play the entire media through without stopping 335 // to buffer, given the current download and playback rates. 336 bool CanPlayThrough(); 337 338 // Called from HTMLMediaElement when owner document activity changes 339 void SetElementVisibility(bool aIsOwnerInvisible, bool aIsOwnerConnected, 340 bool aIsOwnerInBackground, 341 bool aHasOwnerPendingCallbacks); 342 343 // Force override the visible state to hidden. 344 // Called from HTMLMediaElement when testing of video decode suspend from 345 // mochitests. 346 void SetForcedHidden(bool aForcedHidden); 347 348 // Mark the decoder as tainted, meaning suspend-video-decoder is disabled. 349 void SetSuspendTaint(bool aTaint); 350 351 // Returns true if the decoder can't participate in suspend-video-decoder. 352 bool HasSuspendTaint() const; 353 354 void UpdateVideoDecodeMode(); 355 356 void SetSecondaryVideoContainer( 357 const RefPtr<VideoFrameContainer>& aSecondaryVideoContainer); 358 359 void SetIsBackgroundVideoDecodingAllowed(bool aAllowed); 360 361 bool IsVideoDecodingSuspended() const; 362 363 // The MediaDecoderOwner of this decoder wants to resist fingerprinting. 364 bool ShouldResistFingerprinting() const { 365 return mShouldResistFingerprinting; 366 } 367 368 /****** 369 * The following methods must only be called on the main 370 * thread. 371 ******/ 372 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); 377 378 // Called when the video has completed playing. 379 // Call on the main thread only. 380 void PlaybackEnded(); 381 382 void OnSeekRejected(); 383 void OnSeekResolved(); 384 385 // Seeking has started. Inform the element on the main thread. 386 void SeekingStarted(); 387 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()) { 394 return; 395 } 396 UpdateLogicalPositionInternal(); 397 } 398 399 // Find the end of the cached data starting at the current decoder 400 // position. 401 int64_t GetDownloadPosition(); 402 403 // Notifies the element that decoding has failed. 404 void DecodeError(const MediaResult& aError); 405 406 // Indicate whether the media is same-origin with the element. 407 void UpdateSameOriginStatus(bool aSameOrigin); 408 409 MediaDecoderOwner* GetOwner() const; 410 411 AbstractThread* AbstractMainThread() const { return mAbstractMainThread; } 412 413 RefPtr<SetCDMPromise> SetCDMProxy(CDMProxy* aProxy); 414 415 void EnsureTelemetryReported(); 416 417 static bool IsOggEnabled(); 418 static bool IsOpusEnabled(); 419 static bool IsWaveEnabled(); 420 static bool IsWebMEnabled(); 421 422 // Return the frame decode/paint related statistics. 423 FrameStatistics& GetFrameStatistics() { return *mFrameStats; } 424 425 void UpdateReadyState() { 426 MOZ_ASSERT(NS_IsMainThread()); 427 MOZ_DIAGNOSTIC_ASSERT(!IsShutdown()); 428 GetOwner()->UpdateReadyState(); 429 } 430 431 MediaDecoderOwner::NextFrameStatus NextFrameStatus() const { 432 return mNextFrameStatus; 433 } 434 435 virtual MediaDecoderOwner::NextFrameStatus NextFrameBufferedStatus(); 436 437 RefPtr<GenericPromise> RequestDebugInfo(dom::MediaDecoderDebugInfo& aInfo); 438 439 void GetDebugInfo(dom::MediaDecoderDebugInfo& aInfo); 440 441 virtual bool IsHLSDecoder() const { return false; } 442 443 protected: 444 virtual ~MediaDecoder(); 445 446 // Called when the first audio and/or video from the media file has been 447 // loaded by the state machine. Call on the main thread only. 448 virtual void FirstFrameLoaded(UniquePtr<MediaInfo> aInfo, 449 MediaDecoderEventVisibility aEventVisibility); 450 451 // Return error if fail to init the state machine. 452 nsresult CreateAndInitStateMachine(bool aIsLiveStream, 453 bool aDisableExternalEngine = false); 454 455 // Always return a state machine. If the decoder supports using external 456 // engine, `aDisableExternalEngine` can disable the external engine if needed. 457 virtual MediaDecoderStateMachineBase* CreateStateMachine( 458 bool aDisableExternalEngine) MOZ_NONNULL_RETURN = 0; 459 460 void SetStateMachineParameters(); 461 462 // Disconnect any events before shutting down the state machine. 463 void DisconnectEvents(); 464 RefPtr<ShutdownPromise> ShutdownStateMachine(); 465 466 // Called when MediaDecoder shutdown is finished. Subclasses use this to clean 467 // up internal structures, and unregister potential shutdown blockers when 468 // they're done. 469 virtual void ShutdownInternal(); 470 471 bool IsShutdown() const; 472 473 // Called to notify the decoder that the duration has changed. 474 virtual void DurationChanged(); 475 476 // State-watching manager. 477 WatchManager<MediaDecoder> mWatchManager; 478 479 double ExplicitDuration() { return mExplicitDuration.ref(); } 480 481 void SetExplicitDuration(double aValue) { 482 MOZ_DIAGNOSTIC_ASSERT(!IsShutdown()); 483 mExplicitDuration = Some(aValue); 484 485 // We Invoke DurationChanged explicitly, rather than using a watcher, so 486 // that it takes effect immediately, rather than at the end of the current 487 // task. 488 DurationChanged(); 489 } 490 491 virtual void OnPlaybackEvent(const MediaPlaybackEvent& aEvent); 492 493 // Called when the metadata from the media file has been loaded by the 494 // state machine. Call on the main thread only. 495 virtual void MetadataLoaded(UniquePtr<MediaInfo> aInfo, 496 UniquePtr<MetadataTags> aTags, 497 MediaDecoderEventVisibility aEventVisibility); 498 499 void SetLogicalPosition(const media::TimeUnit& aNewPosition); 500 501 /****** 502 * The following members should be accessed with the decoder lock held. 503 ******/ 504 505 // The logical playback position of the media resource in units of 506 // seconds. This corresponds to the "official position" in HTML5. Note that 507 // we need to store this as a double, rather than an int64_t (like 508 // mCurrentPosition), so that |v.currentTime = foo; v.currentTime == foo| 509 // returns true without being affected by rounding errors. 510 double mLogicalPosition; 511 512 // The current playback position of the underlying playback infrastructure. 513 // This corresponds to the "current position" in HTML5. 514 // We allow omx subclasses to substitute an alternative current position for 515 // usage with the audio offload player. 516 virtual media::TimeUnit CurrentPosition() { return mCurrentPosition.Ref(); } 517 518 already_AddRefed<layers::KnowsCompositor> GetCompositor(); 519 520 // Official duration of the media resource as observed by script. 521 // This can be a TimeUnit representing the exact duration found by demuxing, 522 // as a TimeUnit. This can also be a duration set explicitly by script, as a 523 // double. 524 Variant<media::TimeUnit, double> mDuration; 525 526 # ifdef MOZ_WMF_MEDIA_ENGINE 527 // True when we need to update the newly created MDSM's status to make it 528 // consistent with the previous destroyed one. 529 bool mPendingStatusUpdateForNewlyCreatedStateMachine = false; 530 void SetStatusUpdateForNewlyCreatedStateMachineIfNeeded(); 531 # endif 532 533 /****** 534 * The following member variables can be accessed from any thread. 535 ******/ 536 537 RefPtr<MediaFormatReader> mReader; 538 539 // Amount of buffered data ahead of current time required to consider that 540 // the next frame is available. 541 // An arbitrary value of 250ms is used. 542 static constexpr auto DEFAULT_NEXT_FRAME_AVAILABLE_BUFFERED = 543 media::TimeUnit::FromMicroseconds(250000); 544 545 private: 546 // Called when the owner's activity changed. 547 void NotifyCompositor(); 548 549 void OnPlaybackErrorEvent(const MediaResult& aError); 550 551 void OnDecoderDoctorEvent(DecoderDoctorEvent aEvent); 552 553 void OnMediaNotSeekable() { mMediaSeekable = false; } 554 555 void OnNextFrameStatus(MediaDecoderOwner::NextFrameStatus); 556 557 void OnTrackInfoUpdated(const VideoInfo& aVideoInfo, 558 const AudioInfo& aAudioInfo); 559 560 void OnSecondaryVideoContainerInstalled( 561 const RefPtr<VideoFrameContainer>& aSecondaryVideoContainer); 562 563 void FinishShutdown(); 564 565 void ConnectMirrors(MediaDecoderStateMachineBase* aObject); 566 void DisconnectMirrors(); 567 # ifdef MOZ_WMF_MEDIA_ENGINE 568 // Return true if we switched to a new state machine. 569 bool SwitchStateMachine(const MediaResult& aError); 570 # endif 571 572 virtual bool CanPlayThroughImpl() = 0; 573 574 // The state machine object for handling the decoding. It is safe to 575 // call methods of this object from other threads. Its internal data 576 // is synchronised on a monitor. The lifetime of this object is 577 // after mPlayState is LOADING and before mPlayState is SHUTDOWN. It 578 // is safe to access it during this period. 579 // 580 // Explicitly prievate to force access via accessors. 581 RefPtr<MediaDecoderStateMachineBase> mDecoderStateMachine; 582 583 protected: 584 void NotifyReaderDataArrived(); 585 void DiscardOngoingSeekIfExists(); 586 void CallSeek(const SeekTarget& aTarget); 587 588 // Called by MediaResource when the principal of the resource has 589 // changed. Called on main thread only. 590 virtual void NotifyPrincipalChanged(); 591 592 MozPromiseRequestHolder<SeekPromise> mSeekRequest; 593 594 void OnMetadataUpdate(TimedMetadata&& aMetadata); 595 596 // This should only ever be accessed from the main thread. 597 // It is set in the constructor and cleared in Shutdown when the element goes 598 // away. The decoder does not add a reference the element. 599 MediaDecoderOwner* mOwner; 600 601 // The AbstractThread from mOwner. 602 const RefPtr<AbstractThread> mAbstractMainThread; 603 604 // Counters related to decode and presentation of frames. 605 const RefPtr<FrameStatistics> mFrameStats; 606 607 RefPtr<VideoFrameContainer> mVideoFrameContainer; 608 609 // True if the decoder has been directed to minimize its preroll before 610 // playback starts. After the first time playback starts, we don't attempt 611 // to minimize preroll, as we assume the user is likely to keep playing, 612 // or play the media again. 613 const bool mMinimizePreroll; 614 615 // True if we've already fired metadataloaded. 616 bool mFiredMetadataLoaded; 617 618 // True if the media is seekable (i.e. supports random access). 619 bool mMediaSeekable = true; 620 621 // True if the media is only seekable within its buffered ranges 622 // like WebMs with no cues. 623 bool mMediaSeekableOnlyInBufferedRanges = false; 624 625 // Stores media info, including info of audio tracks and video tracks, should 626 // only be accessed from main thread. 627 UniquePtr<MediaInfo> mInfo; 628 629 // True if the owner element is actually visible to users. 630 bool mIsOwnerInvisible; 631 632 // True if the owner element is connected to a document tree. 633 // https://dom.spec.whatwg.org/#connected 634 bool mIsOwnerConnected; 635 636 // True if the owner element is in a backgrounded tab/window. 637 bool mIsOwnerInBackground; 638 639 // True if the owner element has pending rVFC callbacks. 640 bool mHasOwnerPendingCallbacks; 641 642 // If true, forces the decoder to be considered hidden. 643 bool mForcedHidden; 644 645 // True if the decoder has a suspend taint - meaning suspend-video-decoder is 646 // disabled. 647 bool mHasSuspendTaint; 648 649 // If true, the decoder should resist fingerprinting. 650 const bool mShouldResistFingerprinting; 651 652 MediaDecoderOwner::NextFrameStatus mNextFrameStatus = 653 MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE; 654 655 // A listener to receive metadata updates from MDSM. 656 MediaEventListener mTimedMetadataListener; 657 658 MediaEventListener mMetadataLoadedListener; 659 MediaEventListener mFirstFrameLoadedListener; 660 661 MediaEventListener mOnPlaybackEvent; 662 MediaEventListener mOnPlaybackErrorEvent; 663 MediaEventListener mOnDecoderDoctorEvent; 664 MediaEventListener mOnMediaNotSeekable; 665 MediaEventListener mOnEncrypted; 666 MediaEventListener mOnWaitingForKey; 667 MediaEventListener mOnDecodeWarning; 668 MediaEventListener mOnNextFrameStatus; 669 MediaEventListener mOnTrackInfoUpdated; 670 MediaEventListener mOnSecondaryVideoContainerInstalled; 671 672 // True if we have suspended video decoding. 673 bool mIsVideoDecodingSuspended = false; 674 675 protected: 676 // PlaybackRate and pitch preservation status we should start at. 677 double mPlaybackRate; 678 679 // True if the decoder is seeking. 680 Watchable<bool> mLogicallySeeking; 681 682 // Buffered range, mirrored from the reader. 683 Mirror<media::TimeIntervals> mBuffered; 684 685 // NB: Don't use mCurrentPosition directly, but rather CurrentPosition(). 686 Mirror<media::TimeUnit> mCurrentPosition; 687 688 // Duration of the media resource according to the state machine. 689 Mirror<media::NullableTimeUnit> mStateMachineDuration; 690 691 // Used to distinguish whether the audio is producing sound. 692 Mirror<bool> mIsAudioDataAudible; 693 694 // Volume of playback. 0.0 = muted. 1.0 = full volume. 695 Canonical<double> mVolume; 696 697 Canonical<bool> mPreservesPitch; 698 699 Canonical<bool> mLooping; 700 701 Canonical<nsAutoString> mStreamName; 702 703 // The device used with SetSink, or nullptr if no explicit device has been 704 // set. 705 Canonical<RefPtr<AudioDeviceInfo>> mSinkDevice; 706 707 // Set if the decoder is sending video to a secondary container. While set we 708 // should not suspend the decoder. 709 Canonical<RefPtr<VideoFrameContainer>> mSecondaryVideoContainer; 710 711 // Whether this MediaDecoder's output is captured, halted or not captured. 712 // When captured, all decoded data must be played out through mOutputTracks. 713 Canonical<OutputCaptureState> mOutputCaptureState; 714 715 // A dummy track used to access the right MediaTrackGraph instance. Needed 716 // since there's no guarantee that output tracks are present. 717 Canonical<nsMainThreadPtrHandle<SharedDummyTrack>> mOutputDummyTrack; 718 719 // Tracks that, if set, will get data routed through them. 720 Canonical<CopyableTArray<RefPtr<ProcessedMediaTrack>>> mOutputTracks; 721 722 // PrincipalHandle to be used when feeding data into mOutputTracks. 723 Canonical<PrincipalHandle> mOutputPrincipal; 724 725 // Media duration set explicitly by JS. At present, this is only ever present 726 // for MSE. 727 Maybe<double> mExplicitDuration; 728 729 // Set to one of the valid play states. 730 // This can only be changed on the main thread while holding the decoder 731 // monitor. Thus, it can be safely read while holding the decoder monitor 732 // OR on the main thread. 733 Canonical<PlayState> mPlayState; 734 735 // This can only be changed on the main thread. 736 PlayState mNextState = PLAY_STATE_PAUSED; 737 738 // True if the media is same-origin with the element. Data can only be 739 // passed to MediaStreams when this is true. 740 bool mSameOriginMedia; 741 742 // We can allow video decoding in background when we match some special 743 // conditions, eg. when the cursor is hovering over the tab. This observer is 744 // used to listen the related events. 745 RefPtr<BackgroundVideoDecodingPermissionObserver> mVideoDecodingOberver; 746 747 // True if we want to resume video decoding even the media element is in the 748 // background. 749 bool mIsBackgroundVideoDecodingAllowed; 750 751 // True if we want to delay seeking, and and save the latest seeking target to 752 // resume to when we stop delaying seeking. 753 bool mShouldDelaySeek = false; 754 Maybe<SeekTarget> mDelayedSeekTarget; 755 756 public: 757 Canonical<double>& CanonicalVolume() { return mVolume; } 758 Canonical<bool>& CanonicalPreservesPitch() { return mPreservesPitch; } 759 Canonical<bool>& CanonicalLooping() { return mLooping; } 760 Canonical<nsAutoString>& CanonicalStreamName() { return mStreamName; } 761 Canonical<RefPtr<AudioDeviceInfo>>& CanonicalSinkDevice() { 762 return mSinkDevice; 763 } 764 Canonical<RefPtr<VideoFrameContainer>>& CanonicalSecondaryVideoContainer() { 765 return mSecondaryVideoContainer; 766 } 767 Canonical<OutputCaptureState>& CanonicalOutputCaptureState() { 768 return mOutputCaptureState; 769 } 770 Canonical<nsMainThreadPtrHandle<SharedDummyTrack>>& 771 CanonicalOutputDummyTrack() { 772 return mOutputDummyTrack; 773 } 774 Canonical<CopyableTArray<RefPtr<ProcessedMediaTrack>>>& 775 CanonicalOutputTracks() { 776 return mOutputTracks; 777 } 778 Canonical<PrincipalHandle>& CanonicalOutputPrincipal() { 779 return mOutputPrincipal; 780 } 781 Canonical<PlayState>& CanonicalPlayState() { return mPlayState; } 782 783 void UpdateTelemetryHelperBasedOnPlayState(PlayState aState) const; 784 785 TelemetryProbesReporter::Visibility OwnerVisibility() const; 786 787 // Those methods exist to report telemetry related metrics. 788 double GetTotalVideoPlayTimeInSeconds() const; 789 double GetTotalVideoHDRPlayTimeInSeconds() const; 790 double GetVisibleVideoPlayTimeInSeconds() const; 791 double GetInvisibleVideoPlayTimeInSeconds() const; 792 double GetTotalAudioPlayTimeInSeconds() const; 793 double GetAudiblePlayTimeInSeconds() const; 794 double GetInaudiblePlayTimeInSeconds() const; 795 double GetMutedPlayTimeInSeconds() const; 796 797 private: 798 /** 799 * This enum describes the reason why we need to update the logical position. 800 * ePeriodicUpdate : the position grows periodically during playback 801 * eSeamlessLoopingSeeking : the position changes due to demuxer level seek. 802 * eOther : due to normal seeking or other attributes changes, eg. playstate 803 */ 804 enum class PositionUpdate { 805 ePeriodicUpdate, 806 eSeamlessLoopingSeeking, 807 eOther, 808 }; 809 PositionUpdate GetPositionUpdateReason(double aPrevPos, 810 const media::TimeUnit& aCurPos) const; 811 812 // Notify owner when the audible state changed 813 void NotifyAudibleStateChanged(); 814 815 void NotifyVolumeChanged(); 816 817 bool mTelemetryReported; 818 const MediaContainerType mContainerType; 819 bool mCanPlayThrough = false; 820 821 UniquePtr<TelemetryProbesReporter> mTelemetryProbesReporter; 822 823 // The time of creating the media decoder state machine, it's used to record 824 // the probe for measuring the first video frame loaded time. Reset after 825 // reporting the measurement to avoid a dulpicated report. 826 Maybe<TimeStamp> mMDSMCreationTime; 827 }; 828 829 } // namespace mozilla 830 831 #endif