Bug 1943650 - Command-line --help output misformatted after --dbus-service. r=emilio
[gecko.git] / dom / media / webm / WebMDemuxer.h
bloba6306db469a50c7a801beb5a7821702962132505
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
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 #ifndef WebMDemuxer_h_
7 #define WebMDemuxer_h_
9 #include "nsTArray.h"
10 #include "MediaDataDemuxer.h"
11 #include "MediaResource.h"
12 #include "NesteggPacketHolder.h"
14 #include <deque>
15 #include <stdint.h>
16 #include <utility>
18 typedef struct nestegg nestegg;
20 namespace mozilla {
22 class WebMBufferedState;
24 // Queue for holding MediaRawData samples
25 class MediaRawDataQueue {
26 typedef std::deque<RefPtr<MediaRawData>> ContainerType;
28 public:
29 uint32_t GetSize() { return mQueue.size(); }
31 void Push(MediaRawData* aItem) { mQueue.push_back(aItem); }
33 void Push(already_AddRefed<MediaRawData>&& aItem) {
34 mQueue.push_back(std::move(aItem));
37 void PushFront(MediaRawData* aItem) { mQueue.push_front(aItem); }
39 void PushFront(already_AddRefed<MediaRawData>&& aItem) {
40 mQueue.push_front(std::move(aItem));
43 void PushFront(MediaRawDataQueue&& aOther) {
44 while (!aOther.mQueue.empty()) {
45 PushFront(aOther.Pop());
49 already_AddRefed<MediaRawData> PopFront() {
50 RefPtr<MediaRawData> result = std::move(mQueue.front());
51 mQueue.pop_front();
52 return result.forget();
55 already_AddRefed<MediaRawData> Pop() {
56 RefPtr<MediaRawData> result = std::move(mQueue.back());
57 mQueue.pop_back();
58 return result.forget();
61 void Reset() {
62 while (!mQueue.empty()) {
63 mQueue.pop_front();
67 MediaRawDataQueue& operator=(const MediaRawDataQueue& aOther) = delete;
69 const RefPtr<MediaRawData>& First() const { return mQueue.front(); }
71 const RefPtr<MediaRawData>& Last() const { return mQueue.back(); }
73 // Methods for range-based for loops.
74 ContainerType::iterator begin() { return mQueue.begin(); }
76 ContainerType::const_iterator begin() const { return mQueue.begin(); }
78 ContainerType::iterator end() { return mQueue.end(); }
80 ContainerType::const_iterator end() const { return mQueue.end(); }
82 private:
83 ContainerType mQueue;
86 class WebMTrackDemuxer;
88 DDLoggedTypeDeclNameAndBase(WebMDemuxer, MediaDataDemuxer);
89 DDLoggedTypeNameAndBase(WebMTrackDemuxer, MediaTrackDemuxer);
91 class WebMDemuxer : public MediaDataDemuxer,
92 public DecoderDoctorLifeLogger<WebMDemuxer> {
93 public:
94 explicit WebMDemuxer(MediaResource* aResource);
95 // Indicate if the WebMDemuxer is to be used with MediaSource. In which
96 // case the demuxer will stop reads to the last known complete block.
97 WebMDemuxer(
98 MediaResource* aResource, bool aIsMediaSource,
99 Maybe<media::TimeUnit> aFrameEndTimeBeforeRecreateDemuxer = Nothing());
101 RefPtr<InitPromise> Init() override;
103 uint32_t GetNumberTracks(TrackInfo::TrackType aType) const override;
105 UniquePtr<TrackInfo> GetTrackInfo(TrackInfo::TrackType aType,
106 size_t aTrackNumber) const;
108 already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer(
109 TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
111 bool IsSeekable() const override;
113 bool IsSeekableOnlyInBufferedRanges() const override;
115 UniquePtr<EncryptionInfo> GetCrypto() override;
117 bool GetOffsetForTime(uint64_t aTime, int64_t* aOffset);
119 // Demux next WebM packet and append samples to MediaRawDataQueue
120 nsresult GetNextPacket(TrackInfo::TrackType aType,
121 MediaRawDataQueue* aSamples);
123 void Reset(TrackInfo::TrackType aType);
125 // Pushes a packet to the front of the audio packet queue.
126 void PushAudioPacket(NesteggPacketHolder* aItem);
128 // Pushes a packet to the front of the video packet queue.
129 void PushVideoPacket(NesteggPacketHolder* aItem);
131 // Public accessor for nestegg callbacks
132 bool IsMediaSource() const { return mIsMediaSource; }
134 int64_t LastWebMBlockOffset() const { return mLastWebMBlockOffset; }
136 struct NestEggContext {
137 NestEggContext(WebMDemuxer* aParent, MediaResource* aResource)
138 : mParent(aParent), mResource(aResource), mContext(nullptr) {}
140 ~NestEggContext();
142 int Init();
144 // Public accessor for nestegg callbacks
146 bool IsMediaSource() const { return mParent->IsMediaSource(); }
147 MediaResourceIndex* GetResource() { return &mResource; }
149 int64_t GetEndDataOffset() const {
150 return (!mParent->IsMediaSource() || mParent->LastWebMBlockOffset() < 0)
151 ? mResource.GetLength()
152 : mParent->LastWebMBlockOffset();
155 WebMDemuxer* mParent;
156 MediaResourceIndex mResource;
157 nestegg* mContext;
160 private:
161 friend class WebMTrackDemuxer;
163 ~WebMDemuxer();
164 void InitBufferedState();
165 int64_t FloorDefaultDurationToTimecodeScale(nestegg* aContext,
166 unsigned aTrackNumber);
167 nsresult ReadMetadata();
168 void NotifyDataArrived() override;
169 void NotifyDataRemoved() override;
170 void EnsureUpToDateIndex();
172 // A helper to catch bad intervals during `GetBuffered`.
173 // Verifies if the interval given by start and end is valid, returning true if
174 // it is, or false if not. Logs failure reason if the interval is invalid.
175 bool IsBufferedIntervalValid(uint64_t start, uint64_t end);
177 media::TimeIntervals GetBuffered();
178 nsresult SeekInternal(TrackInfo::TrackType aType,
179 const media::TimeUnit& aTarget);
180 CryptoTrack GetTrackCrypto(TrackInfo::TrackType aType, size_t aTrackNumber);
182 // Read a packet from the nestegg file. Returns nullptr if all packets for
183 // the particular track have been read. Pass TrackInfo::kVideoTrack or
184 // TrackInfo::kVideoTrack to indicate the type of the packet we want to read.
185 nsresult NextPacket(TrackInfo::TrackType aType,
186 RefPtr<NesteggPacketHolder>& aPacket);
188 // Internal method that demuxes the next packet from the stream. The caller
189 // is responsible for making sure it doesn't get lost.
190 nsresult DemuxPacket(TrackInfo::TrackType aType,
191 RefPtr<NesteggPacketHolder>& aPacket);
193 // libnestegg audio and video context for webm container.
194 // Access on reader's thread only.
195 NestEggContext mVideoContext;
196 NestEggContext mAudioContext;
197 MediaResourceIndex& Resource(TrackInfo::TrackType aType) {
198 return aType == TrackInfo::kVideoTrack ? mVideoContext.mResource
199 : mAudioContext.mResource;
201 nestegg* Context(TrackInfo::TrackType aType) const {
202 return aType == TrackInfo::kVideoTrack ? mVideoContext.mContext
203 : mAudioContext.mContext;
206 MediaInfo mInfo;
207 nsTArray<RefPtr<WebMTrackDemuxer>> mDemuxers;
209 // Parser state and computed offset-time mappings. Shared by multiple
210 // readers when decoder has been cloned. Main thread only.
211 RefPtr<WebMBufferedState> mBufferedState;
212 RefPtr<MediaByteBuffer> mInitData;
214 // Queue of video and audio packets that have been read but not decoded.
215 WebMPacketQueue mVideoPackets;
216 WebMPacketQueue mAudioPackets;
218 // Index of video and audio track to play
219 uint32_t mVideoTrack;
220 uint32_t mAudioTrack;
222 // Nanoseconds to discard after seeking.
223 uint64_t mSeekPreroll;
225 // Calculate the frame duration from the last decodeable frame using the
226 // previous frame's timestamp. In microseconds.
227 Maybe<int64_t> mLastAudioFrameTime;
228 Maybe<int64_t> mLastVideoFrameTime;
230 Maybe<media::TimeUnit> mVideoFrameEndTimeBeforeReset;
232 // Codec ID of audio track
233 int mAudioCodec;
234 // Codec ID of video track
235 int mVideoCodec;
236 // Default durations of blocks for each track, in microseconds
237 int64_t mAudioDefaultDuration;
238 int64_t mVideoDefaultDuration;
240 // Booleans to indicate if we have audio and/or video data
241 bool mHasVideo;
242 bool mHasAudio;
243 bool mNeedReIndex;
245 // The last complete block parsed by the WebMBufferedState. -1 if not set.
246 // We cache those values rather than retrieving them for performance reasons
247 // as nestegg only performs 1-byte read at a time.
248 int64_t mLastWebMBlockOffset;
249 const bool mIsMediaSource;
250 // Discard padding in WebM cannot occur more than once. This is set to true if
251 // a discard padding element has been found and processed, and the decoding is
252 // expected to error out if another discard padding element is found
253 // subsequently in the byte stream.
254 bool mProcessedDiscardPadding = false;
256 EncryptionInfo mCrypto;
259 class WebMTrackDemuxer : public MediaTrackDemuxer,
260 public DecoderDoctorLifeLogger<WebMTrackDemuxer> {
261 public:
262 WebMTrackDemuxer(WebMDemuxer* aParent, TrackInfo::TrackType aType,
263 uint32_t aTrackNumber);
265 UniquePtr<TrackInfo> GetInfo() const override;
267 RefPtr<SeekPromise> Seek(const media::TimeUnit& aTime) override;
269 RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples = 1) override;
271 void Reset() override;
273 nsresult GetNextRandomAccessPoint(media::TimeUnit* aTime) override;
275 RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint(
276 const media::TimeUnit& aTimeThreshold) override;
278 media::TimeIntervals GetBuffered() override;
280 int64_t GetEvictionOffset(const media::TimeUnit& aTime) override;
282 void BreakCycles() override;
284 private:
285 friend class WebMDemuxer;
286 ~WebMTrackDemuxer();
287 void UpdateSamples(const nsTArray<RefPtr<MediaRawData>>& aSamples);
288 void SetNextKeyFrameTime();
289 nsresult NextSample(RefPtr<MediaRawData>& aData);
290 RefPtr<WebMDemuxer> mParent;
291 TrackInfo::TrackType mType;
292 UniquePtr<TrackInfo> mInfo;
293 Maybe<media::TimeUnit> mNextKeyframeTime;
294 bool mNeedKeyframe;
296 // Queued samples extracted by the demuxer, but not yet returned.
297 MediaRawDataQueue mSamples;
300 } // namespace mozilla
302 #endif