MediaData.h (27152B)
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 MediaData_h 7 #define MediaData_h 8 9 #include "AudioConfig.h" 10 #include "AudioSampleFormat.h" 11 #include "EncoderConfig.h" 12 #include "ImageTypes.h" 13 #include "MediaResult.h" 14 #include "SharedBuffer.h" 15 #include "TimeUnits.h" 16 #include "mozilla/CheckedInt.h" 17 #include "mozilla/DefineEnum.h" 18 #include "mozilla/EnumSet.h" 19 #include "mozilla/Maybe.h" 20 #include "mozilla/PodOperations.h" 21 #include "mozilla/RefPtr.h" 22 #include "mozilla/Result.h" 23 #include "mozilla/Span.h" 24 #include "mozilla/UniquePtr.h" 25 #include "mozilla/UniquePtrExtensions.h" 26 #include "mozilla/gfx/Rect.h" 27 #include "nsString.h" 28 #include "nsTArray.h" 29 30 namespace mozilla { 31 32 namespace layers { 33 class BufferRecycleBin; 34 class Image; 35 class ImageContainer; 36 class KnowsCompositor; 37 } // namespace layers 38 39 class MediaByteBuffer; 40 class TrackInfoSharedPtr; 41 42 // AlignedBuffer: 43 // Memory allocations are fallibles. Methods return a boolean indicating if 44 // memory allocations were successful. Return values should always be checked. 45 // AlignedBuffer::mData will be nullptr if no memory has been allocated or if 46 // an error occurred during construction. 47 // Existing data is only ever modified if new memory allocation has succeeded 48 // and preserved if not. 49 // 50 // The memory referenced by mData will always be Alignment bytes aligned and the 51 // underlying buffer will always have a size such that Alignment bytes blocks 52 // can be used to read the content, regardless of the mSize value. Buffer is 53 // zeroed on creation, elements are not individually constructed. 54 // An Alignment value of 0 means that the data isn't aligned. 55 // 56 // Type must be trivially copyable. 57 // 58 // AlignedBuffer can typically be used in place of UniquePtr<Type[]> however 59 // care must be taken as all memory allocations are fallible. 60 // Example: 61 // auto buffer = MakeUniqueFallible<float[]>(samples) 62 // becomes: AlignedFloatBuffer buffer(samples) 63 // 64 // auto buffer = MakeUnique<float[]>(samples) 65 // becomes: 66 // AlignedFloatBuffer buffer(samples); 67 // if (!buffer) { return NS_ERROR_OUT_OF_MEMORY; } 68 class InflatableShortBuffer; 69 template <typename Type, int Alignment = 32> 70 class AlignedBuffer { 71 public: 72 friend InflatableShortBuffer; 73 AlignedBuffer() 74 : mData(nullptr), mLength(0), mBuffer(nullptr), mCapacity(0) {} 75 76 explicit AlignedBuffer(size_t aLength) 77 : mData(nullptr), mLength(0), mBuffer(nullptr), mCapacity(0) { 78 if (EnsureCapacity(aLength)) { 79 mLength = aLength; 80 } 81 } 82 83 AlignedBuffer(const Type* aData, size_t aLength) : AlignedBuffer(aLength) { 84 if (!mData) { 85 return; 86 } 87 PodCopy(mData, aData, aLength); 88 } 89 90 AlignedBuffer(const AlignedBuffer& aOther) 91 : AlignedBuffer(aOther.Data(), aOther.Length()) {} 92 93 AlignedBuffer(AlignedBuffer&& aOther) noexcept 94 : mData(aOther.mData), 95 mLength(aOther.mLength), 96 mBuffer(std::move(aOther.mBuffer)), 97 mCapacity(aOther.mCapacity) { 98 aOther.mData = nullptr; 99 aOther.mLength = 0; 100 aOther.mCapacity = 0; 101 } 102 103 AlignedBuffer& operator=(AlignedBuffer&& aOther) noexcept { 104 if (&aOther == this) { 105 return *this; 106 } 107 mData = aOther.mData; 108 mLength = aOther.mLength; 109 mBuffer = std::move(aOther.mBuffer); 110 mCapacity = aOther.mCapacity; 111 aOther.mData = nullptr; 112 aOther.mLength = 0; 113 aOther.mCapacity = 0; 114 return *this; 115 } 116 117 Type* Data() const { return mData; } 118 size_t Length() const { return mLength; } 119 size_t Size() const { return mLength * sizeof(Type); } 120 Type& operator[](size_t aIndex) { 121 MOZ_ASSERT(aIndex < mLength); 122 return mData[aIndex]; 123 } 124 const Type& operator[](size_t aIndex) const { 125 MOZ_ASSERT(aIndex < mLength); 126 return mData[aIndex]; 127 } 128 // Set length of buffer, allocating memory as required. 129 // If memory is allocated, additional buffer area is filled with 0. 130 bool SetLength(size_t aLength) { 131 if (aLength > mLength && !EnsureCapacity(aLength)) { 132 return false; 133 } 134 mLength = aLength; 135 return true; 136 } 137 // Add aData at the beginning of buffer. 138 bool Prepend(const Type* aData, size_t aLength) { 139 if (!EnsureCapacity(aLength + mLength)) { 140 return false; 141 } 142 143 // Shift the data to the right by aLength to leave room for the new data. 144 PodMove(mData + aLength, mData, mLength); 145 PodCopy(mData, aData, aLength); 146 147 mLength += aLength; 148 return true; 149 } 150 // Add aData at the end of buffer. 151 bool Append(const Type* aData, size_t aLength) { 152 if (!EnsureCapacity(aLength + mLength)) { 153 return false; 154 } 155 156 PodCopy(mData + mLength, aData, aLength); 157 158 mLength += aLength; 159 return true; 160 } 161 // Replace current content with aData. 162 bool Replace(const Type* aData, size_t aLength) { 163 // If aLength is smaller than our current length, we leave the buffer as is, 164 // only adjusting the reported length. 165 if (!EnsureCapacity(aLength)) { 166 return false; 167 } 168 169 PodCopy(mData, aData, aLength); 170 mLength = aLength; 171 return true; 172 } 173 // Clear the memory buffer. Will set target mData and mLength to 0. 174 void Clear() { 175 mLength = 0; 176 mData = nullptr; 177 } 178 179 // Methods for reporting memory. 180 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { 181 size_t size = aMallocSizeOf(this); 182 size += aMallocSizeOf(mBuffer.get()); 183 return size; 184 } 185 // AlignedBuffer is typically allocated on the stack. As such, you likely 186 // want to use SizeOfExcludingThis 187 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { 188 return aMallocSizeOf(mBuffer.get()); 189 } 190 size_t ComputedSizeOfExcludingThis() const { return mCapacity; } 191 192 // For backward compatibility with UniquePtr<Type[]> 193 Type* get() const { return mData; } 194 explicit operator bool() const { return mData != nullptr; } 195 196 // Size in bytes of extra space allocated for padding. 197 static size_t AlignmentPaddingSize() { return AlignmentOffset() * 2; } 198 199 void PopFront(size_t aCount) { 200 MOZ_DIAGNOSTIC_ASSERT(mLength >= aCount, "Popping too many elements."); 201 PodMove(mData, mData + aCount, mLength - aCount); 202 mLength -= aCount; 203 } 204 205 void PopBack(size_t aCount) { 206 MOZ_DIAGNOSTIC_ASSERT(mLength >= aCount, "Popping too many elements."); 207 mLength -= aCount; 208 } 209 210 private: 211 static size_t AlignmentOffset() { return Alignment ? Alignment - 1 : 0; } 212 213 // Ensure that the backend buffer can hold aLength data. Will update mData. 214 // Will enforce that the start of allocated data is always Alignment bytes 215 // aligned and that it has sufficient end padding to allow for Alignment bytes 216 // block read as required by some data decoders. 217 // Returns false if memory couldn't be allocated. 218 bool EnsureCapacity(size_t aLength) { 219 if (!aLength) { 220 // No need to allocate a buffer yet. 221 return true; 222 } 223 const CheckedInt<size_t> sizeNeeded = 224 CheckedInt<size_t>(aLength) * sizeof(Type) + AlignmentPaddingSize(); 225 226 if (!sizeNeeded.isValid() || sizeNeeded.value() >= INT32_MAX) { 227 // overflow or over an acceptable size. 228 return false; 229 } 230 if (mData && mCapacity >= sizeNeeded.value()) { 231 return true; 232 } 233 auto newBuffer = MakeUniqueFallible<uint8_t[]>(sizeNeeded.value()); 234 if (!newBuffer) { 235 return false; 236 } 237 238 // Find alignment address. 239 const uintptr_t alignmask = AlignmentOffset(); 240 Type* newData = reinterpret_cast<Type*>( 241 (reinterpret_cast<uintptr_t>(newBuffer.get()) + alignmask) & 242 ~alignmask); 243 MOZ_ASSERT(uintptr_t(newData) % (AlignmentOffset() + 1) == 0); 244 245 MOZ_ASSERT(!mLength || mData); 246 247 PodZero(newData + mLength, aLength - mLength); 248 if (mLength) { 249 PodCopy(newData, mData, mLength); 250 } 251 252 mBuffer = std::move(newBuffer); 253 mCapacity = sizeNeeded.value(); 254 mData = newData; 255 256 return true; 257 } 258 Type* mData; 259 size_t mLength{}; // number of elements 260 UniquePtr<uint8_t[]> mBuffer; 261 size_t mCapacity{}; // in bytes 262 }; 263 264 using AlignedByteBuffer = AlignedBuffer<uint8_t>; 265 using AlignedFloatBuffer = AlignedBuffer<float>; 266 using AlignedShortBuffer = AlignedBuffer<int16_t>; 267 using AlignedAudioBuffer = AlignedBuffer<AudioDataValue>; 268 269 // A buffer in which int16_t audio can be written to, and then converted to 270 // float32 audio without reallocating. 271 // This class is useful when an API hands out int16_t audio but the samples 272 // need to be immediately converted to f32. 273 class InflatableShortBuffer { 274 public: 275 explicit InflatableShortBuffer(size_t aElementCount) 276 : mBuffer(aElementCount * 2) {} 277 AlignedFloatBuffer Inflate() { 278 // Convert the data from int16_t to f32 in place, in the same buffer. 279 // The reason this works is because the buffer has in fact twice the 280 // capacity, and the loop goes backward. 281 float* output = reinterpret_cast<float*>(mBuffer.mData); 282 for (size_t i = Length(); i--;) { 283 output[i] = ConvertAudioSample<float>(mBuffer.mData[i]); 284 } 285 AlignedFloatBuffer rv; 286 rv.mBuffer = std::move(mBuffer.mBuffer); 287 rv.mCapacity = mBuffer.mCapacity; 288 rv.mLength = Length(); 289 rv.mData = output; 290 return rv; 291 } 292 size_t Length() const { return mBuffer.mLength / 2; } 293 int16_t* get() const { return mBuffer.get(); } 294 explicit operator bool() const { return mBuffer.mData != nullptr; } 295 296 protected: 297 AlignedShortBuffer mBuffer; 298 }; 299 300 // Container that holds media samples. 301 class MediaData { 302 public: 303 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaData) 304 305 MOZ_DEFINE_ENUM_CLASS_WITH_BASE_AND_TOSTRING_AT_CLASS_SCOPE( 306 Type, uint8_t, (AUDIO_DATA, VIDEO_DATA, RAW_DATA, NULL_DATA)); 307 308 MediaData(Type aType, int64_t aOffset, const media::TimeUnit& aTimestamp, 309 const media::TimeUnit& aDuration) 310 : mType(aType), 311 mOffset(aOffset), 312 mTime(aTimestamp), 313 mTimecode(aTimestamp), 314 mDuration(aDuration), 315 mKeyframe(false) {} 316 317 // Type of contained data. 318 const Type mType; 319 320 // Approximate byte offset where this data was demuxed from its media. 321 int64_t mOffset; 322 323 // Start time of sample. 324 media::TimeUnit mTime; 325 326 // Codec specific internal time code. For Ogg based codecs this is the 327 // granulepos. 328 media::TimeUnit mTimecode; 329 330 // Duration of sample, in microseconds. 331 media::TimeUnit mDuration; 332 333 bool mKeyframe; 334 335 media::TimeUnit GetEndTime() const { return mTime + mDuration; } 336 337 media::TimeUnit GetEndTimecode() const { return mTimecode + mDuration; } 338 339 bool HasValidTime() const { 340 return mTime.IsValid() && mTimecode.IsValid() && mDuration.IsValid() && 341 GetEndTime().IsValid() && GetEndTimecode().IsValid(); 342 } 343 344 template <typename ReturnType> 345 const ReturnType* As() const { 346 MOZ_ASSERT(this->mType == ReturnType::sType); 347 return static_cast<const ReturnType*>(this); 348 } 349 350 template <typename ReturnType> 351 ReturnType* As() { 352 MOZ_ASSERT(this->mType == ReturnType::sType); 353 return static_cast<ReturnType*>(this); 354 } 355 356 protected: 357 explicit MediaData(Type aType) : mType(aType), mOffset(0), mKeyframe(false) {} 358 359 virtual ~MediaData() = default; 360 }; 361 362 // NullData is for decoder generating a sample which doesn't need to be 363 // rendered. 364 class NullData : public MediaData { 365 public: 366 NullData(int64_t aOffset, const media::TimeUnit& aTime, 367 const media::TimeUnit& aDuration) 368 : MediaData(Type::NULL_DATA, aOffset, aTime, aDuration) {} 369 370 static const Type sType = Type::NULL_DATA; 371 }; 372 373 // Holds chunk a decoded interleaved audio frames. 374 class AudioData : public MediaData { 375 public: 376 AudioData(int64_t aOffset, const media::TimeUnit& aTime, 377 AlignedAudioBuffer&& aData, uint32_t aChannels, uint32_t aRate, 378 uint32_t aChannelMap = AudioConfig::ChannelLayout::UNKNOWN_MAP); 379 380 static const Type sType = Type::AUDIO_DATA; 381 static const char* sTypeName; 382 383 nsCString ToString() const; 384 385 // Access the buffer as a Span. 386 Span<AudioDataValue> Data() const; 387 388 // Amount of frames for contained data. 389 uint32_t Frames() const { return mFrames; } 390 391 // Trim the audio buffer such that its apparent content fits within the aTrim 392 // interval. The actual data isn't removed from the buffer and a followup call 393 // to SetTrimWindow could restore the content. mDuration, mTime and mFrames 394 // will be adjusted accordingly. 395 // Warning: rounding may occurs, in which case the new start time of the audio 396 // sample may still be lesser than aTrim.mStart. 397 bool SetTrimWindow(const media::TimeInterval& aTrim); 398 399 // Get the internal audio buffer to be moved. After this call the original 400 // AudioData will be emptied and can't be used again. 401 AlignedAudioBuffer MoveableData(); 402 403 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; 404 405 // If mAudioBuffer is null, creates it from mAudioData. 406 void EnsureAudioBuffer(); 407 408 // Return true if the adjusted time is valid. Caller should handle error when 409 // the result is invalid. 410 bool AdjustForStartTime(const media::TimeUnit& aStartTime); 411 412 // This method is used to adjust the original start time, which would change 413 // `mTime` and `mOriginalTime` together, and should only be used for data 414 // which hasn't been trimmed before. 415 void SetOriginalStartTime(const media::TimeUnit& aStartTime); 416 417 const uint32_t mChannels; 418 // The AudioConfig::ChannelLayout map. Channels are ordered as per SMPTE 419 // definition. A value of UNKNOWN_MAP indicates unknown layout. 420 // ChannelMap is an unsigned bitmap compatible with Windows' WAVE and FFmpeg 421 // channel map. 422 const AudioConfig::ChannelLayout::ChannelMap mChannelMap; 423 const uint32_t mRate; 424 425 // At least one of mAudioBuffer/mAudioData must be non-null. 426 // mChannels channels, each with mFrames frames 427 RefPtr<SharedBuffer> mAudioBuffer; 428 429 protected: 430 ~AudioData() = default; 431 432 private: 433 friend class ArrayOfRemoteAudioData; 434 AudioDataValue* GetAdjustedData() const; 435 media::TimeUnit mOriginalTime; 436 // mFrames frames, each with mChannels values 437 AlignedAudioBuffer mAudioData; 438 Maybe<media::TimeInterval> mTrimWindow; 439 // Amount of frames for contained data. 440 uint32_t mFrames; 441 size_t mDataOffset = 0; 442 }; 443 444 namespace layers { 445 class TextureClient; 446 class PlanarYCbCrImage; 447 } // namespace layers 448 449 class VideoInfo; 450 451 // Holds a decoded video frame, in YCbCr format. These are queued in the reader. 452 class VideoData : public MediaData { 453 public: 454 using IntRect = gfx::IntRect; 455 using IntSize = gfx::IntSize; 456 using ColorDepth = gfx::ColorDepth; 457 using ColorRange = gfx::ColorRange; 458 using YUVColorSpace = gfx::YUVColorSpace; 459 using ColorSpace2 = gfx::ColorSpace2; 460 using ChromaSubsampling = gfx::ChromaSubsampling; 461 using ImageContainer = layers::ImageContainer; 462 using Image = layers::Image; 463 using PlanarYCbCrImage = layers::PlanarYCbCrImage; 464 465 static const Type sType = Type::VIDEO_DATA; 466 static const char* sTypeName; 467 468 // YCbCr data obtained from decoding the video. The index's are: 469 // 0 = Y 470 // 1 = Cb 471 // 2 = Cr 472 struct YCbCrBuffer { 473 struct Plane { 474 uint8_t* mData; 475 uint32_t mWidth; 476 uint32_t mHeight; 477 uint32_t mStride; 478 uint32_t mSkip; 479 }; 480 481 Plane mPlanes[3]{}; 482 YUVColorSpace mYUVColorSpace = YUVColorSpace::Identity; 483 ColorSpace2 mColorPrimaries = ColorSpace2::UNKNOWN; 484 ColorDepth mColorDepth = ColorDepth::COLOR_8; 485 ColorRange mColorRange = ColorRange::LIMITED; 486 ChromaSubsampling mChromaSubsampling = ChromaSubsampling::FULL; 487 }; 488 489 // Extends YCbCrBuffer to support 8-bit per channel conversion with 490 // recyclable plane data. 491 class QuantizableBuffer final : public YCbCrBuffer { 492 public: 493 MediaResult To8BitPerChannel(layers::BufferRecycleBin* aRecycleBin); 494 ~QuantizableBuffer(); 495 496 private: 497 void AllocateRecyclableData(size_t aLength); 498 499 RefPtr<layers::BufferRecycleBin> mRecycleBin; 500 UniquePtr<uint8_t[]> m8bpcPlanes; 501 size_t mAllocatedLength; 502 }; 503 504 // Constructs a VideoData object. If aImage is nullptr, creates a new Image 505 // holding a copy of the YCbCr data passed in aBuffer. If aImage is not 506 // nullptr, it's stored as the underlying video image and aBuffer is assumed 507 // to point to memory within aImage so no copy is made. aTimecode is a codec 508 // specific number representing the timestamp of the frame of video data. 509 // Returns nsnull if an error occurs. This may indicate that memory couldn't 510 // be allocated to create the VideoData object, or it may indicate some 511 // problem with the input data (e.g. negative stride). 512 513 static bool UseUseNV12ForSoftwareDecodedVideoIfPossible( 514 layers::KnowsCompositor* aAllocator); 515 516 // Creates a new VideoData containing a deep copy of aBuffer. May use 517 // aContainer to allocate an Image to hold the copied data. 518 static Result<already_AddRefed<VideoData>, MediaResult> CreateAndCopyData( 519 const VideoInfo& aInfo, ImageContainer* aContainer, int64_t aOffset, 520 const media::TimeUnit& aTime, const media::TimeUnit& aDuration, 521 const YCbCrBuffer& aBuffer, bool aKeyframe, 522 const media::TimeUnit& aTimecode, const IntRect& aPicture, 523 layers::KnowsCompositor* aAllocator); 524 525 static already_AddRefed<VideoData> CreateAndCopyData( 526 const VideoInfo& aInfo, ImageContainer* aContainer, int64_t aOffset, 527 const media::TimeUnit& aTime, const media::TimeUnit& aDuration, 528 const YCbCrBuffer& aBuffer, const YCbCrBuffer::Plane& aAlphaPlane, 529 bool aKeyframe, const media::TimeUnit& aTimecode, 530 const IntRect& aPicture); 531 532 static already_AddRefed<VideoData> CreateFromImage( 533 const IntSize& aDisplay, int64_t aOffset, const media::TimeUnit& aTime, 534 const media::TimeUnit& aDuration, const RefPtr<Image>& aImage, 535 bool aKeyframe, const media::TimeUnit& aTimecode); 536 537 // Initialize PlanarYCbCrImage. Only When aCopyData is true, 538 // video data is copied to PlanarYCbCrImage. 539 static MediaResult SetVideoDataToImage(PlanarYCbCrImage* aVideoImage, 540 const VideoInfo& aInfo, 541 const YCbCrBuffer& aBuffer, 542 const IntRect& aPicture, 543 bool aCopyData); 544 545 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; 546 547 // Dimensions at which to display the video frame. The picture region 548 // will be scaled to this size. This is should be the picture region's 549 // dimensions scaled with respect to its aspect ratio. 550 const IntSize mDisplay; 551 552 // This frame's image. 553 RefPtr<Image> mImage; 554 555 ColorDepth GetColorDepth() const; 556 557 uint32_t mFrameID; 558 559 VideoData(int64_t aOffset, const media::TimeUnit& aTime, 560 const media::TimeUnit& aDuration, bool aKeyframe, 561 const media::TimeUnit& aTimecode, IntSize aDisplay, 562 uint32_t aFrameID); 563 564 nsCString ToString() const; 565 566 void MarkSentToCompositor() { mSentToCompositor = true; } 567 bool IsSentToCompositor() { return mSentToCompositor; } 568 569 void UpdateDuration(const media::TimeUnit& aDuration); 570 void UpdateTimestamp(const media::TimeUnit& aTimestamp); 571 572 // Return true if the adjusted time is valid. Caller should handle error when 573 // the result is invalid. 574 bool AdjustForStartTime(const media::TimeUnit& aStartTime); 575 576 void SetNextKeyFrameTime(const media::TimeUnit& aTime) { 577 mNextKeyFrameTime = aTime; 578 } 579 580 const media::TimeUnit& NextKeyFrameTime() const { return mNextKeyFrameTime; } 581 582 protected: 583 ~VideoData(); 584 585 bool mSentToCompositor; 586 media::TimeUnit mNextKeyFrameTime; 587 }; 588 589 // See https://w3c.github.io/encrypted-media/#scheme-cenc 590 MOZ_DEFINE_ENUM_CLASS_WITH_BASE_AND_TOSTRING(CryptoScheme, uint8_t, 591 (None, Cenc, Cbcs, Cbcs_1_9)); 592 using CryptoSchemeSet = EnumSet<CryptoScheme, uint8_t>; 593 594 nsCString CryptoSchemeSetToString(const CryptoSchemeSet& aSchemes); 595 CryptoScheme StringToCryptoScheme(const nsAString& aString); 596 597 class CryptoTrack { 598 public: 599 CryptoTrack() 600 : mCryptoScheme(CryptoScheme::None), 601 mIVSize(0), 602 mCryptByteBlock(0), 603 mSkipByteBlock(0) {} 604 CryptoScheme mCryptoScheme; 605 int32_t mIVSize; 606 CopyableTArray<uint8_t> mKeyId; 607 uint8_t mCryptByteBlock; 608 uint8_t mSkipByteBlock; 609 CopyableTArray<uint8_t> mConstantIV; 610 611 bool IsEncrypted() const { return mCryptoScheme != CryptoScheme::None; } 612 }; 613 614 class CryptoSample : public CryptoTrack { 615 public: 616 // The num clear bytes in each subsample. The nth element in the array is the 617 // number of clear bytes at the start of the nth subsample. 618 // Clear sizes are stored as uint16_t in containers per ISO/IEC 619 // 23001-7, but we store them as uint32_t for 2 reasons 620 // - The Widevine CDM accepts clear sizes as uint32_t. 621 // - When converting samples to Annex B we modify the clear sizes and 622 // clear sizes near UINT16_MAX can overflow if stored in a uint16_t. 623 CopyableTArray<uint32_t> mPlainSizes; 624 // The num encrypted bytes in each subsample. The nth element in the array is 625 // the number of encrypted bytes at the start of the nth subsample. 626 CopyableTArray<uint32_t> mEncryptedSizes; 627 CopyableTArray<uint8_t> mIV; 628 CopyableTArray<CopyableTArray<uint8_t>> mInitDatas; 629 nsString mInitDataType; 630 }; 631 632 // MediaRawData is a MediaData container used to store demuxed, still compressed 633 // samples. 634 // Use MediaRawData::CreateWriter() to obtain a MediaRawDataWriter object that 635 // provides methods to modify and manipulate the data. 636 // Memory allocations are fallible. Methods return a boolean indicating if 637 // memory allocations were successful. Return values should always be checked. 638 // MediaRawData::mData will be nullptr if no memory has been allocated or if 639 // an error occurred during construction. 640 // Existing data is only ever modified if new memory allocation has succeeded 641 // and preserved if not. 642 // 643 // The memory referenced by mData will always be 32 bytes aligned and the 644 // underlying buffer will always have a size such that 32 bytes blocks can be 645 // used to read the content, regardless of the mSize value. Buffer is zeroed 646 // on creation. 647 // 648 // Typical usage: create new MediaRawData; create the associated 649 // MediaRawDataWriter, call SetSize() to allocate memory, write to mData, 650 // up to mSize bytes. 651 652 class MediaRawData; 653 654 class MediaRawDataWriter { 655 public: 656 // Pointer to data or null if not-yet allocated 657 uint8_t* Data(); 658 // Writeable size of buffer. 659 size_t Size(); 660 // Writeable reference to MediaRawData::mCryptoInternal 661 CryptoSample& mCrypto; 662 663 // Data manipulation methods. mData and mSize may be updated accordingly. 664 665 // Set size of buffer, allocating memory as required. 666 // If memory is allocated, additional buffer area is filled with 0. 667 [[nodiscard]] bool SetSize(size_t aSize); 668 // Add aData at the beginning of buffer. 669 [[nodiscard]] bool Prepend(const uint8_t* aData, size_t aSize); 670 [[nodiscard]] bool Append(const uint8_t* aData, size_t aSize); 671 // Replace current content with aData. 672 [[nodiscard]] bool Replace(const uint8_t* aData, size_t aSize); 673 // Clear the memory buffer. Will set target mData and mSize to 0. 674 void Clear(); 675 // Remove aSize bytes from the front of the sample. 676 void PopFront(size_t aSize); 677 678 private: 679 friend class MediaRawData; 680 explicit MediaRawDataWriter(MediaRawData* aMediaRawData); 681 [[nodiscard]] bool EnsureSize(size_t aSize); 682 MediaRawData* mTarget; 683 }; 684 685 class MediaRawData final : public MediaData { 686 public: 687 MediaRawData(); 688 MediaRawData(const uint8_t* aData, size_t aSize); 689 MediaRawData(const uint8_t* aData, size_t aSize, const uint8_t* aAlphaData, 690 size_t aAlphaSize); 691 explicit MediaRawData(AlignedByteBuffer&& aData); 692 MediaRawData(AlignedByteBuffer&& aData, AlignedByteBuffer&& aAlphaData); 693 694 // Pointer to data or null if not-yet allocated 695 const uint8_t* Data() const { return mBuffer.Data(); } 696 // Pointer to alpha data or null if not-yet allocated 697 const uint8_t* AlphaData() const { return mAlphaBuffer.Data(); } 698 // Size of buffer. 699 size_t Size() const { return mBuffer.Length(); } 700 size_t AlphaSize() const { return mAlphaBuffer.Length(); } 701 size_t ComputedSizeOfIncludingThis() const { 702 return sizeof(*this) + mBuffer.ComputedSizeOfExcludingThis() + 703 mAlphaBuffer.ComputedSizeOfExcludingThis(); 704 } 705 // Access the buffer as a Span. 706 operator Span<const uint8_t>() const { return Span{Data(), Size()}; } 707 708 const CryptoSample& mCrypto; 709 RefPtr<MediaByteBuffer> mExtraData; 710 711 // Used by the Vorbis decoder and Ogg demuxer. 712 // Indicates that this is the last packet of the stream. 713 bool mEOS = false; 714 715 RefPtr<TrackInfoSharedPtr> mTrackInfo; 716 717 // Used to indicate the id of the temporal scalability layer. 718 Maybe<uint8_t> mTemporalLayerId; 719 720 // May contain the original start time and duration of the frames. 721 // mOriginalPresentationWindow.mStart would always be less or equal to mTime 722 // and mOriginalPresentationWindow.mEnd equal or greater to mTime + mDuration. 723 // This is used when the sample should get cropped so that its content will 724 // actually start on mTime and go for mDuration. If this interval is set, then 725 // the decoder should crop the content accordingly. 726 Maybe<media::TimeInterval> mOriginalPresentationWindow; 727 728 // If it's true, the `mCrypto` should be copied into the remote data as well. 729 // Currently this is only used for the media engine DRM playback. 730 bool mShouldCopyCryptoToRemoteRawData = false; 731 732 // Config used to encode this packet. 733 UniquePtr<const EncoderConfig> mConfig; 734 735 // It's only used when the remote decoder reconstructs the media raw data. 736 CryptoSample& GetWritableCrypto() { return mCryptoInternal; } 737 738 // Return a deep copy or nullptr if out of memory. 739 already_AddRefed<MediaRawData> Clone() const; 740 // Create a MediaRawDataWriter for this MediaRawData. The writer is not 741 // thread-safe. 742 UniquePtr<MediaRawDataWriter> CreateWriter(); 743 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; 744 745 protected: 746 ~MediaRawData(); 747 748 private: 749 friend class MediaRawDataWriter; 750 friend class ArrayOfRemoteMediaRawData; 751 AlignedByteBuffer mBuffer; 752 AlignedByteBuffer mAlphaBuffer; 753 CryptoSample mCryptoInternal; 754 MediaRawData(const MediaRawData&); // Not implemented 755 }; 756 757 // MediaByteBuffer is a ref counted infallible TArray. 758 class MediaByteBuffer : public nsTArray<uint8_t> { 759 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaByteBuffer); 760 MediaByteBuffer() = default; 761 explicit MediaByteBuffer(size_t aCapacity) : nsTArray<uint8_t>(aCapacity) {} 762 763 private: 764 ~MediaByteBuffer() = default; 765 }; 766 767 // MediaAlignedByteBuffer is a ref counted AlignedByteBuffer whose memory 768 // allocations are fallible. 769 class MediaAlignedByteBuffer final : public AlignedByteBuffer { 770 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaAlignedByteBuffer); 771 MediaAlignedByteBuffer() = default; 772 MediaAlignedByteBuffer(const uint8_t* aData, size_t aLength) 773 : AlignedByteBuffer(aData, aLength) {} 774 775 private: 776 ~MediaAlignedByteBuffer() = default; 777 }; 778 779 } // namespace mozilla 780 781 #endif // MediaData_h