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