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 #if !defined(MediaDataDemuxer_h) 8 # define MediaDataDemuxer_h 9 10 # include "DecoderDoctorLogger.h" 11 # include "mozilla/MozPromise.h" 12 # include "mozilla/UniquePtr.h" 13 14 # include "MediaData.h" 15 # include "MediaInfo.h" 16 # include "MediaResult.h" 17 # include "TimeUnits.h" 18 # include "nsISupportsImpl.h" 19 # include "mozilla/RefPtr.h" 20 # include "nsTArray.h" 21 22 namespace mozilla { 23 24 class MediaTrackDemuxer; 25 class TrackMetadataHolder; 26 27 DDLoggedTypeDeclName(MediaDataDemuxer); 28 DDLoggedTypeName(MediaTrackDemuxer); 29 30 // Allows reading the media data: to retrieve the metadata and demux samples. 31 // MediaDataDemuxer isn't designed to be thread safe. 32 // When used by the MediaFormatDecoder, care is taken to ensure that the demuxer 33 // will never be called from more than one thread at once. 34 class MediaDataDemuxer : public DecoderDoctorLifeLogger<MediaDataDemuxer> { 35 public: 36 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDataDemuxer) 37 38 typedef MozPromise<MediaResult, MediaResult, /* IsExclusive = */ true> 39 InitPromise; 40 41 // Initializes the demuxer. Other methods cannot be called unless 42 // initialization has completed and succeeded. 43 // Typically a demuxer will wait to parse the metadata before resolving the 44 // promise. The promise must not be resolved until sufficient data is 45 // supplied. For example, an incomplete metadata would cause the promise to be 46 // rejected should no more data be coming, while the demuxer would wait 47 // otherwise. 48 virtual RefPtr<InitPromise> Init() = 0; 49 50 // Returns the number of tracks of aType type available. A value of 51 // 0 indicates that no such type is available. 52 virtual uint32_t GetNumberTracks(TrackInfo::TrackType aType) const = 0; 53 54 // Returns the MediaTrackDemuxer associated with aTrackNumber aType track. 55 // aTrackNumber is not to be confused with the Track ID. 56 // aTrackNumber must be constrained between 0 and GetNumberTracks(aType) - 1 57 // The actual Track ID is to be retrieved by calling 58 // MediaTrackDemuxer::TrackInfo. 59 virtual already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer( 60 TrackInfo::TrackType aType, uint32_t aTrackNumber) = 0; 61 62 // Returns true if the underlying resource allows seeking. 63 virtual bool IsSeekable() const = 0; 64 65 // Returns true if the underlying resource can only seek within buffered 66 // ranges. IsSeekableOnlyInBufferedRanges()67 virtual bool IsSeekableOnlyInBufferedRanges() const { return false; } 68 69 // Returns the media's crypto information, or nullptr if media isn't 70 // encrypted. GetCrypto()71 virtual UniquePtr<EncryptionInfo> GetCrypto() { return nullptr; } 72 73 // Notifies the demuxer that the underlying resource has received more data 74 // since the demuxer was initialized. 75 // The demuxer can use this mechanism to inform all track demuxers that new 76 // data is available and to refresh its buffered range. NotifyDataArrived()77 virtual void NotifyDataArrived() {} 78 79 // Notifies the demuxer that the underlying resource has had data removed 80 // since the demuxer was initialized. 81 // The demuxer can use this mechanism to inform all track demuxers to update 82 // its buffered range. 83 // This will be called should the demuxer be used with MediaSource. NotifyDataRemoved()84 virtual void NotifyDataRemoved() {} 85 86 // Indicate to MediaFormatReader if it should compute the start time 87 // of the demuxed data. If true (default) the first sample returned will be 88 // used as reference time base. ShouldComputeStartTime()89 virtual bool ShouldComputeStartTime() const { return true; } 90 91 protected: 92 virtual ~MediaDataDemuxer() = default; 93 }; 94 95 class MediaTrackDemuxer : public DecoderDoctorLifeLogger<MediaTrackDemuxer> { 96 public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaTrackDemuxer)97 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaTrackDemuxer) 98 99 class SamplesHolder { 100 public: 101 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SamplesHolder) 102 103 void AppendSample(RefPtr<MediaRawData>& aSample) { 104 MOZ_DIAGNOSTIC_ASSERT(aSample->HasValidTime()); 105 mSamples.AppendElement(aSample); 106 } 107 108 const nsTArray<RefPtr<MediaRawData>>& GetSamples() const { 109 return mSamples; 110 } 111 112 // This method is only used to do the move semantic for mSamples, do not 113 // append any element to the samples we returns. We should always append new 114 // sample to mSamples via `AppendSample()`. 115 nsTArray<RefPtr<MediaRawData>>& GetMovableSamples() { return mSamples; } 116 117 private: 118 ~SamplesHolder() = default; 119 nsTArray<RefPtr<MediaRawData>> mSamples; 120 }; 121 122 class SkipFailureHolder { 123 public: SkipFailureHolder(const MediaResult & aFailure,uint32_t aSkipped)124 SkipFailureHolder(const MediaResult& aFailure, uint32_t aSkipped) 125 : mFailure(aFailure), mSkipped(aSkipped) {} 126 MediaResult mFailure; 127 uint32_t mSkipped; 128 }; 129 130 typedef MozPromise<media::TimeUnit, MediaResult, /* IsExclusive = */ true> 131 SeekPromise; 132 typedef MozPromise<RefPtr<SamplesHolder>, MediaResult, 133 /* IsExclusive = */ true> 134 SamplesPromise; 135 typedef MozPromise<uint32_t, SkipFailureHolder, /* IsExclusive = */ true> 136 SkipAccessPointPromise; 137 138 // Returns the TrackInfo (a.k.a Track Description) for this track. 139 // The TrackInfo returned will be: 140 // TrackInfo::kVideoTrack -> VideoInfo. 141 // TrackInfo::kAudioTrack -> AudioInfo. 142 // respectively. 143 virtual UniquePtr<TrackInfo> GetInfo() const = 0; 144 145 // Seeks to aTime. Upon success, SeekPromise will be resolved with the 146 // actual time seeked to. Typically the random access point time 147 virtual RefPtr<SeekPromise> Seek(const media::TimeUnit& aTime) = 0; 148 149 // Returns the next aNumSamples sample(s) available. 150 // If only a lesser amount of samples is available, only those will be 151 // returned. 152 // A aNumSamples value of -1 indicates to return all remaining samples. 153 // A video sample is typically made of a single video frame while an audio 154 // sample will contains multiple audio frames. 155 virtual RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples = 1) = 0; 156 157 // Returns true if a call to GetSamples() may block while waiting on the 158 // underlying resource to return the data. 159 // This is used by the MediaFormatReader to determine if buffering heuristics 160 // should be used. GetSamplesMayBlock()161 virtual bool GetSamplesMayBlock() const { return true; } 162 163 // Cancel all pending actions (Seek, GetSamples) and reset current state 164 // All pending promises are to be rejected with CANCEL. 165 // The next call to GetSamples would return the first sample available in the 166 // track. 167 virtual void Reset() = 0; 168 169 // Returns timestamp of next random access point or an error if the demuxer 170 // can't report this. GetNextRandomAccessPoint(media::TimeUnit * aTime)171 virtual nsresult GetNextRandomAccessPoint(media::TimeUnit* aTime) { 172 return NS_ERROR_NOT_IMPLEMENTED; 173 } 174 175 // Returns timestamp of previous random access point or an error if the 176 // demuxer can't report this. GetPreviousRandomAccessPoint(media::TimeUnit * aTime)177 virtual nsresult GetPreviousRandomAccessPoint(media::TimeUnit* aTime) { 178 return NS_ERROR_NOT_IMPLEMENTED; 179 } 180 181 // Skip frames until the next Random Access Point located after 182 // aTimeThreshold. 183 // The first frame returned by the next call to GetSamples() will be the 184 // first random access point found after aTimeThreshold. 185 // Upon success, returns the number of frames skipped. 186 virtual RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint( 187 const media::TimeUnit& aTimeThreshold) = 0; 188 189 // Gets the resource's offset used for the last Seek() or GetSample(). 190 // A negative value indicates that this functionality isn't supported. GetResourceOffset()191 virtual int64_t GetResourceOffset() const { return -1; } 192 GetType()193 virtual TrackInfo::TrackType GetType() const { return GetInfo()->GetType(); } 194 195 virtual media::TimeIntervals GetBuffered() = 0; 196 197 // By default, it is assumed that the entire resource can be evicted once 198 // all samples have been demuxed. GetEvictionOffset(const media::TimeUnit & aTime)199 virtual int64_t GetEvictionOffset(const media::TimeUnit& aTime) { 200 return INT64_MAX; 201 } 202 203 // If the MediaTrackDemuxer and MediaDataDemuxer hold cross references. 204 // BreakCycles must be overridden. BreakCycles()205 virtual void BreakCycles() {} 206 207 protected: 208 virtual ~MediaTrackDemuxer() = default; 209 }; 210 211 } // namespace mozilla 212 213 #endif // MediaDataDemuxer_h 214