Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/MediaInfo.h
Line
Count
Source (jump to first uncovered line)
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
#if !defined(MediaInfo_h)
7
#define MediaInfo_h
8
9
#include "mozilla/UniquePtr.h"
10
#include "mozilla/RefPtr.h"
11
#include "nsDataHashtable.h"
12
#include "nsString.h"
13
#include "nsTArray.h"
14
#include "AudioConfig.h"
15
#include "ImageTypes.h"
16
#include "MediaData.h"
17
#include "TrackID.h" // for TrackID
18
#include "TimeUnits.h"
19
#include "mozilla/gfx/Point.h" // for gfx::IntSize
20
#include "mozilla/gfx/Rect.h"  // for gfx::IntRect
21
22
namespace mozilla {
23
24
class AudioInfo;
25
class VideoInfo;
26
class TextInfo;
27
28
class MetadataTag
29
{
30
public:
31
  MetadataTag(const nsACString& aKey,
32
              const nsACString& aValue)
33
    : mKey(aKey)
34
    , mValue(aValue)
35
0
  {
36
0
  }
37
  nsCString mKey;
38
  nsCString mValue;
39
};
40
41
typedef nsDataHashtable<nsCStringHashKey, nsCString> MetadataTags;
42
43
class TrackInfo
44
{
45
public:
46
  enum TrackType
47
  {
48
    kUndefinedTrack,
49
    kAudioTrack,
50
    kVideoTrack,
51
    kTextTrack
52
  };
53
  TrackInfo(TrackType aType,
54
            const nsAString& aId,
55
            const nsAString& aKind,
56
            const nsAString& aLabel,
57
            const nsAString& aLanguage,
58
            bool aEnabled,
59
            TrackID aTrackId)
60
    : mId(aId)
61
    , mKind(aKind)
62
    , mLabel(aLabel)
63
    , mLanguage(aLanguage)
64
    , mEnabled(aEnabled)
65
    , mTrackId(aTrackId)
66
    , mIsRenderedExternally(false)
67
    , mType(aType)
68
0
  {
69
0
    MOZ_COUNT_CTOR(TrackInfo);
70
0
  }
71
72
  // Only used for backward compatibility. Do not use in new code.
73
  void Init(const nsAString& aId,
74
            const nsAString& aKind,
75
            const nsAString& aLabel,
76
            const nsAString& aLanguage,
77
            bool aEnabled)
78
0
  {
79
0
    mId = aId;
80
0
    mKind = aKind;
81
0
    mLabel = aLabel;
82
0
    mLanguage = aLanguage;
83
0
    mEnabled = aEnabled;
84
0
  }
85
86
  // Fields common with MediaTrack object.
87
  nsString mId;
88
  nsString mKind;
89
  nsString mLabel;
90
  nsString mLanguage;
91
  bool mEnabled;
92
93
  TrackID mTrackId;
94
95
  nsCString mMimeType;
96
  media::TimeUnit mDuration;
97
  media::TimeUnit mMediaTime;
98
  CryptoTrack mCrypto;
99
100
  nsTArray<MetadataTag> mTags;
101
102
  // True if the track is gonna be (decrypted)/decoded and
103
  // rendered directly by non-gecko components.
104
  bool mIsRenderedExternally;
105
106
  virtual AudioInfo* GetAsAudioInfo()
107
0
  {
108
0
    return nullptr;
109
0
  }
110
  virtual VideoInfo* GetAsVideoInfo()
111
0
  {
112
0
    return nullptr;
113
0
  }
114
  virtual TextInfo* GetAsTextInfo()
115
0
  {
116
0
    return nullptr;
117
0
  }
118
  virtual const AudioInfo* GetAsAudioInfo() const
119
0
  {
120
0
    return nullptr;
121
0
  }
122
  virtual const VideoInfo* GetAsVideoInfo() const
123
0
  {
124
0
    return nullptr;
125
0
  }
126
  virtual const TextInfo* GetAsTextInfo() const
127
0
  {
128
0
    return nullptr;
129
0
  }
130
131
  bool IsAudio() const
132
0
  {
133
0
    return !!GetAsAudioInfo();
134
0
  }
135
  bool IsVideo() const
136
0
  {
137
0
    return !!GetAsVideoInfo();
138
0
  }
139
  bool IsText() const
140
0
  {
141
0
    return !!GetAsTextInfo();
142
0
  }
143
  TrackType GetType() const
144
0
  {
145
0
    return mType;
146
0
  }
147
148
  bool virtual IsValid() const = 0;
149
150
  virtual UniquePtr<TrackInfo> Clone() const = 0;
151
152
  virtual ~TrackInfo()
153
0
  {
154
0
    MOZ_COUNT_DTOR(TrackInfo);
155
0
  }
156
157
protected:
158
  TrackInfo(const TrackInfo& aOther)
159
0
  {
160
0
    mId = aOther.mId;
161
0
    mKind = aOther.mKind;
162
0
    mLabel = aOther.mLabel;
163
0
    mLanguage = aOther.mLanguage;
164
0
    mEnabled = aOther.mEnabled;
165
0
    mTrackId = aOther.mTrackId;
166
0
    mMimeType = aOther.mMimeType;
167
0
    mDuration = aOther.mDuration;
168
0
    mMediaTime = aOther.mMediaTime;
169
0
    mCrypto = aOther.mCrypto;
170
0
    mIsRenderedExternally = aOther.mIsRenderedExternally;
171
0
    mType = aOther.mType;
172
0
    mTags = aOther.mTags;
173
0
    MOZ_COUNT_CTOR(TrackInfo);
174
0
  }
175
176
private:
177
  TrackType mType;
178
};
179
180
// String version of track type.
181
const char* TrackTypeToStr(TrackInfo::TrackType aTrack);
182
183
// Stores info relevant to presenting media frames.
184
class VideoInfo : public TrackInfo
185
{
186
public:
187
  enum Rotation
188
  {
189
    kDegree_0 = 0,
190
    kDegree_90 = 90,
191
    kDegree_180 = 180,
192
    kDegree_270 = 270,
193
  };
194
  VideoInfo()
195
    : VideoInfo(-1, -1)
196
0
  {
197
0
  }
198
199
  explicit VideoInfo(int32_t aWidth, int32_t aHeight)
200
    : VideoInfo(gfx::IntSize(aWidth, aHeight))
201
0
  {
202
0
  }
203
204
  explicit VideoInfo(const gfx::IntSize& aSize)
205
    : TrackInfo(kVideoTrack,
206
                NS_LITERAL_STRING("2"),
207
                NS_LITERAL_STRING("main"),
208
                EmptyString(),
209
                EmptyString(),
210
                true,
211
                2)
212
    , mDisplay(aSize)
213
    , mStereoMode(StereoMode::MONO)
214
    , mImage(aSize)
215
    , mCodecSpecificConfig(new MediaByteBuffer)
216
    , mExtraData(new MediaByteBuffer)
217
    , mRotation(kDegree_0)
218
    , mImageRect(gfx::IntRect(gfx::IntPoint(), aSize))
219
0
  {
220
0
  }
221
222
  VideoInfo(const VideoInfo& aOther)
223
    : TrackInfo(aOther)
224
    , mDisplay(aOther.mDisplay)
225
    , mStereoMode(aOther.mStereoMode)
226
    , mImage(aOther.mImage)
227
    , mCodecSpecificConfig(aOther.mCodecSpecificConfig)
228
    , mExtraData(aOther.mExtraData)
229
    , mRotation(aOther.mRotation)
230
    , mBitDepth(aOther.mBitDepth)
231
    , mImageRect(aOther.mImageRect)
232
    , mAlphaPresent(aOther.mAlphaPresent)
233
0
  {
234
0
  }
235
236
  bool IsValid() const override
237
0
  {
238
0
    return mDisplay.width > 0 && mDisplay.height > 0;
239
0
  }
240
241
  VideoInfo* GetAsVideoInfo() override
242
0
  {
243
0
    return this;
244
0
  }
245
246
  const VideoInfo* GetAsVideoInfo() const override
247
0
  {
248
0
    return this;
249
0
  }
250
251
  UniquePtr<TrackInfo> Clone() const override
252
0
  {
253
0
    return MakeUnique<VideoInfo>(*this);
254
0
  }
255
256
  void SetAlpha(bool aAlphaPresent)
257
0
  {
258
0
    mAlphaPresent = aAlphaPresent;
259
0
  }
260
261
  bool HasAlpha() const
262
0
  {
263
0
    return mAlphaPresent;
264
0
  }
265
266
  gfx::IntRect ImageRect() const
267
0
  {
268
0
    if (mImageRect.Width() < 0 || mImageRect.Height() < 0) {
269
0
      return gfx::IntRect(0, 0, mImage.width, mImage.height);
270
0
    }
271
0
    return mImageRect;
272
0
  }
273
274
0
  void SetImageRect(const gfx::IntRect& aRect) { mImageRect = aRect; }
275
276
  // Returned the crop rectangle scaled to aWidth/aHeight size relative to
277
  // mImage size.
278
  // If aWidth and aHeight are identical to the original mImage.width/mImage.height
279
  // then the scaling ratio will be 1.
280
  // This is used for when the frame size is different from what the container
281
  // reports. This is legal in WebM, and we will preserve the ratio of the crop
282
  // rectangle as it was reported relative to the picture size reported by the
283
  // container.
284
  gfx::IntRect ScaledImageRect(int64_t aWidth, int64_t aHeight) const
285
0
  {
286
0
    if ((aWidth == mImage.width && aHeight == mImage.height) ||
287
0
        !mImage.width ||
288
0
        !mImage.height) {
289
0
      return ImageRect();
290
0
    }
291
0
292
0
    gfx::IntRect imageRect = ImageRect();
293
0
    int64_t w = (aWidth * imageRect.Width()) / mImage.width;
294
0
    int64_t h = (aHeight * imageRect.Height()) / mImage.height;
295
0
    if (!w || !h) {
296
0
      return imageRect;
297
0
    }
298
0
299
0
    imageRect.x = (imageRect.x * aWidth) / mImage.width;
300
0
    imageRect.y = (imageRect.y * aHeight) / mImage.height;
301
0
    imageRect.SetWidth(w);
302
0
    imageRect.SetHeight(h);
303
0
    return imageRect;
304
0
  }
305
306
  Rotation ToSupportedRotation(int32_t aDegree) const
307
0
  {
308
0
    switch (aDegree) {
309
0
      case 90:
310
0
        return kDegree_90;
311
0
      case 180:
312
0
        return kDegree_180;
313
0
      case 270:
314
0
        return kDegree_270;
315
0
      default:
316
0
        NS_WARNING_ASSERTION(aDegree == 0, "Invalid rotation degree, ignored");
317
0
        return kDegree_0;
318
0
    }
319
0
  }
320
321
  // Size in pixels at which the video is rendered. This is after it has
322
  // been scaled by its aspect ratio.
323
  gfx::IntSize mDisplay;
324
325
  // Indicates the frame layout for single track stereo videos.
326
  StereoMode mStereoMode;
327
328
  // Size of the decoded video's image.
329
  gfx::IntSize mImage;
330
331
  RefPtr<MediaByteBuffer> mCodecSpecificConfig;
332
  RefPtr<MediaByteBuffer> mExtraData;
333
334
  // Describing how many degrees video frames should be rotated in clock-wise to
335
  // get correct view.
336
  Rotation mRotation;
337
338
  // Should be 8, 10 or 12. Default value is 8.
339
  uint8_t mBitDepth = 8;
340
341
private:
342
  // mImage may be cropped; currently only used with the WebM container.
343
  // A negative width or height indicate that no cropping is to occur.
344
  gfx::IntRect mImageRect;
345
346
  // Indicates whether or not frames may contain alpha information.
347
  bool mAlphaPresent = false;
348
};
349
350
class AudioInfo : public TrackInfo
351
{
352
public:
353
  AudioInfo()
354
    : TrackInfo(kAudioTrack, NS_LITERAL_STRING("1"), NS_LITERAL_STRING("main"),
355
                EmptyString(), EmptyString(), true, 1)
356
    , mRate(0)
357
    , mChannels(0)
358
    , mChannelMap(AudioConfig::ChannelLayout::UNKNOWN_MAP)
359
    , mBitDepth(0)
360
    , mProfile(0)
361
    , mExtendedProfile(0)
362
    , mCodecSpecificConfig(new MediaByteBuffer)
363
    , mExtraData(new MediaByteBuffer)
364
0
  {
365
0
  }
366
367
  AudioInfo(const AudioInfo& aOther)
368
    : TrackInfo(aOther)
369
    , mRate(aOther.mRate)
370
    , mChannels(aOther.mChannels)
371
    , mChannelMap(aOther.mChannelMap)
372
    , mBitDepth(aOther.mBitDepth)
373
    , mProfile(aOther.mProfile)
374
    , mExtendedProfile(aOther.mExtendedProfile)
375
    , mCodecSpecificConfig(aOther.mCodecSpecificConfig)
376
    , mExtraData(aOther.mExtraData)
377
0
  {
378
0
  }
379
380
  static const uint32_t MAX_RATE = 640000;
381
382
  bool IsValid() const override
383
0
  {
384
0
    return mChannels > 0 && mRate > 0 && mRate <= MAX_RATE;
385
0
  }
386
387
  AudioInfo* GetAsAudioInfo() override
388
0
  {
389
0
    return this;
390
0
  }
391
392
  const AudioInfo* GetAsAudioInfo() const override
393
0
  {
394
0
    return this;
395
0
  }
396
397
  UniquePtr<TrackInfo> Clone() const override
398
0
  {
399
0
    return MakeUnique<AudioInfo>(*this);
400
0
  }
401
402
  // Sample rate.
403
  uint32_t mRate;
404
405
  // Number of audio channels.
406
  uint32_t mChannels;
407
  // The AudioConfig::ChannelLayout map. Channels are ordered as per SMPTE
408
  // definition. A value of UNKNOWN_MAP indicates unknown layout.
409
  // ChannelMap is an unsigned bitmap compatible with Windows' WAVE and FFmpeg
410
  // channel map.
411
  AudioConfig::ChannelLayout::ChannelMap mChannelMap;
412
413
  // Bits per sample.
414
  uint32_t mBitDepth;
415
416
  // Codec profile.
417
  int8_t mProfile;
418
419
  // Extended codec profile.
420
  int8_t mExtendedProfile;
421
422
  RefPtr<MediaByteBuffer> mCodecSpecificConfig;
423
  RefPtr<MediaByteBuffer> mExtraData;
424
};
425
426
class EncryptionInfo
427
{
428
public:
429
  EncryptionInfo()
430
    : mEncrypted(false)
431
0
  {
432
0
  }
433
434
  struct InitData
435
  {
436
    template<typename AInitDatas>
437
    InitData(const nsAString& aType, AInitDatas&& aInitData)
438
      : mType(aType)
439
      , mInitData(std::forward<AInitDatas>(aInitData))
440
0
    {
441
0
    }
Unexecuted instantiation: mozilla::EncryptionInfo::InitData::InitData<nsTArray<unsigned char> const&>(nsTSubstring<char16_t> const&, nsTArray<unsigned char> const&)
Unexecuted instantiation: mozilla::EncryptionInfo::InitData::InitData<nsTArray<unsigned char>&>(nsTSubstring<char16_t> const&, nsTArray<unsigned char>&)
442
443
    // Encryption type to be passed to JS. Usually `cenc'.
444
    nsString mType;
445
446
    // Encryption data.
447
    nsTArray<uint8_t> mInitData;
448
  };
449
  typedef nsTArray<InitData> InitDatas;
450
451
  // True if the stream has encryption metadata
452
  bool IsEncrypted() const
453
0
  {
454
0
    return mEncrypted;
455
0
  }
456
457
  void Reset()
458
0
  {
459
0
    mEncrypted = false;
460
0
    mInitDatas.Clear();
461
0
  }
462
463
  template<typename AInitDatas>
464
  void AddInitData(const nsAString& aType, AInitDatas&& aInitData)
465
0
  {
466
0
    mInitDatas.AppendElement(InitData(aType, std::forward<AInitDatas>(aInitData)));
467
0
    mEncrypted = true;
468
0
  }
Unexecuted instantiation: void mozilla::EncryptionInfo::AddInitData<nsTArray<unsigned char> const&>(nsTSubstring<char16_t> const&, nsTArray<unsigned char> const&)
Unexecuted instantiation: void mozilla::EncryptionInfo::AddInitData<nsTArray<unsigned char>&>(nsTSubstring<char16_t> const&, nsTArray<unsigned char>&)
469
470
  void AddInitData(const EncryptionInfo& aInfo)
471
0
  {
472
0
    mInitDatas.AppendElements(aInfo.mInitDatas);
473
0
    mEncrypted = !!mInitDatas.Length();
474
0
  }
475
476
  // One 'InitData' per encrypted buffer.
477
  InitDatas mInitDatas;
478
private:
479
  bool mEncrypted;
480
};
481
482
class MediaInfo
483
{
484
public:
485
  bool HasVideo() const
486
0
  {
487
0
    return mVideo.IsValid();
488
0
  }
489
490
  void EnableVideo()
491
0
  {
492
0
    if (HasVideo()) {
493
0
      return;
494
0
    }
495
0
    // Set dummy values so that HasVideo() will return true;
496
0
    // See VideoInfo::IsValid()
497
0
    mVideo.mDisplay = gfx::IntSize(1, 1);
498
0
  }
499
500
  bool HasAudio() const
501
0
  {
502
0
    return mAudio.IsValid();
503
0
  }
504
505
  void EnableAudio()
506
0
  {
507
0
    if (HasAudio()) {
508
0
      return;
509
0
    }
510
0
    // Set dummy values so that HasAudio() will return true;
511
0
    // See AudioInfo::IsValid()
512
0
    mAudio.mChannels = 2;
513
0
    mAudio.mRate = 44100;
514
0
  }
515
516
  bool IsEncrypted() const
517
0
  {
518
0
    return (HasAudio() && mAudio.mCrypto.mValid) ||
519
0
           (HasVideo() && mVideo.mCrypto.mValid);
520
0
  }
521
522
  bool HasValidMedia() const
523
0
  {
524
0
    return HasVideo() || HasAudio();
525
0
  }
526
527
  void AssertValid() const
528
0
  {
529
0
    NS_ASSERTION(!HasAudio() || mAudio.mTrackId != TRACK_INVALID,
530
0
                 "Audio track ID must be valid");
531
0
    NS_ASSERTION(!HasVideo() || mVideo.mTrackId != TRACK_INVALID,
532
0
                 "Audio track ID must be valid");
533
0
    NS_ASSERTION(!HasAudio() || !HasVideo() ||
534
0
                 mAudio.mTrackId != mVideo.mTrackId,
535
0
                 "Duplicate track IDs");
536
0
  }
537
538
  // TODO: Store VideoInfo and AudioIndo in arrays to support multi-tracks.
539
  VideoInfo mVideo;
540
  AudioInfo mAudio;
541
542
  // If the metadata includes a duration, we store it here.
543
  media::NullableTimeUnit mMetadataDuration;
544
545
  // The Ogg reader tries to kinda-sorta compute the duration by seeking to the
546
  // end and determining the timestamp of the last frame. This isn't useful as
547
  // a duration until we know the start time, so we need to track it separately.
548
  media::NullableTimeUnit mUnadjustedMetadataEndTime;
549
550
  // True if the media is seekable (i.e. supports random access).
551
  bool mMediaSeekable = true;
552
553
  // True if the media is only seekable within its buffered ranges.
554
  bool mMediaSeekableOnlyInBufferedRanges = false;
555
556
  EncryptionInfo mCrypto;
557
558
  // The minimum of start times of audio and video tracks.
559
  // Use to map the zero time on the media timeline to the first frame.
560
  media::TimeUnit mStartTime;
561
};
562
563
class TrackInfoSharedPtr
564
{
565
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackInfoSharedPtr)
566
public:
567
  TrackInfoSharedPtr(const TrackInfo& aOriginal, uint32_t aStreamID)
568
    : mInfo(aOriginal.Clone())
569
    , mStreamSourceID(aStreamID)
570
    , mMimeType(mInfo->mMimeType)
571
0
  {
572
0
  }
573
574
  uint32_t GetID() const
575
  {
576
    return mStreamSourceID;
577
  }
578
579
  operator const TrackInfo*() const
580
  {
581
    return mInfo.get();
582
  }
583
584
  const TrackInfo* operator*() const
585
0
  {
586
0
    return mInfo.get();
587
0
  }
588
589
  const TrackInfo* operator->() const
590
  {
591
    MOZ_ASSERT(mInfo.get(), "dereferencing a UniquePtr containing nullptr");
592
    return mInfo.get();
593
  }
594
595
  const AudioInfo* GetAsAudioInfo() const
596
0
  {
597
0
    return mInfo ? mInfo->GetAsAudioInfo() : nullptr;
598
0
  }
599
600
  const VideoInfo* GetAsVideoInfo() const
601
0
  {
602
0
    return mInfo ? mInfo->GetAsVideoInfo() : nullptr;
603
0
  }
604
605
  const TextInfo* GetAsTextInfo() const
606
0
  {
607
0
    return mInfo ? mInfo->GetAsTextInfo() : nullptr;
608
0
  }
609
610
private:
611
0
  ~TrackInfoSharedPtr() { }
612
  UniquePtr<TrackInfo> mInfo;
613
  // A unique ID, guaranteed to change when changing streams.
614
  uint32_t mStreamSourceID;
615
616
public:
617
  const nsCString& mMimeType;
618
};
619
620
} // namespace mozilla
621
622
#endif // MediaInfo_h