Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/WebMDemuxer.h
Line
Count
Source (jump to first uncovered line)
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
#if !defined(WebMDemuxer_h_)
7
#define WebMDemuxer_h_
8
9
#include "nsTArray.h"
10
#include "MediaDataDemuxer.h"
11
#include "MediaResource.h"
12
#include "NesteggPacketHolder.h"
13
#include "mozilla/Move.h"
14
15
#include <deque>
16
#include <stdint.h>
17
18
typedef struct nestegg nestegg;
19
20
namespace mozilla {
21
22
class WebMBufferedState;
23
24
// Queue for holding MediaRawData samples
25
class MediaRawDataQueue
26
{
27
  typedef std::deque<RefPtr<MediaRawData>> ContainerType;
28
29
 public:
30
  uint32_t GetSize()
31
  {
32
    return mQueue.size();
33
  }
34
35
  void Push(MediaRawData* aItem)
36
  {
37
    mQueue.push_back(aItem);
38
  }
39
40
  void Push(already_AddRefed<MediaRawData>&& aItem)
41
  {
42
    mQueue.push_back(std::move(aItem));
43
  }
44
45
0
  void PushFront(MediaRawData* aItem) {
46
0
    mQueue.push_front(aItem);
47
0
  }
48
49
  void PushFront(already_AddRefed<MediaRawData>&& aItem)
50
  {
51
    mQueue.push_front(std::move(aItem));
52
  }
53
54
  void PushFront(MediaRawDataQueue&& aOther)
55
  {
56
    while (!aOther.mQueue.empty()) {
57
      PushFront(aOther.Pop());
58
    }
59
  }
60
61
  already_AddRefed<MediaRawData> PopFront()
62
  {
63
    RefPtr<MediaRawData> result = mQueue.front().forget();
64
    mQueue.pop_front();
65
    return result.forget();
66
  }
67
68
  already_AddRefed<MediaRawData> Pop()
69
  {
70
    RefPtr<MediaRawData> result = mQueue.back().forget();
71
    mQueue.pop_back();
72
    return result.forget();
73
  }
74
75
  void Reset()
76
  {
77
    while (!mQueue.empty()) {
78
      mQueue.pop_front();
79
    }
80
  }
81
82
  MediaRawDataQueue& operator=(const MediaRawDataQueue& aOther)
83
0
  {
84
0
    mQueue = aOther.mQueue;
85
0
    return *this;
86
0
  }
87
88
  const RefPtr<MediaRawData>& First() const
89
  {
90
    return mQueue.front();
91
  }
92
93
  const RefPtr<MediaRawData>& Last() const
94
  {
95
    return mQueue.back();
96
  }
97
98
    // Methods for range-based for loops.
99
  ContainerType::iterator begin()
100
  {
101
    return mQueue.begin();
102
  }
103
104
  ContainerType::const_iterator begin() const
105
0
  {
106
0
    return mQueue.begin();
107
0
  }
108
109
  ContainerType::iterator end()
110
  {
111
    return mQueue.end();
112
  }
113
114
  ContainerType::const_iterator end() const
115
0
  {
116
0
    return mQueue.end();
117
0
  }
118
119
private:
120
  ContainerType mQueue;
121
};
122
123
class WebMTrackDemuxer;
124
125
DDLoggedTypeDeclNameAndBase(WebMDemuxer, MediaDataDemuxer);
126
DDLoggedTypeNameAndBase(WebMTrackDemuxer, MediaTrackDemuxer);
127
128
class WebMDemuxer
129
  : public MediaDataDemuxer
130
  , public DecoderDoctorLifeLogger<WebMDemuxer>
131
{
132
public:
133
  explicit WebMDemuxer(MediaResource* aResource);
134
  // Indicate if the WebMDemuxer is to be used with MediaSource. In which
135
  // case the demuxer will stop reads to the last known complete block.
136
  WebMDemuxer(MediaResource* aResource, bool aIsMediaSource);
137
138
  RefPtr<InitPromise> Init() override;
139
140
  uint32_t GetNumberTracks(TrackInfo::TrackType aType) const override;
141
142
  UniquePtr<TrackInfo> GetTrackInfo(TrackInfo::TrackType aType,
143
                                    size_t aTrackNumber) const;
144
145
  already_AddRefed<MediaTrackDemuxer>
146
  GetTrackDemuxer(TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
147
148
  bool IsSeekable() const override;
149
150
  bool IsSeekableOnlyInBufferedRanges() const override;
151
152
  UniquePtr<EncryptionInfo> GetCrypto() override;
153
154
  bool GetOffsetForTime(uint64_t aTime, int64_t* aOffset);
155
156
  // Demux next WebM packet and append samples to MediaRawDataQueue
157
  nsresult GetNextPacket(TrackInfo::TrackType aType,
158
                         MediaRawDataQueue *aSamples);
159
160
  nsresult Reset(TrackInfo::TrackType aType);
161
162
  // Pushes a packet to the front of the audio packet queue.
163
  void PushAudioPacket(NesteggPacketHolder* aItem);
164
165
  // Pushes a packet to the front of the video packet queue.
166
  void PushVideoPacket(NesteggPacketHolder* aItem);
167
168
  // Public accessor for nestegg callbacks
169
  bool IsMediaSource() const
170
  {
171
    return mIsMediaSource;
172
  }
173
174
  int64_t LastWebMBlockOffset() const
175
  {
176
    return mLastWebMBlockOffset;
177
  }
178
179
  struct NestEggContext
180
  {
181
    NestEggContext(WebMDemuxer* aParent, MediaResource* aResource)
182
      : mParent(aParent)
183
      , mResource(aResource)
184
      , mContext(nullptr)
185
    {
186
    }
187
188
    ~NestEggContext();
189
190
    int Init();
191
192
    // Public accessor for nestegg callbacks
193
194
    bool IsMediaSource() const { return mParent->IsMediaSource(); }
195
    MediaResourceIndex* GetResource() { return &mResource; }
196
197
    int64_t GetEndDataOffset() const
198
    {
199
      return (!mParent->IsMediaSource() || mParent->LastWebMBlockOffset() < 0)
200
             ? mResource.GetLength()
201
             : mParent->LastWebMBlockOffset();
202
    }
203
204
    WebMDemuxer* mParent;
205
    MediaResourceIndex mResource;
206
    nestegg* mContext;
207
  };
208
209
private:
210
  friend class WebMTrackDemuxer;
211
212
  ~WebMDemuxer();
213
  void InitBufferedState();
214
  nsresult ReadMetadata();
215
  void NotifyDataArrived() override;
216
  void NotifyDataRemoved() override;
217
  void EnsureUpToDateIndex();
218
  media::TimeIntervals GetBuffered();
219
  nsresult SeekInternal(TrackInfo::TrackType aType,
220
                        const media::TimeUnit& aTarget);
221
  CryptoTrack GetTrackCrypto(TrackInfo::TrackType aType, size_t aTrackNumber);
222
223
  // Read a packet from the nestegg file. Returns nullptr if all packets for
224
  // the particular track have been read. Pass TrackInfo::kVideoTrack or
225
  // TrackInfo::kVideoTrack to indicate the type of the packet we want to read.
226
  nsresult NextPacket(TrackInfo::TrackType aType,
227
                      RefPtr<NesteggPacketHolder>& aPacket);
228
229
  // Internal method that demuxes the next packet from the stream. The caller
230
  // is responsible for making sure it doesn't get lost.
231
  nsresult DemuxPacket(TrackInfo::TrackType aType,
232
                       RefPtr<NesteggPacketHolder>& aPacket);
233
234
  // libnestegg audio and video context for webm container.
235
  // Access on reader's thread only.
236
  NestEggContext mVideoContext;
237
  NestEggContext mAudioContext;
238
  MediaResourceIndex& Resource(TrackInfo::TrackType aType)
239
  {
240
    return aType == TrackInfo::kVideoTrack
241
           ? mVideoContext.mResource : mAudioContext.mResource;
242
  }
243
  nestegg* Context(TrackInfo::TrackType aType) const
244
  {
245
    return aType == TrackInfo::kVideoTrack
246
           ? mVideoContext.mContext : mAudioContext.mContext;
247
  }
248
249
  MediaInfo mInfo;
250
  nsTArray<RefPtr<WebMTrackDemuxer>> mDemuxers;
251
252
  // Parser state and computed offset-time mappings.  Shared by multiple
253
  // readers when decoder has been cloned.  Main thread only.
254
  RefPtr<WebMBufferedState> mBufferedState;
255
  RefPtr<MediaByteBuffer> mInitData;
256
257
258
  // Queue of video and audio packets that have been read but not decoded.
259
  WebMPacketQueue mVideoPackets;
260
  WebMPacketQueue mAudioPackets;
261
262
  // Index of video and audio track to play
263
  uint32_t mVideoTrack;
264
  uint32_t mAudioTrack;
265
266
  // Nanoseconds to discard after seeking.
267
  uint64_t mSeekPreroll;
268
269
  // Calculate the frame duration from the last decodeable frame using the
270
  // previous frame's timestamp.  In NS.
271
  Maybe<int64_t> mLastAudioFrameTime;
272
  Maybe<int64_t> mLastVideoFrameTime;
273
274
  // Codec ID of audio track
275
  int mAudioCodec;
276
  // Codec ID of video track
277
  int mVideoCodec;
278
279
  // Booleans to indicate if we have audio and/or video data
280
  bool mHasVideo;
281
  bool mHasAudio;
282
  bool mNeedReIndex;
283
284
  // The last complete block parsed by the WebMBufferedState. -1 if not set.
285
  // We cache those values rather than retrieving them for performance reasons
286
  // as nestegg only performs 1-byte read at a time.
287
  int64_t mLastWebMBlockOffset;
288
  const bool mIsMediaSource;
289
290
  Maybe<gfx::IntSize> mLastSeenFrameSize;
291
  // This will be populated only if a resolution change occurs, otherwise it
292
  // will be left as null so the original metadata is used
293
  RefPtr<TrackInfoSharedPtr> mSharedVideoTrackInfo;
294
295
  EncryptionInfo mCrypto;
296
};
297
298
class WebMTrackDemuxer
299
  : public MediaTrackDemuxer
300
  , public DecoderDoctorLifeLogger<WebMTrackDemuxer>
301
{
302
public:
303
  WebMTrackDemuxer(WebMDemuxer* aParent,
304
                  TrackInfo::TrackType aType,
305
                  uint32_t aTrackNumber);
306
307
  UniquePtr<TrackInfo> GetInfo() const override;
308
309
  RefPtr<SeekPromise> Seek(const media::TimeUnit& aTime) override;
310
311
  RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples = 1) override;
312
313
  void Reset() override;
314
315
  nsresult GetNextRandomAccessPoint(media::TimeUnit* aTime) override;
316
317
  RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint(
318
    const media::TimeUnit& aTimeThreshold) override;
319
320
  media::TimeIntervals GetBuffered() override;
321
322
  int64_t GetEvictionOffset(const media::TimeUnit& aTime) override;
323
324
  void BreakCycles() override;
325
326
private:
327
  friend class WebMDemuxer;
328
  ~WebMTrackDemuxer();
329
  void UpdateSamples(nsTArray<RefPtr<MediaRawData>>& aSamples);
330
  void SetNextKeyFrameTime();
331
  nsresult NextSample(RefPtr<MediaRawData>& aData);
332
  RefPtr<WebMDemuxer> mParent;
333
  TrackInfo::TrackType mType;
334
  UniquePtr<TrackInfo> mInfo;
335
  Maybe<media::TimeUnit> mNextKeyframeTime;
336
  bool mNeedKeyframe;
337
338
  // Queued samples extracted by the demuxer, but not yet returned.
339
  MediaRawDataQueue mSamples;
340
};
341
342
} // namespace mozilla
343
344
#endif