1 /* Gstreamer
2 * Copyright (C) <2018> Collabora Ltd.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19 #include <gst/check/gstcheck.h>
20 #include <gst/codecparsers/gsth265parser.h>
21
22 unsigned char slice_eos_slice_eob[] = {
23 0x00, 0x00, 0x00, 0x01, 0x26, 0x01, 0xaf, 0x06, 0xb8, 0x63, 0xef, 0x3a,
24 0x7f, 0x3e, 0x53, 0xff, 0xff, 0xf2, 0x4a, 0xef, 0xff, 0xfe, 0x6a, 0x5d,
25 0x60, 0xbc, 0xf8, 0x29, 0xeb, 0x9c, 0x4a, 0xb5, 0xcc, 0x76, 0x30, 0xa0,
26 0x7c, 0xd3, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x19, 0x30,
27 0x00, 0x00, 0x00, 0x01, 0x48, 0x01,
28 0x00, 0x00, 0x00, 0x01, 0x26, 0x01, 0xaf, 0x06, 0xb8, 0x63, 0xef, 0x3a,
29 0x7f, 0x3e, 0x53, 0xff, 0xff, 0xf2, 0x4a, 0xef, 0xff, 0xfe, 0x6a, 0x5d,
30 0x60, 0xbc, 0xf8, 0x29, 0xeb, 0x9c, 0x4a, 0xb5, 0xcc, 0x76, 0x30, 0xa0,
31 0x7c, 0xd3, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x19, 0x30,
32 0x00, 0x00, 0x00, 0x01, 0x4a, 0x01,
33 };
34
35 static const guint8 h265_vps_with_nonzero_max_layer_id[] = {
36 0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01,
37 0xff, 0xff, 0x01, 0x60, 0x00, 0x00, 0x03, 0x00,
38 0xb0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00,
39 0x5d, 0xac, 0x59
40 };
41
GST_START_TEST(test_h265_parse_slice_eos_slice_eob)42 GST_START_TEST (test_h265_parse_slice_eos_slice_eob)
43 {
44 GstH265ParserResult res;
45 GstH265NalUnit nalu;
46 GstH265Parser *const parser = gst_h265_parser_new ();
47 const guint8 *buf = slice_eos_slice_eob;
48 guint n, buf_size = sizeof (slice_eos_slice_eob);
49
50 res = gst_h265_parser_identify_nalu (parser, buf, 0, buf_size, &nalu);
51
52 assert_equals_int (res, GST_H265_PARSER_OK);
53 assert_equals_int (nalu.type, GST_H265_NAL_SLICE_IDR_W_RADL);
54 assert_equals_int (nalu.size, 43);
55
56 n = nalu.offset + nalu.size;
57 buf += n;
58 buf_size -= n;
59
60 res = gst_h265_parser_identify_nalu (parser, buf, 0, buf_size, &nalu);
61
62 assert_equals_int (res, GST_H265_PARSER_OK);
63 assert_equals_int (nalu.type, GST_H265_NAL_EOS);
64 assert_equals_int (nalu.size, 2);
65
66 n = nalu.offset + nalu.size;
67 buf += n;
68 buf_size -= n;
69
70 res = gst_h265_parser_identify_nalu (parser, buf, 0, buf_size, &nalu);
71
72 assert_equals_int (res, GST_H265_PARSER_OK);
73 assert_equals_int (nalu.type, GST_H265_NAL_SLICE_IDR_W_RADL);
74 assert_equals_int (nalu.size, 43);
75
76 n = nalu.offset + nalu.size;
77 buf += n;
78 buf_size -= n;
79
80 res = gst_h265_parser_identify_nalu (parser, buf, 0, buf_size, &nalu);
81
82 assert_equals_int (res, GST_H265_PARSER_OK);
83 assert_equals_int (nalu.type, GST_H265_NAL_EOB);
84 assert_equals_int (nalu.size, 2);
85
86 gst_h265_parser_free (parser);
87 }
88
89 GST_END_TEST;
90
GST_START_TEST(test_h265_parse_slice_6bytes)91 GST_START_TEST (test_h265_parse_slice_6bytes)
92 {
93 GstH265ParserResult res;
94 GstH265NalUnit nalu;
95 GstH265Parser *const parser = gst_h265_parser_new ();
96 const guint8 *buf = slice_eos_slice_eob;
97
98 res = gst_h265_parser_identify_nalu (parser, buf, 0, 6, &nalu);
99
100 assert_equals_int (res, GST_H265_PARSER_NO_NAL_END);
101 assert_equals_int (nalu.type, GST_H265_NAL_SLICE_IDR_W_RADL);
102 assert_equals_int (nalu.size, 2);
103
104 gst_h265_parser_free (parser);
105 }
106
107 GST_END_TEST;
108
GST_START_TEST(test_h265_base_profiles)109 GST_START_TEST (test_h265_base_profiles)
110 {
111 GstH265ProfileTierLevel ptl;
112
113 memset (&ptl, 0, sizeof (ptl));
114
115 ptl.profile_idc = 1;
116 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
117 GST_H265_PROFILE_MAIN);
118 ptl.profile_idc = 2;
119 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
120 GST_H265_PROFILE_MAIN_10);
121 ptl.profile_idc = 3;
122 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
123 GST_H265_PROFILE_MAIN_STILL_PICTURE);
124
125 ptl.profile_idc = 42;
126 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
127 GST_H265_PROFILE_INVALID);
128 }
129
130 GST_END_TEST;
131
GST_START_TEST(test_h265_base_profiles_compat)132 GST_START_TEST (test_h265_base_profiles_compat)
133 {
134 GstH265ProfileTierLevel ptl;
135
136 memset (&ptl, 0, sizeof (ptl));
137
138 ptl.profile_compatibility_flag[1] = 1;
139 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
140 GST_H265_PROFILE_MAIN);
141 ptl.profile_compatibility_flag[1] = 0;
142
143 ptl.profile_compatibility_flag[2] = 1;
144 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
145 GST_H265_PROFILE_MAIN_10);
146 ptl.profile_compatibility_flag[2] = 0;
147
148 ptl.profile_compatibility_flag[3] = 1;
149 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
150 GST_H265_PROFILE_MAIN_STILL_PICTURE);
151 ptl.profile_compatibility_flag[3] = 0;
152
153 ptl.profile_idc = 42;
154 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
155 GST_H265_PROFILE_INVALID);
156 }
157
158 GST_END_TEST;
159
160 static void
set_format_range_fields(GstH265ProfileTierLevel * ptl,guint8 max_12bit_constraint_flag,guint8 max_10bit_constraint_flag,guint8 max_8bit_constraint_flag,guint8 max_422chroma_constraint_flag,guint8 max_420chroma_constraint_flag,guint8 max_monochrome_constraint_flag,guint8 intra_constraint_flag,guint8 one_picture_only_constraint_flag,guint8 lower_bit_rate_constraint_flag)161 set_format_range_fields (GstH265ProfileTierLevel * ptl,
162 guint8 max_12bit_constraint_flag,
163 guint8 max_10bit_constraint_flag,
164 guint8 max_8bit_constraint_flag,
165 guint8 max_422chroma_constraint_flag,
166 guint8 max_420chroma_constraint_flag,
167 guint8 max_monochrome_constraint_flag,
168 guint8 intra_constraint_flag,
169 guint8 one_picture_only_constraint_flag,
170 guint8 lower_bit_rate_constraint_flag)
171 {
172 ptl->max_12bit_constraint_flag = max_12bit_constraint_flag;
173 ptl->max_10bit_constraint_flag = max_10bit_constraint_flag;
174 ptl->max_8bit_constraint_flag = max_8bit_constraint_flag;
175 ptl->max_422chroma_constraint_flag = max_422chroma_constraint_flag;
176 ptl->max_420chroma_constraint_flag = max_420chroma_constraint_flag;
177 ptl->max_monochrome_constraint_flag = max_monochrome_constraint_flag;
178 ptl->intra_constraint_flag = intra_constraint_flag;
179 ptl->one_picture_only_constraint_flag = one_picture_only_constraint_flag;
180 ptl->lower_bit_rate_constraint_flag = lower_bit_rate_constraint_flag;
181 }
182
GST_START_TEST(test_h265_format_range_profiles_exact_match)183 GST_START_TEST (test_h265_format_range_profiles_exact_match)
184 {
185 /* Test all the combinations from Table A.2 */
186 GstH265ProfileTierLevel ptl;
187
188 memset (&ptl, 0, sizeof (ptl));
189 ptl.profile_idc = 4;
190
191 set_format_range_fields (&ptl, 1, 1, 1, 1, 1, 1, 0, 0, 1);
192 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
193 GST_H265_PROFILE_MONOCHROME);
194
195 set_format_range_fields (&ptl, 1, 0, 0, 1, 1, 1, 0, 0, 1);
196 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
197 GST_H265_PROFILE_MONOCHROME_12);
198
199 set_format_range_fields (&ptl, 0, 0, 0, 1, 1, 1, 0, 0, 1);
200 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
201 GST_H265_PROFILE_MONOCHROME_16);
202
203 set_format_range_fields (&ptl, 1, 0, 0, 1, 1, 0, 0, 0, 1);
204 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
205 GST_H265_PROFILE_MAIN_12);
206
207 set_format_range_fields (&ptl, 1, 1, 0, 1, 0, 0, 0, 0, 1);
208 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
209 GST_H265_PROFILE_MAIN_422_10);
210
211 set_format_range_fields (&ptl, 1, 0, 0, 1, 0, 0, 0, 0, 1);
212 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
213 GST_H265_PROFILE_MAIN_422_12);
214
215 set_format_range_fields (&ptl, 1, 1, 1, 0, 0, 0, 0, 0, 1);
216 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
217 GST_H265_PROFILE_MAIN_444);
218
219 set_format_range_fields (&ptl, 1, 1, 0, 0, 0, 0, 0, 0, 1);
220 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
221 GST_H265_PROFILE_MAIN_444_10);
222
223 set_format_range_fields (&ptl, 1, 0, 0, 0, 0, 0, 0, 0, 1);
224 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
225 GST_H265_PROFILE_MAIN_444_12);
226
227 set_format_range_fields (&ptl, 1, 1, 1, 1, 1, 0, 1, 0, 0);
228 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
229 GST_H265_PROFILE_MAIN_INTRA);
230 set_format_range_fields (&ptl, 1, 1, 1, 1, 1, 0, 1, 0, 1);
231 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
232 GST_H265_PROFILE_MAIN_INTRA);
233
234 set_format_range_fields (&ptl, 1, 1, 0, 1, 1, 0, 1, 0, 0);
235 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
236 GST_H265_PROFILE_MAIN_10_INTRA);
237 set_format_range_fields (&ptl, 1, 1, 0, 1, 1, 0, 1, 0, 1);
238 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
239 GST_H265_PROFILE_MAIN_10_INTRA);
240
241 set_format_range_fields (&ptl, 1, 0, 0, 1, 1, 0, 1, 0, 0);
242 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
243 GST_H265_PROFILE_MAIN_12_INTRA);
244 set_format_range_fields (&ptl, 1, 0, 0, 1, 1, 0, 1, 0, 1);
245 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
246 GST_H265_PROFILE_MAIN_12_INTRA);
247
248 set_format_range_fields (&ptl, 1, 1, 0, 1, 0, 0, 1, 0, 0);
249 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
250 GST_H265_PROFILE_MAIN_422_10_INTRA);
251 set_format_range_fields (&ptl, 1, 1, 0, 1, 0, 0, 1, 0, 1);
252 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
253 GST_H265_PROFILE_MAIN_422_10_INTRA);
254
255 set_format_range_fields (&ptl, 1, 0, 0, 1, 0, 0, 1, 0, 0);
256 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
257 GST_H265_PROFILE_MAIN_422_12_INTRA);
258 set_format_range_fields (&ptl, 1, 0, 0, 1, 0, 0, 1, 0, 1);
259 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
260 GST_H265_PROFILE_MAIN_422_12_INTRA);
261
262 set_format_range_fields (&ptl, 1, 1, 1, 0, 0, 0, 1, 0, 0);
263 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
264 GST_H265_PROFILE_MAIN_444_INTRA);
265 set_format_range_fields (&ptl, 1, 1, 1, 0, 0, 0, 1, 0, 1);
266 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
267 GST_H265_PROFILE_MAIN_444_INTRA);
268
269 set_format_range_fields (&ptl, 1, 1, 0, 0, 0, 0, 1, 0, 0);
270 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
271 GST_H265_PROFILE_MAIN_444_10_INTRA);
272 set_format_range_fields (&ptl, 1, 1, 0, 0, 0, 0, 1, 0, 1);
273 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
274 GST_H265_PROFILE_MAIN_444_10_INTRA);
275
276 set_format_range_fields (&ptl, 1, 0, 0, 0, 0, 0, 1, 0, 0);
277 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
278 GST_H265_PROFILE_MAIN_444_12_INTRA);
279 set_format_range_fields (&ptl, 1, 0, 0, 0, 0, 0, 1, 0, 1);
280 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
281 GST_H265_PROFILE_MAIN_444_12_INTRA);
282
283 set_format_range_fields (&ptl, 0, 0, 0, 0, 0, 0, 1, 0, 0);
284 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
285 GST_H265_PROFILE_MAIN_444_16_INTRA);
286 set_format_range_fields (&ptl, 0, 0, 0, 0, 0, 0, 1, 0, 1);
287 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
288 GST_H265_PROFILE_MAIN_444_16_INTRA);
289
290 set_format_range_fields (&ptl, 1, 1, 1, 0, 0, 0, 1, 1, 0);
291 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
292 GST_H265_PROFILE_MAIN_444_STILL_PICTURE);
293 set_format_range_fields (&ptl, 1, 1, 1, 0, 0, 0, 1, 1, 1);
294 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
295 GST_H265_PROFILE_MAIN_444_STILL_PICTURE);
296
297 set_format_range_fields (&ptl, 0, 0, 0, 0, 0, 0, 1, 1, 0);
298 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
299 GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE);
300 set_format_range_fields (&ptl, 0, 0, 0, 0, 0, 0, 1, 1, 1);
301 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
302 GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE);
303 }
304
305 GST_END_TEST;
306
GST_START_TEST(test_h265_format_range_profiles_partial_match)307 GST_START_TEST (test_h265_format_range_profiles_partial_match)
308 {
309 /* Test matching compatible profiles from non-standard bitstream */
310 GstH265ProfileTierLevel ptl;
311
312 memset (&ptl, 0, sizeof (ptl));
313 ptl.profile_idc = 4;
314
315 set_format_range_fields (&ptl, 1, 1, 1, 1, 0, 0, 0, 0, 1);
316 g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
317 GST_H265_PROFILE_MAIN_444);
318 }
319
320 GST_END_TEST;
321
GST_START_TEST(test_h265_parse_vps)322 GST_START_TEST (test_h265_parse_vps)
323 {
324 /* Parsing non-zero vps_max_layer_id in VPS
325 * https://bugzilla.gnome.org/show_bug.cgi?id=797279 */
326 GstH265Parser *parser;
327 GstH265NalUnit nalu;
328 GstH265ParserResult res;
329 GstH265VPS vps;
330 GstH265Profile profile;
331
332 parser = gst_h265_parser_new ();
333
334 res = gst_h265_parser_identify_nalu_unchecked (parser,
335 h265_vps_with_nonzero_max_layer_id, 0,
336 sizeof (h265_vps_with_nonzero_max_layer_id), &nalu);
337
338 assert_equals_int (res, GST_H265_PARSER_OK);
339 assert_equals_int (nalu.type, GST_H265_NAL_VPS);
340
341 res = gst_h265_parser_parse_vps (parser, &nalu, &vps);
342 assert_equals_int (res, GST_H265_PARSER_OK);
343
344 assert_equals_int (vps.id, 0);
345 assert_equals_int (vps.max_layers_minus1, 0);
346 assert_equals_int (vps.max_sub_layers_minus1, 0);
347 assert_equals_int (vps.temporal_id_nesting_flag, 1);
348
349 profile = gst_h265_profile_tier_level_get_profile (&vps.profile_tier_level);
350
351 assert_equals_int (profile, GST_H265_PROFILE_MAIN);
352 assert_equals_int (vps.sub_layer_ordering_info_present_flag, 1);
353
354 assert_equals_int (vps.max_dec_pic_buffering_minus1[0], 1);
355 assert_equals_int (vps.max_num_reorder_pics[0], 0);
356 assert_equals_int (vps.max_latency_increase_plus1[0], 0);
357
358 assert_equals_int (vps.max_layer_id, 5);
359 assert_equals_int (vps.num_layer_sets_minus1, 0);
360
361 assert_equals_int (vps.timing_info_present_flag, 0);
362 assert_equals_int (vps.vps_extension, 0);
363
364 gst_h265_parser_free (parser);
365 }
366
367 GST_END_TEST;
368
369 static Suite *
h265parser_suite(void)370 h265parser_suite (void)
371 {
372 Suite *s = suite_create ("H265 Parser library");
373
374 TCase *tc_chain = tcase_create ("general");
375
376 suite_add_tcase (s, tc_chain);
377 tcase_add_test (tc_chain, test_h265_parse_slice_eos_slice_eob);
378 tcase_add_test (tc_chain, test_h265_parse_slice_6bytes);
379 tcase_add_test (tc_chain, test_h265_base_profiles);
380 tcase_add_test (tc_chain, test_h265_base_profiles_compat);
381 tcase_add_test (tc_chain, test_h265_format_range_profiles_exact_match);
382 tcase_add_test (tc_chain, test_h265_format_range_profiles_partial_match);
383 tcase_add_test (tc_chain, test_h265_parse_vps);
384
385 return s;
386 }
387
388 GST_CHECK_MAIN (h265parser);
389