tor-browser

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

TestByteStreams.cpp (57351B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=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 https://mozilla.org/MPL/2.0/. */
      6 
      7 #include "AnnexB.h"
      8 #include "BufferReader.h"
      9 #include "ByteWriter.h"
     10 #include "H264.h"
     11 #include "H265.h"
     12 #include "gtest/gtest.h"
     13 
     14 namespace mozilla {
     15 
     16 // Create AVCC style extra data (the contents on an AVCC box). Note
     17 // NALLengthSize will be 4 so AVCC samples need to set their data up
     18 // accordingly.
     19 static already_AddRefed<MediaByteBuffer> GetExtraData() {
     20  // Extra data with
     21  // - baseline profile(0x42 == 66).
     22  // - constraint flags 0 and 1 set(0xc0) -- normal for baseline profile.
     23  // - level 4.0 (0x28 == 40).
     24  // - 1280 * 720 resolution.
     25  return H264::CreateExtraData(0x42, 0xc0, H264_LEVEL{0x28}, {1280, 720});
     26 }
     27 
     28 // Create an AVCC style sample with requested size in bytes. This sample is
     29 // setup to contain a single NAL (in practice samples can contain many). The
     30 // sample sets its NAL size to aSampleSize - 4 and stores that size in the first
     31 // 4 bytes. Aside from the NAL size at the start, the data is uninitialized
     32 // (beware)! aSampleSize is a uint32_t as samples larger than can be expressed
     33 // by a uint32_t are not to spec.
     34 static already_AddRefed<MediaRawData> GetAvccSample(uint32_t aSampleSize) {
     35  if (aSampleSize < 4) {
     36    // Stop tests asking for insane samples.
     37    EXPECT_FALSE(true) << "Samples should be requested with sane sizes";
     38  }
     39  nsTArray<uint8_t> sampleData;
     40 
     41  // Write the NAL size.
     42  ByteWriter<BigEndian> writer(sampleData);
     43  EXPECT_TRUE(writer.WriteU32(aSampleSize - 4));
     44 
     45  // Write the 'NAL'. Beware, this data is uninitialized.
     46  sampleData.AppendElements(static_cast<size_t>(aSampleSize) - 4);
     47  RefPtr<MediaRawData> rawData =
     48      new MediaRawData{sampleData.Elements(), sampleData.Length()};
     49  EXPECT_NE(rawData->Data(), nullptr);
     50 
     51  // Set extra data.
     52  rawData->mExtraData = GetExtraData();
     53  return rawData.forget();
     54 }
     55 
     56 static const uint8_t sHvccBytesBuffer[] = {
     57    1 /* version */,
     58    1 /* general_profile_space/general_tier_flag/general_profile_idc */,
     59    0x60 /* general_profile_compatibility_flags 1/4 */,
     60    0 /* general_profile_compatibility_flags 2/4 */,
     61    0 /* general_profile_compatibility_flags 3/4 */,
     62    0 /* general_profile_compatibility_flags 4/4 */,
     63    0x90 /* general_constraint_indicator_flags 1/6 */,
     64    0 /* general_constraint_indicator_flags 2/6 */,
     65    0 /* general_constraint_indicator_flags 3/6 */,
     66    0 /* general_constraint_indicator_flags 4/6 */,
     67    0 /* general_constraint_indicator_flags 5/6 */,
     68    0 /* general_constraint_indicator_flags 6/6 */,
     69    0x5A /* general_level_idc */,
     70    0 /* min_spatial_segmentation_idc 1/2 */,
     71    0 /* min_spatial_segmentation_idc 2/2 */,
     72    0 /* parallelismType */,
     73    1 /* chroma_format_idc */,
     74    0 /* bit_depth_luma_minus8 */,
     75    0 /* bit_depth_chroma_minus8 */,
     76    0 /* avgFrameRate 1/2 */,
     77    0 /* avgFrameRate 2/2 */,
     78    0x0F /* constantFrameRate/numTemporalLayers/temporalIdNested/lengthSizeMinusOne
     79          */
     80    ,
     81    2 /* numOfArrays */,
     82    /* SPS Array */
     83    0x21 /* NAL_unit_type (SPS) */,
     84    0 /* numNalus 1/2 */,
     85    1 /* numNalus 2/2 */,
     86 
     87    /* SPS */
     88    0 /* nalUnitLength 1/2 */,
     89    8 /* nalUnitLength 2/2 (header + rsbp) */,
     90    0x42 /* NALU header 1/2 */,
     91    0 /* NALU header 2/2 */,
     92    0 /* rbsp 1/6 */,
     93    0 /* rbsp 2/6 */,
     94    0 /* rbsp 3/6 */,
     95    0 /* rbsp 4/6 */,
     96    0 /* rbsp 5/6 */,
     97    0 /* rbsp 6/6 */,
     98 
     99    /* PPS Array */
    100    0x22 /* NAL_unit_type (PPS) */,
    101    0 /* numNalus 1/2 */,
    102    1 /* numNalus 2/2 */,
    103 
    104    /* PPS */
    105    0 /* nalUnitLength 1/2 */,
    106    3 /* nalUnitLength 2/2 (header + rsbp) */,
    107    0x44 /* NALU header 1/2 */,
    108    0 /* NALU header 2/2 */,
    109    0 /* rbsp */,
    110 };
    111 
    112 // Create a HVCC sample, which contain fake data, in given size.
    113 static already_AddRefed<MediaRawData> GetHVCCSample(uint32_t aSampleSize) {
    114  if (aSampleSize < 4) {
    115    // Stop tests asking for insane samples.
    116    EXPECT_FALSE(true) << "Samples should be requested with sane sizes";
    117  }
    118  auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    119  extradata->AppendElements(sHvccBytesBuffer, std::size(sHvccBytesBuffer));
    120 
    121  // Write the NAL size.
    122  nsTArray<uint8_t> sampleData;
    123  ByteWriter<BigEndian> writer(sampleData);
    124  EXPECT_TRUE(writer.WriteU32(aSampleSize - 4));  // Assume it's a 4 bytes NALU
    125 
    126  // Fill fake empty data
    127  for (uint32_t idx = 0; idx < aSampleSize - 4; idx++) {
    128    sampleData.AppendElement(0);
    129  }
    130  RefPtr<MediaRawData> rawData =
    131      new MediaRawData{sampleData.Elements(), sampleData.Length()};
    132  EXPECT_NE(rawData->Data(), nullptr);
    133  EXPECT_EQ(rawData->Size(), aSampleSize);
    134  rawData->mExtraData = extradata;
    135  return rawData.forget();
    136 }
    137 
    138 // Create a HVCC sample by using given data in given size.
    139 static already_AddRefed<MediaRawData> GetHVCCSample(
    140    const uint8_t* aData, const uint32_t aDataLength) {
    141  if (aDataLength < 4) {
    142    // Stop tests asking for insane samples.
    143    EXPECT_FALSE(true) << "Samples should be requested with sane sizes";
    144  }
    145  auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    146  extradata->AppendElements(sHvccBytesBuffer, std::size(sHvccBytesBuffer));
    147 
    148  // Write the NAL size.
    149  nsTArray<uint8_t> sampleData;
    150  ByteWriter<BigEndian> writer(sampleData);
    151  EXPECT_TRUE(writer.WriteU32(aDataLength));  // Assume it's a 4 bytes NALU
    152  sampleData.AppendElements(aData, aDataLength);
    153 
    154  RefPtr<MediaRawData> rawData =
    155      new MediaRawData{sampleData.Elements(), sampleData.Length()};
    156  EXPECT_NE(rawData->Data(), nullptr);
    157  EXPECT_EQ(rawData->Size(), aDataLength + 4);
    158  rawData->mExtraData = extradata;
    159  return rawData.forget();
    160 }
    161 
    162 // Create a HVCC samples by given NALUs.
    163 static already_AddRefed<MediaRawData> GetHVCCSamples(
    164    const nsTArray<Span<const uint8_t>>& aNALUs) {
    165  nsTArray<uint8_t> data;
    166  ByteWriter<BigEndian> writer(data);
    167 
    168  size_t totalSize = 0;
    169 
    170  for (const auto& nalu : aNALUs) {
    171    if (nalu.size() < 2) {
    172      // NAL unit header is at least 2 bytes.
    173      EXPECT_FALSE(true) << "Samples should be requested with sane sizes";
    174      return nullptr;
    175    }
    176    totalSize += nalu.size();
    177    EXPECT_TRUE(writer.WriteU32(nalu.size()));  // Assume it's a 4 bytes NALU
    178    data.AppendElements(nalu.data(), nalu.size());
    179  }
    180 
    181  RefPtr<MediaRawData> rawData =
    182      new MediaRawData{data.Elements(), data.Length()};
    183  auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    184  extradata->AppendElements(sHvccBytesBuffer, std::size(sHvccBytesBuffer));
    185  rawData->mExtraData = extradata;
    186 
    187  EXPECT_NE(rawData->Data(), nullptr);
    188  EXPECT_EQ(rawData->Size(), totalSize + 4 * aNALUs.Length());
    189  return rawData.forget();
    190 }
    191 
    192 // Test that conversion from AVCC to AnnexB works as expected.
    193 TEST(AnnexB, AVCCToAnnexBConversion)
    194 {
    195  RefPtr<MediaRawData> rawData{GetAvccSample(128)};
    196 
    197  {
    198    // Test conversion of data when not adding SPS works as expected.
    199    RefPtr<MediaRawData> rawDataClone = rawData->Clone();
    200    Result<Ok, nsresult> result =
    201        AnnexB::ConvertAVCCSampleToAnnexB(rawDataClone, /* aAddSps */ false);
    202    EXPECT_TRUE(result.isOk()) << "Conversion should succeed";
    203    EXPECT_EQ(rawDataClone->Size(), rawData->Size())
    204        << "AnnexB sample should be the same size as the AVCC sample -- the 4 "
    205           "byte NAL length data (AVCC) is replaced with 4 bytes of NAL "
    206           "separator (AnnexB)";
    207    EXPECT_TRUE(AnnexB::IsAnnexB(*rawDataClone))
    208        << "The sample should be AnnexB following conversion";
    209  }
    210 
    211  {
    212    // Test that the SPS data is not added if the frame is not a keyframe.
    213    RefPtr<MediaRawData> rawDataClone = rawData->Clone();
    214    rawDataClone->mKeyframe =
    215        false;  // false is the default, but let's be sure.
    216    Result<Ok, nsresult> result =
    217        AnnexB::ConvertAVCCSampleToAnnexB(rawDataClone, /* aAddSps */ true);
    218    EXPECT_TRUE(result.isOk()) << "Conversion should succeed";
    219    EXPECT_EQ(rawDataClone->Size(), rawData->Size())
    220        << "AnnexB sample should be the same size as the AVCC sample -- the 4 "
    221           "byte NAL length data (AVCC) is replaced with 4 bytes of NAL "
    222           "separator (AnnexB) and SPS data is not added as the frame is not a "
    223           "keyframe";
    224    EXPECT_TRUE(AnnexB::IsAnnexB(*rawDataClone))
    225        << "The sample should be AnnexB following conversion";
    226  }
    227 
    228  {
    229    // Test that the SPS data is added to keyframes.
    230    RefPtr<MediaRawData> rawDataClone = rawData->Clone();
    231    rawDataClone->mKeyframe = true;
    232    Result<Ok, nsresult> result =
    233        AnnexB::ConvertAVCCSampleToAnnexB(rawDataClone, /* aAddSps */ true);
    234    EXPECT_TRUE(result.isOk()) << "Conversion should succeed";
    235    EXPECT_GT(rawDataClone->Size(), rawData->Size())
    236        << "AnnexB sample should be larger than the AVCC sample because we've "
    237           "added SPS data";
    238    EXPECT_TRUE(AnnexB::IsAnnexB(*rawDataClone))
    239        << "The sample should be AnnexB following conversion";
    240    // We could verify the SPS and PPS data we add, but we don't have great
    241    // tooling to do so. Consider doing so in future.
    242  }
    243 
    244  {
    245    // Test conversion involving subsample encryption doesn't overflow vlaues.
    246    const uint32_t sampleSize = UINT16_MAX * 2;
    247    RefPtr<MediaRawData> rawCryptoData{GetAvccSample(sampleSize)};
    248    // Need to be a keyframe to test prepending SPS + PPS to sample.
    249    rawCryptoData->mKeyframe = true;
    250    UniquePtr<MediaRawDataWriter> rawDataWriter = rawCryptoData->CreateWriter();
    251 
    252    rawDataWriter->mCrypto.mCryptoScheme = CryptoScheme::Cenc;
    253 
    254    // We want to check that the clear size doesn't overflow during conversion.
    255    // This size originates in a uint16_t, but since it can grow during AnnexB
    256    // we cover it here.
    257    const uint16_t clearSize = UINT16_MAX - 10;
    258    // Set a clear size very close to uint16_t max value.
    259    rawDataWriter->mCrypto.mPlainSizes.AppendElement(clearSize);
    260    rawDataWriter->mCrypto.mEncryptedSizes.AppendElement(sampleSize -
    261                                                         clearSize);
    262 
    263    RefPtr<MediaRawData> rawCryptoDataClone = rawCryptoData->Clone();
    264    Result<Ok, nsresult> result = AnnexB::ConvertAVCCSampleToAnnexB(
    265        rawCryptoDataClone, /* aAddSps */ true);
    266    EXPECT_TRUE(result.isOk()) << "Conversion should succeed";
    267    EXPECT_GT(rawCryptoDataClone->Size(), rawCryptoData->Size())
    268        << "AnnexB sample should be larger than the AVCC sample because we've "
    269           "added SPS data";
    270    EXPECT_GT(rawCryptoDataClone->mCrypto.mPlainSizes[0],
    271              rawCryptoData->mCrypto.mPlainSizes[0])
    272        << "Conversion should have increased clear data sizes without overflow";
    273    EXPECT_EQ(rawCryptoDataClone->mCrypto.mEncryptedSizes[0],
    274              rawCryptoData->mCrypto.mEncryptedSizes[0])
    275        << "Conversion should not affect encrypted sizes";
    276    EXPECT_TRUE(AnnexB::IsAnnexB(*rawCryptoDataClone))
    277        << "The sample should be AnnexB following conversion";
    278  }
    279 }
    280 
    281 TEST(AnnexB, HVCCToAnnexBConversion)
    282 {
    283  RefPtr<MediaRawData> rawData{GetHVCCSample(128)};
    284  {
    285    // Test conversion of data when not adding SPS works as expected.
    286    RefPtr<MediaRawData> rawDataClone = rawData->Clone();
    287    Result<Ok, nsresult> result =
    288        AnnexB::ConvertHVCCSampleToAnnexB(rawDataClone, /* aAddSps */ false);
    289    EXPECT_TRUE(result.isOk()) << "Conversion should succeed";
    290    EXPECT_EQ(rawDataClone->Size(), rawData->Size())
    291        << "AnnexB sample should be the same size as the HVCC sample -- the 4 "
    292           "byte NAL length data (HVCC) is replaced with 4 bytes of NAL "
    293           "separator (AnnexB)";
    294    EXPECT_TRUE(AnnexB::IsAnnexB(*rawDataClone))
    295        << "The sample should be AnnexB following conversion";
    296  }
    297  {
    298    // Test that the SPS data is not added if the frame is not a keyframe.
    299    RefPtr<MediaRawData> rawDataClone = rawData->Clone();
    300    rawDataClone->mKeyframe =
    301        false;  // false is the default, but let's be sure.
    302    Result<Ok, nsresult> result =
    303        AnnexB::ConvertHVCCSampleToAnnexB(rawDataClone, /* aAddSps */ true);
    304    EXPECT_TRUE(result.isOk()) << "Conversion should succeed";
    305    EXPECT_EQ(rawDataClone->Size(), rawData->Size())
    306        << "AnnexB sample should be the same size as the HVCC sample -- the 4 "
    307           "byte NAL length data (HVCC) is replaced with 4 bytes of NAL "
    308           "separator (AnnexB) and SPS data is not added as the frame is not a "
    309           "keyframe";
    310    EXPECT_TRUE(AnnexB::IsAnnexB(*rawDataClone))
    311        << "The sample should be AnnexB following conversion";
    312  }
    313  {
    314    // Test that the SPS data is added to keyframes.
    315    RefPtr<MediaRawData> rawDataClone = rawData->Clone();
    316    rawDataClone->mKeyframe = true;
    317    Result<Ok, nsresult> result =
    318        AnnexB::ConvertHVCCSampleToAnnexB(rawDataClone, /* aAddSps */ true);
    319    EXPECT_TRUE(result.isOk()) << "Conversion should succeed";
    320    EXPECT_GT(rawDataClone->Size(), rawData->Size())
    321        << "AnnexB sample should be larger than the HVCC sample because we've "
    322           "added SPS data";
    323    EXPECT_TRUE(AnnexB::IsAnnexB(*rawDataClone))
    324        << "The sample should be AnnexB following conversion";
    325    // We could verify the SPS and PPS data we add, but we don't have great
    326    // tooling to do so. Consider doing so in future.
    327  }
    328  {
    329    // Test conversion involving subsample encryption doesn't overflow values.
    330    const uint32_t sampleSize = UINT16_MAX * 2;
    331    RefPtr<MediaRawData> rawCryptoData{GetHVCCSample(sampleSize)};
    332    // Need to be a keyframe to test prepending SPS + PPS to sample.
    333    rawCryptoData->mKeyframe = true;
    334    UniquePtr<MediaRawDataWriter> rawDataWriter = rawCryptoData->CreateWriter();
    335 
    336    rawDataWriter->mCrypto.mCryptoScheme = CryptoScheme::Cenc;
    337 
    338    // We want to check that the clear size doesn't overflow during conversion.
    339    // This size originates in a uint16_t, but since it can grow during AnnexB
    340    // we cover it here.
    341    const uint16_t clearSize = UINT16_MAX - 10;
    342    // Set a clear size very close to uint16_t max value.
    343    rawDataWriter->mCrypto.mPlainSizes.AppendElement(clearSize);
    344    rawDataWriter->mCrypto.mEncryptedSizes.AppendElement(sampleSize -
    345                                                         clearSize);
    346 
    347    RefPtr<MediaRawData> rawCryptoDataClone = rawCryptoData->Clone();
    348    Result<Ok, nsresult> result = AnnexB::ConvertHVCCSampleToAnnexB(
    349        rawCryptoDataClone, /* aAddSps */ true);
    350    EXPECT_TRUE(result.isOk()) << "Conversion should succeed";
    351    EXPECT_GT(rawCryptoDataClone->Size(), rawCryptoData->Size())
    352        << "AnnexB sample should be larger than the HVCC sample because we've "
    353           "added SPS data";
    354    EXPECT_GT(rawCryptoDataClone->mCrypto.mPlainSizes[0],
    355              rawCryptoData->mCrypto.mPlainSizes[0])
    356        << "Conversion should have increased clear data sizes without overflow";
    357    EXPECT_EQ(rawCryptoDataClone->mCrypto.mEncryptedSizes[0],
    358              rawCryptoData->mCrypto.mEncryptedSizes[0])
    359        << "Conversion should not affect encrypted sizes";
    360    EXPECT_TRUE(AnnexB::IsAnnexB(*rawCryptoDataClone))
    361        << "The sample should be AnnexB following conversion";
    362  }
    363 }
    364 
    365 TEST(H264, AVCCParsingSuccess)
    366 {
    367  {
    368    // AVCC without SPS, PPS and SPSExt
    369    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    370    uint8_t avccBytesBuffer[] = {
    371        1 /* version */,
    372        0x64 /* profile (High) */,
    373        0 /* profile compat (0) */,
    374        40 /* level (40) */,
    375        0xfc | 3 /* nal size - 1 */,
    376        0xe0 /* num SPS (0) */,
    377        0 /* num PPS (0) */
    378    };
    379    extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    380    auto res = AVCCConfig::Parse(extradata);
    381    EXPECT_TRUE(res.isOk());
    382    const auto avcc = res.unwrap();
    383    EXPECT_EQ(avcc.mConfigurationVersion, 1);
    384    EXPECT_EQ(avcc.mAVCProfileIndication, 0x64);
    385    EXPECT_EQ(avcc.mProfileCompatibility, 0);
    386    EXPECT_EQ(avcc.mAVCLevelIndication, 40);
    387    EXPECT_EQ(avcc.NALUSize(), 4);
    388    EXPECT_EQ(avcc.NumSPS(), 0u);
    389    EXPECT_EQ(avcc.NumPPS(), 0u);
    390    EXPECT_TRUE(avcc.mChromaFormat.isNothing());
    391    EXPECT_TRUE(avcc.mBitDepthLumaMinus8.isNothing());
    392    EXPECT_TRUE(avcc.mBitDepthChromaMinus8.isNothing());
    393    EXPECT_EQ(avcc.NumSPSExt(), 0u);
    394    EXPECT_EQ(avcc.mSPSExts.Length(), 0u);
    395  }
    396  {
    397    // AVCC with SPS, PPS but no chroma format, lumn/chrom bit depth and SPSExt.
    398    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    399    const uint8_t avccBytesBuffer[] = {
    400        // configurationVersion
    401        0x01,
    402        // AVCProfileIndication (e.g., High Profile = 100)
    403        0x64,
    404        // profile_compatibility
    405        0x00,
    406        // AVCLevelIndication
    407        0x1E,
    408        // 6 bits reserved (111111) + 2 bits lengthSizeMinusOne (3 -> 4 bytes)
    409        0xFF,
    410        // 3 bits reserved (111) + 5 bits numOfSPS (1)
    411        0xE1,
    412        // SPS[0] length = 0x0004
    413        0x00,
    414        0x04,
    415        // SPS NAL unit (fake)
    416        0x67,
    417        0x64,
    418        0x00,
    419        0x1F,
    420        // numOfPPS = 1
    421        0x01,
    422        // PPS[0] length = 0x0002
    423        0x00,
    424        0x02,
    425        // PPS NAL unit (fake)
    426        0x68,
    427        0xCE,
    428    };
    429    extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    430    auto res = AVCCConfig::Parse(extradata);
    431    EXPECT_TRUE(res.isOk());
    432    const auto avcc = res.unwrap();
    433    EXPECT_EQ(avcc.mConfigurationVersion, 1);
    434    EXPECT_EQ(avcc.mAVCProfileIndication, 0x64);
    435    EXPECT_EQ(avcc.mProfileCompatibility, 0);
    436    EXPECT_EQ(avcc.mAVCLevelIndication, 0x1E);
    437    EXPECT_EQ(avcc.NALUSize(), 4);
    438    EXPECT_EQ(avcc.NumSPS(), 1u);
    439    EXPECT_EQ(avcc.NumPPS(), 1u);
    440    EXPECT_TRUE(avcc.mChromaFormat.isNothing());
    441    EXPECT_TRUE(avcc.mBitDepthLumaMinus8.isNothing());
    442    EXPECT_TRUE(avcc.mBitDepthChromaMinus8.isNothing());
    443    EXPECT_EQ(avcc.NumSPSExt(), 0u);
    444    EXPECT_EQ(avcc.mSPSExts.Length(), 0u);
    445  }
    446  {
    447    // AVCC with SPS, PPS and SPSExt.
    448    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    449    const uint8_t avccBytesBuffer[] = {
    450        // configurationVersion
    451        0x01,
    452        // AVCProfileIndication (e.g., High Profile = 100)
    453        0x64,
    454        // profile_compatibility
    455        0x00,
    456        // AVCLevelIndication
    457        0x1E,
    458        // 6 bits reserved (111111) + 2 bits lengthSizeMinusOne (3 -> 4 bytes)
    459        0xFF,
    460        // 3 bits reserved (111) + 5 bits numOfSPS (1)
    461        0xE1,
    462        // SPS[0] length = 0x0004
    463        0x00, 0x04,
    464        // SPS NAL unit (fake)
    465        0x67, 0x64, 0x00, 0x1F,
    466        // numOfPPS = 1
    467        0x01,
    468        // PPS[0] length = 0x0002
    469        0x00, 0x02,
    470        // PPS NAL unit (fake)
    471        0x68, 0xCE,
    472        // 6 bits reserved (111111) + 2 bits chroma_format (0 -> 4:2:0)
    473        0xFC,
    474        // 5 bits reserved (11111) + 3 bits bit_depth_luma_minus8 (0 -> 8-bit)
    475        0xF8,
    476        // 5 bits reserved (11111) + 3 bits bit_depth_chroma_minus8 (0 -> 8-bit)
    477        0xF8,
    478        // numOfSPSext = 1
    479        0x01,
    480        // SPS Ext[0] length = 0x0003
    481        0x00, 0x03,
    482        // SPS Ext NAL unit (fake)
    483        0x6D, 0xB2, 0x20};
    484    extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    485    auto res = AVCCConfig::Parse(extradata);
    486    EXPECT_TRUE(res.isOk());
    487    const auto avcc = res.unwrap();
    488    EXPECT_EQ(avcc.mConfigurationVersion, 1);
    489    EXPECT_EQ(avcc.mAVCProfileIndication, 0x64);
    490    EXPECT_EQ(avcc.mProfileCompatibility, 0);
    491    EXPECT_EQ(avcc.mAVCLevelIndication, 0x1E);
    492    EXPECT_EQ(avcc.NALUSize(), 4);
    493    EXPECT_EQ(avcc.NumSPS(), 1u);
    494    EXPECT_EQ(avcc.NumPPS(), 1u);
    495    EXPECT_EQ(*avcc.mChromaFormat, 0);
    496    EXPECT_EQ(*avcc.mBitDepthLumaMinus8, 0);
    497    EXPECT_EQ(*avcc.mBitDepthChromaMinus8, 0);
    498    EXPECT_EQ(avcc.NumSPSExt(), 1u);
    499  }
    500  // Following part are optional, fail to parse them won't cause an actual error
    501  {
    502    // SPS Ext length = 0x0004, but only provides 2 bytes of data
    503    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    504    const uint8_t avccBytesBuffer[] = {
    505        0x01,              // configurationVersion
    506        0x64, 0x00, 0x1E,  // High profile
    507        0xFF,              // reserved + lengthSizeMinusOne
    508        0xE1,              // reserved + 1 SPS
    509        0x00, 0x01,        // SPS length = 1
    510        0x67,              // SPS NAL
    511        0x01,              // 1 PPS
    512        0x00, 0x01,        // PPS length = 1
    513        0x68,              // PPS NAL
    514        0xFC,              // expect at least 32 bits but not enough
    515    };
    516    extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    517    auto res = AVCCConfig::Parse(extradata);
    518    EXPECT_TRUE(res.isOk());
    519    const auto avcc = res.unwrap();
    520    EXPECT_EQ(avcc.mConfigurationVersion, 1);
    521    EXPECT_EQ(avcc.mAVCProfileIndication, 0x64);
    522    EXPECT_EQ(avcc.mProfileCompatibility, 0);
    523    EXPECT_EQ(avcc.mAVCLevelIndication, 0x1E);
    524    EXPECT_EQ(avcc.NALUSize(), 4);
    525    EXPECT_EQ(avcc.NumSPS(), 1u);
    526    EXPECT_EQ(avcc.NumPPS(), 1u);
    527    EXPECT_TRUE(avcc.mChromaFormat.isNothing());
    528    EXPECT_TRUE(avcc.mBitDepthLumaMinus8.isNothing());
    529    EXPECT_TRUE(avcc.mBitDepthChromaMinus8.isNothing());
    530    EXPECT_EQ(avcc.NumSPSExt(), 0u);
    531  }
    532  {
    533    // SPS Ext length = 0x0004, but only provides 2 bytes of data
    534    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    535    const uint8_t avccBytesBuffer[] = {
    536        0x01,              // configurationVersion
    537        0x64, 0x00, 0x1E,  // High profile
    538        0xFF,              // reserved + lengthSizeMinusOne
    539        0xE1,              // reserved + 1 SPS
    540        0x00, 0x01,        // SPS length = 1
    541        0x67,              // SPS NAL
    542        0x01,              // 1 PPS
    543        0x00, 0x01,        // PPS length = 1
    544        0x68,              // PPS NAL
    545        0xFC,              // reserved + chroma_format=0
    546        0xF8,              // reserved + bit_depth_luma_minus8=0
    547        0xF8,              // reserved + bit_depth_chroma_minus8=0
    548        0x01,              // numOfSPSExt = 1
    549        0x00, 0x04,        // SPS Ext length = 4
    550        0x6A, 0x01         // Only 2 bytes of SPSExt NAL
    551    };
    552    extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    553    auto res = AVCCConfig::Parse(extradata);
    554    EXPECT_TRUE(res.isOk());
    555    const auto avcc = res.unwrap();
    556    EXPECT_EQ(avcc.mConfigurationVersion, 1);
    557    EXPECT_EQ(avcc.mAVCProfileIndication, 0x64);
    558    EXPECT_EQ(avcc.mProfileCompatibility, 0);
    559    EXPECT_EQ(avcc.mAVCLevelIndication, 0x1E);
    560    EXPECT_EQ(avcc.NALUSize(), 4);
    561    EXPECT_EQ(avcc.NumSPS(), 1u);
    562    EXPECT_EQ(avcc.NumPPS(), 1u);
    563    EXPECT_EQ(*avcc.mChromaFormat, 0);
    564    EXPECT_EQ(*avcc.mBitDepthLumaMinus8, 0);
    565    EXPECT_EQ(*avcc.mBitDepthChromaMinus8, 0);
    566    EXPECT_EQ(avcc.NumSPSExt(), 0u);
    567  }
    568  {
    569    // Insuffient data, wrong SPSEXT length
    570    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    571    const uint8_t avccBytesBuffer[] = {
    572        0x01,              // configurationVersion
    573        0x64, 0x00, 0x1E,  // High profile
    574        0xFF,              // reserved + lengthSizeMinusOne
    575        0xE1,              // reserved + 1 SPS
    576        0x00, 0x01,        // SPS length = 1
    577        0x67,              // SPS NAL
    578        0x01,              // 1 PPS
    579        0x00, 0x01,        // PPS length = 1
    580        0x68,              // PPS NAL
    581        0xFC,              // reserved + chroma_format=0
    582        0xF8,              // reserved + bit_depth_luma_minus8=0
    583        0xF8,              // reserved + bit_depth_chroma_minus8=0
    584        0x01,              // numOfSPSExt = 1
    585        0x00,              // Wrong SPS Ext length, should be 16 bits
    586    };
    587    extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    588    auto res = AVCCConfig::Parse(extradata);
    589    EXPECT_TRUE(res.isOk());
    590    const auto avcc = res.unwrap();
    591    EXPECT_EQ(avcc.mConfigurationVersion, 1);
    592    EXPECT_EQ(avcc.mAVCProfileIndication, 0x64);
    593    EXPECT_EQ(avcc.mProfileCompatibility, 0);
    594    EXPECT_EQ(avcc.mAVCLevelIndication, 0x1E);
    595    EXPECT_EQ(avcc.NALUSize(), 4);
    596    EXPECT_EQ(avcc.NumSPS(), 1u);
    597    EXPECT_EQ(avcc.NumPPS(), 1u);
    598    EXPECT_EQ(*avcc.mChromaFormat, 0);
    599    EXPECT_EQ(*avcc.mBitDepthLumaMinus8, 0);
    600    EXPECT_EQ(*avcc.mBitDepthChromaMinus8, 0);
    601    EXPECT_EQ(avcc.NumSPSExt(), 0u);
    602  }
    603  {
    604    //  Expect SPSExt payload, but the payload is an incorrect NALU type
    605    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    606    const uint8_t avccBytesBuffer[] = {
    607        0x01,              // configurationVersion
    608        0x64, 0x00, 0x1E,  // High profile
    609        0xFF,              // reserved + lengthSizeMinusOne
    610        0xE1,              // reserved + 1 SPS
    611        0x00, 0x01,        // SPS length = 1
    612        0x67,              // SPS NAL
    613        0x01,              // 1 PPS
    614        0x00, 0x01,        // PPS length = 1
    615        0x68,              // PPS NAL
    616        0xFC,              // reserved + chroma_format=0
    617        0xF8,              // reserved + bit_depth_luma_minus8=0
    618        0xF8,              // reserved + bit_depth_chroma_minus8=0
    619        0x01,              // numOfSPSExt = 1
    620        0x00, 0x03,        // SPS Ext[0] length = 0x0003
    621        0x77, 0xB2, 0x20,  // Expect SPSExt, but wrong NALU type
    622    };
    623    extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    624    auto res = AVCCConfig::Parse(extradata);
    625    EXPECT_TRUE(res.isOk());
    626    const auto avcc = res.unwrap();
    627    EXPECT_EQ(avcc.mConfigurationVersion, 1);
    628    EXPECT_EQ(avcc.mAVCProfileIndication, 0x64);
    629    EXPECT_EQ(avcc.mProfileCompatibility, 0);
    630    EXPECT_EQ(avcc.mAVCLevelIndication, 0x1E);
    631    EXPECT_EQ(avcc.NALUSize(), 4);
    632    EXPECT_EQ(avcc.NumSPS(), 1u);
    633    EXPECT_EQ(avcc.NumPPS(), 1u);
    634    EXPECT_EQ(*avcc.mChromaFormat, 0);
    635    EXPECT_EQ(*avcc.mBitDepthLumaMinus8, 0);
    636    EXPECT_EQ(*avcc.mBitDepthChromaMinus8, 0);
    637    EXPECT_EQ(avcc.NumSPSExt(), 0u);
    638  }
    639 }
    640 
    641 TEST(H264, AVCCParsingFailure)
    642 {
    643  {
    644    // Incorrect version
    645    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    646    uint8_t avccBytesBuffer[] = {
    647        2 /* version */,
    648        0x64 /* profile (High) */,
    649        0 /* profile compat (0) */,
    650        40 /* level (40) */,
    651        0xfc | 3 /* nal size - 1 */,
    652        0xe0 /* num SPS (0) */,
    653        0 /* num PPS (0) */
    654    };
    655    extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    656    auto avcc = AVCCConfig::Parse(extradata);
    657    EXPECT_TRUE(avcc.isErr());
    658  }
    659  {
    660    // Insuffient data (lacking of PPS)
    661    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    662    uint8_t avccBytesBuffer[] = {
    663        1 /* version */,
    664        0x64 /* profile (High) */,
    665        0 /* profile compat (0) */,
    666        40 /* level (40) */,
    667        0xfc | 3 /* nal size - 1 */,
    668        0xe0 /* num SPS (0) */,
    669    };
    670    extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    671    auto avcc = AVCCConfig::Parse(extradata);
    672    EXPECT_TRUE(avcc.isErr());
    673  }
    674  {
    675    // Insuffient data, wrong SPS length
    676    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    677    const uint8_t avccBytesBuffer[] = {
    678        0x01,              // configurationVersion
    679        0x64, 0x00, 0x1E,  // profile, compat, level
    680        0xFF,              // reserved + lengthSizeMinusOne (2 bits)
    681        0xE1,              // reserved + 1 SPS
    682        0x00,              // Wrong SPS length, should be 16 bits
    683    };
    684    extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    685    auto res = AVCCConfig::Parse(extradata);
    686    EXPECT_TRUE(res.isErr());
    687  }
    688  {
    689    // SPS length = 0x0004, but only provides 2 bytes of data
    690    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    691    const uint8_t avccBytesBuffer[] = {
    692        0x01,              // configurationVersion
    693        0x64, 0x00, 0x1E,  // profile, compat, level
    694        0xFF,              // reserved + lengthSizeMinusOne (2 bits)
    695        0xE1,              // reserved + 1 SPS
    696        0x00, 0x04,        // SPS length = 4
    697        0x67, 0x42         // Only 2 bytes of SPS payload (should be 4)
    698    };
    699    extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    700    auto res = AVCCConfig::Parse(extradata);
    701    EXPECT_TRUE(res.isErr());
    702  }
    703  {
    704    // Expect SPS payload, but the payload is an incorrect NALU type
    705    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    706    const uint8_t avccBytesBuffer[] = {
    707        0x01,              // configurationVersion
    708        0x64, 0x00, 0x1E,  // profile, compat, level
    709        0xFF,              // reserved + lengthSizeMinusOne (2 bits)
    710        0xE1,              // reserved + 1 SPS
    711        0x00, 0x02,        // SPS length = 2
    712        0x55, 0xCE,        // Expect SPS, but wrong NALU type
    713    };
    714    extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    715    auto res = AVCCConfig::Parse(extradata);
    716    EXPECT_TRUE(res.isErr());
    717  }
    718  {
    719    // Missing numOfPictureParameterSets
    720    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    721    const uint8_t avccBytesBuffer[] = {
    722        0x01,              // configurationVersion
    723        0x64, 0x00, 0x1E,  // profile, compat, level
    724        0xFF,              // reserved + lengthSizeMinusOne
    725        0xE1,              // reserved + 1 SPS
    726        0x00, 0x02,        // SPS length = 2
    727        0x67, 0x42,        // SPS NAL
    728    };
    729    extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    730    auto res = AVCCConfig::Parse(extradata);
    731    EXPECT_TRUE(res.isErr());
    732  }
    733  {
    734    // PPS length = 0x0003, but only provides 1 byte of data
    735    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    736    const uint8_t avccBytesBuffer[] = {
    737        0x01,              // configurationVersion
    738        0x64, 0x00, 0x1E,  // profile, compat, level
    739        0xFF,              // reserved + lengthSizeMinusOne
    740        0xE1,              // reserved + 1 SPS
    741        0x00, 0x02,        // SPS length = 2
    742        0x67, 0x42,        // SPS NAL
    743        0x01,              // 1 PPS
    744        0x00, 0x03,        // PPS length = 3
    745        0x68               // Only 1 byte instead of 3
    746    };
    747    extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    748    auto res = AVCCConfig::Parse(extradata);
    749    EXPECT_TRUE(res.isErr());
    750  }
    751  {
    752    // Insufficient data, wrong PPS length
    753    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    754    const uint8_t avccBytesBuffer[] = {
    755        0x01,              // configurationVersion
    756        0x64, 0x00, 0x1E,  // profile, compat, level
    757        0xFF,              // reserved + lengthSizeMinusOne
    758        0xE1,              // reserved + 1 SPS
    759        0x00, 0x02,        // SPS length = 2
    760        0x67, 0x42,        // SPS NAL
    761        0x01,              // 1 PPS
    762        0x00               // Wrong PPS length, should be 16 bits
    763    };
    764    extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    765    auto res = AVCCConfig::Parse(extradata);
    766    EXPECT_TRUE(res.isErr());
    767  }
    768  {
    769    // Expect PPS payload, but the payload is an incorrect NALU type
    770    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    771    const uint8_t avccBytesBuffer[] = {
    772        0x01,              // configurationVersion
    773        0x64, 0x00, 0x1E,  // High profile
    774        0xFF,              // reserved + lengthSizeMinusOne
    775        0xE1,              // reserved + 1 SPS
    776        0x00, 0x01,        // SPS length = 1
    777        0x67,              // SPS NAL
    778        0x01,              // 1 PPS
    779        0x00, 0x01,        // PPS length = 1
    780        0x70               // Expect PPS, but wrong NALU type
    781    };
    782    extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    783    auto res = AVCCConfig::Parse(extradata);
    784    EXPECT_TRUE(res.isErr());
    785  }
    786 }
    787 
    788 TEST(H264, CreateNewExtraData)
    789 {
    790  // First create an AVCC config without sps, pps
    791  auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    792  const uint8_t avccBytesBuffer[] = {
    793      0x01,  // configurationVersion
    794      0x64,  // AVCProfileIndication (High Profile = 100)
    795      0x00,  // profile_compatibility
    796      0x1E,  // AVCLevelIndication (Level 3.0)
    797      0xFF,  // 6 bits reserved (111111) + 2 bits lengthSizeMinusOne (3 -> 4
    798             // bytes)
    799      0xE0,  // 3 bits reserved (111) + 5 bits numOfSPS = 0
    800      0x00,  // numOfPPS = 0
    801      0xFC,  // 6 bits reserved (111111) + 2 bits chroma_format = 0 (4:2:0)
    802      0xF8,  // 5 bits reserved (11111) + 3 bits bit_depth_luma_minus8 = 0
    803             // (8-bit)
    804      0xF8,  // 5 bits reserved (11111) + 3 bits bit_depth_chroma_minus8 = 0
    805             // (8-bit)
    806      0x00   // numOfSequenceParameterSetExt = 0
    807  };
    808  extradata->AppendElements(avccBytesBuffer, std::size(avccBytesBuffer));
    809  auto res = AVCCConfig::Parse(extradata);
    810  EXPECT_TRUE(res.isOk());
    811  auto avcc = res.unwrap();
    812  EXPECT_EQ(avcc.NumSPS(), 0u);
    813  EXPECT_EQ(avcc.NumPPS(), 0u);
    814 
    815  // Create new extradata with 1 SPS
    816  const uint8_t sps[] = {
    817      0x67,
    818      0x64,
    819      0x00,
    820      0x1F,
    821  };
    822  H264NALU spsNALU = H264NALU(sps, std::size(sps));
    823  avcc.mSPSs.AppendElement(spsNALU);
    824  extradata = avcc.CreateNewExtraData();
    825  res = AVCCConfig::Parse(extradata);
    826  EXPECT_TRUE(res.isOk());
    827  avcc = res.unwrap();
    828  EXPECT_EQ(avcc.NumSPS(), 1u);
    829  EXPECT_EQ(avcc.NumPPS(), 0u);
    830 
    831  // Create new extradata with 1 SPS and 1 PPS
    832  const uint8_t pps[] = {
    833      0x68,
    834      0xCE,
    835  };
    836  H264NALU ppsNALU = H264NALU(pps, std::size(pps));
    837  avcc.mPPSs.AppendElement(ppsNALU);
    838  extradata = avcc.CreateNewExtraData();
    839  res = AVCCConfig::Parse(extradata);
    840  EXPECT_TRUE(res.isOk());
    841  avcc = res.unwrap();
    842  EXPECT_EQ(avcc.NumSPS(), 1u);
    843  EXPECT_EQ(avcc.NumPPS(), 1u);
    844 
    845  // Create new extradata with 2 SPS and 1 PPS
    846  avcc.mSPSs.AppendElement(spsNALU);
    847  extradata = avcc.CreateNewExtraData();
    848  res = AVCCConfig::Parse(extradata);
    849  EXPECT_TRUE(res.isOk());
    850  avcc = res.unwrap();
    851  EXPECT_EQ(avcc.NumSPS(), 2u);
    852  EXPECT_EQ(avcc.NumPPS(), 1u);
    853 
    854  // Create new extradata with 2 SPS and 2 PPS
    855  avcc.mPPSs.AppendElement(ppsNALU);
    856  extradata = avcc.CreateNewExtraData();
    857  res = AVCCConfig::Parse(extradata);
    858  EXPECT_TRUE(res.isOk());
    859  avcc = res.unwrap();
    860  EXPECT_EQ(avcc.NumSPS(), 2u);
    861  EXPECT_EQ(avcc.NumPPS(), 2u);
    862 
    863  // Besides SPS and PPS, let's ensure chroma_format, bit_depth_luma_minus8 and
    864  // bit_depth_chroma_minus8 are preserved correctly as well
    865  EXPECT_EQ(*avcc.mChromaFormat, 0);
    866  EXPECT_EQ(*avcc.mBitDepthLumaMinus8, 0);
    867  EXPECT_EQ(*avcc.mBitDepthChromaMinus8, 0);
    868 
    869  // Use a wrong attribute, which will generate an invalid config
    870  avcc.mConfigurationVersion = 5;
    871  extradata = avcc.CreateNewExtraData();
    872  res = AVCCConfig::Parse(extradata);
    873  EXPECT_TRUE(res.isErr());
    874 }
    875 
    876 TEST(H264, AnnexBExtractExtraDataForAVCC)
    877 {
    878  // First create an AnnexB config
    879  const uint8_t annexBBytesBuffer[]{// AnnexB delimiter
    880                                    0x00, 0x00, 0x00, 0x01,
    881                                    // SPS NAL unit
    882                                    0x67, 0x64, 0x00, 0x1F,
    883                                    // AnnexB delimiter
    884                                    0x00, 0x00, 0x00, 0x01,
    885                                    // PPS NAL unit
    886                                    0x68, 0xCE};
    887  auto annexBExtradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    888  annexBExtradata->AppendElements(annexBBytesBuffer,
    889                                  std::size(annexBBytesBuffer));
    890 
    891  // Extract the AVCC extradata from the AnnexB bytestream
    892  auto avccExtradata = AnnexB::ExtractExtraDataForAVCC(*annexBExtradata);
    893  ASSERT_TRUE(!!avccExtradata);
    894 
    895  // Now parse that extradata to make sure it matches the original AnnexB
    896  auto res = AVCCConfig::Parse(avccExtradata);
    897  ASSERT_TRUE(res.isOk());
    898  auto avcc = res.unwrap();
    899  EXPECT_EQ(avcc.NumSPS(), 1u);
    900  EXPECT_EQ(avcc.NumSPSExt(), 0u);
    901  EXPECT_EQ(avcc.NumPPS(), 1u);
    902  EXPECT_EQ(avcc.NALUSize(), 4);
    903  EXPECT_EQ(avcc.mConfigurationVersion, 1u);
    904  EXPECT_EQ(avcc.mAVCProfileIndication, 100u);
    905  EXPECT_EQ(avcc.mProfileCompatibility, 0u);
    906  EXPECT_EQ(avcc.mAVCLevelIndication, 31u);
    907 }
    908 
    909 TEST(H265, HVCCParsingSuccess)
    910 {
    911  {
    912    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    913    uint8_t hvccBytesBuffer[] = {
    914        1 /* version */,
    915        1 /* general_profile_space/general_tier_flag/general_profile_idc */,
    916        0x60 /* general_profile_compatibility_flags 1/4 */,
    917        0 /* general_profile_compatibility_flags 2/4 */,
    918        0 /* general_profile_compatibility_flags 3/4 */,
    919        0 /* general_profile_compatibility_flags 4/4 */,
    920        0x90 /* general_constraint_indicator_flags 1/6 */,
    921        0 /* general_constraint_indicator_flags 2/6 */,
    922        0 /* general_constraint_indicator_flags 3/6 */,
    923        0 /* general_constraint_indicator_flags 4/6 */,
    924        0 /* general_constraint_indicator_flags 5/6 */,
    925        0 /* general_constraint_indicator_flags 6/6 */,
    926        0x5A /* general_level_idc */,
    927        0 /* min_spatial_segmentation_idc 1/2 */,
    928        0 /* min_spatial_segmentation_idc 2/2 */,
    929        0 /* parallelismType */,
    930        1 /* chroma_format_idc */,
    931        0 /* bit_depth_luma_minus8 */,
    932        0 /* bit_depth_chroma_minus8 */,
    933        0 /* avgFrameRate 1/2 */,
    934        0 /* avgFrameRate 2/2 */,
    935        0x0F /* constantFrameRate/numTemporalLayers/temporalIdNested/lengthSizeMinusOne
    936              */
    937        ,
    938        0 /* numOfArrays */,
    939    };
    940    extradata->AppendElements(hvccBytesBuffer, std::size(hvccBytesBuffer));
    941    auto rv = HVCCConfig::Parse(extradata);
    942    EXPECT_TRUE(rv.isOk());
    943    auto hvcc = rv.unwrap();
    944    EXPECT_EQ(hvcc.configurationVersion, 1);
    945    EXPECT_EQ(hvcc.general_profile_space, 0);
    946    EXPECT_EQ(hvcc.general_tier_flag, false);
    947    EXPECT_EQ(hvcc.general_profile_idc, 1);
    948    EXPECT_EQ(hvcc.general_profile_compatibility_flags, (uint32_t)0x60000000);
    949    EXPECT_EQ(hvcc.general_constraint_indicator_flags,
    950              (uint64_t)0x900000000000);
    951    EXPECT_EQ(hvcc.general_level_idc, 0x5A);
    952    EXPECT_EQ(hvcc.min_spatial_segmentation_idc, 0);
    953    EXPECT_EQ(hvcc.parallelismType, 0);
    954    EXPECT_EQ(hvcc.chroma_format_idc, 1);
    955    EXPECT_EQ(hvcc.bit_depth_luma_minus8, 0);
    956    EXPECT_EQ(hvcc.bit_depth_chroma_minus8, 0);
    957    EXPECT_EQ(hvcc.avgFrameRate, 0);
    958    EXPECT_EQ(hvcc.constantFrameRate, 0);
    959    EXPECT_EQ(hvcc.numTemporalLayers, 1);
    960    EXPECT_EQ(hvcc.temporalIdNested, true);
    961    EXPECT_EQ(hvcc.NALUSize(), 4);
    962    EXPECT_EQ(hvcc.mNALUs.Length(), uint32_t(0));
    963  }
    964  {
    965    // Multple NALUs
    966    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
    967    uint8_t hvccBytesBuffer[] = {
    968        1 /* version */,
    969        1 /* general_profile_space/general_tier_flag/general_profile_idc */,
    970        0x60 /* general_profile_compatibility_flags 1/4 */,
    971        0 /* general_profile_compatibility_flags 2/4 */,
    972        0 /* general_profile_compatibility_flags 3/4 */,
    973        0 /* general_profile_compatibility_flags 4/4 */,
    974        0x90 /* general_constraint_indicator_flags 1/6 */,
    975        0 /* general_constraint_indicator_flags 2/6 */,
    976        0 /* general_constraint_indicator_flags 3/6 */,
    977        0 /* general_constraint_indicator_flags 4/6 */,
    978        0 /* general_constraint_indicator_flags 5/6 */,
    979        0 /* general_constraint_indicator_flags 6/6 */,
    980        0x5A /* general_level_idc */,
    981        0 /* min_spatial_segmentation_idc 1/2 */,
    982        0 /* min_spatial_segmentation_idc 2/2 */,
    983        0 /* parallelismType */,
    984        1 /* chroma_format_idc */,
    985        0 /* bit_depth_luma_minus8 */,
    986        0 /* bit_depth_chroma_minus8 */,
    987        0 /* avgFrameRate 1/2 */,
    988        0 /* avgFrameRate 2/2 */,
    989        0x0F /* constantFrameRate/numTemporalLayers/temporalIdNested/lengthSizeMinusOne
    990              */
    991        ,
    992        2 /* numOfArrays */,
    993        /* SPS Array */
    994        0x21 /* NAL_unit_type (SPS) */,
    995        0 /* numNalus 1/2 */,
    996        1 /* numNalus 2/2 */,
    997 
    998        /* SPS */
    999        0 /* nalUnitLength 1/2 */,
   1000        8 /* nalUnitLength 2/2 (header + rsbp) */,
   1001        0x42 /* NALU header 1/2 */,
   1002        0 /* NALU header 2/2 */,
   1003        0 /* rbsp 1/6 */,
   1004        0 /* rbsp 2/6 */,
   1005        0 /* rbsp 3/6 */,
   1006        0 /* rbsp 4/6 */,
   1007        0 /* rbsp 5/6 */,
   1008        0 /* rbsp 6/6 */,
   1009 
   1010        /* PPS Array */
   1011        0x22 /* NAL_unit_type (PPS) */,
   1012        0 /* numNalus 1/2 */,
   1013        2 /* numNalus 2/2 */,
   1014 
   1015        /* PPS 1 */
   1016        0 /* nalUnitLength 1/2 */,
   1017        3 /* nalUnitLength 2/2 (header + rsbp) */,
   1018        0x44 /* NALU header 1/2 */,
   1019        0 /* NALU header 2/2 */,
   1020        0 /* rbsp */,
   1021 
   1022        /* PPS 2 */
   1023        0 /* nalUnitLength 1/2 */,
   1024        3 /* nalUnitLength 2/2 (header + rsbp) */,
   1025        0x44 /* NALU header 1/2 */,
   1026        0 /* NALU header 2/2 */,
   1027        0 /* rbsp */,
   1028    };
   1029    extradata->AppendElements(hvccBytesBuffer, std::size(hvccBytesBuffer));
   1030    auto rv = HVCCConfig::Parse(extradata);
   1031    EXPECT_TRUE(rv.isOk());
   1032    auto hvcc = rv.unwrap();
   1033    // Check NALU, it should contain 1 SPS and 2 PPS.
   1034    EXPECT_EQ(hvcc.mNALUs.Length(), uint32_t(3));
   1035    EXPECT_EQ(hvcc.mNALUs[0].mNalUnitType, H265NALU::NAL_TYPES::SPS_NUT);
   1036    EXPECT_EQ(hvcc.mNALUs[0].mNuhLayerId, 0);
   1037    EXPECT_EQ(hvcc.mNALUs[0].mNuhTemporalIdPlus1, 0);
   1038    EXPECT_EQ(hvcc.mNALUs[0].IsSPS(), true);
   1039    EXPECT_EQ(hvcc.mNALUs[0].mNALU.Length(), 8u);
   1040 
   1041    EXPECT_EQ(hvcc.mNALUs[1].mNalUnitType, H265NALU::NAL_TYPES::PPS_NUT);
   1042    EXPECT_EQ(hvcc.mNALUs[1].mNuhLayerId, 0);
   1043    EXPECT_EQ(hvcc.mNALUs[1].mNuhTemporalIdPlus1, 0);
   1044    EXPECT_EQ(hvcc.mNALUs[1].IsSPS(), false);
   1045    EXPECT_EQ(hvcc.mNALUs[1].mNALU.Length(), 3u);
   1046 
   1047    EXPECT_EQ(hvcc.mNALUs[2].mNalUnitType, H265NALU::NAL_TYPES::PPS_NUT);
   1048    EXPECT_EQ(hvcc.mNALUs[2].mNuhLayerId, 0);
   1049    EXPECT_EQ(hvcc.mNALUs[2].mNuhTemporalIdPlus1, 0);
   1050    EXPECT_EQ(hvcc.mNALUs[2].IsSPS(), false);
   1051    EXPECT_EQ(hvcc.mNALUs[2].mNALU.Length(), 3u);
   1052  }
   1053 }
   1054 
   1055 TEST(H265, HVCCParsingFailure)
   1056 {
   1057  {
   1058    // Incorrect version
   1059    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
   1060    uint8_t hvccBytesBuffer[] = {
   1061        2 /* version */,
   1062        1 /* general_profile_space/general_tier_flag/general_profile_idc */,
   1063        0x60 /* general_profile_compatibility_flags 1/4 */,
   1064        0 /* general_profile_compatibility_flags 2/4 */,
   1065        0 /* general_profile_compatibility_flags 3/4 */,
   1066        0 /* general_profile_compatibility_flags 4/4 */,
   1067        0x90 /* general_constraint_indicator_flags 1/6 */,
   1068        0 /* general_constraint_indicator_flags 2/6 */,
   1069        0 /* general_constraint_indicator_flags 3/6 */,
   1070        0 /* general_constraint_indicator_flags 4/6 */,
   1071        0 /* general_constraint_indicator_flags 5/6 */,
   1072        0 /* general_constraint_indicator_flags 6/6 */,
   1073        0x5A /* general_level_idc */,
   1074        0 /* min_spatial_segmentation_idc 1/2 */,
   1075        0 /* min_spatial_segmentation_idc 2/2 */,
   1076        0 /* parallelismType */,
   1077        1 /* chroma_format_idc */,
   1078        0 /* bit_depth_luma_minus8 */,
   1079        0 /* bit_depth_chroma_minus8 */,
   1080        0 /* avgFrameRate 1/2 */,
   1081        0 /* avgFrameRate 2/2 */,
   1082        0x0F /* constantFrameRate/numTemporalLayers/temporalIdNested/lengthSizeMinusOne
   1083              */
   1084        ,
   1085        0 /* numOfArrays */,
   1086    };
   1087    extradata->AppendElements(hvccBytesBuffer, std::size(hvccBytesBuffer));
   1088    auto avcc = HVCCConfig::Parse(extradata);
   1089    EXPECT_TRUE(avcc.isErr());
   1090  }
   1091  {
   1092    // Insuffient data
   1093    auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
   1094    uint8_t hvccBytesBuffer[] = {
   1095        1 /* version */,
   1096        1 /* general_profile_space/general_tier_flag/general_profile_idc */,
   1097        0x60 /* general_profile_compatibility_flags 1/4 */,
   1098        0 /* general_profile_compatibility_flags 2/4 */,
   1099        0 /* general_profile_compatibility_flags 3/4 */,
   1100        0 /* general_profile_compatibility_flags 4/4 */,
   1101        0x90 /* general_constraint_indicator_flags 1/6 */,
   1102        0 /* general_constraint_indicator_flags 2/6 */,
   1103        0 /* general_constraint_indicator_flags 3/6 */,
   1104        0 /* general_constraint_indicator_flags 4/6 */,
   1105        0 /* general_constraint_indicator_flags 5/6 */,
   1106        0 /* general_constraint_indicator_flags 6/6 */,
   1107        0x5A /* general_level_idc */
   1108    };
   1109    extradata->AppendElements(hvccBytesBuffer, std::size(hvccBytesBuffer));
   1110    auto avcc = HVCCConfig::Parse(extradata);
   1111    EXPECT_TRUE(avcc.isErr());
   1112  }
   1113 }
   1114 
   1115 TEST(H265, HVCCToAnnexB)
   1116 {
   1117  auto extradata = MakeRefPtr<mozilla::MediaByteBuffer>();
   1118  uint8_t hvccBytesBuffer[] = {
   1119      1 /* version */,
   1120      1 /* general_profile_space/general_tier_flag/general_profile_idc */,
   1121      0x60 /* general_profile_compatibility_flags 1/4 */,
   1122      0 /* general_profile_compatibility_flags 2/4 */,
   1123      0 /* general_profile_compatibility_flags 3/4 */,
   1124      0 /* general_profile_compatibility_flags 4/4 */,
   1125      0x90 /* general_constraint_indicator_flags 1/6 */,
   1126      0 /* general_constraint_indicator_flags 2/6 */,
   1127      0 /* general_constraint_indicator_flags 3/6 */,
   1128      0 /* general_constraint_indicator_flags 4/6 */,
   1129      0 /* general_constraint_indicator_flags 5/6 */,
   1130      0 /* general_constraint_indicator_flags 6/6 */,
   1131      0x5A /* general_level_idc */,
   1132      0 /* min_spatial_segmentation_idc 1/2 */,
   1133      0 /* min_spatial_segmentation_idc 2/2 */,
   1134      0 /* parallelismType */,
   1135      1 /* chroma_format_idc */,
   1136      0 /* bit_depth_luma_minus8 */,
   1137      0 /* bit_depth_chroma_minus8 */,
   1138      0 /* avgFrameRate 1/2 */,
   1139      0 /* avgFrameRate 2/2 */,
   1140      0x0F /* constantFrameRate/numTemporalLayers/temporalIdNested/lengthSizeMinusOne
   1141            */
   1142      ,
   1143      2 /* numOfArrays */,
   1144      /* SPS Array */
   1145      0x21 /* NAL_unit_type (SPS) */,
   1146      0 /* numNalus 1/2 */,
   1147      1 /* numNalus 2/2 */,
   1148 
   1149      /* SPS */
   1150      0 /* nalUnitLength 1/2 */,
   1151      3 /* nalUnitLength 2/2 (header + rsbp) */,
   1152      0x42 /* NALU header 1/2 */,
   1153      0 /* NALU header 2/2 */,
   1154      0 /* rbsp */,
   1155 
   1156      /* PPS Array */
   1157      0x22 /* NAL_unit_type (PPS) */,
   1158      0 /* numNalus 1/2 */,
   1159      1 /* numNalus 2/2 */,
   1160 
   1161      /* PPS */
   1162      0 /* nalUnitLength 1/2 */,
   1163      3 /* nalUnitLength 2/2 (header + rsbp) */,
   1164      0x44 /* NALU header 1/2 */,
   1165      0 /* NALU header 2/2 */,
   1166      0 /* rbsp */,
   1167  };
   1168  extradata->AppendElements(hvccBytesBuffer, std::size(hvccBytesBuffer));
   1169 
   1170  // We convert hvcc extra-data to annexb format, then parse each nalu to see if
   1171  // they are still correct or not.
   1172  const size_t naluBytesSize = 3;  // NAL size is 3, see nalUnitLength above
   1173  const size_t delimiterBytesSize = 4;  // 0x00000001
   1174  const size_t naluPlusDelimiterBytesSize = naluBytesSize + delimiterBytesSize;
   1175  RefPtr<mozilla::MediaByteBuffer> annexBExtraData =
   1176      AnnexB::ConvertHVCCExtraDataToAnnexB(extradata);
   1177  // 2 NALU, sps and pps
   1178  EXPECT_EQ(annexBExtraData->Length(), naluPlusDelimiterBytesSize * 2);
   1179 
   1180  H265NALU sps(
   1181      static_cast<uint8_t*>(annexBExtraData->Elements() + delimiterBytesSize),
   1182      naluBytesSize);
   1183  EXPECT_EQ(sps.mNalUnitType, H265NALU::NAL_TYPES::SPS_NUT);
   1184  EXPECT_EQ(sps.mNuhLayerId, 0);
   1185  EXPECT_EQ(sps.mNuhTemporalIdPlus1, 0);
   1186  EXPECT_EQ(sps.IsSPS(), true);
   1187  EXPECT_EQ(sps.mNALU.Length(), 3u);
   1188 
   1189  H265NALU pps(
   1190      static_cast<uint8_t*>(annexBExtraData->Elements() +
   1191                            naluPlusDelimiterBytesSize + delimiterBytesSize),
   1192      naluBytesSize);
   1193  EXPECT_EQ(pps.mNalUnitType, H265NALU::NAL_TYPES::PPS_NUT);
   1194  EXPECT_EQ(pps.mNuhLayerId, 0);
   1195  EXPECT_EQ(pps.mNuhTemporalIdPlus1, 0);
   1196  EXPECT_EQ(pps.IsSPS(), false);
   1197  EXPECT_EQ(pps.mNALU.Length(), 3u);
   1198 }
   1199 
   1200 TEST(H265, AnnexBToHVCC)
   1201 {
   1202  RefPtr<MediaRawData> rawData{GetHVCCSample(128)};
   1203  RefPtr<MediaRawData> rawDataClone = rawData->Clone();
   1204  Result<Ok, nsresult> result =
   1205      AnnexB::ConvertHVCCSampleToAnnexB(rawDataClone, /* aAddSps */ false);
   1206  EXPECT_TRUE(result.isOk()) << "HVCC to AnnexB Conversion should succeed";
   1207  EXPECT_TRUE(AnnexB::IsAnnexB(*rawDataClone))
   1208      << "The sample should be AnnexB following conversion";
   1209 
   1210  auto rv = AnnexB::ConvertSampleToHVCC(rawDataClone);
   1211  EXPECT_TRUE(rv.isOk()) << "AnnexB to HVCC Conversion should succeed";
   1212  EXPECT_TRUE(AnnexB::IsHVCC(rawDataClone))
   1213      << "The sample should be HVCC following conversion";
   1214 }
   1215 
   1216 // This is SPS from 'hevc_white_frame.mp4'
   1217 static const uint8_t sSps[] = {
   1218    0x42, 0x01, 0x01, 0x01, 0x60, 0x00, 0x00, 0x03, 0x00, 0x90, 0x00,
   1219    0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x5d, 0xa0, 0x02, 0x00, 0x80,
   1220    0x30, 0x16, 0x59, 0x59, 0xa4, 0x93, 0x2b, 0xc0, 0x5a, 0x02, 0x00,
   1221    0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x3c, 0x10};
   1222 
   1223 // This is VPS from 'hevc_white_frame.mp4'
   1224 static const uint8_t sVps[] = {0x40, 0x01, 0x0C, 0x01, 0xFF, 0xFF, 0x01, 0x60,
   1225                               0x00, 0x00, 0x03, 0x00, 0x90, 0x00, 0x00, 0x03,
   1226                               0x00, 0x00, 0x03, 0x00, 0x3F, 0x95, 0x98, 0x09};
   1227 
   1228 // This is PPS from 'hevc_white_frame.mp4'
   1229 static const uint8_t sPps[] = {0x44, 0x01, 0xC1, 0x72, 0xB4, 0x62, 0x40};
   1230 
   1231 TEST(H265, ExtractHVCCExtraData)
   1232 {
   1233  RefPtr<MediaRawData> rawData{GetHVCCSample(sSps, std::size(sSps))};
   1234  RefPtr<MediaByteBuffer> extradata = H265::ExtractHVCCExtraData(rawData);
   1235  EXPECT_TRUE(extradata);
   1236  auto rv = HVCCConfig::Parse(extradata);
   1237  EXPECT_TRUE(rv.isOk());
   1238  auto hvcc = rv.unwrap();
   1239  EXPECT_EQ(hvcc.mNALUs.Length(), 1u);
   1240  EXPECT_EQ(hvcc.mNALUs[0].mNalUnitType, H265NALU::NAL_TYPES::SPS_NUT);
   1241  EXPECT_EQ(hvcc.mNALUs[0].mNuhLayerId, 0u);
   1242  EXPECT_EQ(hvcc.mNALUs[0].mNuhTemporalIdPlus1, 1);
   1243  EXPECT_EQ(hvcc.mNALUs[0].IsSPS(), true);
   1244  EXPECT_EQ(hvcc.mNALUs[0].mNALU.Length(), 43u);
   1245 
   1246  nsTArray<Span<const uint8_t>> nalus;
   1247  nalus.AppendElement(Span<const uint8_t>{sSps, std::size(sSps)});
   1248  nalus.AppendElement(Span<const uint8_t>{sVps, std::size(sVps)});
   1249  nalus.AppendElement(Span<const uint8_t>{sPps, std::size(sPps)});
   1250 
   1251  RefPtr<MediaRawData> rawData2{GetHVCCSamples(nalus)};
   1252  RefPtr<MediaByteBuffer> extradata2 = H265::ExtractHVCCExtraData(rawData2);
   1253  EXPECT_TRUE(extradata2);
   1254  auto rv2 = HVCCConfig::Parse(extradata2);
   1255  EXPECT_TRUE(rv2.isOk());
   1256  auto hvcc2 = rv2.unwrap();
   1257  EXPECT_EQ(hvcc2.mNALUs.Length(), 3u);
   1258 
   1259  EXPECT_EQ(hvcc2.mNALUs[0].mNalUnitType, H265NALU::NAL_TYPES::VPS_NUT);
   1260  EXPECT_EQ(hvcc2.mNALUs[0].mNuhLayerId, 0u);
   1261  EXPECT_EQ(hvcc2.mNALUs[0].mNuhTemporalIdPlus1, 1);
   1262  EXPECT_EQ(hvcc2.mNALUs[0].IsVPS(), true);
   1263  EXPECT_EQ(hvcc2.mNALUs[0].mNALU.Length(), std::size(sVps));
   1264 
   1265  EXPECT_EQ(hvcc2.mNALUs[1].mNalUnitType, H265NALU::NAL_TYPES::SPS_NUT);
   1266  EXPECT_EQ(hvcc2.mNALUs[1].mNuhLayerId, 0u);
   1267  EXPECT_EQ(hvcc2.mNALUs[1].mNuhTemporalIdPlus1, 1);
   1268  EXPECT_EQ(hvcc2.mNALUs[1].IsSPS(), true);
   1269  EXPECT_EQ(hvcc2.mNALUs[1].mNALU.Length(), std::size(sSps));
   1270 
   1271  EXPECT_EQ(hvcc2.mNALUs[2].mNalUnitType, H265NALU::NAL_TYPES::PPS_NUT);
   1272  EXPECT_EQ(hvcc2.mNALUs[2].mNuhLayerId, 0u);
   1273  EXPECT_EQ(hvcc2.mNALUs[2].mNuhTemporalIdPlus1, 1);
   1274  EXPECT_EQ(hvcc2.mNALUs[2].IsPPS(), true);
   1275  EXPECT_EQ(hvcc2.mNALUs[2].mNALU.Length(), std::size(sPps));
   1276 }
   1277 
   1278 TEST(H265, DecodeSPSFromSPSNALU)
   1279 {
   1280  H265NALU nalu{sSps, std::size(sSps)};
   1281  auto rv = H265::DecodeSPSFromSPSNALU(nalu);
   1282  EXPECT_TRUE(rv.isOk());
   1283  auto sps = rv.unwrap();
   1284  // Examine the value by using HEVCESBrowser.
   1285  EXPECT_EQ(sps.sps_video_parameter_set_id, 0u);
   1286  EXPECT_EQ(sps.sps_max_sub_layers_minus1, 0u);
   1287  EXPECT_EQ(sps.sps_temporal_id_nesting_flag, 1);
   1288  EXPECT_EQ(sps.profile_tier_level.general_profile_space, 0u);
   1289  EXPECT_EQ(sps.profile_tier_level.general_tier_flag, false);
   1290  EXPECT_EQ(sps.profile_tier_level.general_profile_idc, 1u);
   1291  EXPECT_EQ(sps.profile_tier_level.general_profile_compatibility_flags,
   1292            0x60000000u);
   1293  EXPECT_EQ(sps.profile_tier_level.general_progressive_source_flag, true);
   1294  EXPECT_EQ(sps.profile_tier_level.general_interlaced_source_flag, false);
   1295  EXPECT_EQ(sps.profile_tier_level.general_non_packed_constraint_flag, false);
   1296  EXPECT_EQ(sps.profile_tier_level.general_frame_only_constraint_flag, true);
   1297  EXPECT_EQ(sps.profile_tier_level.general_level_idc, 93u);
   1298  EXPECT_EQ(sps.sps_seq_parameter_set_id, 0u);
   1299  EXPECT_EQ(sps.chroma_format_idc, 1u);
   1300  EXPECT_EQ(sps.separate_colour_plane_flag, false);
   1301  EXPECT_EQ(sps.pic_width_in_luma_samples, 1024u);
   1302  EXPECT_EQ(sps.pic_height_in_luma_samples, 768u);
   1303  EXPECT_EQ(sps.conformance_window_flag, false);
   1304  EXPECT_EQ(sps.bit_depth_luma_minus8, 0u);
   1305  EXPECT_EQ(sps.bit_depth_chroma_minus8, 0u);
   1306  EXPECT_EQ(sps.log2_max_pic_order_cnt_lsb_minus4, 4u);
   1307  EXPECT_EQ(sps.sps_sub_layer_ordering_info_present_flag, true);
   1308  EXPECT_EQ(sps.sps_max_dec_pic_buffering_minus1[0], 4u);
   1309  EXPECT_EQ(sps.sps_max_num_reorder_pics[0], 2u);
   1310  EXPECT_EQ(sps.sps_max_latency_increase_plus1[0], 5u);
   1311  EXPECT_EQ(sps.log2_min_luma_coding_block_size_minus3, 0u);
   1312  EXPECT_EQ(sps.log2_diff_max_min_luma_coding_block_size, 3u);
   1313  EXPECT_EQ(sps.log2_min_luma_transform_block_size_minus2, 0u);
   1314  EXPECT_EQ(sps.log2_diff_max_min_luma_transform_block_size, 3u);
   1315  EXPECT_EQ(sps.max_transform_hierarchy_depth_inter, 0u);
   1316  EXPECT_EQ(sps.max_transform_hierarchy_depth_inter, 0u);
   1317  EXPECT_EQ(sps.pcm_enabled_flag, false);
   1318  EXPECT_EQ(sps.num_short_term_ref_pic_sets, 0u);
   1319  EXPECT_EQ(sps.sps_temporal_mvp_enabled_flag, true);
   1320  EXPECT_EQ(sps.strong_intra_smoothing_enabled_flag, true);
   1321  EXPECT_TRUE(sps.vui_parameters);
   1322  EXPECT_EQ(sps.vui_parameters->video_full_range_flag, false);
   1323 
   1324  // Test public methods
   1325  EXPECT_EQ(sps.BitDepthLuma(), 8u);
   1326  EXPECT_EQ(sps.BitDepthChroma(), 8u);
   1327  const auto imgSize = sps.GetImageSize();
   1328  EXPECT_EQ(imgSize.Width(), 1024);
   1329  EXPECT_EQ(imgSize.Height(), 768);
   1330  const auto disSize = sps.GetDisplaySize();
   1331  EXPECT_EQ(disSize, imgSize);
   1332  EXPECT_EQ(sps.ColorDepth(), gfx::ColorDepth::COLOR_8);
   1333  EXPECT_EQ(sps.ColorSpace(), gfx::YUVColorSpace::BT709);
   1334  EXPECT_EQ(sps.IsFullColorRange(), false);
   1335  EXPECT_EQ(sps.ColorPrimaries(), 2u);
   1336  EXPECT_EQ(sps.TransferFunction(), 2u);
   1337 }
   1338 
   1339 TEST(H265, SPSIteratorAndCreateNewExtraData)
   1340 {
   1341  // The fake extradata has 3 NALUs (1 vps, 1 sps and 1 pps).
   1342  RefPtr<MediaByteBuffer> extradata = H265::CreateFakeExtraData();
   1343  EXPECT_TRUE(extradata);
   1344  auto rv = HVCCConfig::Parse(extradata);
   1345  EXPECT_TRUE(rv.isOk());
   1346  auto hvcc = rv.unwrap();
   1347  EXPECT_EQ(hvcc.mNALUs.Length(), 3u);
   1348  EXPECT_EQ(hvcc.NumSPS(), 1u);
   1349 
   1350  // SPSIterator should be able to access the SPS
   1351  SPSIterator it(hvcc);
   1352  auto* sps = *it;
   1353  EXPECT_TRUE(sps);
   1354 
   1355  // This SPS should match the one retrieved from the HVCC.
   1356  auto spsMaybe = hvcc.GetFirstAvaiableNALU(H265NALU::NAL_TYPES::SPS_NUT);
   1357  EXPECT_TRUE(spsMaybe);
   1358  auto rv1 = H265::DecodeSPSFromSPSNALU(*sps);
   1359  auto rv2 = H265::DecodeSPSFromSPSNALU(spsMaybe.ref());
   1360  EXPECT_TRUE(rv1.isOk());
   1361  EXPECT_TRUE(rv2.isOk());
   1362  EXPECT_EQ(rv1.unwrap(), rv2.unwrap());
   1363 
   1364  // The iterator becomes invalid after advancing, as there is only one SPS.
   1365  EXPECT_FALSE(*(++it));
   1366 
   1367  // Retrieve other NALUs to test the creation of new extradata.
   1368  auto ppsMaybe = hvcc.GetFirstAvaiableNALU(H265NALU::NAL_TYPES::PPS_NUT);
   1369  EXPECT_TRUE(ppsMaybe);
   1370  auto vpsMaybe = hvcc.GetFirstAvaiableNALU(H265NALU::NAL_TYPES::VPS_NUT);
   1371  EXPECT_TRUE(vpsMaybe);
   1372  nsTArray<H265NALU> nalus;
   1373  nalus.AppendElement(*spsMaybe);
   1374  nalus.AppendElement(*ppsMaybe);
   1375  nalus.AppendElement(*vpsMaybe);
   1376  RefPtr<MediaByteBuffer> newExtradata = H265::CreateNewExtraData(hvcc, nalus);
   1377  EXPECT_TRUE(newExtradata);
   1378 
   1379  // The new extradata should match the original extradata.
   1380  auto rv3 = HVCCConfig::Parse(extradata);
   1381  EXPECT_TRUE(rv3.isOk());
   1382  auto hvcc2 = rv3.unwrap();
   1383  EXPECT_EQ(hvcc.mNALUs.Length(), hvcc2.mNALUs.Length());
   1384  EXPECT_EQ(hvcc.NumSPS(), hvcc2.NumSPS());
   1385 }
   1386 
   1387 TEST(H265, ConfWindowTest)
   1388 {
   1389  // This sps contains some cropping information, which will crop video from the
   1390  // resolution 3840x2176 to 3840x2160.
   1391  static const uint8_t sSpsConfWindow[] = {
   1392      0x42, 0x01, 0x01, 0x01, 0x40, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00,
   1393      0x00, 0x00, 0x99, 0xA0, 0x01, 0xE0, 0x20, 0x02, 0x20, 0x7C, 0x4E, 0x59,
   1394      0x95, 0x29, 0x08, 0x46, 0x46, 0xFF, 0xC3, 0x01, 0x6A, 0x02, 0x02, 0x02,
   1395      0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0xE3, 0x00, 0x2E, 0xF2,
   1396      0x88, 0x00, 0x02, 0x62, 0x5A, 0x00, 0x00, 0x13, 0x12, 0xD0, 0x20};
   1397 
   1398  H265NALU nalu{sSpsConfWindow, std::size(sSpsConfWindow)};
   1399  auto rv = H265::DecodeSPSFromSPSNALU(nalu);
   1400  EXPECT_TRUE(rv.isOk());
   1401  auto sps = rv.unwrap();
   1402  EXPECT_EQ(sps.chroma_format_idc, 1u);
   1403  EXPECT_EQ(sps.pic_width_in_luma_samples, 3840u);
   1404  EXPECT_EQ(sps.pic_height_in_luma_samples, 2176u);
   1405  EXPECT_EQ(sps.conformance_window_flag, true);
   1406  EXPECT_EQ(sps.conf_win_left_offset, 0u);
   1407  EXPECT_EQ(sps.conf_win_right_offset, 0u);
   1408  EXPECT_EQ(sps.conf_win_top_offset, 0u);
   1409  EXPECT_EQ(sps.conf_win_bottom_offset, 8u);
   1410 
   1411  const auto imgSize = sps.GetImageSize();
   1412  EXPECT_EQ(imgSize.Width(), 3840);
   1413  EXPECT_EQ(imgSize.Height(), 2160);  // cropped height
   1414 
   1415  const auto disSize = sps.GetDisplaySize();
   1416  EXPECT_EQ(disSize, imgSize);
   1417 }
   1418 
   1419 TEST(H265, ColorPrimariesTest)
   1420 {
   1421  // This sps contains a BT2020 color primaries information.
   1422  static const uint8_t sSPSColorPrimariesBT2020[] = {
   1423      0x42, 0x01, 0x01, 0x02, 0x20, 0x00, 0x00, 0x03, 0x00, 0xB0, 0x00, 0x00,
   1424      0x03, 0x00, 0x00, 0x03, 0x00, 0xB4, 0xA0, 0x01, 0xF8, 0x20, 0x02, 0xF4,
   1425      0x4D, 0x88, 0x17, 0xB9, 0x16, 0x55, 0x35, 0x09, 0x10, 0x09, 0x00, 0x80};
   1426 
   1427  H265NALU nalu{sSPSColorPrimariesBT2020, std::size(sSPSColorPrimariesBT2020)};
   1428  auto rv = H265::DecodeSPSFromSPSNALU(nalu);
   1429  EXPECT_TRUE(rv.isOk());
   1430  auto sps = rv.unwrap();
   1431  EXPECT_EQ(sps.ColorPrimaries(), 9 /* CP_BT2020 */);
   1432 }
   1433 
   1434 }  // namespace mozilla