tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MediaInfo.h (23514B)


      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 #ifndef MediaInfo_h
      7 #define MediaInfo_h
      8 
      9 #include "AudioConfig.h"
     10 #include "ImageTypes.h"
     11 #include "MediaData.h"
     12 #include "TimeUnits.h"
     13 #include "mozilla/RefPtr.h"
     14 #include "mozilla/UniquePtr.h"
     15 #include "mozilla/Variant.h"
     16 #include "mozilla/gfx/Point.h"  // for gfx::IntSize
     17 #include "mozilla/gfx/Rect.h"   // for gfx::IntRect
     18 #include "mozilla/gfx/Types.h"  // for gfx::ColorDepth
     19 #include "nsString.h"
     20 #include "nsTArray.h"
     21 #include "nsTHashMap.h"
     22 
     23 namespace mozilla {
     24 
     25 class AudioInfo;
     26 class VideoInfo;
     27 class TextInfo;
     28 
     29 class MetadataTag {
     30 public:
     31  MetadataTag(const nsACString& aKey, const nsACString& aValue)
     32      : mKey(aKey), mValue(aValue) {}
     33  nsCString mKey;
     34  nsCString mValue;
     35  bool operator==(const MetadataTag& rhs) const {
     36    return mKey == rhs.mKey && mValue == rhs.mValue;
     37  }
     38 };
     39 
     40 using MetadataTags = nsTHashMap<nsCStringHashKey, nsCString>;
     41 
     42 // Start codec specific data structs. If modifying these remember to also
     43 // modify the MediaIPCUtils so that any new members are sent across IPC.
     44 
     45 // Generic types, we should prefer a specific type when we can.
     46 
     47 // Generic empty type. Prefer to use a specific type but not populate members
     48 // if possible, as that helps with type checking.
     49 struct NoCodecSpecificData {
     50  bool operator==(const NoCodecSpecificData& rhs) const { return true; }
     51 };
     52 
     53 // Generic binary blob type. Prefer not to use this structure. It's here to ease
     54 // the transition to codec specific structures in the code.
     55 struct AudioCodecSpecificBinaryBlob {
     56  bool operator==(const AudioCodecSpecificBinaryBlob& rhs) const {
     57    return *mBinaryBlob == *rhs.mBinaryBlob;
     58  }
     59 
     60  RefPtr<MediaByteBuffer> mBinaryBlob{new MediaByteBuffer};
     61 };
     62 
     63 // End generic types.
     64 
     65 // Audio codec specific data types.
     66 
     67 struct AacCodecSpecificData {
     68  bool operator==(const AacCodecSpecificData& rhs) const {
     69    return *mEsDescriptorBinaryBlob == *rhs.mEsDescriptorBinaryBlob &&
     70           *mDecoderConfigDescriptorBinaryBlob ==
     71               *rhs.mDecoderConfigDescriptorBinaryBlob;
     72  }
     73  // An explanation for the necessity of handling the encoder delay and the
     74  // padding is available here:
     75  // https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFAppenG/QTFFAppenG.html
     76 
     77  // The number of frames that should be skipped from the beginning of the
     78  // decoded stream.
     79  uint32_t mEncoderDelayFrames{0};
     80 
     81  // The total number of frames of the media, that is, excluding the encoder
     82  // delay and the padding of the last packet, that must be discarded.
     83  uint64_t mMediaFrameCount{0};
     84 
     85  // The bytes of the ES_Descriptor field parsed out of esds box. We store
     86  // this as a blob as some decoders want this.
     87  RefPtr<MediaByteBuffer> mEsDescriptorBinaryBlob{new MediaByteBuffer};
     88 
     89  // The bytes of the DecoderConfigDescriptor field within the parsed
     90  // ES_Descriptor. This is a subset of the ES_Descriptor, so it is technically
     91  // redundant to store both. However, some decoders expect this binary blob
     92  // instead of the whole ES_Descriptor, so both are stored for convenience
     93  // and clarity (rather than reparsing the ES_Descriptor).
     94  // TODO(bug 1768562): use a Span to track this rather than duplicating data.
     95  RefPtr<MediaByteBuffer> mDecoderConfigDescriptorBinaryBlob{
     96      new MediaByteBuffer};
     97 };
     98 
     99 struct FlacCodecSpecificData {
    100  bool operator==(const FlacCodecSpecificData& rhs) const {
    101    return *mStreamInfoBinaryBlob == *rhs.mStreamInfoBinaryBlob;
    102  }
    103 
    104  // A binary blob of the data from the METADATA_BLOCK_STREAMINFO block
    105  // in the flac header.
    106  // See https://xiph.org/flac/format.html#metadata_block_streaminfo
    107  // Consumers of this data (ffmpeg) take a blob, so we don't parse the data,
    108  // just store the blob. For headerless flac files this will be left empty.
    109  RefPtr<MediaByteBuffer> mStreamInfoBinaryBlob{new MediaByteBuffer};
    110 };
    111 
    112 struct Mp3CodecSpecificData final {
    113  bool operator==(const Mp3CodecSpecificData& rhs) const {
    114    return mEncoderDelayFrames == rhs.mEncoderDelayFrames &&
    115           mEncoderPaddingFrames == rhs.mEncoderPaddingFrames;
    116  }
    117 
    118  auto MutTiedFields() {
    119    return std::tie(mEncoderDelayFrames, mEncoderPaddingFrames);
    120  }
    121 
    122  // The number of frames that should be skipped from the beginning of the
    123  // decoded stream.
    124  // See https://bugzilla.mozilla.org/show_bug.cgi?id=1566389 for more info.
    125  uint32_t mEncoderDelayFrames{0};
    126 
    127  // The number of frames that should be skipped from the end of the decoded
    128  // stream.
    129  // See https://bugzilla.mozilla.org/show_bug.cgi?id=1566389 for more info.
    130  uint32_t mEncoderPaddingFrames{0};
    131 };
    132 
    133 struct OpusCodecSpecificData {
    134  bool operator==(const OpusCodecSpecificData& rhs) const {
    135    return mContainerCodecDelayFrames == rhs.mContainerCodecDelayFrames &&
    136           *mHeadersBinaryBlob == *rhs.mHeadersBinaryBlob;
    137  }
    138  // The codec delay (aka pre-skip) in audio frames.
    139  // See https://tools.ietf.org/html/rfc7845#section-4.2 for more info.
    140  // This member should store the codec delay parsed from the container file.
    141  // In some cases (such as the ogg container), this information is derived
    142  // from the same headers stored in the header blob, making storing this
    143  // separately redundant. However, other containers store the delay in
    144  // addition to the header blob, in which case we can check this container
    145  // delay against the header delay to ensure they're consistent.
    146  int64_t mContainerCodecDelayFrames{-1};
    147 
    148  // A binary blob of opus header data, specifically the Identification Header.
    149  // See https://datatracker.ietf.org/doc/html/rfc7845.html#section-5.1
    150  RefPtr<MediaByteBuffer> mHeadersBinaryBlob{new MediaByteBuffer};
    151 };
    152 
    153 struct VorbisCodecSpecificData {
    154  bool operator==(const VorbisCodecSpecificData& rhs) const {
    155    return *mHeadersBinaryBlob == *rhs.mHeadersBinaryBlob;
    156  }
    157 
    158  // A binary blob of headers in the 'extradata' format (the format ffmpeg
    159  // expects for packing the extradata field). This is also the format some
    160  // containers use for storing the data. Specifically, this format consists of
    161  // the page_segments field, followed by the segment_table field, followed by
    162  // the three Vorbis header packets, respectively the identification header,
    163  // the comments header, and the setup header, in that order.
    164  // See also https://xiph.org/vorbis/doc/framing.html and
    165  // https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-610004.2
    166  RefPtr<MediaByteBuffer> mHeadersBinaryBlob{new MediaByteBuffer};
    167 };
    168 
    169 struct WaveCodecSpecificData {
    170  bool operator==(const WaveCodecSpecificData& rhs) const { return true; }
    171  // Intentionally empty. We don't store any wave specific data, but this
    172  // variant is useful for type checking.
    173 };
    174 
    175 using AudioCodecSpecificVariant =
    176    mozilla::Variant<NoCodecSpecificData, AudioCodecSpecificBinaryBlob,
    177                     AacCodecSpecificData, FlacCodecSpecificData,
    178                     Mp3CodecSpecificData, OpusCodecSpecificData,
    179                     VorbisCodecSpecificData, WaveCodecSpecificData>;
    180 
    181 // Returns a binary blob representation of the AudioCodecSpecificVariant. This
    182 // does not guarantee that a binary representation exists. Will return an empty
    183 // buffer if no representation exists. Prefer `GetAudioCodecSpecificBlob` which
    184 // asserts if getting a blob is unexpected for a given codec config.
    185 inline already_AddRefed<MediaByteBuffer> ForceGetAudioCodecSpecificBlob(
    186    const AudioCodecSpecificVariant& v) {
    187  return v.match(
    188      [](const NoCodecSpecificData&) {
    189        return RefPtr<MediaByteBuffer>(new MediaByteBuffer).forget();
    190      },
    191      [](const AudioCodecSpecificBinaryBlob& binaryBlob) {
    192        return RefPtr<MediaByteBuffer>(binaryBlob.mBinaryBlob).forget();
    193      },
    194      [](const AacCodecSpecificData& aacData) {
    195        // We return the mDecoderConfigDescriptor blob here, as it is more
    196        // commonly used by decoders at time of writing than the
    197        // ES_Descriptor data. However, consumers of this data should
    198        // prefer getting one or the other specifically, rather than
    199        // calling this.
    200        return RefPtr<MediaByteBuffer>(
    201                   aacData.mDecoderConfigDescriptorBinaryBlob)
    202            .forget();
    203      },
    204      [](const FlacCodecSpecificData& flacData) {
    205        return RefPtr<MediaByteBuffer>(flacData.mStreamInfoBinaryBlob).forget();
    206      },
    207      [](const Mp3CodecSpecificData&) {
    208        return RefPtr<MediaByteBuffer>(new MediaByteBuffer).forget();
    209      },
    210      [](const OpusCodecSpecificData& opusData) {
    211        return RefPtr<MediaByteBuffer>(opusData.mHeadersBinaryBlob).forget();
    212      },
    213      [](const VorbisCodecSpecificData& vorbisData) {
    214        return RefPtr<MediaByteBuffer>(vorbisData.mHeadersBinaryBlob).forget();
    215      },
    216      [](const WaveCodecSpecificData&) {
    217        return RefPtr<MediaByteBuffer>(new MediaByteBuffer).forget();
    218      });
    219 }
    220 
    221 // Same as `ForceGetAudioCodecSpecificBlob` but with extra asserts to ensure
    222 // we're not trying to get a binary blob from codecs where we don't store the
    223 // information as a blob or where a blob is ambiguous.
    224 inline already_AddRefed<MediaByteBuffer> GetAudioCodecSpecificBlob(
    225    const AudioCodecSpecificVariant& v) {
    226  return ForceGetAudioCodecSpecificBlob(v);
    227 }
    228 
    229 // End audio codec specific data types.
    230 
    231 // End codec specific data structs.
    232 
    233 class TrackInfo {
    234 public:
    235  enum TrackType { kUndefinedTrack, kAudioTrack, kVideoTrack, kTextTrack };
    236  TrackInfo(TrackType aType, const nsAString& aId, const nsAString& aKind,
    237            const nsAString& aLabel, const nsAString& aLanguage, bool aEnabled,
    238            uint32_t aTrackId)
    239      : mId(aId),
    240        mKind(aKind),
    241        mLabel(aLabel),
    242        mLanguage(aLanguage),
    243        mEnabled(aEnabled),
    244        mTrackId(aTrackId),
    245        mIsRenderedExternally(false),
    246        mType(aType) {
    247    MOZ_COUNT_CTOR(TrackInfo);
    248  }
    249 
    250  // Only used for backward compatibility. Do not use in new code.
    251  void Init(const nsAString& aId, const nsAString& aKind,
    252            const nsAString& aLabel, const nsAString& aLanguage,
    253            bool aEnabled) {
    254    mId = aId;
    255    mKind = aKind;
    256    mLabel = aLabel;
    257    mLanguage = aLanguage;
    258    mEnabled = aEnabled;
    259  }
    260 
    261  // Fields common with MediaTrack object.
    262  nsString mId;
    263  nsString mKind;
    264  nsString mLabel;
    265  nsString mLanguage;
    266  bool mEnabled;
    267 
    268  uint32_t mTrackId;
    269 
    270  nsCString mMimeType;
    271  media::TimeUnit mDuration;
    272  media::TimeUnit mMediaTime;
    273  uint32_t mTimeScale = 0;
    274  CryptoTrack mCrypto;
    275 
    276  CopyableTArray<MetadataTag> mTags;
    277 
    278  // True if the track is gonna be (decrypted)/decoded and
    279  // rendered directly by non-gecko components.
    280  bool mIsRenderedExternally;
    281 
    282  virtual AudioInfo* GetAsAudioInfo() { return nullptr; }
    283  virtual VideoInfo* GetAsVideoInfo() { return nullptr; }
    284  virtual TextInfo* GetAsTextInfo() { return nullptr; }
    285  virtual const AudioInfo* GetAsAudioInfo() const { return nullptr; }
    286  virtual const VideoInfo* GetAsVideoInfo() const { return nullptr; }
    287  virtual const TextInfo* GetAsTextInfo() const { return nullptr; }
    288 
    289  bool IsAudio() const { return !!GetAsAudioInfo(); }
    290  bool IsVideo() const { return !!GetAsVideoInfo(); }
    291  bool IsText() const { return !!GetAsTextInfo(); }
    292  TrackType GetType() const { return mType; }
    293 
    294  virtual nsCString ToString() const;
    295 
    296  bool virtual IsValid() const = 0;
    297 
    298  virtual UniquePtr<TrackInfo> Clone() const = 0;
    299 
    300  MOZ_COUNTED_DTOR_VIRTUAL(TrackInfo)
    301 
    302 protected:
    303  TrackInfo(const TrackInfo& aOther) {
    304    mId = aOther.mId;
    305    mKind = aOther.mKind;
    306    mLabel = aOther.mLabel;
    307    mLanguage = aOther.mLanguage;
    308    mEnabled = aOther.mEnabled;
    309    mTrackId = aOther.mTrackId;
    310    mMimeType = aOther.mMimeType;
    311    mDuration = aOther.mDuration;
    312    mMediaTime = aOther.mMediaTime;
    313    mCrypto = aOther.mCrypto;
    314    mIsRenderedExternally = aOther.mIsRenderedExternally;
    315    mType = aOther.mType;
    316    mTags = aOther.mTags.Clone();
    317    MOZ_COUNT_CTOR(TrackInfo);
    318  }
    319  bool IsEqualTo(const TrackInfo& rhs) const;
    320 
    321 private:
    322  TrackType mType;
    323 };
    324 
    325 // String version of track type.
    326 const char* TrackTypeToStr(TrackInfo::TrackType aTrack);
    327 
    328 enum class VideoRotation {
    329  kDegree_0 = 0,
    330  kDegree_90 = 90,
    331  kDegree_180 = 180,
    332  kDegree_270 = 270,
    333 };
    334 
    335 // Stores info relevant to presenting media frames.
    336 class VideoInfo : public TrackInfo {
    337 public:
    338  VideoInfo() : VideoInfo(-1, -1) {}
    339 
    340  VideoInfo(int32_t aWidth, int32_t aHeight)
    341      : VideoInfo(gfx::IntSize(aWidth, aHeight)) {}
    342 
    343  explicit VideoInfo(const gfx::IntSize& aSize)
    344      : TrackInfo(kVideoTrack, u"2"_ns, u"main"_ns, u""_ns, u""_ns, true, 2),
    345        mDisplay(aSize),
    346        mStereoMode(StereoMode::MONO),
    347        mImage(aSize),
    348        mCodecSpecificConfig(new MediaByteBuffer),
    349        mExtraData(new MediaByteBuffer),
    350        mRotation(VideoRotation::kDegree_0) {}
    351 
    352  VideoInfo(const VideoInfo& aOther) : TrackInfo(aOther) {
    353    if (aOther.mCodecSpecificConfig) {
    354      mCodecSpecificConfig = new MediaByteBuffer();
    355      mCodecSpecificConfig->AppendElements(
    356          reinterpret_cast<uint8_t*>(aOther.mCodecSpecificConfig->Elements()),
    357          aOther.mCodecSpecificConfig->Length());
    358    }
    359    if (aOther.mExtraData) {
    360      mExtraData = new MediaByteBuffer();
    361      mExtraData->AppendElements(
    362          reinterpret_cast<uint8_t*>(aOther.mExtraData->Elements()),
    363          aOther.mExtraData->Length());
    364    }
    365    mDisplay = aOther.mDisplay;
    366    mStereoMode = aOther.mStereoMode;
    367    mImage = aOther.mImage;
    368    mRotation = aOther.mRotation;
    369    mColorDepth = aOther.mColorDepth;
    370    mColorSpace = aOther.mColorSpace;
    371    mColorPrimaries = aOther.mColorPrimaries;
    372    mTransferFunction = aOther.mTransferFunction;
    373    mColorRange = aOther.mColorRange;
    374    mImageRect = aOther.mImageRect;
    375    mAlphaPresent = aOther.mAlphaPresent;
    376    mFrameRate = aOther.mFrameRate;
    377  };
    378 
    379  bool operator==(const VideoInfo& rhs) const;
    380 
    381  bool IsValid() const override {
    382    return mDisplay.width > 0 && mDisplay.height > 0;
    383  }
    384 
    385  VideoInfo* GetAsVideoInfo() override { return this; }
    386 
    387  const VideoInfo* GetAsVideoInfo() const override { return this; }
    388 
    389  UniquePtr<TrackInfo> Clone() const override {
    390    return MakeUnique<VideoInfo>(*this);
    391  }
    392 
    393  void SetAlpha(bool aAlphaPresent) { mAlphaPresent = aAlphaPresent; }
    394 
    395  bool HasAlpha() const { return mAlphaPresent; }
    396 
    397  gfx::IntRect ImageRect() const {
    398    if (!mImageRect) {
    399      return gfx::IntRect(0, 0, mImage.width, mImage.height);
    400    }
    401    return *mImageRect;
    402  }
    403 
    404  void SetImageRect(const gfx::IntRect& aRect) { mImageRect = Some(aRect); }
    405  void ResetImageRect() { mImageRect.reset(); }
    406 
    407  // Returned the crop rectangle scaled to aWidth/aHeight size relative to
    408  // mImage size.
    409  // If aWidth and aHeight are identical to the original
    410  // mImage.width/mImage.height then the scaling ratio will be 1. This is used
    411  // for when the frame size is different from what the container reports. This
    412  // is legal in WebM, and we will preserve the ratio of the crop rectangle as
    413  // it was reported relative to the picture size reported by the container.
    414  gfx::IntRect ScaledImageRect(int64_t aWidth, int64_t aHeight) const {
    415    if ((aWidth == mImage.width && aHeight == mImage.height) || !mImage.width ||
    416        !mImage.height) {
    417      return ImageRect();
    418    }
    419 
    420    gfx::IntRect imageRect = ImageRect();
    421    int64_t w = (aWidth * imageRect.Width()) / mImage.width;
    422    int64_t h = (aHeight * imageRect.Height()) / mImage.height;
    423    if (!w || !h) {
    424      return imageRect;
    425    }
    426 
    427    imageRect.x = AssertedCast<int>((imageRect.x * aWidth) / mImage.width);
    428    imageRect.y = AssertedCast<int>((imageRect.y * aHeight) / mImage.height);
    429    imageRect.SetWidth(AssertedCast<int>(w));
    430    imageRect.SetHeight(AssertedCast<int>(h));
    431    return imageRect;
    432  }
    433 
    434  VideoRotation ToSupportedRotation(int32_t aDegree) const {
    435    switch (aDegree) {
    436      case 90:
    437        return VideoRotation::kDegree_90;
    438      case 180:
    439        return VideoRotation::kDegree_180;
    440      case 270:
    441        return VideoRotation::kDegree_270;
    442      default:
    443        NS_WARNING_ASSERTION(aDegree == 0, "Invalid rotation degree, ignored");
    444        return VideoRotation::kDegree_0;
    445    }
    446  }
    447 
    448  nsCString ToString() const override;
    449 
    450  // Size in pixels at which the video is rendered. This is after it has
    451  // been scaled by its aspect ratio.
    452  gfx::IntSize mDisplay;
    453 
    454  // Indicates the frame layout for single track stereo videos.
    455  StereoMode mStereoMode;
    456 
    457  // Size of the decoded video's image.
    458  gfx::IntSize mImage;
    459 
    460  RefPtr<MediaByteBuffer> mCodecSpecificConfig;
    461  RefPtr<MediaByteBuffer> mExtraData;
    462 
    463  // Describing how many degrees video frames should be rotated in clock-wise to
    464  // get correct view.
    465  VideoRotation mRotation;
    466 
    467  // Should be 8, 10 or 12. Default value is 8.
    468  gfx::ColorDepth mColorDepth = gfx::ColorDepth::COLOR_8;
    469 
    470  // Matrix coefficients (if specified by the video) imply a colorspace.
    471  Maybe<gfx::YUVColorSpace> mColorSpace;
    472 
    473  // Color primaries are independent from the coefficients.
    474  Maybe<gfx::ColorSpace2> mColorPrimaries;
    475 
    476  // Transfer functions get their own member, which may not be strongly
    477  // correlated to the colorspace.
    478  Maybe<gfx::TransferFunction> mTransferFunction;
    479 
    480  // True indicates no restriction on Y, U, V values (otherwise 16-235 for 8
    481  // bits etc)
    482  gfx::ColorRange mColorRange = gfx::ColorRange::LIMITED;
    483 
    484  Maybe<int32_t> GetFrameRate() const { return mFrameRate; }
    485  void SetFrameRate(int32_t aRate) { mFrameRate = Some(aRate); }
    486 
    487 private:
    488  friend struct IPC::ParamTraits<VideoInfo>;
    489 
    490  // mImage may be cropped; currently only used with the WebM container.
    491  // If unset, no cropping is to occur.
    492  Maybe<gfx::IntRect> mImageRect;
    493 
    494  // Indicates whether or not frames may contain alpha information.
    495  bool mAlphaPresent = false;
    496 
    497  Maybe<int32_t> mFrameRate;
    498 };
    499 
    500 class AudioInfo : public TrackInfo {
    501 public:
    502  AudioInfo()
    503      : TrackInfo(kAudioTrack, u"1"_ns, u"main"_ns, u""_ns, u""_ns, true, 1),
    504        mRate(0),
    505        mChannels(0),
    506        mChannelMap(AudioConfig::ChannelLayout::UNKNOWN_MAP),
    507        mBitDepth(0),
    508        mProfile(0),
    509        mExtendedProfile(0) {}
    510 
    511  AudioInfo(const AudioInfo& aOther) = default;
    512 
    513  bool operator==(const AudioInfo& rhs) const;
    514 
    515  static const uint32_t MAX_RATE = 768000;
    516  static const uint32_t MAX_CHANNEL_COUNT = 256;
    517 
    518  bool IsValid() const override {
    519    return mChannels > 0 && mChannels <= MAX_CHANNEL_COUNT && mRate > 0 &&
    520           mRate <= MAX_RATE;
    521  }
    522 
    523  AudioInfo* GetAsAudioInfo() override { return this; }
    524 
    525  const AudioInfo* GetAsAudioInfo() const override { return this; }
    526 
    527  nsCString ToString() const override;
    528 
    529  UniquePtr<TrackInfo> Clone() const override {
    530    return MakeUnique<AudioInfo>(*this);
    531  }
    532 
    533  // Sample rate.
    534  uint32_t mRate;
    535 
    536  // Number of audio channels.
    537  uint32_t mChannels;
    538  // The AudioConfig::ChannelLayout map. Channels are ordered as per SMPTE
    539  // definition. A value of UNKNOWN_MAP indicates unknown layout.
    540  // ChannelMap is an unsigned bitmap compatible with Windows' WAVE and FFmpeg
    541  // channel map.
    542  AudioConfig::ChannelLayout::ChannelMap mChannelMap;
    543 
    544  // Bits per sample.
    545  uint32_t mBitDepth;
    546 
    547  // Codec profile.
    548  uint8_t mProfile;
    549 
    550  // Extended codec profile.
    551  uint8_t mExtendedProfile;
    552 
    553  AudioCodecSpecificVariant mCodecSpecificConfig{NoCodecSpecificData{}};
    554 };
    555 
    556 class EncryptionInfo {
    557 public:
    558  EncryptionInfo() : mEncrypted(false) {}
    559 
    560  struct InitData {
    561    template <typename AInitDatas>
    562    InitData(const nsAString& aType, AInitDatas&& aInitData)
    563        : mType(aType), mInitData(std::forward<AInitDatas>(aInitData)) {}
    564 
    565    // Encryption type to be passed to JS. Usually `cenc'.
    566    nsString mType;
    567 
    568    // Encryption data.
    569    CopyableTArray<uint8_t> mInitData;
    570  };
    571  using InitDatas = CopyableTArray<InitData>;
    572 
    573  // True if the stream has encryption metadata
    574  bool IsEncrypted() const { return mEncrypted; }
    575 
    576  void Reset() {
    577    mEncrypted = false;
    578    mInitDatas.Clear();
    579  }
    580 
    581  template <typename AInitDatas>
    582  void AddInitData(const nsAString& aType, AInitDatas&& aInitData) {
    583    mInitDatas.AppendElement(
    584        InitData(aType, std::forward<AInitDatas>(aInitData)));
    585    mEncrypted = true;
    586  }
    587 
    588  void AddInitData(const EncryptionInfo& aInfo) {
    589    mInitDatas.AppendElements(aInfo.mInitDatas);
    590    mEncrypted = !!mInitDatas.Length();
    591  }
    592 
    593  // One 'InitData' per encrypted buffer.
    594  InitDatas mInitDatas;
    595 
    596 private:
    597  bool mEncrypted;
    598 };
    599 
    600 class MediaInfo {
    601 public:
    602  bool HasVideo() const { return mVideo.IsValid(); }
    603 
    604  void EnableVideo() {
    605    if (HasVideo()) {
    606      return;
    607    }
    608    // Set dummy values so that HasVideo() will return true;
    609    // See VideoInfo::IsValid()
    610    mVideo.mDisplay = gfx::IntSize(1, 1);
    611  }
    612 
    613  bool HasAudio() const { return mAudio.IsValid(); }
    614 
    615  void EnableAudio() {
    616    if (HasAudio()) {
    617      return;
    618    }
    619    // Set dummy values so that HasAudio() will return true;
    620    // See AudioInfo::IsValid()
    621    mAudio.mChannels = 2;
    622    mAudio.mRate = 44100;
    623  }
    624 
    625  bool IsEncrypted() const {
    626    return (HasAudio() && mAudio.mCrypto.IsEncrypted()) ||
    627           (HasVideo() && mVideo.mCrypto.IsEncrypted());
    628  }
    629 
    630  bool HasValidMedia() const { return HasVideo() || HasAudio(); }
    631 
    632  // TODO: Store VideoInfo and AudioIndo in arrays to support multi-tracks.
    633  VideoInfo mVideo;
    634  AudioInfo mAudio;
    635 
    636  // If the metadata includes a duration, we store it here.
    637  media::NullableTimeUnit mMetadataDuration;
    638 
    639  // The Ogg reader tries to kinda-sorta compute the duration by seeking to the
    640  // end and determining the timestamp of the last frame. This isn't useful as
    641  // a duration until we know the start time, so we need to track it separately.
    642  media::NullableTimeUnit mUnadjustedMetadataEndTime;
    643 
    644  // True if the media is seekable (i.e. supports random access).
    645  bool mMediaSeekable = true;
    646 
    647  // True if the media is only seekable within its buffered ranges.
    648  bool mMediaSeekableOnlyInBufferedRanges = false;
    649 
    650  EncryptionInfo mCrypto;
    651 
    652  // The minimum of start times of audio and video tracks.
    653  // Use to map the zero time on the media timeline to the first frame.
    654  media::TimeUnit mStartTime;
    655 };
    656 
    657 class TrackInfoSharedPtr {
    658  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackInfoSharedPtr)
    659 public:
    660  TrackInfoSharedPtr(const TrackInfo& aOriginal, uint32_t aStreamID)
    661      : mInfo(aOriginal.Clone()),
    662        mStreamSourceID(aStreamID),
    663        mMimeType(mInfo->mMimeType) {}
    664 
    665  uint32_t GetID() const { return mStreamSourceID; }
    666 
    667  operator const TrackInfo*() const { return mInfo.get(); }
    668 
    669  const TrackInfo* operator*() const { return mInfo.get(); }
    670 
    671  const TrackInfo* operator->() const {
    672    MOZ_ASSERT(mInfo.get(), "dereferencing a UniquePtr containing nullptr");
    673    return mInfo.get();
    674  }
    675 
    676  const AudioInfo* GetAsAudioInfo() const {
    677    return mInfo ? mInfo->GetAsAudioInfo() : nullptr;
    678  }
    679 
    680  const VideoInfo* GetAsVideoInfo() const {
    681    return mInfo ? mInfo->GetAsVideoInfo() : nullptr;
    682  }
    683 
    684  const TextInfo* GetAsTextInfo() const {
    685    return mInfo ? mInfo->GetAsTextInfo() : nullptr;
    686  }
    687 
    688 private:
    689  ~TrackInfoSharedPtr() = default;
    690  UniquePtr<TrackInfo> mInfo;
    691  // A unique ID, guaranteed to change when changing streams.
    692  uint32_t mStreamSourceID;
    693 
    694 public:
    695  const nsCString& mMimeType;
    696 };
    697 
    698 }  // namespace mozilla
    699 
    700 #endif  // MediaInfo_h