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