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