LCOV - code coverage report
Current view: top level - dom/media - MediaData.h (source / functions) Hit Total Coverage
Test: output.info Lines: 3 135 2.2 %
Date: 2017-07-14 16:53:18 Functions: 3 66 4.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13