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: ~MediaDataDemuxer()92 virtual ~MediaDataDemuxer() {} 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 nsTArray<RefPtr<MediaRawData>> mSamples; 103 104 private: 105 ~SamplesHolder() {} 106 }; 107 108 class SkipFailureHolder { 109 public: SkipFailureHolder(const MediaResult & aFailure,uint32_t aSkipped)110 SkipFailureHolder(const MediaResult& aFailure, uint32_t aSkipped) 111 : mFailure(aFailure), mSkipped(aSkipped) {} 112 MediaResult mFailure; 113 uint32_t mSkipped; 114 }; 115 116 typedef MozPromise<media::TimeUnit, MediaResult, /* IsExclusive = */ true> 117 SeekPromise; 118 typedef MozPromise<RefPtr<SamplesHolder>, MediaResult, 119 /* IsExclusive = */ true> 120 SamplesPromise; 121 typedef MozPromise<uint32_t, SkipFailureHolder, /* IsExclusive = */ true> 122 SkipAccessPointPromise; 123 124 // Returns the TrackInfo (a.k.a Track Description) for this track. 125 // The TrackInfo returned will be: 126 // TrackInfo::kVideoTrack -> VideoInfo. 127 // TrackInfo::kAudioTrack -> AudioInfo. 128 // respectively. 129 virtual UniquePtr<TrackInfo> GetInfo() const = 0; 130 131 // Seeks to aTime. Upon success, SeekPromise will be resolved with the 132 // actual time seeked to. Typically the random access point time 133 virtual RefPtr<SeekPromise> Seek(const media::TimeUnit& aTime) = 0; 134 135 // Returns the next aNumSamples sample(s) available. 136 // If only a lesser amount of samples is available, only those will be 137 // returned. 138 // A aNumSamples value of -1 indicates to return all remaining samples. 139 // A video sample is typically made of a single video frame while an audio 140 // sample will contains multiple audio frames. 141 virtual RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples = 1) = 0; 142 143 // Returns true if a call to GetSamples() may block while waiting on the 144 // underlying resource to return the data. 145 // This is used by the MediaFormatReader to determine if buffering heuristics 146 // should be used. GetSamplesMayBlock()147 virtual bool GetSamplesMayBlock() const { return true; } 148 149 // Cancel all pending actions (Seek, GetSamples) and reset current state 150 // All pending promises are to be rejected with CANCEL. 151 // The next call to GetSamples would return the first sample available in the 152 // track. 153 virtual void Reset() = 0; 154 155 // Returns timestamp of next random access point or an error if the demuxer 156 // can't report this. GetNextRandomAccessPoint(media::TimeUnit * aTime)157 virtual nsresult GetNextRandomAccessPoint(media::TimeUnit* aTime) { 158 return NS_ERROR_NOT_IMPLEMENTED; 159 } 160 161 // Returns timestamp of previous random access point or an error if the 162 // demuxer can't report this. GetPreviousRandomAccessPoint(media::TimeUnit * aTime)163 virtual nsresult GetPreviousRandomAccessPoint(media::TimeUnit* aTime) { 164 return NS_ERROR_NOT_IMPLEMENTED; 165 } 166 167 // Skip frames until the next Random Access Point located after 168 // aTimeThreshold. 169 // The first frame returned by the next call to GetSamples() will be the 170 // first random access point found after aTimeThreshold. 171 // Upon success, returns the number of frames skipped. 172 virtual RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint( 173 const media::TimeUnit& aTimeThreshold) = 0; 174 175 // Gets the resource's offset used for the last Seek() or GetSample(). 176 // A negative value indicates that this functionality isn't supported. GetResourceOffset()177 virtual int64_t GetResourceOffset() const { return -1; } 178 GetType()179 virtual TrackInfo::TrackType GetType() const { return GetInfo()->GetType(); } 180 181 virtual media::TimeIntervals GetBuffered() = 0; 182 183 // By default, it is assumed that the entire resource can be evicted once 184 // all samples have been demuxed. GetEvictionOffset(const media::TimeUnit & aTime)185 virtual int64_t GetEvictionOffset(const media::TimeUnit& aTime) { 186 return INT64_MAX; 187 } 188 189 // If the MediaTrackDemuxer and MediaDataDemuxer hold cross references. 190 // BreakCycles must be overridden. BreakCycles()191 virtual void BreakCycles() {} 192 193 protected: ~MediaTrackDemuxer()194 virtual ~MediaTrackDemuxer() {} 195 }; 196 197 } // namespace mozilla 198 199 #endif // MediaDataDemuxer_h 200