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