1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci#include "libavutil/common.h" 20cabdff1aSopenharmony_ci#include "libavcodec/h265_profile_level.h" 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_cistatic const struct { 23cabdff1aSopenharmony_ci int width; 24cabdff1aSopenharmony_ci int height; 25cabdff1aSopenharmony_ci int level_idc; 26cabdff1aSopenharmony_ci} test_sizes[] = { 27cabdff1aSopenharmony_ci // First level usable at standard sizes, from H.265 table A.9. 28cabdff1aSopenharmony_ci { 176, 144, 30 }, // QCIF 29cabdff1aSopenharmony_ci { 352, 288, 60 }, // CIF 30cabdff1aSopenharmony_ci { 640, 480, 90 }, // VGA 31cabdff1aSopenharmony_ci { 720, 480, 90 }, // NTSC 32cabdff1aSopenharmony_ci { 720, 576, 90 }, // PAL 33cabdff1aSopenharmony_ci { 1024, 768, 93 }, // XGA 34cabdff1aSopenharmony_ci { 1280, 720, 93 }, // 720p 35cabdff1aSopenharmony_ci { 1280, 1024, 120 }, // SXGA 36cabdff1aSopenharmony_ci { 1920, 1080, 120 }, // 1080p 37cabdff1aSopenharmony_ci { 2048, 1080, 120 }, // 2Kx1080 38cabdff1aSopenharmony_ci { 2048, 1536, 150 }, // 4XGA 39cabdff1aSopenharmony_ci { 3840, 2160, 150 }, // 4K 40cabdff1aSopenharmony_ci { 7680, 4320, 180 }, // 8K 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_ci // Overly wide or tall sizes. 43cabdff1aSopenharmony_ci { 1, 512, 30 }, 44cabdff1aSopenharmony_ci { 1, 1024, 63 }, 45cabdff1aSopenharmony_ci { 1, 2048, 90 }, 46cabdff1aSopenharmony_ci { 1, 4096, 120 }, 47cabdff1aSopenharmony_ci { 1, 8192, 150 }, 48cabdff1aSopenharmony_ci { 1, 16384, 180 }, 49cabdff1aSopenharmony_ci { 1, 32768, 0 }, 50cabdff1aSopenharmony_ci { 512, 1, 30 }, 51cabdff1aSopenharmony_ci { 1024, 1, 63 }, 52cabdff1aSopenharmony_ci { 2048, 1, 90 }, 53cabdff1aSopenharmony_ci { 4096, 1, 120 }, 54cabdff1aSopenharmony_ci { 8192, 1, 150 }, 55cabdff1aSopenharmony_ci { 16384, 1, 180 }, 56cabdff1aSopenharmony_ci { 32768, 1, 0 }, 57cabdff1aSopenharmony_ci { 2800, 256, 93 }, 58cabdff1aSopenharmony_ci { 2816, 128, 120 }, 59cabdff1aSopenharmony_ci { 256, 4208, 120 }, 60cabdff1aSopenharmony_ci { 128, 4224, 150 }, 61cabdff1aSopenharmony_ci { 8432, 256, 150 }, 62cabdff1aSopenharmony_ci { 8448, 128, 180 }, 63cabdff1aSopenharmony_ci { 256, 16880, 180 }, 64cabdff1aSopenharmony_ci { 128, 16896, 0 }, 65cabdff1aSopenharmony_ci}; 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_cistatic const struct { 68cabdff1aSopenharmony_ci int width; 69cabdff1aSopenharmony_ci int height; 70cabdff1aSopenharmony_ci int dpb_size; 71cabdff1aSopenharmony_ci int level_idc; 72cabdff1aSopenharmony_ci} test_dpb[] = { 73cabdff1aSopenharmony_ci // First level usable for some DPB sizes. 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_ci // L1: 176 * 144 = 25344 <= 36864 * 3/4 = 27648 76cabdff1aSopenharmony_ci // L2: <= 122880 * 1/4 = 30720 77cabdff1aSopenharmony_ci { 176, 144, 8, 30 }, 78cabdff1aSopenharmony_ci { 176, 144, 9, 60 }, 79cabdff1aSopenharmony_ci 80cabdff1aSopenharmony_ci // L2: 352 * 288 = 101376 <= 122880 81cabdff1aSopenharmony_ci // L2.1: <= 245760 * 1/2 = 122880 82cabdff1aSopenharmony_ci // L3: <= 552960 * 1/4 = 138240 83cabdff1aSopenharmony_ci { 352, 288, 6, 60 }, 84cabdff1aSopenharmony_ci { 352, 288, 7, 63 }, 85cabdff1aSopenharmony_ci { 352, 288, 13, 90 }, 86cabdff1aSopenharmony_ci 87cabdff1aSopenharmony_ci // L3.1: 1280 * 720 = 921600 <= 983040 88cabdff1aSopenharmony_ci // L4: <= 2228224 * 1/2 = 1114112 89cabdff1aSopenharmony_ci // L5: <= 8912896 * 1/4 = 2228224 90cabdff1aSopenharmony_ci { 1280, 720, 6, 93 }, 91cabdff1aSopenharmony_ci { 1280, 720, 12, 120 }, 92cabdff1aSopenharmony_ci { 1280, 720, 16, 150 }, 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_ci // L5: 3840 * 2160 = 8294400 <= 8912896 95cabdff1aSopenharmony_ci // L6: <= 35651584 * 1/4 = 8912896 96cabdff1aSopenharmony_ci { 3840, 2160, 6, 150 }, 97cabdff1aSopenharmony_ci { 3840, 2160, 7, 180 }, 98cabdff1aSopenharmony_ci { 3840, 2160, 16, 180 }, 99cabdff1aSopenharmony_ci}; 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_cistatic const H265RawProfileTierLevel profile_main = { 102cabdff1aSopenharmony_ci // CpbNalFactor = 1100 103cabdff1aSopenharmony_ci .general_profile_space = 0, 104cabdff1aSopenharmony_ci .general_profile_idc = 1, 105cabdff1aSopenharmony_ci .general_tier_flag = 0, 106cabdff1aSopenharmony_ci .general_profile_compatibility_flag[1] = 1, 107cabdff1aSopenharmony_ci}; 108cabdff1aSopenharmony_ci 109cabdff1aSopenharmony_cistatic const H265RawProfileTierLevel profile_main_12 = { 110cabdff1aSopenharmony_ci // CpbNalFactor = 1650 111cabdff1aSopenharmony_ci .general_profile_space = 0, 112cabdff1aSopenharmony_ci .general_profile_idc = 4, 113cabdff1aSopenharmony_ci .general_tier_flag = 0, 114cabdff1aSopenharmony_ci .general_profile_compatibility_flag[4] = 1, 115cabdff1aSopenharmony_ci .general_max_12bit_constraint_flag = 1, 116cabdff1aSopenharmony_ci .general_max_10bit_constraint_flag = 0, 117cabdff1aSopenharmony_ci .general_max_8bit_constraint_flag = 0, 118cabdff1aSopenharmony_ci .general_max_422chroma_constraint_flag = 1, 119cabdff1aSopenharmony_ci .general_max_420chroma_constraint_flag = 1, 120cabdff1aSopenharmony_ci .general_max_monochrome_constraint_flag = 0, 121cabdff1aSopenharmony_ci .general_intra_constraint_flag = 0, 122cabdff1aSopenharmony_ci .general_one_picture_only_constraint_flag = 0, 123cabdff1aSopenharmony_ci .general_lower_bit_rate_constraint_flag = 1, 124cabdff1aSopenharmony_ci}; 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_cistatic const H265RawProfileTierLevel profile_main_422_12_intra = { 127cabdff1aSopenharmony_ci // CpbNalFactor = 2200 128cabdff1aSopenharmony_ci .general_profile_space = 0, 129cabdff1aSopenharmony_ci .general_profile_idc = 4, 130cabdff1aSopenharmony_ci .general_tier_flag = 0, 131cabdff1aSopenharmony_ci .general_profile_compatibility_flag[4] = 1, 132cabdff1aSopenharmony_ci .general_max_12bit_constraint_flag = 1, 133cabdff1aSopenharmony_ci .general_max_10bit_constraint_flag = 0, 134cabdff1aSopenharmony_ci .general_max_8bit_constraint_flag = 0, 135cabdff1aSopenharmony_ci .general_max_422chroma_constraint_flag = 1, 136cabdff1aSopenharmony_ci .general_max_420chroma_constraint_flag = 0, 137cabdff1aSopenharmony_ci .general_max_monochrome_constraint_flag = 0, 138cabdff1aSopenharmony_ci .general_intra_constraint_flag = 1, 139cabdff1aSopenharmony_ci .general_one_picture_only_constraint_flag = 0, 140cabdff1aSopenharmony_ci}; 141cabdff1aSopenharmony_ci 142cabdff1aSopenharmony_cistatic const H265RawProfileTierLevel profile_ht_444_14 = { 143cabdff1aSopenharmony_ci // CpbNalFactor = 3850 144cabdff1aSopenharmony_ci .general_profile_space = 0, 145cabdff1aSopenharmony_ci .general_profile_idc = 5, 146cabdff1aSopenharmony_ci .general_tier_flag = 0, 147cabdff1aSopenharmony_ci .general_profile_compatibility_flag[5] = 1, 148cabdff1aSopenharmony_ci .general_max_14bit_constraint_flag = 1, 149cabdff1aSopenharmony_ci .general_max_12bit_constraint_flag = 0, 150cabdff1aSopenharmony_ci .general_max_10bit_constraint_flag = 0, 151cabdff1aSopenharmony_ci .general_max_8bit_constraint_flag = 0, 152cabdff1aSopenharmony_ci .general_max_422chroma_constraint_flag = 0, 153cabdff1aSopenharmony_ci .general_max_420chroma_constraint_flag = 0, 154cabdff1aSopenharmony_ci .general_max_monochrome_constraint_flag = 0, 155cabdff1aSopenharmony_ci .general_intra_constraint_flag = 0, 156cabdff1aSopenharmony_ci .general_one_picture_only_constraint_flag = 0, 157cabdff1aSopenharmony_ci .general_lower_bit_rate_constraint_flag = 1, 158cabdff1aSopenharmony_ci}; 159cabdff1aSopenharmony_ci 160cabdff1aSopenharmony_cistatic const H265RawProfileTierLevel profile_main_high_tier = { 161cabdff1aSopenharmony_ci // CpbNalFactor = 1100 162cabdff1aSopenharmony_ci .general_profile_space = 0, 163cabdff1aSopenharmony_ci .general_profile_idc = 1, 164cabdff1aSopenharmony_ci .general_tier_flag = 1, 165cabdff1aSopenharmony_ci .general_profile_compatibility_flag[1] = 1, 166cabdff1aSopenharmony_ci}; 167cabdff1aSopenharmony_ci 168cabdff1aSopenharmony_cistatic const struct { 169cabdff1aSopenharmony_ci int64_t bitrate; 170cabdff1aSopenharmony_ci const H265RawProfileTierLevel *ptl; 171cabdff1aSopenharmony_ci int level_idc; 172cabdff1aSopenharmony_ci} test_bitrate[] = { 173cabdff1aSopenharmony_ci // First level usable for some bitrates and profiles. 174cabdff1aSopenharmony_ci 175cabdff1aSopenharmony_ci // L2.1: 3000 * 1100 = 3300000 176cabdff1aSopenharmony_ci // L3: 6000 * 1100 = 6600000 177cabdff1aSopenharmony_ci { 4000000, &profile_main, 90 }, 178cabdff1aSopenharmony_ci // L2: 1500 * 1650 = 2475000 179cabdff1aSopenharmony_ci // L2.1: 3000 * 1650 = 4950000 180cabdff1aSopenharmony_ci { 4000000, &profile_main_12, 63 }, 181cabdff1aSopenharmony_ci // L1: 350 * 2200 * 2 = 1540000 182cabdff1aSopenharmony_ci // L2: 1500 * 2200 * 2 = 6600000 183cabdff1aSopenharmony_ci { 4000000, &profile_main_422_12_intra, 60 }, 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_ci // L5.1: 40000 * 1100 = 44000000 186cabdff1aSopenharmony_ci // L5.2: 60000 * 1100 = 66000000 187cabdff1aSopenharmony_ci { 50000000, &profile_main, 156 }, 188cabdff1aSopenharmony_ci // L5: 25000 * 1650 = 41250000 189cabdff1aSopenharmony_ci // L5.1: 40000 * 1650 = 66000000 190cabdff1aSopenharmony_ci { 50000000, &profile_main_12, 153 }, 191cabdff1aSopenharmony_ci // L3.1: 10000 * 2200 * 2 = 44000000 192cabdff1aSopenharmony_ci // L4: 12000 * 2200 * 2 = 52800000 193cabdff1aSopenharmony_ci { 50000000, &profile_main_422_12_intra, 120 }, 194cabdff1aSopenharmony_ci // L2: 1500 * 3850 * 6 = 34650000 195cabdff1aSopenharmony_ci // L2.1: 3000 * 3850 * 6 = 69300000 196cabdff1aSopenharmony_ci { 50000000, &profile_ht_444_14, 63 }, 197cabdff1aSopenharmony_ci 198cabdff1aSopenharmony_ci // Level changes based on tier. 199cabdff1aSopenharmony_ci { 1000, &profile_main, 30 }, 200cabdff1aSopenharmony_ci { 1000, &profile_main_high_tier, 120 }, 201cabdff1aSopenharmony_ci { 40000000, &profile_main, 153 }, 202cabdff1aSopenharmony_ci { 40000000, &profile_main_high_tier, 123 }, 203cabdff1aSopenharmony_ci { 200000000, &profile_main, 186 }, 204cabdff1aSopenharmony_ci { 200000000, &profile_main_high_tier, 156 }, 205cabdff1aSopenharmony_ci 206cabdff1aSopenharmony_ci // Overflowing 32-bit integers. 207cabdff1aSopenharmony_ci // L6: 60000 * 3850 * 6 = 1386000000 208cabdff1aSopenharmony_ci // L6.1: 120000 * 3850 * 6 = 2772000000 209cabdff1aSopenharmony_ci // L6.2: 240000 * 3850 * 6 = 5544000000 210cabdff1aSopenharmony_ci { INT64_C(2700000000), &profile_ht_444_14, 183 }, 211cabdff1aSopenharmony_ci { INT64_C(4200000000), &profile_ht_444_14, 186 }, 212cabdff1aSopenharmony_ci { INT64_C(5600000000), &profile_ht_444_14, 0 }, 213cabdff1aSopenharmony_ci}; 214cabdff1aSopenharmony_ci 215cabdff1aSopenharmony_cistatic const struct { 216cabdff1aSopenharmony_ci int slice_segments; 217cabdff1aSopenharmony_ci int tile_rows; 218cabdff1aSopenharmony_ci int tile_cols; 219cabdff1aSopenharmony_ci int level_idc; 220cabdff1aSopenharmony_ci} test_fragments[] = { 221cabdff1aSopenharmony_ci // Slices. 222cabdff1aSopenharmony_ci { 4, 1, 1, 30 }, 223cabdff1aSopenharmony_ci { 32, 1, 1, 93 }, 224cabdff1aSopenharmony_ci { 70, 1, 1, 120 }, 225cabdff1aSopenharmony_ci { 80, 1, 1, 150 }, 226cabdff1aSopenharmony_ci { 201, 1, 1, 180 }, 227cabdff1aSopenharmony_ci { 600, 1, 1, 180 }, 228cabdff1aSopenharmony_ci { 601, 1, 1, 0 }, 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci // Tiles. 231cabdff1aSopenharmony_ci { 1, 2, 1, 90 }, 232cabdff1aSopenharmony_ci { 1, 1, 2, 90 }, 233cabdff1aSopenharmony_ci { 1, 3, 3, 93 }, 234cabdff1aSopenharmony_ci { 1, 4, 2, 120 }, 235cabdff1aSopenharmony_ci { 1, 2, 4, 120 }, 236cabdff1aSopenharmony_ci { 1, 11, 10, 150 }, 237cabdff1aSopenharmony_ci { 1, 10, 11, 180 }, 238cabdff1aSopenharmony_ci { 1, 22, 20, 180 }, 239cabdff1aSopenharmony_ci { 1, 20, 22, 0 }, 240cabdff1aSopenharmony_ci}; 241cabdff1aSopenharmony_ci 242cabdff1aSopenharmony_ciint main(void) 243cabdff1aSopenharmony_ci{ 244cabdff1aSopenharmony_ci const H265ProfileDescriptor *profile; 245cabdff1aSopenharmony_ci const H265LevelDescriptor *level; 246cabdff1aSopenharmony_ci int i; 247cabdff1aSopenharmony_ci 248cabdff1aSopenharmony_ci#define CHECK(expected, format, ...) do { \ 249cabdff1aSopenharmony_ci if (expected ? (!level || level->level_idc != expected) \ 250cabdff1aSopenharmony_ci : !!level) { \ 251cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Incorrect level for " \ 252cabdff1aSopenharmony_ci format ": expected %d, got %d.\n", __VA_ARGS__, \ 253cabdff1aSopenharmony_ci expected, level ? level->level_idc : -1); \ 254cabdff1aSopenharmony_ci return 1; \ 255cabdff1aSopenharmony_ci } \ 256cabdff1aSopenharmony_ci } while (0) 257cabdff1aSopenharmony_ci 258cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(test_sizes); i++) { 259cabdff1aSopenharmony_ci level = ff_h265_guess_level(&profile_main, 0, 260cabdff1aSopenharmony_ci test_sizes[i].width, 261cabdff1aSopenharmony_ci test_sizes[i].height, 262cabdff1aSopenharmony_ci 0, 0, 0, 0); 263cabdff1aSopenharmony_ci CHECK(test_sizes[i].level_idc, "size %dx%d", 264cabdff1aSopenharmony_ci test_sizes[i].width, test_sizes[i].height); 265cabdff1aSopenharmony_ci } 266cabdff1aSopenharmony_ci 267cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(test_dpb); i++) { 268cabdff1aSopenharmony_ci level = ff_h265_guess_level(&profile_main, 0, 269cabdff1aSopenharmony_ci test_dpb[i].width, 270cabdff1aSopenharmony_ci test_dpb[i].height, 271cabdff1aSopenharmony_ci 0, 0, 0, test_dpb[i].dpb_size); 272cabdff1aSopenharmony_ci CHECK(test_dpb[i].level_idc, "size %dx%d dpb %d", 273cabdff1aSopenharmony_ci test_dpb[i].width, test_dpb[i].height, 274cabdff1aSopenharmony_ci test_dpb[i].dpb_size); 275cabdff1aSopenharmony_ci } 276cabdff1aSopenharmony_ci 277cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(test_bitrate); i++) { 278cabdff1aSopenharmony_ci profile = ff_h265_get_profile(test_bitrate[i].ptl); 279cabdff1aSopenharmony_ci level = ff_h265_guess_level(test_bitrate[i].ptl, 280cabdff1aSopenharmony_ci test_bitrate[i].bitrate, 281cabdff1aSopenharmony_ci 0, 0, 0, 0, 0, 0); 282cabdff1aSopenharmony_ci CHECK(test_bitrate[i].level_idc, "bitrate %"PRId64" profile %s", 283cabdff1aSopenharmony_ci test_bitrate[i].bitrate, profile->name); 284cabdff1aSopenharmony_ci } 285cabdff1aSopenharmony_ci 286cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(test_fragments); i++) { 287cabdff1aSopenharmony_ci level = ff_h265_guess_level(&profile_main, 0, 0, 0, 288cabdff1aSopenharmony_ci test_fragments[i].slice_segments, 289cabdff1aSopenharmony_ci test_fragments[i].tile_rows, 290cabdff1aSopenharmony_ci test_fragments[i].tile_cols, 0); 291cabdff1aSopenharmony_ci CHECK(test_fragments[i].level_idc, "%d slices %dx%d tiles", 292cabdff1aSopenharmony_ci test_fragments[i].slice_segments, 293cabdff1aSopenharmony_ci test_fragments[i].tile_cols, test_fragments[i].tile_rows); 294cabdff1aSopenharmony_ci } 295cabdff1aSopenharmony_ci 296cabdff1aSopenharmony_ci return 0; 297cabdff1aSopenharmony_ci} 298