tor-browser

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

TestExtractAV1CodecDetails.cpp (12073B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include <gtest/gtest.h>
      7 #include <stdint.h>
      8 
      9 #include "AOMDecoder.h"
     10 #include "VideoUtils.h"
     11 
     12 namespace mozilla {
     13 void PrintTo(const AOMDecoder::AV1SequenceInfo& aInfo, std::ostream* aStream) {
     14  nsAutoCString formatted = nsAutoCString();
     15  formatted.AppendPrintf(
     16      "av01.%01u.%02u%c.%02u.%01u.%01u%01u%01u.%02u.%02u.%02u.%01u (res: "
     17      "%ux%u) operating points: [",
     18      aInfo.mProfile, aInfo.mOperatingPoints[0].mLevel,
     19      aInfo.mOperatingPoints[0].mTier == 1 ? 'H' : 'M', aInfo.mBitDepth,
     20      aInfo.mMonochrome, aInfo.mSubsamplingX, aInfo.mSubsamplingY,
     21      static_cast<uint8_t>(aInfo.mChromaSamplePosition),
     22      static_cast<uint8_t>(aInfo.mColorSpace.mPrimaries),
     23      static_cast<uint8_t>(aInfo.mColorSpace.mTransfer),
     24      static_cast<uint8_t>(aInfo.mColorSpace.mMatrix),
     25      static_cast<uint8_t>(aInfo.mColorSpace.mRange), aInfo.mImage.Width(),
     26      aInfo.mImage.Height());
     27  size_t opCount = aInfo.mOperatingPoints.Length();
     28  for (size_t i = 0; i < opCount; i++) {
     29    const auto& op = aInfo.mOperatingPoints[i];
     30    formatted.AppendPrintf("{ layers: %x, level: %u, tier: %u }", op.mLayers,
     31                           op.mLevel, op.mTier);
     32    if (i != opCount - 1) {
     33      formatted.Append(", ");
     34    }
     35  }
     36  formatted.Append("]");
     37  *aStream << formatted;
     38 }
     39 }  // namespace mozilla
     40 
     41 using namespace mozilla;
     42 
     43 struct AV1TestData {
     44  const char* mCodecParameterString;
     45  const bool mExpectedValue;
     46  const char* mComment;
     47 };
     48 
     49 TEST(ExtractAV1CodecDetails, TestInputData)
     50 {
     51  AV1TestData tests[] = {
     52      // Format is:
     53      // av01.N.NN[MH].NN.B.BBN.NN.NN.NN.B
     54      // where
     55      //   N = decimal digit
     56      //   [] = single character
     57      //   B = binary digit
     58      // Field order:
     59      // <sample entry 4CC>.<profile>.<level><tier>.<bitDepth>
     60      // [.<monochrome>.<chromaSubsampling>
     61      // .<colorPrimaries>.<transferCharacteristics>.<matrixCoefficients>
     62      // .<videoFullRangeFlag>]
     63 
     64      // Format checks
     65      {"av01.0.10M.08", true, "Minimum length"},
     66      {"av1.0.10M.08", false, "Invalid 4CC"},
     67      {"av01..10M.08", false, "Blank field"},
     68      {"av01.-1.10M.08", false, "Negative field"},
     69      {"av01.0.10M.8", false, "Missing leading zeros"},
     70 
     71      // Field counts
     72      {"av01", false, "0 of 4 required fields"},
     73      {"av01.0", false, "1 of 4 required fields"},
     74      {"av01.0.10", false, "2 of 4 required fields"},
     75      {"av01.0.10M", false, "3 of 4 required fields"},
     76      {"av01.0.10M.08.0", false, "5 fields, AV1 requires 4 or 10"},
     77      {"av01.0.10M.08.0.110.01.01.01", false, "9 fields, AV1 requires 4 or 10"},
     78      {"av01.0.10M.08.0.110.01.01.01.0", true, "Maximum fields"},
     79      {"av01.0.10M.08.0.110.01.01.01.0.0", false, "Too many fields"},
     80 
     81      // "Comments" are allowed (unknown characters at the end of fields)
     82      {"av01.0.10M.08this is ignored", true, "Minimum length with comment"},
     83      {"av01.0.10Mbad comment", false, "Comment before required field"},
     84      {"av01.0.10M.08.0.110.01.01.01.0also ignored", true,
     85       "Maximum length with comment"},
     86 
     87      // Begin field checks
     88 
     89      // -- Profile --
     90      // Main Profile (0) tested above
     91 
     92      // High Profile requires 4:4:4 chroma subsampling without monochrome
     93      {"av01.1.10M.08", false, "High Profile (1) without parameters"},
     94      {"av01.1.10M.08.0.000.01.01.01.0", true, "High Profile (1)"},
     95 
     96      // Professional requires either of:
     97      // - 8bit or 10bit at 4:2:2
     98      // - 12bit at any subsampling
     99      {"av01.2.10M.10.0.100.01.01.01.0", true,
    100       "Professional Profile (2) 10-bit 4:2:2"},
    101      {"av01.2.10M.12.0.110.01.01.01.0", true,
    102       "Professional Profile (2) 12-bit 4:2:0"},
    103 
    104      {"av01.3.10M.12.0.000.01.01.01.0", false, "Invalid Profile 3"},
    105 
    106      // -- Level --
    107      {"av01.0.00M.08", true, "Level 0 (2.1)"},
    108      // Level 4.2 (10) tested above
    109      {"av01.0.14M.08", true, "Level 14 (5.2)"},
    110      {"av01.0.23M.08", true, "Level 23 (7.3)"},
    111      {"av01.0.24M.08", false, "Level 24 (Reserved)"},
    112 
    113      // -- Tier --
    114      // Main tier tested above
    115      {"av01.0.10H.08", true, "High tier"},
    116 
    117      // -- Bit depth --
    118      // 8-bit tested above with Main and High Profiles
    119      {"av01.0.10M.10", true, "Main 10-bit"},
    120      {"av01.1.10M.10.0.000.01.01.01.0", true, "High 10-bit"},
    121      {"av01.1.10M.12.0.000.01.01.01.0", false, "High 12-bit (Invalid)"},
    122      // Valid 12-bit tested for Professional Profile
    123 
    124      // -- Monochrome --
    125      // Monochrome off tested above
    126      {"av01.0.10M.08.1.110.01.01.01.0", true, "Main 8-bit monochrome"},
    127      {"av01.1.10M.10.1.000.01.01.01.0", false,
    128       "4:4:4 is incompatible with monochrome"},
    129      {"av01.2.10M.10.1.100.01.01.01.0", false,
    130       "4:2:0 is incompatible with monochrome"},
    131      {"av01.2.10M.12.1.110.01.01.01.0", true,
    132       "Professional 12-bit monochrome"},
    133 
    134      // -- Chroma subsampling --
    135      // Field is parsed by digits <x><y><position>
    136      // where positions are [unknown, vertical, colocated]
    137      {"av01.0.10M.08.0.112.01.01.01.0", true, "Chroma colocated"},
    138      // Main Profile, 4:2:0 tested above
    139      {"av01.0.10M.08.0.100.01.01.01.0", false,
    140       "4:2:2 not allowed on Main Profile"},
    141      // High Profile, 4:4:4 tested above
    142      {"av01.1.10M.08.0.110.01.01.01.0", false,
    143       "4:4:4 required on High Profile"},
    144      {"av01.2.10M.08.0.110.01.01.01.0", false,
    145       "4:2:0 not allowed on 8-bit Professional"},
    146      // Professional Profile, 8-bit 4:2:2 tested above
    147      // Professional Profile, 12-bit 4:2:0 tested above
    148      {"av01.2.10M.12.0.100.01.01.01.0", true, "12-bit 4:2:2"},
    149      {"av01.2.10M.12.0.000.01.01.01.0", true, "12-bit 4:4:4"},
    150 
    151      {"av01.2.10M.08.0.101.01.01.01.0", false, "Chroma position with 4:2:2"},
    152      {"av01.1.10M.08.0.001.01.01.01.0", false, "Chroma position with 4:4:4"},
    153      {"av01.0.10M.08.0.113.01.01.01.0", false, "Chroma position 3 (Reserved)"},
    154 
    155      // -- Color primaries --
    156      // 0, 3, [13-21], >23 are reserved
    157      // 1 (BT709) is tested above
    158      {"av01.0.10M.10.0.110.09.16.09.0", true,
    159       "Color space: BT2020/SMPTE2084/BT2020NCL"},
    160      {"av01.0.10M.10.0.110.00.16.09.0", false, "Primaries 0: Reserved"},
    161      {"av01.0.10M.10.0.110.03.16.09.0", false, "Primaries 3: Reserved"},
    162      {"av01.0.10M.10.0.110.13.16.09.0", false, "Primaries 13: Reserved"},
    163      {"av01.0.10M.10.0.110.21.16.09.0", false, "Primaries 21: Reserved"},
    164      {"av01.0.10M.10.0.110.22.16.09.0", true, "Primaries 22: EBU3213"},
    165      {"av01.0.10M.10.0.110.23.16.09.0", false, "Primaries 23: Reserved"},
    166 
    167      // -- Transfer characteristics --
    168      // 0, 3, >19 are all reserved
    169      // 1 (BT709) is tested above
    170      // 16 (SMPTE2084) is tested above
    171      {"av01.0.10M.10.0.110.09.14.09.0", true,
    172       "Color space: BT2020/BT2020 10-bit/BT2020NCL"},
    173      {"av01.0.10M.10.0.110.09.00.09.0", false, "Transfer 0: Reserved"},
    174      {"av01.0.10M.10.0.110.09.03.09.0", false, "Transfer 3: Reserved"},
    175      {"av01.0.10M.10.0.110.09.20.09.0", false, "Transfer 20: Reserved"},
    176 
    177      // -- Matrix coefficients --
    178      // 3, >15 are all reserved
    179      // 1 (BT709) is tested above
    180      // 9 (BT2020NCL) is tested above
    181      {"av01.1.10M.10.0.000.01.13.00.1", true, "4:4:4 10-bit sRGB"},
    182      {"av01.1.10M.10.0.000.01.13.00.0", false, "sRGB requires full range"},
    183      {"av01.2.10M.10.0.100.01.13.00.1", false,
    184       "Subsampling incompatible with sRGB"},
    185      {"av01.2.10M.12.0.000.01.13.00.1", true, "4:4:4 12-bit sRGB"},
    186      {"av01.2.10M.12.0.000.01.01.15.1", false, "Matrix 15: Reserved"},
    187 
    188      // -- Color range --
    189      // Full range and limited range tested above
    190      {"av01.0.10M.12.0.002.01.13.00.2", false, "Color range 2 invalid"},
    191  };
    192 
    193  for (const auto& data : tests) {
    194    auto info = AOMDecoder::CreateSequenceInfoFromCodecs(
    195        NS_ConvertUTF8toUTF16(data.mCodecParameterString));
    196    nsAutoCString desc = nsAutoCString(data.mCodecParameterString,
    197                                       strlen(data.mCodecParameterString));
    198    desc.AppendLiteral(" (");
    199    desc.Append(data.mComment, strlen(data.mComment));
    200    desc.AppendLiteral(")");
    201    EXPECT_EQ(info.isSome(), data.mExpectedValue) << desc;
    202 
    203    if (info.isSome()) {
    204      AOMDecoder::AV1SequenceInfo inputInfo = info.value();
    205      inputInfo.mImage = gfx::IntSize(1920, 1080);
    206      RefPtr<MediaByteBuffer> buffer = new MediaByteBuffer();
    207      bool wroteSequenceHeader;
    208      AOMDecoder::WriteAV1CBox(inputInfo, buffer, wroteSequenceHeader);
    209      EXPECT_EQ(wroteSequenceHeader, data.mExpectedValue) << desc;
    210      // Read equality test will fail also, don't clutter.
    211      if (!wroteSequenceHeader) {
    212        continue;
    213      }
    214      AOMDecoder::AV1SequenceInfo parsedInfo;
    215      bool readSequenceHeader;
    216      AOMDecoder::ReadAV1CBox(buffer, parsedInfo, readSequenceHeader);
    217      EXPECT_EQ(wroteSequenceHeader, readSequenceHeader) << desc;
    218      EXPECT_EQ(inputInfo, parsedInfo) << desc;
    219    }
    220  }
    221 }
    222 
    223 TEST(ExtractAV1CodecDetails, TestParsingOutput)
    224 {
    225  auto info = AOMDecoder::CreateSequenceInfoFromCodecs(
    226      nsString(u"av01.0.14M.08.0.112.01.01.01.0"));
    227  EXPECT_TRUE(info.isSome());
    228 
    229  if (info.isSome()) {
    230    EXPECT_EQ(info->mProfile, 0u);
    231    EXPECT_EQ(info->mOperatingPoints.Length(), 1u);
    232    EXPECT_EQ(info->mOperatingPoints[0].mLayers, 0u);
    233    EXPECT_EQ(info->mOperatingPoints[0].mLevel, 14u);
    234    EXPECT_EQ(info->mOperatingPoints[0].mTier, 0u);
    235    EXPECT_EQ(info->mBitDepth, 8u);
    236    EXPECT_EQ(info->mMonochrome, false);
    237    EXPECT_EQ(info->mSubsamplingX, true);
    238    EXPECT_EQ(info->mSubsamplingY, true);
    239    EXPECT_EQ(info->mChromaSamplePosition,
    240              AOMDecoder::ChromaSamplePosition::Colocated);
    241    EXPECT_EQ(info->mColorSpace.mPrimaries, gfx::CICP::CP_BT709);
    242    EXPECT_EQ(info->mColorSpace.mTransfer, gfx::CICP::TC_BT709);
    243    EXPECT_EQ(info->mColorSpace.mMatrix, gfx::CICP::MC_BT709);
    244    EXPECT_EQ(info->mColorSpace.mRange, gfx::ColorRange::LIMITED);
    245  }
    246 
    247  info = AOMDecoder::CreateSequenceInfoFromCodecs(
    248      nsString(u"av01.1.11H.10.0.000.07.07.07.1"));
    249  EXPECT_TRUE(info.isSome());
    250 
    251  if (info.isSome()) {
    252    EXPECT_EQ(info->mProfile, 1u);
    253    EXPECT_EQ(info->mOperatingPoints.Length(), 1u);
    254    EXPECT_EQ(info->mOperatingPoints[0].mLayers, 0u);
    255    EXPECT_EQ(info->mOperatingPoints[0].mLevel, 11u);
    256    EXPECT_EQ(info->mOperatingPoints[0].mTier, 1u);
    257    EXPECT_EQ(info->mBitDepth, 10u);
    258    EXPECT_EQ(info->mMonochrome, false);
    259    EXPECT_EQ(info->mSubsamplingX, false);
    260    EXPECT_EQ(info->mSubsamplingY, false);
    261    EXPECT_EQ(info->mChromaSamplePosition,
    262              AOMDecoder::ChromaSamplePosition::Unknown);
    263    EXPECT_EQ(info->mColorSpace.mPrimaries, gfx::CICP::CP_SMPTE240);
    264    EXPECT_EQ(info->mColorSpace.mTransfer, gfx::CICP::TC_SMPTE240);
    265    EXPECT_EQ(info->mColorSpace.mMatrix, gfx::CICP::MC_SMPTE240);
    266    EXPECT_EQ(info->mColorSpace.mRange, gfx::ColorRange::FULL);
    267  }
    268 
    269  info = AOMDecoder::CreateSequenceInfoFromCodecs(
    270      nsString(u"av01.2.22H.12.1.110.10.08.04.1"));
    271  EXPECT_TRUE(info.isSome());
    272 
    273  if (info.isSome()) {
    274    EXPECT_EQ(info->mProfile, 2u);
    275    EXPECT_EQ(info->mOperatingPoints.Length(), 1u);
    276    EXPECT_EQ(info->mOperatingPoints[0].mLayers, 0u);
    277    EXPECT_EQ(info->mOperatingPoints[0].mLevel, 22u);
    278    EXPECT_EQ(info->mOperatingPoints[0].mTier, 1u);
    279    EXPECT_EQ(info->mBitDepth, 12u);
    280    EXPECT_EQ(info->mMonochrome, true);
    281    EXPECT_EQ(info->mSubsamplingX, true);
    282    EXPECT_EQ(info->mSubsamplingY, true);
    283    EXPECT_EQ(info->mChromaSamplePosition,
    284              AOMDecoder::ChromaSamplePosition::Unknown);
    285    EXPECT_EQ(info->mColorSpace.mPrimaries, gfx::CICP::CP_XYZ);
    286    EXPECT_EQ(info->mColorSpace.mTransfer, gfx::CICP::TC_LINEAR);
    287    EXPECT_EQ(info->mColorSpace.mMatrix, gfx::CICP::MC_FCC);
    288    EXPECT_EQ(info->mColorSpace.mRange, gfx::ColorRange::FULL);
    289  }
    290 }