Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  TrackBuffersManager.h   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#ifndef MOZILLA_TRACKBUFFERSMANAGER_H_
#define MOZILLA_TRACKBUFFERSMANAGER_H_

#include "mozilla/Atomics.h"
#include "mozilla/EventTargetCapability.h"
#include "mozilla/Maybe.h"
#include "mozilla/Mutex.h"
#include "mozilla/NotNull.h"
#include "mozilla/TaskQueue.h"
#include "mozilla/dom/MediaDebugInfoBinding.h"

#include "MediaContainerType.h"
#include "MediaData.h"
#include "MediaDataDemuxer.h"
#include "MediaResult.h"
#include "MediaSourceDecoder.h"
#include "MediaSpan.h"
#include "SourceBufferTask.h"
#include "TimeUnits.h"
#include "nsTArray.h"

namespace mozilla {

class AbstractThread;
class ContainerParser;
class MediaByteBuffer;
class MediaRawData;
class MediaSourceDemuxer;
class SourceBufferResource;

class SourceBufferTaskQueue {
 public:
  SourceBufferTaskQueue() = default;

  ~SourceBufferTaskQueue() {
    MOZ_ASSERT(mQueue.IsEmpty(), "All tasks must have been processed");
  }

  void Push(SourceBufferTask* aTask) { mQueue.AppendElement(aTask); }

  already_AddRefed<SourceBufferTask> Pop() {
    if (!mQueue.Length()) {
      return nullptr;
    }
    RefPtr<SourceBufferTask> task = std::move(mQueue[0]);
    mQueue.RemoveElementAt(0);
    return task.forget();
  }

  nsTArray<RefPtr<SourceBufferTask>>::size_type Length() const {
    return mQueue.Length();
  }

 private:
  nsTArray<RefPtr<SourceBufferTask>> mQueue;
};

DDLoggedTypeDeclName(TrackBuffersManager);

class TrackBuffersManager final
    : public DecoderDoctorLifeLogger<TrackBuffersManager> {
 public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackBuffersManager);

  enum class EvictDataResult : int8_t {
    NO_DATA_EVICTED,
    CANT_EVICT,
    BUFFER_FULL,
  };

  using TrackType = TrackInfo::TrackType;
  using MediaType = MediaData::Type;
  using TrackBuffer = nsTArray<RefPtr<MediaRawData>>;
  using AppendPromise = SourceBufferTask::AppendPromise;
  using RangeRemovalPromise = SourceBufferTask::RangeRemovalPromise;

  // Interface for SourceBuffer
  TrackBuffersManager(MediaSourceDecoder* aParentDecoder,
                      const MediaContainerType& aType);

  // Queue a task to add data to the end of the input buffer and run the MSE
  // Buffer Append Algorithm
  // 3.5.5 Buffer Append Algorithm.
  // http://w3c.github.io/media-source/index.html#sourcebuffer-buffer-append
  RefPtr<AppendPromise> AppendData(already_AddRefed<MediaByteBuffer> aData,
                                   const SourceBufferAttributes& aAttributes);

  // Queue a task to abort any pending AppendData.
  // Does nothing at this stage.
  void AbortAppendData();

  // Queue a task to run MSE Reset Parser State Algorithm.
  // 3.5.2 Reset Parser State
  void ResetParserState(SourceBufferAttributes& aAttributes);

  // Queue a task to run the MSE range removal algorithm.
  // http://w3c.github.io/media-source/#sourcebuffer-coded-frame-removal
  RefPtr<RangeRemovalPromise> RangeRemoval(media::TimeUnit aStart,
                                           media::TimeUnit aEnd);

  // Schedule data eviction if necessary as the next call to AppendData will
  // add aSize bytes.
  // Eviction is done in two steps, first remove data up to aPlaybackTime
  // and if still more space is needed remove from the end.
  EvictDataResult EvictData(const media::TimeUnit& aPlaybackTime, int64_t aSize,
                            TrackType aType);

  // Schedule data eviction if necessary and the size of eviction would be
  // determined automatically. This is currently used when the buffer's size is
  // close to full and the normal procedure to evict data is not enough.
  void EvictDataWithoutSize(TrackType aType, const media::TimeUnit& aTarget);

  // Queue a task to run ChangeType
  void ChangeType(const MediaContainerType& aType);

  // Returns the buffered range currently managed.
  // This may be called on any thread.
  // Buffered must conform to
  // http://w3c.github.io/media-source/index.html#widl-SourceBuffer-buffered
  media::TimeIntervals Buffered() const;
  media::TimeUnit HighestStartTime() const;
  media::TimeUnit HighestEndTime() const;

  // Return the size of the data managed by this SourceBufferContentManager.
  int64_t GetSize() const;

  // Indicate that the MediaSource parent object got into "ended" state.
  void Ended();

  // The parent SourceBuffer is about to be destroyed.
  void Detach();

  // Return the eviction threshold, in bytes, for a track type (audio or video).
  // When the track type isn't passed in (kUndefinedTrack), this returns the
  // value for video if a video track is present. Specifying the track type
  // explicitely is useful when initialization hasn't finished, but the track
  // type is known already.
  int64_t EvictionThreshold(
      TrackInfo::TrackType aType = TrackInfo::TrackType::kUndefinedTrack) const;

  // Interface for MediaSourceDemuxer
  MediaInfo GetMetadata() const;
  const TrackBuffer& GetTrackBuffer(TrackInfo::TrackType aTrack) const;
  const media::TimeIntervals& Buffered(TrackInfo::TrackType) const;
  const media::TimeUnit& HighestStartTime(TrackInfo::TrackType) const;
  media::TimeIntervals SafeBuffered(TrackInfo::TrackType) const;
  bool IsEnded() const { return mEnded; }
  uint32_t Evictable(TrackInfo::TrackType aTrack) const;
  media::TimeUnit Seek(TrackInfo::TrackType aTrack,
                       const media::TimeUnit& aTime,
                       const media::TimeUnit& aFuzz);
  uint32_t SkipToNextRandomAccessPoint(TrackInfo::TrackType aTrack,
                                       const media::TimeUnit& aTimeThreadshold,
                                       const media::TimeUnit& aFuzz,
                                       bool& aFound);

  already_AddRefed<MediaRawData> GetSample(TrackInfo::TrackType aTrack,
                                           const media::TimeUnit& aFuzz,
                                           MediaResult& aResult);
  int32_t FindCurrentPosition(TrackInfo::TrackType aTrack,
                              const media::TimeUnit& aFuzz) const
      MOZ_REQUIRES(mTaskQueueCapability);

  // Will set the next GetSample index if needed. This information is determined
  // through the value of mNextSampleTimecode. Return false if the index
  // couldn't be determined or if there's nothing more that could be demuxed.
  // This occurs if either the track buffer doesn't contain the required
  // timecode or is empty.
  nsresult SetNextGetSampleIndexIfNeeded(TrackInfo::TrackType aTrack,
                                         const media::TimeUnit& aFuzz)
      MOZ_REQUIRES(mTaskQueueCapability);

  media::TimeUnit GetNextRandomAccessPoint(TrackInfo::TrackType aTrack,
                                           const media::TimeUnit& aFuzz);

  // Requests that the TrackBuffersManager populates aInfo with debug
  // information. This may be done asynchronously, and aInfo should *not* be
  // accessed by the caller until the returned promise is resolved or rejected.
  RefPtr<GenericPromise> RequestDebugInfo(
      dom::TrackBuffersManagerDebugInfo& aInfo) const;
  void AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes) const;

 private:
  using CodedFrameProcessingPromise = MozPromise<bool, MediaResult, true>;

  ~TrackBuffersManager();
  // All following functions run on the taskqueue.
  RefPtr<AppendPromise> DoAppendData(already_AddRefed<MediaByteBuffer> aData,
                                     const SourceBufferAttributes& aAttributes);
  void ScheduleSegmentParserLoop() MOZ_REQUIRES(mTaskQueueCapability);
  void SegmentParserLoop() MOZ_REQUIRES(mTaskQueueCapability);
  void InitializationSegmentReceived() MOZ_REQUIRES(mTaskQueueCapability);
  void ShutdownDemuxers() MOZ_REQUIRES(mTaskQueueCapability);
  void CreateDemuxerforMIMEType() MOZ_REQUIRES(mTaskQueueCapability);
  void ResetDemuxingState() MOZ_REQUIRES(mTaskQueueCapability);
  void NeedMoreData() MOZ_REQUIRES(mTaskQueueCapability);
  void RejectAppend(const MediaResult& aRejectValue, const char* aName)
      MOZ_REQUIRES(mTaskQueueCapability);
  // Will return a promise that will be resolved once all frames of the current
  // media segment have been processed.
  RefPtr<CodedFrameProcessingPromise> CodedFrameProcessing()
      MOZ_REQUIRES(mTaskQueueCapability);
  void CompleteCodedFrameProcessing() MOZ_REQUIRES(mTaskQueueCapability);
  // Called by ResetParserState.
  void CompleteResetParserState() MOZ_REQUIRES(mTaskQueueCapability);
  RefPtr<RangeRemovalPromise> CodedFrameRemovalWithPromise(
      const media::TimeInterval& aInterval) MOZ_REQUIRES(mTaskQueueCapability);
  bool CodedFrameRemoval(const media::TimeInterval& aInterval)
      MOZ_REQUIRES(mTaskQueueCapability);
  // Removes all coded frames -- this is not to spec and should be used as a
  // last resort to clear buffers only if other methods cannot.
  void RemoveAllCodedFrames() MOZ_REQUIRES(mTaskQueueCapability);
  void SetAppendState(SourceBufferAttributes::AppendState aAppendState)
      MOZ_REQUIRES(mTaskQueueCapability);

  bool HasVideo() const { return mVideoTracks.mNumTracks > 0; }
  bool HasAudio() const { return mAudioTracks.mNumTracks > 0; }

  // The input buffer as per
  // http://w3c.github.io/media-source/index.html#sourcebuffer-input-buffer
  Maybe<MediaSpan> mInputBuffer MOZ_GUARDED_BY(mTaskQueueCapability);
  // Buffer full flag as per
  // https://w3c.github.io/media-source/#sourcebuffer-buffer-full-flag. Accessed
  // on both the main thread and the task queue.
  Atomic<bool> mBufferFull;
  bool mFirstInitializationSegmentReceived MOZ_GUARDED_BY(mTaskQueueCapability);
  bool mChangeTypeReceived MOZ_GUARDED_BY(mTaskQueueCapability);
  // Set to true once a new segment is started.
  bool mNewMediaSegmentStarted MOZ_GUARDED_BY(mTaskQueueCapability);
  bool mActiveTrack MOZ_GUARDED_BY(mTaskQueueCapability);
  MediaContainerType mType MOZ_GUARDED_BY(mTaskQueueCapability);

  // ContainerParser objects and methods.
  // Those are used to parse the incoming input buffer.

  // Recreate the ContainerParser and if aReuseInitData is true then
  // feed it with the previous init segment found.
  void RecreateParser(bool aReuseInitData) MOZ_REQUIRES(mTaskQueueCapability);
  UniquePtr<ContainerParser> mParser;

  // Demuxer objects and methods.
  void AppendDataToCurrentInputBuffer(const MediaSpan& aData)
      MOZ_REQUIRES(mTaskQueueCapability);

  RefPtr<MediaByteBuffer> mInitData MOZ_GUARDED_BY(mTaskQueueCapability);

  // Checks if a new set of init data is a repeat of the last set of init data
  // received. Because streams may retransmit the same init data (or
  // functionally equivalent init data) we do not want to perform costly
  // operations each time we receive init data, only when it's actually
  // different data.
  bool IsRepeatInitData(const MediaInfo& aNewMediaInfo) const
      MOZ_REQUIRES(mTaskQueueCapability);

  // Temporary input buffer to handle partial media segment header.
  // We store the current input buffer content into it should we need to
  // reinitialize the demuxer once we have some samples and a discontinuity is
  // detected.
  Maybe<MediaSpan> mPendingInputBuffer MOZ_GUARDED_BY(mTaskQueueCapability);
  RefPtr<SourceBufferResource> mCurrentInputBuffer
      MOZ_GUARDED_BY(mTaskQueueCapability);
  RefPtr<MediaDataDemuxer> mInputDemuxer MOZ_GUARDED_BY(mTaskQueueCapability);
  // Length already processed in current media segment.
  uint64_t mProcessedInput MOZ_GUARDED_BY(mTaskQueueCapability);
  Maybe<media::TimeUnit> mLastParsedEndTime
      MOZ_GUARDED_BY(mTaskQueueCapability);

  void OnDemuxerInitDone(const MediaResult& aResult);
  void OnDemuxerInitFailed(const MediaResult& aError);
  void OnDemuxerResetDone(const MediaResult& aResult)
      MOZ_REQUIRES(mTaskQueueCapability);
  MozPromiseRequestHolder<MediaDataDemuxer::InitPromise> mDemuxerInitRequest;

  void OnDemuxFailed(TrackType aTrack, const MediaResult& aError)
      MOZ_REQUIRES(mTaskQueueCapability);
  void DoDemuxVideo() MOZ_REQUIRES(mTaskQueueCapability);
  void OnVideoDemuxCompleted(
      const RefPtr<MediaTrackDemuxer::SamplesHolder>& aSamples);
  void OnVideoDemuxFailed(const MediaResult& aError) {
    mVideoTracks.mDemuxRequest.Complete();
    mTaskQueueCapability->AssertOnCurrentThread();
    OnDemuxFailed(TrackType::kVideoTrack, aError);
  }
  void DoDemuxAudio() MOZ_REQUIRES(mTaskQueueCapability);
  void OnAudioDemuxCompleted(
      const RefPtr<MediaTrackDemuxer::SamplesHolder>& aSamples);
  void OnAudioDemuxFailed(const MediaResult& aError) {
    mAudioTracks.mDemuxRequest.Complete();
    mTaskQueueCapability->AssertOnCurrentThread();
    OnDemuxFailed(TrackType::kAudioTrack, aError);
  }

  // Dispatches an "encrypted" event is any sample in array has initData
  // present.
  void MaybeDispatchEncryptedEvent(
      const nsTArray<RefPtr<MediaRawData>>& aSamples);

  void DoEvictData(const media::TimeUnit& aPlaybackTime,
                   Maybe<int64_t> aSizeToEvict)
      MOZ_REQUIRES(mTaskQueueCapability);

  void GetDebugInfo(dom::TrackBuffersManagerDebugInfo& aInfo) const
      MOZ_REQUIRES(mTaskQueueCapability);

  struct TrackData {
    TrackData() : mNumTracks(0), mNeedRandomAccessPoint(true), mSizeBuffer(0) {}
    Atomic<uint32_t> mNumTracks;
    // Definition of variables:
    // https://w3c.github.io/media-source/#track-buffers
    // Last decode timestamp variable that stores the decode timestamp of the
    // last coded frame appended in the current coded frame group.
    // The variable is initially unset to indicate that no coded frames have
    // been appended yet.
    Maybe<media::TimeUnit> mLastDecodeTimestamp;
    // Last frame duration variable that stores the coded frame duration of the
    // last coded frame appended in the current coded frame group.
    // The variable is initially unset to indicate that no coded frames have
    // been appended yet.
    Maybe<media::TimeUnit> mLastFrameDuration;
    // Highest end timestamp variable that stores the highest coded frame end
    // timestamp across all coded frames in the current coded frame group that
    // were appended to this track buffer.
    // The variable is initially unset to indicate that no coded frames have
    // been appended yet.
    Maybe<media::TimeUnit> mHighestEndTimestamp;
    // Highest presentation timestamp in track buffer.
    // Protected by global monitor, except when reading on the task queue as it
    // is only written there.
    media::TimeUnit mHighestStartTimestamp;
    // Longest frame duration seen since last random access point.
    // Only ever accessed when mLastDecodeTimestamp and mLastFrameDuration are
    // set.
    media::TimeUnit mLongestFrameDuration;
    // Need random access point flag variable that keeps track of whether the
    // track buffer is waiting for a random access point coded frame.
    // The variable is initially set to true to indicate that random access
    // point coded frame is needed before anything can be added to the track
    // buffer.
    bool mNeedRandomAccessPoint;
    RefPtr<MediaTrackDemuxer> mDemuxer;
    MozPromiseRequestHolder<MediaTrackDemuxer::SamplesPromise> mDemuxRequest;
    // Highest end timestamp of the last media segment demuxed.
    media::TimeUnit mLastParsedEndTime;

    // If set, position where the next contiguous frame will be inserted.
    // If a discontinuity is detected, it will be unset and recalculated upon
    // the next insertion.
    Maybe<uint32_t> mNextInsertionIndex;
    // Samples just demuxed, but not yet parsed.
    TrackBuffer mQueuedSamples;
    const TrackBuffer& GetTrackBuffer() const {
      MOZ_RELEASE_ASSERT(mBuffers.Length(),
                         "TrackBuffer must have been created");
      return mBuffers.LastElement();
    }
    TrackBuffer& GetTrackBuffer() {
      MOZ_RELEASE_ASSERT(mBuffers.Length(),
                         "TrackBuffer must have been created");
      return mBuffers.LastElement();
    }
    // We only manage a single track of each type at this time.
    nsTArray<TrackBuffer> mBuffers;
    // Track buffer ranges variable that represents the presentation time ranges
    // occupied by the coded frames currently stored in the track buffer.
    media::TimeIntervals mBufferedRanges;
    // Sanitized mBufferedRanges with a fuzz of half a sample's duration applied
    // This buffered ranges is the basis of what is exposed to the JS.
    media::TimeIntervals mSanitizedBufferedRanges;
    // Byte size of all samples contained in this track buffer.
    uint32_t mSizeBuffer;
    // TrackInfo of the first metadata received.
    RefPtr<TrackInfoSharedPtr> mInfo;
    // TrackInfo of the last metadata parsed (updated with each init segment.
    RefPtr<TrackInfoSharedPtr> mLastInfo;

    // If set, position of the next sample to be retrieved by GetSample().
    // If the position is equal to the TrackBuffer's length, it indicates that
    // we've reached EOS.
    Maybe<uint32_t> mNextGetSampleIndex;
    // Approximation of the next sample's decode timestamp.
    media::TimeUnit mNextSampleTimecode;
    // Approximation of the next sample's presentation timestamp.
    media::TimeUnit mNextSampleTime;

    struct EvictionIndex {
      EvictionIndex() { Reset(); }
      void Reset() {
        mEvictable = 0;
        mLastIndex = 0;
      }
      uint32_t mEvictable = 0;
      uint32_t mLastIndex = 0;
    };
    // Size of data that can be safely evicted during the next eviction
    // cycle.
    // We consider as evictable all frames up to the last keyframe prior to
    // mNextGetSampleIndex. If mNextGetSampleIndex isn't set, then we assume
    // that we can't yet evict data.
    // Protected by global monitor, except when reading on the task queue as it
    // is only written there.
    EvictionIndex mEvictionIndex;

    void ResetAppendState() {
      mLastDecodeTimestamp.reset();
      mLastFrameDuration.reset();
      mHighestEndTimestamp.reset();
      mNeedRandomAccessPoint = true;
      mNextInsertionIndex.reset();
    }

    void Reset() {
      ResetAppendState();
      mEvictionIndex.Reset();
      for (auto& buffer : mBuffers) {
        buffer.Clear();
      }
      mSizeBuffer = 0;
      mNextGetSampleIndex.reset();
      mBufferedRanges.Clear();
      mSanitizedBufferedRanges.Clear();
    }

    void AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes) const;
  };

  void CheckSequenceDiscontinuity(const media::TimeUnit& aPresentationTime)
      MOZ_REQUIRES(mTaskQueueCapability);
  void ProcessFrames(TrackBuffer& aSamples, TrackData& aTrackData)
      MOZ_REQUIRES(mTaskQueueCapability);
  media::TimeInterval PresentationInterval(const TrackBuffer& aSamples) const
      MOZ_REQUIRES(mTaskQueueCapability);
  bool CheckNextInsertionIndex(TrackData& aTrackData,
                               const media::TimeUnit& aSampleTime)
      MOZ_REQUIRES(mTaskQueueCapability);
  void InsertFrames(TrackBuffer& aSamples,
                    const media::TimeIntervals& aIntervals,
                    TrackData& aTrackData) MOZ_REQUIRES(mTaskQueueCapability);
  void UpdateHighestTimestamp(TrackData& aTrackData,
                              const media::TimeUnit& aHighestTime)
      MOZ_REQUIRES(mTaskQueueCapability);
  // Remove all frames and their dependencies contained in aIntervals.
  // Return the index at which frames were first removed or 0 if no frames
  // removed.
  enum class RemovalMode {
    kRemoveFrame,
    kTruncateFrame,
  };
  uint32_t RemoveFrames(const media::TimeIntervals& aIntervals,
                        TrackData& aTrackData, uint32_t aStartIndex,
                        RemovalMode aMode);
  // Recalculate track's evictable amount.
  void ResetEvictionIndex(TrackData& aTrackData);
  void UpdateEvictionIndex(TrackData& aTrackData, uint32_t aCurrentIndex);
  // Find index of sample. Return a negative value if not found.
  uint32_t FindSampleIndex(const TrackBuffer& aTrackBuffer,
                           const media::TimeInterval& aInterval);
  const MediaRawData* GetSample(TrackInfo::TrackType aTrack, uint32_t aIndex,
                                const media::TimeUnit& aExpectedDts,
                                const media::TimeUnit& aExpectedPts,
                                const media::TimeUnit& aFuzz);
  void UpdateBufferedRanges();
  void RejectProcessing(const MediaResult& aRejectValue, const char* aName);
  void ResolveProcessing(bool aResolveValue, const char* aName);
  MozPromiseRequestHolder<CodedFrameProcessingPromise> mProcessingRequest;
  MozPromiseHolder<CodedFrameProcessingPromise> mProcessingPromise;

  // Trackbuffers definition.
  nsTArray<const TrackData*> GetTracksList() const;
  nsTArray<TrackData*> GetTracksList();
  TrackData& GetTracksData(TrackType aTrack) {
    switch (aTrack) {
      case TrackType::kVideoTrack:
        return mVideoTracks;
      case TrackType::kAudioTrack:
      default:
        return mAudioTracks;
    }
  }
  const TrackData& GetTracksData(TrackType aTrack) const {
    switch (aTrack) {
      case TrackType::kVideoTrack:
        return mVideoTracks;
      case TrackType::kAudioTrack:
      default:
        return mAudioTracks;
    }
  }
  TrackData mVideoTracks;
  TrackData mAudioTracks;

  // TaskQueue methods and objects.
  RefPtr<TaskQueue> GetTaskQueueSafe() const {
    MutexAutoLock mut(mMutex);
    return mTaskQueue;
  }
  NotNull<AbstractThread*> TaskQueueFromTaskQueue() const {
#ifdef DEBUG
    RefPtr<TaskQueue> taskQueue = GetTaskQueueSafe();
    MOZ_ASSERT(taskQueue && taskQueue->IsCurrentThreadIn());
#endif
    return WrapNotNull(mTaskQueue.get());
  }
  bool OnTaskQueue() const {
    auto taskQueue = TaskQueueFromTaskQueue();
    return taskQueue->IsCurrentThreadIn();
  }
  void ResetTaskQueue() {
    MutexAutoLock mut(mMutex);
    mTaskQueue = nullptr;
  }

  // SourceBuffer Queues and running context.
  SourceBufferTaskQueue mQueue;
  void QueueTask(SourceBufferTask* aTask);
  void ProcessTasks();
  // Set if the TrackBuffersManager is currently processing a task.
  // At this stage, this task is always a AppendBufferTask.
  RefPtr<SourceBufferTask> mCurrentTask MOZ_GUARDED_BY(mTaskQueueCapability);
  // Current SourceBuffer state for ongoing task.
  // Its content is returned to the SourceBuffer once the AppendBufferTask has
  // completed.
  UniquePtr<SourceBufferAttributes> mSourceBufferAttributes
      MOZ_GUARDED_BY(mTaskQueueCapability);
  // The current sourcebuffer append window. It's content is equivalent to
  // mSourceBufferAttributes.mAppendWindowStart/End
  media::Interval<double> mAppendWindow MOZ_GUARDED_BY(mTaskQueueCapability);

  // Strong references to external objects.
  nsMainThreadPtrHandle<MediaSourceDecoder> mParentDecoder;

  const RefPtr<AbstractThread> mAbstractMainThread;

  // Return public highest end time across all aTracks.
  // Monitor must be held.
  media::TimeUnit HighestEndTime(
      nsTArray<const media::TimeIntervals*>& aTracks) const;

  // Set to true if mediasource state changed to ended.
  Atomic<bool> mEnded;

  // Global size of this source buffer content.
  Atomic<int64_t> mSizeSourceBuffer;
  const int64_t mVideoEvictionThreshold;
  const int64_t mAudioEvictionThreshold;
  // A ratio of buffer fullness that we use for the auto eviction,
  const double mEvictionBufferWatermarkRatio;
  enum class EvictionState {
    NO_EVICTION_NEEDED,
    EVICTION_NEEDED,
    EVICTION_COMPLETED,
  };
  Atomic<EvictionState> mEvictionState;

  // Monitor to protect following objects accessed across multiple threads.
  mutable Mutex mMutex MOZ_UNANNOTATED;
  // mTaskQueue is only ever written after construction on the task queue.
  // As such, it can be accessed while on task queue without the need for the
  // mutex.
  RefPtr<TaskQueue> mTaskQueue;
  // Stable audio and video track time ranges.
  media::TimeIntervals mVideoBufferedRanges;
  media::TimeIntervals mAudioBufferedRanges;
  // MediaInfo of the first init segment read.
  MediaInfo mInfo;
  // End mutex protected members.

  // EventTargetCapability used to ensure we're running on the task queue
  // as expected for various accesses.
  // TODO: we could store only this and dispatch to it, rather than also having
  // mTaskQueue. However, there's special locking around mTaskQueue, so we keep
  // both for now.
  Maybe<EventTargetCapability<TaskQueue>> mTaskQueueCapability;

  Maybe<media::TimeUnit> mFrameEndTimeBeforeRecreateDemuxer;
};

}  // namespace mozilla

#endif /* MOZILLA_TRACKBUFFERSMANAGER_H_ */

Messung V0.5
C=93 H=97 G=94

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge