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
8 
9 #include "AudioSampleFormat.h"
10 #include "ImageTypes.h"
11 #include "SharedBuffer.h"
12 #include "TimeUnits.h"
13 #include "mozilla/CheckedInt.h"
14 #include "mozilla/PodOperations.h"
15 #include "mozilla/RefPtr.h"
16 #include "mozilla/Span.h"
17 #include "mozilla/UniquePtr.h"
18 #include "mozilla/UniquePtrExtensions.h"
19 #include "mozilla/gfx/Rect.h"
20 #include "nsString.h"
21 #include "nsTArray.h"
22 
23 namespace mozilla {
24 
25 namespace layers {
26 class Image;
27 class ImageContainer;
28 class KnowsCompositor;
29 }  // namespace layers
30 
31 class MediaByteBuffer;
32 class TrackInfoSharedPtr;
33 
34 // AlignedBuffer:
35 // Memory allocations are fallibles. Methods return a boolean indicating if
36 // memory allocations were successful. Return values should always be checked.
37 // AlignedBuffer::mData will be nullptr if no memory has been allocated or if
38 // an error occurred during construction.
39 // Existing data is only ever modified if new memory allocation has succeeded
40 // and preserved if not.
41 //
42 // The memory referenced by mData will always be Alignment bytes aligned and the
43 // underlying buffer will always have a size such that Alignment bytes blocks
44 // can be used to read the content, regardless of the mSize value. Buffer is
45 // zeroed on creation, elements are not individually constructed.
46 // An Alignment value of 0 means that the data isn't aligned.
47 //
48 // Type must be trivially copyable.
49 //
50 // AlignedBuffer can typically be used in place of UniquePtr<Type[]> however
51 // care must be taken as all memory allocations are fallible.
52 // Example:
53 // auto buffer = MakeUniqueFallible<float[]>(samples)
54 // becomes: AlignedFloatBuffer buffer(samples)
55 //
56 // auto buffer = MakeUnique<float[]>(samples)
57 // becomes:
58 // AlignedFloatBuffer buffer(samples);
59 // if (!buffer) { return NS_ERROR_OUT_OF_MEMORY; }
60 
61 template <typename Type, int Alignment = 32>
62 class AlignedBuffer {
63  public:
AlignedBuffer()64   AlignedBuffer()
65       : mData(nullptr), mLength(0), mBuffer(nullptr), mCapacity(0) {}
66 
AlignedBuffer(size_t aLength)67   explicit AlignedBuffer(size_t aLength)
68       : mData(nullptr), mLength(0), mBuffer(nullptr), mCapacity(0) {
69     if (EnsureCapacity(aLength)) {
70       mLength = aLength;
71     }
72   }
73 
AlignedBuffer(const Type * aData,size_t aLength)74   AlignedBuffer(const Type* aData, size_t aLength) : AlignedBuffer(aLength) {
75     if (!mData) {
76       return;
77     }
78     PodCopy(mData, aData, aLength);
79   }
80 
AlignedBuffer(const AlignedBuffer & aOther)81   AlignedBuffer(const AlignedBuffer& aOther)
82       : AlignedBuffer(aOther.Data(), aOther.Length()) {}
83 
AlignedBuffer(AlignedBuffer && aOther)84   AlignedBuffer(AlignedBuffer&& aOther)
85       : mData(aOther.mData),
86         mLength(aOther.mLength),
87         mBuffer(Move(aOther.mBuffer)),
88         mCapacity(aOther.mCapacity) {
89     aOther.mData = nullptr;
90     aOther.mLength = 0;
91     aOther.mCapacity = 0;
92   }
93 
94   AlignedBuffer& operator=(AlignedBuffer&& aOther) {
95     this->~AlignedBuffer();
96     new (this) AlignedBuffer(Move(aOther));
97     return *this;
98   }
99 
Data()100   Type* Data() const { return mData; }
Length()101   size_t Length() const { return mLength; }
Size()102   size_t Size() const { return mLength * sizeof(Type); }
103   Type& operator[](size_t aIndex) {
104     MOZ_ASSERT(aIndex < mLength);
105     return mData[aIndex];
106   }
107   const Type& operator[](size_t aIndex) const {
108     MOZ_ASSERT(aIndex < mLength);
109     return mData[aIndex];
110   }
111   // Set length of buffer, allocating memory as required.
112   // If length is increased, new buffer area is filled with 0.
SetLength(size_t aLength)113   bool SetLength(size_t aLength) {
114     if (aLength > mLength && !EnsureCapacity(aLength)) {
115       return false;
116     }
117     mLength = aLength;
118     return true;
119   }
120   // Add aData at the beginning of buffer.
Prepend(const Type * aData,size_t aLength)121   bool Prepend(const Type* aData, size_t aLength) {
122     if (!EnsureCapacity(aLength + mLength)) {
123       return false;
124     }
125 
126     // Shift the data to the right by aLength to leave room for the new data.
127     PodMove(mData + aLength, mData, mLength);
128     PodCopy(mData, aData, aLength);
129 
130     mLength += aLength;
131     return true;
132   }
133   // Add aData at the end of buffer.
Append(const Type * aData,size_t aLength)134   bool Append(const Type* aData, size_t aLength) {
135     if (!EnsureCapacity(aLength + mLength)) {
136       return false;
137     }
138 
139     PodCopy(mData + mLength, aData, aLength);
140 
141     mLength += aLength;
142     return true;
143   }
144   // Replace current content with aData.
Replace(const Type * aData,size_t aLength)145   bool Replace(const Type* aData, size_t aLength) {
146     // If aLength is smaller than our current length, we leave the buffer as is,
147     // only adjusting the reported length.
148     if (!EnsureCapacity(aLength)) {
149       return false;
150     }
151 
152     PodCopy(mData, aData, aLength);
153     mLength = aLength;
154     return true;
155   }
156   // Clear the memory buffer. Will set target mData and mLength to 0.
Clear()157   void Clear() {
158     mLength = 0;
159     mData = nullptr;
160   }
161 
162   // Methods for reporting memory.
SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)163   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
164     size_t size = aMallocSizeOf(this);
165     size += aMallocSizeOf(mBuffer.get());
166     return size;
167   }
168   // AlignedBuffer is typically allocated on the stack. As such, you likely
169   // want to use SizeOfExcludingThis
SizeOfExcludingThis(MallocSizeOf aMallocSizeOf)170   size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
171     return aMallocSizeOf(mBuffer.get());
172   }
ComputedSizeOfExcludingThis()173   size_t ComputedSizeOfExcludingThis() const { return mCapacity; }
174 
175   // For backward compatibility with UniquePtr<Type[]>
get()176   Type* get() const { return mData; }
177   explicit operator bool() const { return mData != nullptr; }
178 
179   // Size in bytes of extra space allocated for padding.
AlignmentPaddingSize()180   static size_t AlignmentPaddingSize() { return AlignmentOffset() * 2; }
181 
PopFront(size_t aSize)182   void PopFront(size_t aSize) {
183     MOZ_ASSERT(mLength >= aSize);
184     PodMove(mData, mData + aSize, mLength - aSize);
185     mLength -= aSize;
186   }
187 
188  private:
AlignmentOffset()189   static size_t AlignmentOffset() { return Alignment ? Alignment - 1 : 0; }
190 
191   // Ensure that the backend buffer can hold aLength data. Will update mData.
192   // Will enforce that the start of allocated data is always Alignment bytes
193   // aligned and that it has sufficient end padding to allow for Alignment bytes
194   // block read as required by some data decoders.
195   // Returns false if memory couldn't be allocated.
EnsureCapacity(size_t aLength)196   bool EnsureCapacity(size_t aLength) {
197     if (!aLength) {
198       // No need to allocate a buffer yet.
199       return true;
200     }
201     const CheckedInt<size_t> sizeNeeded =
202         CheckedInt<size_t>(aLength) * sizeof(Type) + AlignmentPaddingSize();
203 
204     if (!sizeNeeded.isValid() || sizeNeeded.value() >= INT32_MAX) {
205       // overflow or over an acceptable size.
206       return false;
207     }
208     if (mData && mCapacity >= sizeNeeded.value()) {
209       return true;
210     }
211     auto newBuffer = MakeUniqueFallible<uint8_t[]>(sizeNeeded.value());
212     if (!newBuffer) {
213       return false;
214     }
215 
216     // Find alignment address.
217     const uintptr_t alignmask = AlignmentOffset();
218     Type* newData = reinterpret_cast<Type*>(
219         (reinterpret_cast<uintptr_t>(newBuffer.get()) + alignmask) &
220         ~alignmask);
221     MOZ_ASSERT(uintptr_t(newData) % (AlignmentOffset() + 1) == 0);
222 
223     MOZ_ASSERT(!mLength || mData);
224 
225     PodZero(newData + mLength, aLength - mLength);
226     if (mLength) {
227       PodCopy(newData, mData, mLength);
228     }
229 
230     mBuffer = Move(newBuffer);
231     mCapacity = sizeNeeded.value();
232     mData = newData;
233 
234     return true;
235   }
236   Type* mData;
237   size_t mLength;
238   UniquePtr<uint8_t[]> mBuffer;
239   size_t mCapacity;
240 };
241 
242 typedef AlignedBuffer<uint8_t> AlignedByteBuffer;
243 typedef AlignedBuffer<float> AlignedFloatBuffer;
244 typedef AlignedBuffer<int16_t> AlignedShortBuffer;
245 typedef AlignedBuffer<AudioDataValue> AlignedAudioBuffer;
246 
247 // Container that holds media samples.
248 class MediaData {
249  public:
250   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaData)
251 
252   enum Type { AUDIO_DATA = 0, VIDEO_DATA, RAW_DATA, NULL_DATA };
253 
MediaData(Type aType,int64_t aOffset,const media::TimeUnit & aTimestamp,const media::TimeUnit & aDuration,uint32_t aFrames)254   MediaData(Type aType, int64_t aOffset, const media::TimeUnit& aTimestamp,
255             const media::TimeUnit& aDuration, uint32_t aFrames)
256       : mType(aType),
257         mOffset(aOffset),
258         mTime(aTimestamp),
259         mTimecode(aTimestamp),
260         mDuration(aDuration),
261         mFrames(aFrames),
262         mKeyframe(false) {}
263 
264   // Type of contained data.
265   const Type mType;
266 
267   // Approximate byte offset where this data was demuxed from its media.
268   int64_t mOffset;
269 
270   // Start time of sample.
271   media::TimeUnit mTime;
272 
273   // Codec specific internal time code. For Ogg based codecs this is the
274   // granulepos.
275   media::TimeUnit mTimecode;
276 
277   // Duration of sample, in microseconds.
278   media::TimeUnit mDuration;
279 
280   // Amount of frames for contained data.
281   const uint32_t mFrames;
282 
283   bool mKeyframe;
284 
GetEndTime()285   media::TimeUnit GetEndTime() const { return mTime + mDuration; }
286 
AdjustForStartTime(int64_t aStartTime)287   bool AdjustForStartTime(int64_t aStartTime) {
288     mTime = mTime - media::TimeUnit::FromMicroseconds(aStartTime);
289     return !mTime.IsNegative();
290   }
291 
292   template <typename ReturnType>
As()293   const ReturnType* As() const {
294     MOZ_ASSERT(this->mType == ReturnType::sType);
295     return static_cast<const ReturnType*>(this);
296   }
297 
298   template <typename ReturnType>
As()299   ReturnType* As() {
300     MOZ_ASSERT(this->mType == ReturnType::sType);
301     return static_cast<ReturnType*>(this);
302   }
303 
304  protected:
MediaData(Type aType,uint32_t aFrames)305   MediaData(Type aType, uint32_t aFrames)
306       : mType(aType), mOffset(0), mFrames(aFrames), mKeyframe(false) {}
307 
~MediaData()308   virtual ~MediaData() {}
309 };
310 
311 // NullData is for decoder generating a sample which doesn't need to be
312 // rendered.
313 class NullData : public MediaData {
314  public:
NullData(int64_t aOffset,const media::TimeUnit & aTime,const media::TimeUnit & aDuration)315   NullData(int64_t aOffset, const media::TimeUnit& aTime,
316            const media::TimeUnit& aDuration)
317       : MediaData(NULL_DATA, aOffset, aTime, aDuration, 0) {}
318 
319   static const Type sType = NULL_DATA;
320 };
321 
322 // Holds chunk a decoded audio frames.
323 class AudioData : public MediaData {
324  public:
AudioData(int64_t aOffset,const media::TimeUnit & aTime,const media::TimeUnit & aDuration,uint32_t aFrames,AlignedAudioBuffer && aData,uint32_t aChannels,uint32_t aRate)325   AudioData(int64_t aOffset, const media::TimeUnit& aTime,
326             const media::TimeUnit& aDuration, uint32_t aFrames,
327             AlignedAudioBuffer&& aData, uint32_t aChannels, uint32_t aRate)
328       : MediaData(sType, aOffset, aTime, aDuration, aFrames),
329         mChannels(aChannels),
330         mRate(aRate),
331         mAudioData(Move(aData)) {}
332 
333   static const Type sType = AUDIO_DATA;
334   static const char* sTypeName;
335 
336   // Creates a new AudioData identical to aOther, but with a different
337   // specified timestamp and duration. All data from aOther is copied
338   // into the new AudioData but the audio data which is transferred.
339   // After such call, the original aOther is unusable.
340   static already_AddRefed<AudioData> TransferAndUpdateTimestampAndDuration(
341       AudioData* aOther, const media::TimeUnit& aTimestamp,
342       const media::TimeUnit& aDuration);
343 
344   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
345 
346   // If mAudioBuffer is null, creates it from mAudioData.
347   void EnsureAudioBuffer();
348 
349   // To check whether mAudioData has audible signal, it's used to distinguish
350   // the audiable data and silent data.
351   bool IsAudible() const;
352 
353   const uint32_t mChannels;
354   const uint32_t mRate;
355   // At least one of mAudioBuffer/mAudioData must be non-null.
356   // mChannels channels, each with mFrames frames
357   RefPtr<SharedBuffer> mAudioBuffer;
358   // mFrames frames, each with mChannels values
359   AlignedAudioBuffer mAudioData;
360 
361  protected:
~AudioData()362   ~AudioData() {}
363 };
364 
365 namespace layers {
366 class TextureClient;
367 class PlanarYCbCrImage;
368 }  // namespace layers
369 
370 class VideoInfo;
371 
372 // Holds a decoded video frame, in YCbCr format. These are queued in the reader.
373 class VideoData : public MediaData {
374  public:
375   typedef gfx::IntRect IntRect;
376   typedef gfx::IntSize IntSize;
377   typedef layers::ImageContainer ImageContainer;
378   typedef layers::Image Image;
379   typedef layers::PlanarYCbCrImage PlanarYCbCrImage;
380 
381   static const Type sType = VIDEO_DATA;
382   static const char* sTypeName;
383 
384   // YCbCr data obtained from decoding the video. The index's are:
385   //   0 = Y
386   //   1 = Cb
387   //   2 = Cr
388   struct YCbCrBuffer {
389     struct Plane {
390       uint8_t* mData;
391       uint32_t mWidth;
392       uint32_t mHeight;
393       uint32_t mStride;
394       uint32_t mOffset;
395       uint32_t mSkip;
396     };
397 
398     Plane mPlanes[3];
399     YUVColorSpace mYUVColorSpace = YUVColorSpace::BT601;
400     uint32_t mBitDepth = 8;
401   };
402 
403   class Listener {
404    public:
405     virtual void OnSentToCompositor() = 0;
~Listener()406     virtual ~Listener() {}
407   };
408 
409   // Constructs a VideoData object. If aImage is nullptr, creates a new Image
410   // holding a copy of the YCbCr data passed in aBuffer. If aImage is not
411   // nullptr, it's stored as the underlying video image and aBuffer is assumed
412   // to point to memory within aImage so no copy is made. aTimecode is a codec
413   // specific number representing the timestamp of the frame of video data.
414   // Returns nsnull if an error occurs. This may indicate that memory couldn't
415   // be allocated to create the VideoData object, or it may indicate some
416   // problem with the input data (e.g. negative stride).
417 
418   // Creates a new VideoData containing a deep copy of aBuffer. May use
419   // aContainer to allocate an Image to hold the copied data.
420   static already_AddRefed<VideoData> CreateAndCopyData(
421       const VideoInfo& aInfo, ImageContainer* aContainer, int64_t aOffset,
422       const media::TimeUnit& aTime, const media::TimeUnit& aDuration,
423       const YCbCrBuffer& aBuffer, bool aKeyframe,
424       const media::TimeUnit& aTimecode, const IntRect& aPicture,
425       layers::KnowsCompositor* aAllocator = nullptr);
426 
427   static already_AddRefed<VideoData> CreateAndCopyData(
428       const VideoInfo& aInfo, ImageContainer* aContainer, int64_t aOffset,
429       const media::TimeUnit& aTime, const media::TimeUnit& aDuration,
430       const YCbCrBuffer& aBuffer, const YCbCrBuffer::Plane& aAlphaPlane,
431       bool aKeyframe, const media::TimeUnit& aTimecode,
432       const IntRect& aPicture);
433 
434   static already_AddRefed<VideoData> CreateFromImage(
435       const IntSize& aDisplay, int64_t aOffset, const media::TimeUnit& aTime,
436       const media::TimeUnit& aDuration, const RefPtr<Image>& aImage,
437       bool aKeyframe, const media::TimeUnit& aTimecode);
438 
439   // Initialize PlanarYCbCrImage. Only When aCopyData is true,
440   // video data is copied to PlanarYCbCrImage.
441   static bool SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
442                                   const VideoInfo& aInfo,
443                                   const YCbCrBuffer& aBuffer,
444                                   const IntRect& aPicture, bool aCopyData);
445 
446   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
447 
448   // Dimensions at which to display the video frame. The picture region
449   // will be scaled to this size. This is should be the picture region's
450   // dimensions scaled with respect to its aspect ratio.
451   const IntSize mDisplay;
452 
453   // This frame's image.
454   RefPtr<Image> mImage;
455 
456   int32_t mFrameID;
457 
458   VideoData(int64_t aOffset, const media::TimeUnit& aTime,
459             const media::TimeUnit& aDuration, bool aKeyframe,
460             const media::TimeUnit& aTimecode, IntSize aDisplay,
461             uint32_t aFrameID);
462 
463   void SetListener(UniquePtr<Listener> aListener);
464   void MarkSentToCompositor();
IsSentToCompositor()465   bool IsSentToCompositor() { return mSentToCompositor; }
466 
467   void UpdateDuration(const media::TimeUnit& aDuration);
468   void UpdateTimestamp(const media::TimeUnit& aTimestamp);
469 
SetNextKeyFrameTime(const media::TimeUnit & aTime)470   void SetNextKeyFrameTime(const media::TimeUnit& aTime) {
471     mNextKeyFrameTime = aTime;
472   }
473 
NextKeyFrameTime()474   const media::TimeUnit& NextKeyFrameTime() const { return mNextKeyFrameTime; }
475 
476  protected:
477   ~VideoData();
478 
479   bool mSentToCompositor;
480   UniquePtr<Listener> mListener;
481   media::TimeUnit mNextKeyFrameTime;
482 };
483 
484 class CryptoTrack {
485  public:
CryptoTrack()486   CryptoTrack() : mValid(false), mMode(0), mIVSize(0) {}
487   bool mValid;
488   int32_t mMode;
489   int32_t mIVSize;
490   nsTArray<uint8_t> mKeyId;
491 };
492 
493 class CryptoSample : public CryptoTrack {
494  public:
495   nsTArray<uint16_t> mPlainSizes;
496   nsTArray<uint32_t> mEncryptedSizes;
497   nsTArray<uint8_t> mIV;
498   nsTArray<nsTArray<uint8_t>> mInitDatas;
499   nsString mInitDataType;
500 };
501 
502 // MediaRawData is a MediaData container used to store demuxed, still compressed
503 // samples.
504 // Use MediaRawData::CreateWriter() to obtain a MediaRawDataWriter object that
505 // provides methods to modify and manipulate the data.
506 // Memory allocations are fallible. Methods return a boolean indicating if
507 // memory allocations were successful. Return values should always be checked.
508 // MediaRawData::mData will be nullptr if no memory has been allocated or if
509 // an error occurred during construction.
510 // Existing data is only ever modified if new memory allocation has succeeded
511 // and preserved if not.
512 //
513 // The memory referenced by mData will always be 32 bytes aligned and the
514 // underlying buffer will always have a size such that 32 bytes blocks can be
515 // used to read the content, regardless of the mSize value. Buffer is zeroed
516 // on creation.
517 //
518 // Typical usage: create new MediaRawData; create the associated
519 // MediaRawDataWriter, call SetSize() to allocate memory, write to mData,
520 // up to mSize bytes.
521 
522 class MediaRawData;
523 
524 class MediaRawDataWriter {
525  public:
526   // Pointer to data or null if not-yet allocated
527   uint8_t* Data();
528   // Writeable size of buffer.
529   size_t Size();
530   // Writeable reference to MediaRawData::mCryptoInternal
531   CryptoSample& mCrypto;
532 
533   // Data manipulation methods. mData and mSize may be updated accordingly.
534 
535   // Set size of buffer, allocating memory as required.
536   // If size is increased, new buffer area is filled with 0.
537   bool SetSize(size_t aSize);
538   // Add aData at the beginning of buffer.
539   bool Prepend(const uint8_t* aData, size_t aSize);
540   // Replace current content with aData.
541   bool Replace(const uint8_t* aData, size_t aSize);
542   // Clear the memory buffer. Will set target mData and mSize to 0.
543   void Clear();
544   // Remove aSize bytes from the front of the sample.
545   void PopFront(size_t aSize);
546 
547  private:
548   friend class MediaRawData;
549   explicit MediaRawDataWriter(MediaRawData* aMediaRawData);
550   bool EnsureSize(size_t aSize);
551   MediaRawData* mTarget;
552 };
553 
554 class MediaRawData : public MediaData {
555  public:
556   MediaRawData();
557   MediaRawData(const uint8_t* aData, size_t aSize);
558   MediaRawData(const uint8_t* aData, size_t aSize, const uint8_t* aAlphaData,
559                size_t aAlphaSize);
560 
561   // Pointer to data or null if not-yet allocated
Data()562   const uint8_t* Data() const { return mBuffer.Data(); }
563   // Pointer to alpha data or null if not-yet allocated
AlphaData()564   const uint8_t* AlphaData() const { return mAlphaBuffer.Data(); }
565   // Size of buffer.
Size()566   size_t Size() const { return mBuffer.Length(); }
AlphaSize()567   size_t AlphaSize() const { return mAlphaBuffer.Length(); }
ComputedSizeOfIncludingThis()568   size_t ComputedSizeOfIncludingThis() const {
569     return sizeof(*this) + mBuffer.ComputedSizeOfExcludingThis() +
570            mAlphaBuffer.ComputedSizeOfExcludingThis();
571   }
572   // Access the buffer as a Span.
573   operator Span<const uint8_t>() { return MakeSpan(Data(), Size()); }
574 
575   const CryptoSample& mCrypto;
576   RefPtr<MediaByteBuffer> mExtraData;
577 
578   // Used by the Vorbis decoder and Ogg demuxer.
579   // Indicates that this is the last packet of the stream.
580   bool mEOS = false;
581 
582   // Indicate to the audio decoder that mDiscardPadding frames should be
583   // trimmed.
584   uint32_t mDiscardPadding = 0;
585 
586   RefPtr<TrackInfoSharedPtr> mTrackInfo;
587 
588   // Return a deep copy or nullptr if out of memory.
589   virtual already_AddRefed<MediaRawData> Clone() const;
590   // Create a MediaRawDataWriter for this MediaRawData. The caller must
591   // delete the writer once done. The writer is not thread-safe.
592   virtual MediaRawDataWriter* CreateWriter();
593   virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
594 
595  protected:
596   ~MediaRawData();
597 
598  private:
599   friend class MediaRawDataWriter;
600   AlignedByteBuffer mBuffer;
601   AlignedByteBuffer mAlphaBuffer;
602   CryptoSample mCryptoInternal;
603   MediaRawData(const MediaRawData&);  // Not implemented
604 };
605 
606 // MediaByteBuffer is a ref counted infallible TArray.
607 class MediaByteBuffer : public nsTArray<uint8_t> {
608   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaByteBuffer);
609   MediaByteBuffer() = default;
MediaByteBuffer(size_t aCapacity)610   explicit MediaByteBuffer(size_t aCapacity) : nsTArray<uint8_t>(aCapacity) {}
611 
612  private:
~MediaByteBuffer()613   ~MediaByteBuffer() {}
614 };
615 
616 }  // namespace mozilla
617 
618 #endif  // MediaData_h
619