tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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