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