tor-browser

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

TrackBuffersManager.h (25094B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      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 #ifndef MOZILLA_TRACKBUFFERSMANAGER_H_
      8 #define MOZILLA_TRACKBUFFERSMANAGER_H_
      9 
     10 #include "MediaContainerType.h"
     11 #include "MediaData.h"
     12 #include "MediaDataDemuxer.h"
     13 #include "MediaResult.h"
     14 #include "MediaSourceDecoder.h"
     15 #include "MediaSpan.h"
     16 #include "SourceBufferTask.h"
     17 #include "TimeUnits.h"
     18 #include "mozilla/Atomics.h"
     19 #include "mozilla/EventTargetCapability.h"
     20 #include "mozilla/Maybe.h"
     21 #include "mozilla/Mutex.h"
     22 #include "mozilla/NotNull.h"
     23 #include "mozilla/TaskQueue.h"
     24 #include "mozilla/dom/MediaDebugInfoBinding.h"
     25 #include "nsTArray.h"
     26 
     27 namespace mozilla {
     28 
     29 class AbstractThread;
     30 class ContainerParser;
     31 class MediaByteBuffer;
     32 class MediaRawData;
     33 class MediaSourceDemuxer;
     34 class SourceBufferResource;
     35 
     36 namespace dom {
     37 enum class MediaSourceEndOfStreamError : uint8_t;
     38 }  // namespace dom
     39 
     40 class SourceBufferTaskQueue {
     41 public:
     42  SourceBufferTaskQueue() = default;
     43 
     44  ~SourceBufferTaskQueue() {
     45    MOZ_ASSERT(mQueue.IsEmpty(), "All tasks must have been processed");
     46  }
     47 
     48  void Push(SourceBufferTask* aTask) { mQueue.AppendElement(aTask); }
     49 
     50  already_AddRefed<SourceBufferTask> Pop() {
     51    if (!mQueue.Length()) {
     52      return nullptr;
     53    }
     54    RefPtr<SourceBufferTask> task = std::move(mQueue[0]);
     55    mQueue.RemoveElementAt(0);
     56    return task.forget();
     57  }
     58 
     59  nsTArray<RefPtr<SourceBufferTask>>::size_type Length() const {
     60    return mQueue.Length();
     61  }
     62 
     63 private:
     64  nsTArray<RefPtr<SourceBufferTask>> mQueue;
     65 };
     66 
     67 DDLoggedTypeDeclName(TrackBuffersManager);
     68 
     69 class TrackBuffersManager final
     70    : public DecoderDoctorLifeLogger<TrackBuffersManager> {
     71 public:
     72  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackBuffersManager);
     73 
     74  enum class EvictDataResult : int8_t {
     75    NO_DATA_EVICTED,
     76    CANT_EVICT,
     77    BUFFER_FULL,
     78  };
     79 
     80  using TrackType = TrackInfo::TrackType;
     81  using MediaType = MediaData::Type;
     82  using TrackBuffer = nsTArray<RefPtr<MediaRawData>>;
     83  using AppendPromise = SourceBufferTask::AppendPromise;
     84  using RangeRemovalPromise = SourceBufferTask::RangeRemovalPromise;
     85 
     86  // Interface for SourceBuffer
     87  TrackBuffersManager(MediaSourceDecoder* aParentDecoder,
     88                      const MediaContainerType& aType);
     89 
     90  // Queue a task to add data to the end of the input buffer and run the MSE
     91  // Buffer Append Algorithm
     92  // 3.5.5 Buffer Append Algorithm.
     93  // http://w3c.github.io/media-source/index.html#sourcebuffer-buffer-append
     94  RefPtr<AppendPromise> AppendData(already_AddRefed<MediaByteBuffer> aData,
     95                                   const SourceBufferAttributes& aAttributes);
     96 
     97  // Queue a task to abort any pending AppendData.
     98  // Does nothing at this stage.
     99  void AbortAppendData();
    100 
    101  // Queue a task to run MSE Reset Parser State Algorithm.
    102  // 3.5.2 Reset Parser State
    103  void ResetParserState(SourceBufferAttributes& aAttributes);
    104 
    105  // Queue a task to run the MSE range removal algorithm.
    106  // http://w3c.github.io/media-source/#sourcebuffer-coded-frame-removal
    107  RefPtr<RangeRemovalPromise> RangeRemoval(media::TimeUnit aStart,
    108                                           media::TimeUnit aEnd);
    109 
    110  // Schedule data eviction if necessary as the next call to AppendData will
    111  // add aSize bytes.
    112  // Eviction is done in two steps, first remove data up to aPlaybackTime
    113  // and if still more space is needed remove from the end.
    114  EvictDataResult EvictData(const media::TimeUnit& aPlaybackTime, int64_t aSize,
    115                            TrackType aType);
    116 
    117  // Schedule data eviction if necessary and the size of eviction would be
    118  // determined automatically. This is currently used when the buffer's size is
    119  // close to full and the normal procedure to evict data is not enough.
    120  void EvictDataWithoutSize(TrackType aType, const media::TimeUnit& aTarget);
    121 
    122  // Queue a task to run ChangeType
    123  void ChangeType(const MediaContainerType& aType);
    124 
    125  // Returns the buffered range currently managed.
    126  // This may be called on any thread.
    127  // Buffered must conform to
    128  // http://w3c.github.io/media-source/index.html#widl-SourceBuffer-buffered
    129  media::TimeIntervals Buffered() const;
    130  media::TimeUnit HighestStartTime() const;
    131  media::TimeUnit HighestEndTime() const;
    132 
    133  // Return the size of the data managed by this SourceBufferContentManager.
    134  int64_t GetSize() const;
    135 
    136  // Indicate that the MediaSource parent object got into "ended" state.
    137  void SetEnded(const dom::Optional<dom::MediaSourceEndOfStreamError>& aError);
    138 
    139  // The parent SourceBuffer is about to be destroyed.
    140  void Detach();
    141 
    142  // Return the eviction threshold, in bytes, for a track type (audio or video).
    143  // When the track type isn't passed in (kUndefinedTrack), this returns the
    144  // value for video if a video track is present. Specifying the track type
    145  // explicitely is useful when initialization hasn't finished, but the track
    146  // type is known already.
    147  int64_t EvictionThreshold(
    148      TrackInfo::TrackType aType = TrackInfo::TrackType::kUndefinedTrack) const;
    149 
    150  // Interface for MediaSourceDemuxer
    151  MediaInfo GetMetadata() const;
    152  const TrackBuffer& GetTrackBuffer(TrackInfo::TrackType aTrack) const;
    153  const media::TimeIntervals& Buffered(TrackInfo::TrackType) const;
    154  const media::TimeUnit& HighestStartTime(TrackInfo::TrackType) const;
    155  media::TimeIntervals SafeBuffered(TrackInfo::TrackType) const;
    156  bool HaveAllData() const { return mHaveAllData; }
    157  uint32_t Evictable(TrackInfo::TrackType aTrack) const;
    158  media::TimeUnit Seek(TrackInfo::TrackType aTrack,
    159                       const media::TimeUnit& aTime,
    160                       const media::TimeUnit& aFuzz);
    161  uint32_t SkipToNextRandomAccessPoint(TrackInfo::TrackType aTrack,
    162                                       const media::TimeUnit& aTimeThreadshold,
    163                                       const media::TimeUnit& aFuzz,
    164                                       bool& aFound);
    165 
    166  already_AddRefed<MediaRawData> GetSample(TrackInfo::TrackType aTrack,
    167                                           const media::TimeUnit& aFuzz,
    168                                           MediaResult& aResult);
    169  int32_t FindCurrentPosition(TrackInfo::TrackType aTrack,
    170                              const media::TimeUnit& aFuzz) const
    171      MOZ_REQUIRES(mTaskQueueCapability);
    172 
    173  // Will set the next GetSample index if needed. This information is determined
    174  // through the value of mNextSampleTimecode. Return false if the index
    175  // couldn't be determined or if there's nothing more that could be demuxed.
    176  // This occurs if either the track buffer doesn't contain the required
    177  // timecode or is empty.
    178  nsresult SetNextGetSampleIndexIfNeeded(TrackInfo::TrackType aTrack,
    179                                         const media::TimeUnit& aFuzz)
    180      MOZ_REQUIRES(mTaskQueueCapability);
    181 
    182  media::TimeUnit GetNextRandomAccessPoint(TrackInfo::TrackType aTrack,
    183                                           const media::TimeUnit& aFuzz);
    184 
    185  // Requests that the TrackBuffersManager populates aInfo with debug
    186  // information. This may be done asynchronously, and aInfo should *not* be
    187  // accessed by the caller until the returned promise is resolved or rejected.
    188  RefPtr<GenericPromise> RequestDebugInfo(
    189      dom::TrackBuffersManagerDebugInfo& aInfo) const;
    190  void AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes) const;
    191 
    192 private:
    193  using CodedFrameProcessingPromise = MozPromise<bool, MediaResult, true>;
    194 
    195  ~TrackBuffersManager();
    196  // main thread:
    197  void Reopen();
    198 
    199  // All following functions run on the taskqueue.
    200  RefPtr<AppendPromise> DoAppendData(already_AddRefed<MediaByteBuffer> aData,
    201                                     const SourceBufferAttributes& aAttributes);
    202  void ScheduleSegmentParserLoop() MOZ_REQUIRES(mTaskQueueCapability);
    203  void SegmentParserLoop() MOZ_REQUIRES(mTaskQueueCapability);
    204  void InitializationSegmentReceived() MOZ_REQUIRES(mTaskQueueCapability);
    205  void ShutdownDemuxers() MOZ_REQUIRES(mTaskQueueCapability);
    206  void CreateDemuxerforMIMEType() MOZ_REQUIRES(mTaskQueueCapability);
    207  void ResetDemuxingState() MOZ_REQUIRES(mTaskQueueCapability);
    208  void NeedMoreData() MOZ_REQUIRES(mTaskQueueCapability);
    209  void RejectAppend(const MediaResult& aRejectValue, const char* aName)
    210      MOZ_REQUIRES(mTaskQueueCapability);
    211  // Will return a promise that will be resolved once all frames of the current
    212  // media segment have been processed.
    213  RefPtr<CodedFrameProcessingPromise> CodedFrameProcessing()
    214      MOZ_REQUIRES(mTaskQueueCapability);
    215  void CompleteCodedFrameProcessing() MOZ_REQUIRES(mTaskQueueCapability);
    216  // Called by ResetParserState.
    217  void CompleteResetParserState() MOZ_REQUIRES(mTaskQueueCapability);
    218  RefPtr<RangeRemovalPromise> CodedFrameRemovalWithPromise(
    219      const media::TimeInterval& aInterval) MOZ_REQUIRES(mTaskQueueCapability);
    220  bool CodedFrameRemoval(const media::TimeInterval& aInterval)
    221      MOZ_REQUIRES(mTaskQueueCapability);
    222  // Removes all coded frames -- this is not to spec and should be used as a
    223  // last resort to clear buffers only if other methods cannot.
    224  void RemoveAllCodedFrames() MOZ_REQUIRES(mTaskQueueCapability);
    225  void SetAppendState(SourceBufferAttributes::AppendState aAppendState)
    226      MOZ_REQUIRES(mTaskQueueCapability);
    227 
    228  bool HasVideo() const { return mVideoTracks.mNumTracks > 0; }
    229  bool HasAudio() const { return mAudioTracks.mNumTracks > 0; }
    230 
    231  // The input buffer as per
    232  // http://w3c.github.io/media-source/index.html#sourcebuffer-input-buffer
    233  Maybe<MediaSpan> mInputBuffer MOZ_GUARDED_BY(mTaskQueueCapability);
    234  // Buffer full flag as per
    235  // https://w3c.github.io/media-source/#sourcebuffer-buffer-full-flag. Accessed
    236  // on both the main thread and the task queue.
    237  Atomic<bool> mBufferFull;
    238  bool mFirstInitializationSegmentReceived MOZ_GUARDED_BY(mTaskQueueCapability);
    239  bool mChangeTypeReceived MOZ_GUARDED_BY(mTaskQueueCapability);
    240  // Set to true once a new segment is started.
    241  bool mNewMediaSegmentStarted MOZ_GUARDED_BY(mTaskQueueCapability);
    242  bool mActiveTrack MOZ_GUARDED_BY(mTaskQueueCapability);
    243  MediaContainerType mType MOZ_GUARDED_BY(mTaskQueueCapability);
    244 
    245  // ContainerParser objects and methods.
    246  // Those are used to parse the incoming input buffer.
    247 
    248  // Recreate the ContainerParser and if aReuseInitData is true then
    249  // feed it with the previous init segment found.
    250  void RecreateParser(bool aReuseInitData) MOZ_REQUIRES(mTaskQueueCapability);
    251  UniquePtr<ContainerParser> mParser;
    252 
    253  // Demuxer objects and methods.
    254  void AppendDataToCurrentInputBuffer(const MediaSpan& aData)
    255      MOZ_REQUIRES(mTaskQueueCapability);
    256 
    257  RefPtr<MediaByteBuffer> mInitData MOZ_GUARDED_BY(mTaskQueueCapability);
    258 
    259  // Checks if a new set of init data is a repeat of the last set of init data
    260  // received. Because streams may retransmit the same init data (or
    261  // functionally equivalent init data) we do not want to perform costly
    262  // operations each time we receive init data, only when it's actually
    263  // different data.
    264  bool IsRepeatInitData(const MediaInfo& aNewMediaInfo) const
    265      MOZ_REQUIRES(mTaskQueueCapability);
    266 
    267  // Temporary input buffer to handle partial media segment header.
    268  // We store the current input buffer content into it should we need to
    269  // reinitialize the demuxer once we have some samples and a discontinuity is
    270  // detected.
    271  Maybe<MediaSpan> mPendingInputBuffer MOZ_GUARDED_BY(mTaskQueueCapability);
    272  RefPtr<SourceBufferResource> mCurrentInputBuffer
    273      MOZ_GUARDED_BY(mTaskQueueCapability);
    274  RefPtr<MediaDataDemuxer> mInputDemuxer MOZ_GUARDED_BY(mTaskQueueCapability);
    275  // Length already processed in current media segment.
    276  uint64_t mProcessedInput MOZ_GUARDED_BY(mTaskQueueCapability);
    277  Maybe<media::TimeUnit> mLastParsedEndTime
    278      MOZ_GUARDED_BY(mTaskQueueCapability);
    279 
    280  void OnDemuxerInitDone(const MediaResult& aResult);
    281  void OnDemuxerInitFailed(const MediaResult& aError);
    282  void OnDemuxerResetDone(const MediaResult& aResult)
    283      MOZ_REQUIRES(mTaskQueueCapability);
    284  MozPromiseRequestHolder<MediaDataDemuxer::InitPromise> mDemuxerInitRequest;
    285 
    286  void OnDemuxFailed(TrackType aTrack, const MediaResult& aError)
    287      MOZ_REQUIRES(mTaskQueueCapability);
    288  void DoDemuxVideo() MOZ_REQUIRES(mTaskQueueCapability);
    289  void OnVideoDemuxCompleted(
    290      const RefPtr<MediaTrackDemuxer::SamplesHolder>& aSamples);
    291  void OnVideoDemuxFailed(const MediaResult& aError) {
    292    mVideoTracks.mDemuxRequest.Complete();
    293    mTaskQueueCapability->AssertOnCurrentThread();
    294    OnDemuxFailed(TrackType::kVideoTrack, aError);
    295  }
    296  void DoDemuxAudio() MOZ_REQUIRES(mTaskQueueCapability);
    297  void OnAudioDemuxCompleted(
    298      const RefPtr<MediaTrackDemuxer::SamplesHolder>& aSamples);
    299  void OnAudioDemuxFailed(const MediaResult& aError) {
    300    mAudioTracks.mDemuxRequest.Complete();
    301    mTaskQueueCapability->AssertOnCurrentThread();
    302    OnDemuxFailed(TrackType::kAudioTrack, aError);
    303  }
    304 
    305  // Dispatches an "encrypted" event is any sample in array has initData
    306  // present.
    307  void MaybeDispatchEncryptedEvent(
    308      const nsTArray<RefPtr<MediaRawData>>& aSamples);
    309 
    310  void DoEvictData(const media::TimeUnit& aPlaybackTime,
    311                   Maybe<int64_t> aSizeToEvict)
    312      MOZ_REQUIRES(mTaskQueueCapability);
    313 
    314  void GetDebugInfo(dom::TrackBuffersManagerDebugInfo& aInfo) const
    315      MOZ_REQUIRES(mTaskQueueCapability);
    316 
    317  struct TrackData {
    318    TrackData() : mNumTracks(0), mNeedRandomAccessPoint(true), mSizeBuffer(0) {}
    319    Atomic<uint32_t> mNumTracks;
    320    // Definition of variables:
    321    // https://w3c.github.io/media-source/#track-buffers
    322    // Last decode timestamp variable that stores the decode timestamp of the
    323    // last coded frame appended in the current coded frame group.
    324    // The variable is initially unset to indicate that no coded frames have
    325    // been appended yet.
    326    Maybe<media::TimeUnit> mLastDecodeTimestamp;
    327    // Last frame duration variable that stores the coded frame duration of the
    328    // last coded frame appended in the current coded frame group.
    329    // The variable is initially unset to indicate that no coded frames have
    330    // been appended yet.
    331    Maybe<media::TimeUnit> mLastFrameDuration;
    332    // Highest end timestamp variable that stores the highest coded frame end
    333    // timestamp across all coded frames in the current coded frame group that
    334    // were appended to this track buffer.
    335    // The variable is initially unset to indicate that no coded frames have
    336    // been appended yet.
    337    Maybe<media::TimeUnit> mHighestEndTimestamp;
    338    // Highest presentation timestamp in track buffer.
    339    // Protected by global monitor, except when reading on the task queue as it
    340    // is only written there.
    341    media::TimeUnit mHighestStartTimestamp;
    342    // Longest frame duration seen since last random access point.
    343    // Only ever accessed when mLastDecodeTimestamp and mLastFrameDuration are
    344    // set.
    345    media::TimeUnit mLongestFrameDuration;
    346    // Need random access point flag variable that keeps track of whether the
    347    // track buffer is waiting for a random access point coded frame.
    348    // The variable is initially set to true to indicate that random access
    349    // point coded frame is needed before anything can be added to the track
    350    // buffer.
    351    bool mNeedRandomAccessPoint;
    352    RefPtr<MediaTrackDemuxer> mDemuxer;
    353    MozPromiseRequestHolder<MediaTrackDemuxer::SamplesPromise> mDemuxRequest;
    354    // Highest end timestamp of the last media segment demuxed.
    355    media::TimeUnit mLastParsedEndTime;
    356 
    357    // If set, position where the next contiguous frame will be inserted.
    358    // If a discontinuity is detected, it will be unset and recalculated upon
    359    // the next insertion.
    360    Maybe<uint32_t> mNextInsertionIndex;
    361    // Samples just demuxed, but not yet parsed.
    362    TrackBuffer mQueuedSamples;
    363    const TrackBuffer& GetTrackBuffer() const {
    364      MOZ_RELEASE_ASSERT(mBuffers.Length(),
    365                         "TrackBuffer must have been created");
    366      return mBuffers.LastElement();
    367    }
    368    TrackBuffer& GetTrackBuffer() {
    369      MOZ_RELEASE_ASSERT(mBuffers.Length(),
    370                         "TrackBuffer must have been created");
    371      return mBuffers.LastElement();
    372    }
    373    // We only manage a single track of each type at this time.
    374    nsTArray<TrackBuffer> mBuffers;
    375    // Track buffer ranges variable that represents the presentation time ranges
    376    // occupied by the coded frames currently stored in the track buffer.
    377    media::TimeIntervals mBufferedRanges;
    378    // Sanitized mBufferedRanges with a fuzz of half a sample's duration applied
    379    // This buffered ranges is the basis of what is exposed to the JS.
    380    media::TimeIntervals mSanitizedBufferedRanges;
    381    // Byte size of all samples contained in this track buffer.
    382    uint32_t mSizeBuffer;
    383    // TrackInfo of the first metadata received.
    384    RefPtr<TrackInfoSharedPtr> mInfo;
    385    // TrackInfo of the last metadata parsed (updated with each init segment.
    386    RefPtr<TrackInfoSharedPtr> mLastInfo;
    387 
    388    // If set, position of the next sample to be retrieved by GetSample().
    389    // If the position is equal to the TrackBuffer's length, it indicates that
    390    // we've reached EOS.
    391    Maybe<uint32_t> mNextGetSampleIndex;
    392    // Approximation of the next sample's decode timestamp.
    393    media::TimeUnit mNextSampleTimecode;
    394    // Approximation of the next sample's presentation timestamp.
    395    media::TimeUnit mNextSampleTime;
    396 
    397    struct EvictionIndex {
    398      EvictionIndex() { Reset(); }
    399      void Reset() {
    400        mEvictable = 0;
    401        mLastIndex = 0;
    402      }
    403      uint32_t mEvictable = 0;
    404      uint32_t mLastIndex = 0;
    405    };
    406    // Size of data that can be safely evicted during the next eviction
    407    // cycle.
    408    // We consider as evictable all frames up to the last keyframe prior to
    409    // mNextGetSampleIndex. If mNextGetSampleIndex isn't set, then we assume
    410    // that we can't yet evict data.
    411    // Protected by global monitor, except when reading on the task queue as it
    412    // is only written there.
    413    EvictionIndex mEvictionIndex;
    414 
    415    void ResetAppendState() {
    416      mLastDecodeTimestamp.reset();
    417      mLastFrameDuration.reset();
    418      mHighestEndTimestamp.reset();
    419      mNeedRandomAccessPoint = true;
    420      mNextInsertionIndex.reset();
    421    }
    422 
    423    void Reset() {
    424      ResetAppendState();
    425      mEvictionIndex.Reset();
    426      for (auto& buffer : mBuffers) {
    427        buffer.Clear();
    428      }
    429      mSizeBuffer = 0;
    430      mNextGetSampleIndex.reset();
    431      mBufferedRanges.Clear();
    432      mSanitizedBufferedRanges.Clear();
    433    }
    434 
    435    void AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes) const;
    436  };
    437 
    438  void CheckSequenceDiscontinuity(const media::TimeUnit& aPresentationTime)
    439      MOZ_REQUIRES(mTaskQueueCapability);
    440  void ProcessFrames(TrackBuffer& aSamples, TrackData& aTrackData)
    441      MOZ_REQUIRES(mTaskQueueCapability);
    442  media::TimeInterval PresentationInterval(const TrackBuffer& aSamples) const
    443      MOZ_REQUIRES(mTaskQueueCapability);
    444  bool CheckNextInsertionIndex(TrackData& aTrackData,
    445                               const media::TimeUnit& aSampleTime)
    446      MOZ_REQUIRES(mTaskQueueCapability);
    447  void InsertFrames(TrackBuffer& aSamples,
    448                    const media::TimeIntervals& aIntervals,
    449                    TrackData& aTrackData) MOZ_REQUIRES(mTaskQueueCapability);
    450  void UpdateHighestTimestamp(TrackData& aTrackData,
    451                              const media::TimeUnit& aHighestTime)
    452      MOZ_REQUIRES(mTaskQueueCapability);
    453  // Remove all frames and their dependencies contained in aIntervals.
    454  // Return the index at which frames were first removed or 0 if no frames
    455  // removed.
    456  enum class RemovalMode {
    457    kRemoveFrame,
    458    kTruncateFrame,
    459  };
    460  uint32_t RemoveFrames(const media::TimeIntervals& aIntervals,
    461                        TrackData& aTrackData, uint32_t aStartIndex,
    462                        RemovalMode aMode);
    463  // Recalculate track's evictable amount.
    464  void ResetEvictionIndex(TrackData& aTrackData);
    465  void UpdateEvictionIndex(TrackData& aTrackData, uint32_t aCurrentIndex);
    466  // Find index of sample. Return a negative value if not found.
    467  uint32_t FindSampleIndex(const TrackBuffer& aTrackBuffer,
    468                           const media::TimeInterval& aInterval);
    469  const MediaRawData* GetSample(TrackInfo::TrackType aTrack, uint32_t aIndex,
    470                                const media::TimeUnit& aExpectedDts,
    471                                const media::TimeUnit& aExpectedPts,
    472                                const media::TimeUnit& aFuzz);
    473  void UpdateBufferedRanges();
    474  void RejectProcessing(const MediaResult& aRejectValue, const char* aName);
    475  void ResolveProcessing(bool aResolveValue, const char* aName);
    476  MozPromiseRequestHolder<CodedFrameProcessingPromise> mProcessingRequest;
    477  MozPromiseHolder<CodedFrameProcessingPromise> mProcessingPromise;
    478 
    479  // Trackbuffers definition.
    480  nsTArray<const TrackData*> GetTracksList() const;
    481  nsTArray<TrackData*> GetTracksList();
    482  TrackData& GetTracksData(TrackType aTrack) {
    483    switch (aTrack) {
    484      case TrackType::kVideoTrack:
    485        return mVideoTracks;
    486      case TrackType::kAudioTrack:
    487      default:
    488        return mAudioTracks;
    489    }
    490  }
    491  const TrackData& GetTracksData(TrackType aTrack) const {
    492    switch (aTrack) {
    493      case TrackType::kVideoTrack:
    494        return mVideoTracks;
    495      case TrackType::kAudioTrack:
    496      default:
    497        return mAudioTracks;
    498    }
    499  }
    500  TrackData mVideoTracks;
    501  TrackData mAudioTracks;
    502 
    503  // TaskQueue methods and objects.
    504  RefPtr<TaskQueue> GetTaskQueueSafe() const {
    505    MutexAutoLock mut(mMutex);
    506    return mTaskQueue;
    507  }
    508  NotNull<AbstractThread*> TaskQueueFromTaskQueue() const {
    509 #ifdef DEBUG
    510    RefPtr<TaskQueue> taskQueue = GetTaskQueueSafe();
    511    MOZ_ASSERT(taskQueue && taskQueue->IsCurrentThreadIn());
    512 #endif
    513    return WrapNotNull(mTaskQueue.get());
    514  }
    515  bool OnTaskQueue() const {
    516    auto taskQueue = TaskQueueFromTaskQueue();
    517    return taskQueue->IsCurrentThreadIn();
    518  }
    519  void ResetTaskQueue() {
    520    MutexAutoLock mut(mMutex);
    521    mTaskQueue = nullptr;
    522  }
    523 
    524  // SourceBuffer Queues and running context.
    525  SourceBufferTaskQueue mQueue;
    526  void QueueTask(SourceBufferTask* aTask);
    527  void ProcessTasks();
    528  // Set if the TrackBuffersManager is currently processing a task.
    529  // At this stage, this task is always a AppendBufferTask.
    530  RefPtr<SourceBufferTask> mCurrentTask MOZ_GUARDED_BY(mTaskQueueCapability);
    531  // Current SourceBuffer state for ongoing task.
    532  // Its content is returned to the SourceBuffer once the AppendBufferTask has
    533  // completed.
    534  UniquePtr<SourceBufferAttributes> mSourceBufferAttributes
    535      MOZ_GUARDED_BY(mTaskQueueCapability);
    536  // The current sourcebuffer append window. It's content is equivalent to
    537  // mSourceBufferAttributes.mAppendWindowStart/End
    538  media::Interval<double> mAppendWindow MOZ_GUARDED_BY(mTaskQueueCapability);
    539 
    540  // Strong references to external objects.
    541  nsMainThreadPtrHandle<MediaSourceDecoder> mParentDecoder;
    542 
    543  const RefPtr<AbstractThread> mAbstractMainThread;
    544 
    545  // Return public highest end time across all aTracks.
    546  // Monitor must be held.
    547  media::TimeUnit HighestEndTime(
    548      nsTArray<const media::TimeIntervals*>& aTracks) const;
    549 
    550  // true if endOfStream() has been called without error.
    551  Atomic<bool> mHaveAllData{false};
    552 
    553  // Global size of this source buffer content.
    554  Atomic<int64_t> mSizeSourceBuffer;
    555  const int64_t mVideoEvictionThreshold;
    556  const int64_t mAudioEvictionThreshold;
    557  // A ratio of buffer fullness that we use for the auto eviction,
    558  const double mEvictionBufferWatermarkRatio;
    559  enum class EvictionState {
    560    NO_EVICTION_NEEDED,
    561    EVICTION_NEEDED,
    562    EVICTION_COMPLETED,
    563  };
    564  Atomic<EvictionState> mEvictionState;
    565 
    566  // Monitor to protect following objects accessed across multiple threads.
    567  mutable Mutex mMutex MOZ_UNANNOTATED;
    568  // mTaskQueue is only ever written after construction on the task queue.
    569  // As such, it can be accessed while on task queue without the need for the
    570  // mutex.
    571  RefPtr<TaskQueue> mTaskQueue;
    572  // Stable audio and video track time ranges.
    573  media::TimeIntervals mVideoBufferedRanges;
    574  media::TimeIntervals mAudioBufferedRanges;
    575  // MediaInfo of the first init segment read.
    576  MediaInfo mInfo;
    577  // Set to true if MediaSource readyState has changed to ended.
    578  bool mEnded MOZ_GUARDED_BY(mMutex) = false;
    579  // End mutex protected members.
    580 
    581  // EventTargetCapability used to ensure we're running on the task queue
    582  // as expected for various accesses.
    583  // TODO: we could store only this and dispatch to it, rather than also having
    584  // mTaskQueue. However, there's special locking around mTaskQueue, so we keep
    585  // both for now.
    586  Maybe<EventTargetCapability<TaskQueue>> mTaskQueueCapability;
    587 
    588  Maybe<media::TimeUnit> mFrameEndTimeBeforeRecreateDemuxer;
    589 };
    590 
    591 }  // namespace mozilla
    592 
    593 #endif /* MOZILLA_TRACKBUFFERSMANAGER_H_ */