tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MediaData.h (27152B)


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