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 }