1 /*
2 * GStreamer
3 *
4 * unit test for h265parse
5 *
6 * Copyright (C) 2019 Stéphane Cerveau <scerveau@collabora.com>
7 * Copyright (C) 2019 Collabora Ltd.
8 * @author George Kiagiadakis <george.kiagiadakis@collabora.com>
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the
22 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
24 */
25
26 #include <gst/check/check.h>
27 #include "parser.h"
28
29 #define SRC_CAPS_TMPL "video/x-h265, parsed=(boolean)false"
30 #define SINK_CAPS_TMPL "video/x-h265, parsed=(boolean)true"
31
32 GstStaticPadTemplate sinktemplate_bs_au = GST_STATIC_PAD_TEMPLATE ("sink",
33 GST_PAD_SINK,
34 GST_PAD_ALWAYS,
35 GST_STATIC_CAPS (SINK_CAPS_TMPL
36 ", stream-format = (string) byte-stream, alignment = (string) au")
37 );
38
39 GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
40 GST_PAD_SRC,
41 GST_PAD_ALWAYS,
42 GST_STATIC_CAPS (SRC_CAPS_TMPL)
43 );
44
45 /* Data generated with:
46 *
47 * gst-launch-1.0 videotestsrc num-buffers=1 ! video/x-raw,width=16,height=16 ! x265enc option-string="max-cll=1000,400:master-display=G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,1)" ! h265parse ! fakesink
48 *
49 * x265enc SEI has been dropped.
50 *
51 */
52
53 static const guint8 h265_vps[] = {
54 0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x01, 0x60, 0x00,
55 0x00, 0x03, 0x00, 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x3f, 0x95,
56 0x98, 0x09
57 };
58
59 static const guint8 h265_sps[] = {
60 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x01, 0x60, 0x00, 0x00, 0x03, 0x00,
61 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x3f, 0xa0, 0x88, 0x45, 0x96,
62 0x56, 0x6a, 0xbc, 0xaf, 0xff, 0x00, 0x01, 0x00, 0x01, 0x6a, 0x0c, 0x02, 0x0c,
63 0x08, 0x00, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0xf0, 0x40
64 };
65
66 static const guint8 h265_pps[] = {
67 0x00, 0x00, 0x00, 0x01, 0x44, 0x01, 0xc1, 0x73, 0xd0, 0x89
68 };
69
70 static const guint8 h265_idr[] = {
71 0x00, 0x00, 0x00, 0x01, 0x26, 0x01, 0xaf, 0x06, 0xb8, 0xcf, 0xbc, 0x65, 0x85,
72 0x3b, 0x49, 0xff, 0xd0, 0x2c, 0xff, 0x3b, 0x61, 0x6d, 0x1b, 0xae, 0xf1, 0xf4,
73 0x96, 0x15, 0xef, 0x3e, 0xc6, 0x67, 0x3c, 0x0a, 0xd0, 0x6a, 0xb9, 0xfb, 0xf8,
74 0xb4, 0xb8, 0x4a, 0x4c, 0x4e, 0xe2, 0xf6, 0xb0, 0x29, 0x41, 0x4e, 0x14, 0xe8,
75 0x1f, 0x41, 0x58, 0xcb, 0x7a, 0x94, 0xdc, 0xba, 0x3d, 0x2e, 0xe0, 0x83, 0x4d,
76 0x3c, 0x3d, 0x2d, 0x70, 0xd1, 0xc4, 0x3d, 0x65, 0xf8, 0x3a, 0xe3, 0xdf, 0xb1,
77 0xf1, 0x1c, 0x48, 0x45, 0x63, 0x5b, 0x55, 0x0e, 0x0d, 0xef, 0xfc, 0x07, 0xd3,
78 0xce, 0x14, 0xc2, 0xac, 0x79, 0xd6, 0x1c, 0x44, 0x2c, 0xbd, 0x00, 0xff, 0xe5,
79 0x0c, 0x09, 0x3a, 0x3b, 0x53, 0xa8, 0x58, 0xb5, 0xb0, 0x29, 0xe6, 0x64, 0x14,
80 0x3a, 0xec, 0x8c, 0x7d, 0xd9, 0x19, 0xb4, 0xc2, 0x75, 0x37, 0xa2, 0x64, 0xa3,
81 0x1f, 0x26, 0x78, 0xe0, 0xa4, 0xde, 0xed, 0xb1, 0x52, 0x67, 0x90, 0xf1, 0x8e,
82 0xf9, 0x99, 0xa8, 0x9e, 0xfa, 0x55, 0xfc, 0x92, 0x3d, 0xd1, 0x03, 0xff, 0xff,
83 0xf7, 0x79, 0xaf, 0xa5, 0x90, 0x72, 0x35, 0x4e, 0x64, 0x16, 0x48, 0xa8, 0x28,
84 0xc4, 0xcf, 0x51, 0x83, 0x78, 0x6d, 0x90, 0x3a, 0xdf, 0xff, 0xb1, 0x1b, 0xb4,
85 0x3e, 0xa5, 0xd3, 0xc9, 0x2b, 0x75, 0x16, 0x01, 0x16, 0xa6, 0xc5, 0x1d, 0x1e,
86 0xd6, 0x63, 0x0c, 0xba, 0x2f, 0x77, 0x58, 0x5a, 0x4c, 0xb6, 0x49, 0x63, 0xb4,
87 0xa5, 0xb3, 0x25, 0x1b, 0xfd, 0xea, 0x13, 0x8b, 0xb3, 0x8f, 0x42, 0x81, 0xa1,
88 0x89, 0xe1, 0x36, 0x80, 0x11, 0x3c, 0x88, 0x84, 0x29, 0x51, 0x59, 0x2c, 0xb2,
89 0x9c, 0x90, 0xa5, 0x12, 0x80, 0x2d, 0x16, 0x61, 0x8e, 0xf1, 0x28, 0xba, 0x0f,
90 0x71, 0xdf, 0x7b, 0xdb, 0xd7, 0xb0, 0x3d, 0xa1, 0xbe, 0x4f, 0x7c, 0xcf, 0x09,
91 0x73, 0xe1, 0x10, 0xea, 0x64, 0x96, 0x89, 0x5d, 0x7e, 0x7f, 0x26, 0x18, 0x43,
92 0xbb, 0x0d, 0x2c, 0x95, 0xaa, 0xec, 0x03, 0x9d, 0x55, 0x56, 0xdf, 0xd3, 0x7e,
93 0x4f, 0xf7, 0x47, 0x60, 0x89, 0x35, 0x6e, 0x08, 0x9a, 0xcf, 0x11, 0x26, 0xc3,
94 0xec, 0x31, 0x23, 0xca, 0x51, 0x10, 0x80
95 };
96
97 /* Content light level information SEI message */
98 static const guint8 h265_sei_clli[] = {
99 0x00, 0x00, 0x00, 0x01, 0x4e, 0x01, 0x90, 0x04, 0x03, 0xe8, 0x01, 0x90, 0x80
100 };
101
102 /* Mastering display colour volume information SEI message */
103 static const guint8 h265_sei_mdcv[] = {
104 0x00, 0x00, 0x00, 0x01, 0x4e, 0x01, 0x89, 0x18, 0x33, 0xc2, 0x86, 0xc4, 0x1d,
105 0x4c, 0x0b, 0xb8, 0x84, 0xd0, 0x3e, 0x80, 0x3d, 0x13, 0x40, 0x42, 0x00, 0x98,
106 0x96, 0x80, 0x00, 0x00, 0x03, 0x00, 0x01, 0x80
107 };
108
109
110 /* single-sliced data, generated with:
111 * gst-launch-1.0 videotestsrc num-buffers=1 pattern=green \
112 * ! video/x-raw,width=128,height=128 \
113 * ! x265enc
114 * ! fakesink dump=1
115 */
116
117 static const guint8 h265_128x128_vps[] = {
118 0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01,
119 0xff, 0xff, 0x01, 0x60, 0x00, 0x00, 0x03, 0x00,
120 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00,
121 0x3f, 0x95, 0x98, 0x09
122 };
123
124 static const guint8 h265_128x128_sps[] = {
125 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x01,
126 0x60, 0x00, 0x00, 0x03, 0x00, 0x90, 0x00, 0x00,
127 0x03, 0x00, 0x00, 0x03, 0x00, 0x3f, 0xa0, 0x10,
128 0x20, 0x20, 0x59, 0x65, 0x66, 0x92, 0x4c, 0xaf,
129 0xff, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00,
130 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x1e,
131 0x08
132 };
133
134 static const guint8 h265_128x128_pps[] = {
135 0x00, 0x00, 0x00, 0x01, 0x44, 0x01, 0xc1, 0x72,
136 0xb4, 0x22, 0x40
137 };
138
139 static const guint8 h265_128x128_slice_idr_n_lp[] = {
140 0x00, 0x00, 0x00, 0x01, 0x28, 0x01, 0xaf, 0x0e,
141 0xe0, 0x34, 0x82, 0x15, 0x84, 0xf4, 0x70, 0x4f,
142 0xff, 0xed, 0x41, 0x3f, 0xff, 0xe4, 0xcd, 0xc4,
143 0x7c, 0x03, 0x0c, 0xc2, 0xbb, 0xb0, 0x74, 0xe5,
144 0xef, 0x4f, 0xe1, 0xa3, 0xd4, 0x00, 0x02, 0xc2
145 };
146
147 /* multi-sliced data, generated on zynqultrascaleplus with:
148 * gst-launch-1.0 videotestsrc num-buffers=1 pattern=green \
149 * ! video/x-raw,width=128,height=128 \
150 * ! omxh265enc num-slices=2 \
151 * ! fakesink dump=1
152 */
153
154 static const guint8 h265_128x128_sliced_vps[] = {
155 0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01,
156 0xff, 0xff, 0x01, 0x40, 0x00, 0x00, 0x03, 0x00,
157 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00,
158 0x1e, 0x25, 0x02, 0x40
159 };
160
161 static const guint8 h265_128x128_sliced_sps[] = {
162 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x01,
163 0x40, 0x00, 0x00, 0x03, 0x00, 0x90, 0x00, 0x00,
164 0x03, 0x00, 0x00, 0x03, 0x00, 0x1e, 0xa0, 0x10,
165 0x20, 0x20, 0x59, 0xe9, 0x6e, 0x44, 0xa1, 0x73,
166 0x50, 0x60, 0x20, 0x2e, 0x10, 0x00, 0x00, 0x03,
167 0x00, 0x10, 0x00, 0x00, 0x03, 0x01, 0xe5, 0x1a,
168 0xff, 0xff, 0x10, 0x3e, 0x80, 0x5d, 0xf7, 0xc2,
169 0x01, 0x04
170 };
171
172 static const guint8 h265_128x128_sliced_pps[] = {
173 0x00, 0x00, 0x00, 0x01, 0x44, 0x01, 0xc0, 0x71,
174 0x81, 0x8d, 0xb2
175 };
176
177 static const guint8 h265_128x128_slice_1_idr_n_lp[] = {
178 0x00, 0x00, 0x00, 0x01, 0x28, 0x01, 0xac, 0x46,
179 0x13, 0xb6, 0x45, 0x43, 0xaf, 0xee, 0x3d, 0x3f,
180 0x76, 0xe5, 0x73, 0x2f, 0xee, 0xd2, 0xeb, 0xbf,
181 0x80
182 };
183
184 static const guint8 h265_128x128_slice_2_idr_n_lp[] = {
185 0x00, 0x00, 0x00, 0x01, 0x28, 0x01, 0x30, 0xc4,
186 0x60, 0x13, 0xb6, 0x45, 0x43, 0xaf, 0xee, 0x3d,
187 0x3f, 0x76, 0xe5, 0x73, 0x2f, 0xee, 0xd2, 0xeb,
188 0xbf, 0x80
189 };
190
191 static const gchar *ctx_suite;
192 static gboolean ctx_codec_data;
193
194 /* A single access unit comprising of VPS, SPS, PPS and IDR frame */
195 static gboolean
verify_buffer_bs_au(buffer_verify_data_s * vdata,GstBuffer * buffer)196 verify_buffer_bs_au (buffer_verify_data_s * vdata, GstBuffer * buffer)
197 {
198 GstMapInfo map;
199
200 fail_unless (ctx_sink_template == &sinktemplate_bs_au);
201
202 gst_buffer_map (buffer, &map, GST_MAP_READ);
203 fail_unless (map.size > 4);
204
205 if (vdata->buffer_counter == 0) {
206 guint8 *data = map.data;
207
208 /* VPS, SPS, PPS */
209 fail_unless (map.size == vdata->data_to_verify_size +
210 ctx_headers[0].size + ctx_headers[1].size + ctx_headers[2].size);
211
212 fail_unless (memcmp (data, ctx_headers[0].data, ctx_headers[0].size) == 0);
213 data += ctx_headers[0].size;
214 fail_unless (memcmp (data, ctx_headers[1].data, ctx_headers[1].size) == 0);
215 data += ctx_headers[1].size;
216 fail_unless (memcmp (data, ctx_headers[2].data, ctx_headers[2].size) == 0);
217 data += ctx_headers[2].size;
218
219 /* IDR frame */
220 fail_unless (memcmp (data, vdata->data_to_verify,
221 vdata->data_to_verify_size) == 0);
222 } else {
223 /* IDR frame */
224 fail_unless (map.size == vdata->data_to_verify_size);
225
226 fail_unless (memcmp (map.data, vdata->data_to_verify, map.size) == 0);
227 }
228
229 gst_buffer_unmap (buffer, &map);
230 return TRUE;
231 }
232
GST_START_TEST(test_parse_normal)233 GST_START_TEST (test_parse_normal)
234 {
235 gst_parser_test_normal (h265_idr, sizeof (h265_idr));
236 }
237
238 GST_END_TEST;
239
240
GST_START_TEST(test_parse_drain_single)241 GST_START_TEST (test_parse_drain_single)
242 {
243 gst_parser_test_drain_single (h265_idr, sizeof (h265_idr));
244 }
245
246 GST_END_TEST;
247
248
GST_START_TEST(test_parse_split)249 GST_START_TEST (test_parse_split)
250 {
251 gst_parser_test_split (h265_idr, sizeof (h265_idr));
252 }
253
254 GST_END_TEST;
255
256
257 #define structure_get_int(s,f) \
258 (g_value_get_int(gst_structure_get_value(s,f)))
259 #define fail_unless_structure_field_int_equals(s,field,num) \
260 fail_unless_equals_int (structure_get_int(s,field), num)
261
262 #define structure_get_string(s,f) \
263 (g_value_get_string(gst_structure_get_value(s,f)))
264 #define fail_unless_structure_field_string_equals(s,field,name) \
265 fail_unless_equals_string (structure_get_string(s,field), name)
266
GST_START_TEST(test_parse_detect_stream)267 GST_START_TEST (test_parse_detect_stream)
268 {
269 GstCaps *caps;
270 GstStructure *s;
271
272 caps = gst_parser_test_get_output_caps (h265_idr, sizeof (h265_idr), NULL);
273 fail_unless (caps != NULL);
274
275 /* Check that the negotiated caps are as expected */
276 GST_DEBUG ("output caps: %" GST_PTR_FORMAT, caps);
277 s = gst_caps_get_structure (caps, 0);
278 fail_unless (gst_structure_has_name (s, "video/x-h265"));
279 fail_unless_structure_field_int_equals (s, "width", 16);
280 fail_unless_structure_field_int_equals (s, "height", 16);
281 fail_unless_structure_field_string_equals (s, "stream-format", "byte-stream");
282 fail_unless_structure_field_string_equals (s, "alignment", "au");
283 fail_unless_structure_field_string_equals (s, "profile", "main");
284 fail_unless_structure_field_string_equals (s, "tier", "main");
285 fail_unless_structure_field_string_equals (s, "level", "2.1");
286
287 gst_caps_unref (caps);
288 }
289
290 GST_END_TEST;
291
GST_START_TEST(test_parse_detect_stream_with_hdr_sei)292 GST_START_TEST (test_parse_detect_stream_with_hdr_sei)
293 {
294 GstCaps *caps;
295 GstStructure *s;
296 guint8 *h265_idr_plus_sei;
297 gsize h265_idr_plus_sei_size =
298 sizeof (h265_sei_clli) + sizeof (h265_sei_mdcv) + sizeof (h265_idr);
299
300 h265_idr_plus_sei = malloc (h265_idr_plus_sei_size);
301
302 memcpy (h265_idr_plus_sei, h265_sei_clli, sizeof (h265_sei_clli));
303 memcpy (h265_idr_plus_sei + sizeof (h265_sei_clli), h265_sei_mdcv,
304 sizeof (h265_sei_mdcv));
305 memcpy (h265_idr_plus_sei + sizeof (h265_sei_clli) + sizeof (h265_sei_mdcv),
306 h265_idr, sizeof (h265_idr));
307
308 caps =
309 gst_parser_test_get_output_caps (h265_idr_plus_sei,
310 h265_idr_plus_sei_size, NULL);
311 fail_unless (caps != NULL);
312
313 /* Check that the negotiated caps are as expected */
314 GST_DEBUG ("output caps: %" GST_PTR_FORMAT, caps);
315 s = gst_caps_get_structure (caps, 0);
316 fail_unless (gst_structure_has_name (s, "video/x-h265"));
317 fail_unless_structure_field_int_equals (s, "width", 16);
318 fail_unless_structure_field_int_equals (s, "height", 16);
319 fail_unless_structure_field_string_equals (s, "stream-format", "byte-stream");
320 fail_unless_structure_field_string_equals (s, "alignment", "au");
321 fail_unless_structure_field_string_equals (s, "profile", "main");
322 fail_unless_structure_field_string_equals (s, "tier", "main");
323 fail_unless_structure_field_string_equals (s, "level", "2.1");
324 fail_unless_structure_field_string_equals (s, "mastering-display-info",
325 "34000:16000:13250:34500:7500:3000:15635:16450:10000000:1");
326 fail_unless_structure_field_string_equals (s, "content-light-level",
327 "1000:400");
328
329 g_free (h265_idr_plus_sei);
330 gst_caps_unref (caps);
331 }
332
333 GST_END_TEST;
334
335 static Suite *
h265parse_suite(void)336 h265parse_suite (void)
337 {
338 Suite *s = suite_create (ctx_suite);
339 TCase *tc_chain = tcase_create ("general");
340
341 suite_add_tcase (s, tc_chain);
342 tcase_add_test (tc_chain, test_parse_normal);
343 tcase_add_test (tc_chain, test_parse_drain_single);
344 tcase_add_test (tc_chain, test_parse_split);
345 tcase_add_test (tc_chain, test_parse_detect_stream);
346 tcase_add_test (tc_chain, test_parse_detect_stream_with_hdr_sei);
347
348 return s;
349 }
350
351
352 /* helper methods for GstHasness based tests */
353
354 static inline GstBuffer *
wrap_buffer(const guint8 * buf,gsize size,GstClockTime pts,GstBufferFlags flags)355 wrap_buffer (const guint8 * buf, gsize size, GstClockTime pts,
356 GstBufferFlags flags)
357 {
358 GstBuffer *buffer;
359
360 buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
361 (gpointer) buf, size, 0, size, NULL, NULL);
362 GST_BUFFER_PTS (buffer) = pts;
363 GST_BUFFER_FLAGS (buffer) |= flags;
364
365 return buffer;
366 }
367
368 static inline GstBuffer *
composite_buffer(GstClockTime pts,GstBufferFlags flags,gint count,...)369 composite_buffer (GstClockTime pts, GstBufferFlags flags, gint count, ...)
370 {
371 va_list vl;
372 gint i;
373 const guint8 *data;
374 gsize size;
375 GstBuffer *buffer;
376
377 va_start (vl, count);
378
379 buffer = gst_buffer_new ();
380 for (i = 0; i < count; i++) {
381 data = va_arg (vl, guint8 *);
382 size = va_arg (vl, gsize);
383
384 buffer = gst_buffer_append (buffer, wrap_buffer (data, size, 0, 0));
385 }
386 GST_BUFFER_PTS (buffer) = pts;
387 GST_BUFFER_FLAGS (buffer) |= flags;
388
389 va_end (vl);
390
391 return buffer;
392 }
393
394 static inline void
pull_and_check_full(GstHarness * h,const guint8 * data,gsize size,GstClockTime pts,GstBufferFlags flags)395 pull_and_check_full (GstHarness * h, const guint8 * data, gsize size,
396 GstClockTime pts, GstBufferFlags flags)
397 {
398 GstBuffer *b = gst_harness_pull (h);
399 gst_check_buffer_data (b, data, size);
400 fail_unless_equals_clocktime (GST_BUFFER_PTS (b), pts);
401 if (flags)
402 fail_unless (GST_BUFFER_FLAG_IS_SET (b, flags));
403 gst_buffer_unref (b);
404 }
405
406 #define pull_and_check(h, data, pts, flags) \
407 pull_and_check_full (h, data, sizeof (data), pts, flags)
408
409 #define pull_and_check_composite(h, pts, flags, ...) \
410 G_STMT_START { \
411 GstMapInfo info; \
412 GstBuffer *cb; \
413 \
414 cb = composite_buffer (0, 0, __VA_ARGS__); \
415 gst_buffer_map (cb, &info, GST_MAP_READ); \
416 \
417 pull_and_check_full (h, info.data, info.size, pts, flags); \
418 \
419 gst_buffer_unmap (cb, &info); \
420 gst_buffer_unref (cb); \
421 } G_STMT_END
422
423 #define pull_and_drop(h) \
424 G_STMT_START { \
425 GstBuffer *b = gst_harness_pull (h); \
426 gst_buffer_unref (b); \
427 } G_STMT_END
428
429 #define HEADER_DATA \
430 const guint8 * const vps = sliced ? h265_128x128_sliced_vps : h265_128x128_vps; \
431 const guint8 * const sps = sliced ? h265_128x128_sliced_sps : h265_128x128_sps; \
432 const guint8 * const pps = sliced ? h265_128x128_sliced_pps : h265_128x128_pps; \
433 const gsize vps_size = sliced ? sizeof (h265_128x128_sliced_vps) : sizeof (h265_128x128_vps); \
434 const gsize sps_size = sliced ? sizeof (h265_128x128_sliced_sps) : sizeof (h265_128x128_sps); \
435 const gsize pps_size = sliced ? sizeof (h265_128x128_sliced_pps) : sizeof (h265_128x128_pps)
436
437 #define SLICE_DATA \
438 const guint8 * const slice_1 = sliced ? h265_128x128_slice_1_idr_n_lp : h265_128x128_slice_idr_n_lp; \
439 const guint8 * const slice_2 = sliced ? h265_128x128_slice_2_idr_n_lp : NULL; \
440 const gsize slice_1_size = sliced ? sizeof (h265_128x128_slice_1_idr_n_lp) : sizeof (h265_128x128_slice_idr_n_lp); \
441 const gsize slice_2_size = sliced ? sizeof (h265_128x128_slice_2_idr_n_lp) : 0
442
443 #define bytestream_set_caps(h, in_align, out_align) \
444 gst_harness_set_caps_str (h, \
445 "video/x-h265, parsed=(boolean)false, stream-format=byte-stream, alignment=" in_align ", framerate=30/1", \
446 "video/x-h265, parsed=(boolean)true, stream-format=byte-stream, alignment=" out_align)
447
448 static inline void
bytestream_push_first_au_inalign_nal(GstHarness * h,gboolean sliced)449 bytestream_push_first_au_inalign_nal (GstHarness * h, gboolean sliced)
450 {
451 HEADER_DATA;
452 SLICE_DATA;
453 GstBuffer *buf;
454
455 buf = wrap_buffer (vps, vps_size, 10, 0);
456 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
457
458 buf = wrap_buffer (sps, sps_size, 10, 0);
459 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
460
461 buf = wrap_buffer (pps, pps_size, 10, 0);
462 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
463
464 buf = wrap_buffer (slice_1, slice_1_size, 10, 0);
465 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
466
467 if (sliced) {
468 buf = wrap_buffer (slice_2, slice_2_size, 10, 0);
469 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
470 }
471 }
472
473 static inline void
bytestream_push_first_au_inalign_au(GstHarness * h,gboolean sliced)474 bytestream_push_first_au_inalign_au (GstHarness * h, gboolean sliced)
475 {
476 HEADER_DATA;
477 SLICE_DATA;
478 GstBuffer *buf;
479
480 buf = composite_buffer (10, 0, sliced ? 5 : 4,
481 vps, vps_size, sps, sps_size, pps, pps_size,
482 slice_1, slice_1_size, slice_2, slice_2_size);
483 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
484 }
485
486 /* tests */
487
488 static void
test_flow_outalign_nal(GstHarness * h)489 test_flow_outalign_nal (GstHarness * h)
490 {
491 GstBuffer *buf;
492
493 /* drop the first AU - tested separately */
494 fail_unless (gst_harness_buffers_in_queue (h) > 0);
495 while (gst_harness_buffers_in_queue (h) > 0)
496 pull_and_drop (h);
497
498 buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
499 sizeof (h265_128x128_slice_idr_n_lp), 100, 0);
500 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
501 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
502 pull_and_check (h, h265_128x128_slice_idr_n_lp, 100, 0);
503
504 buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
505 sizeof (h265_128x128_slice_idr_n_lp), 200, 0);
506 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
507 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
508 pull_and_check (h, h265_128x128_slice_idr_n_lp, 200, 0);
509 }
510
511 static void
test_flow_outalign_au(GstHarness * h)512 test_flow_outalign_au (GstHarness * h)
513 {
514 GstBuffer *buf;
515
516 /* drop the first AU - tested separately */
517 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
518 pull_and_drop (h);
519
520 buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
521 sizeof (h265_128x128_slice_idr_n_lp), 100, 0);
522 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
523 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
524 pull_and_check (h, h265_128x128_slice_idr_n_lp, 100, 0);
525
526 buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
527 sizeof (h265_128x128_slice_idr_n_lp), 200, 0);
528 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
529 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
530 pull_and_check (h, h265_128x128_slice_idr_n_lp, 200, 0);
531 }
532
GST_START_TEST(test_flow_nal_nal)533 GST_START_TEST (test_flow_nal_nal)
534 {
535 GstHarness *h = gst_harness_new ("h265parse");
536
537 bytestream_set_caps (h, "nal", "nal");
538 bytestream_push_first_au_inalign_nal (h, FALSE);
539 test_flow_outalign_nal (h);
540
541 gst_harness_teardown (h);
542 }
543
544 GST_END_TEST;
545
GST_START_TEST(test_flow_au_nal)546 GST_START_TEST (test_flow_au_nal)
547 {
548 GstHarness *h = gst_harness_new ("h265parse");
549
550 bytestream_set_caps (h, "au", "nal");
551 bytestream_push_first_au_inalign_au (h, FALSE);
552 test_flow_outalign_nal (h);
553
554 gst_harness_teardown (h);
555 }
556
557 GST_END_TEST;
558
GST_START_TEST(test_flow_nal_au)559 GST_START_TEST (test_flow_nal_au)
560 {
561 GstHarness *h = gst_harness_new ("h265parse");
562 GstBuffer *buf;
563
564 bytestream_set_caps (h, "nal", "au");
565 bytestream_push_first_au_inalign_nal (h, FALSE);
566
567 /* special case because we have latency */
568
569 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
570
571 buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
572 sizeof (h265_128x128_slice_idr_n_lp), 100, 0);
573 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
574
575 /* drop the first AU - tested separately */
576 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
577 pull_and_drop (h);
578
579 buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
580 sizeof (h265_128x128_slice_idr_n_lp), 200, 0);
581 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
582
583 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
584 pull_and_check (h, h265_128x128_slice_idr_n_lp, 100, 0);
585
586 gst_harness_teardown (h);
587 }
588
589 GST_END_TEST;
590
GST_START_TEST(test_flow_au_au)591 GST_START_TEST (test_flow_au_au)
592 {
593 GstHarness *h = gst_harness_new ("h265parse");
594
595 bytestream_set_caps (h, "au", "au");
596 bytestream_push_first_au_inalign_au (h, FALSE);
597 test_flow_outalign_au (h);
598
599 gst_harness_teardown (h);
600 }
601
602 GST_END_TEST;
603
604 static void
test_headers_outalign_nal(GstHarness * h)605 test_headers_outalign_nal (GstHarness * h)
606 {
607 /* 5 -> AUD + VPS + SPS + PPS + slice */
608 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 4);
609
610 /* parser must have inserted AUD before the headers, with the same PTS */
611 pull_and_check (h, h265_128x128_vps, 10, 0);
612 pull_and_check (h, h265_128x128_sps, 10, 0);
613 pull_and_check (h, h265_128x128_pps, 10, 0);
614
615 /* FIXME The timestamp should be 10 really, but base parse refuse to repeat
616 * the same TS for two consecutive calls to _finish_frame(), see [0] for
617 * more details. It's not a huge issue, the decoder can fix it for now.
618 *
619 * [0] https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/287
620 */
621 pull_and_check (h, h265_128x128_slice_idr_n_lp, -1, 0);
622 }
623
624 static void
test_headers_outalign_au(GstHarness * h)625 test_headers_outalign_au (GstHarness * h)
626 {
627 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
628 pull_and_check_composite (h, 10, 0, 4,
629 h265_128x128_vps, sizeof (h265_128x128_vps),
630 h265_128x128_sps, sizeof (h265_128x128_sps),
631 h265_128x128_pps, sizeof (h265_128x128_pps),
632 h265_128x128_slice_idr_n_lp, sizeof (h265_128x128_slice_idr_n_lp));
633 }
634
GST_START_TEST(test_headers_nal_nal)635 GST_START_TEST (test_headers_nal_nal)
636 {
637 GstHarness *h = gst_harness_new ("h265parse");
638
639 bytestream_set_caps (h, "nal", "nal");
640 bytestream_push_first_au_inalign_nal (h, FALSE);
641 test_headers_outalign_nal (h);
642
643 gst_harness_teardown (h);
644 }
645
646 GST_END_TEST;
647
GST_START_TEST(test_headers_au_nal)648 GST_START_TEST (test_headers_au_nal)
649 {
650 GstHarness *h = gst_harness_new ("h265parse");
651
652 bytestream_set_caps (h, "au", "nal");
653 bytestream_push_first_au_inalign_au (h, FALSE);
654 test_headers_outalign_nal (h);
655
656 gst_harness_teardown (h);
657 }
658
659 GST_END_TEST;
660
GST_START_TEST(test_headers_au_au)661 GST_START_TEST (test_headers_au_au)
662 {
663 GstHarness *h = gst_harness_new ("h265parse");
664
665 bytestream_set_caps (h, "au", "au");
666 bytestream_push_first_au_inalign_au (h, FALSE);
667 test_headers_outalign_au (h);
668
669 gst_harness_teardown (h);
670 }
671
672 GST_END_TEST;
673
GST_START_TEST(test_latency_nal_nal)674 GST_START_TEST (test_latency_nal_nal)
675 {
676 GstHarness *h = gst_harness_new ("h265parse");
677
678 bytestream_set_caps (h, "nal", "nal");
679 bytestream_push_first_au_inalign_nal (h, FALSE);
680
681 fail_unless_equals_clocktime (gst_harness_query_latency (h), 0);
682
683 gst_harness_teardown (h);
684 }
685
686 GST_END_TEST;
687
GST_START_TEST(test_latency_au_nal)688 GST_START_TEST (test_latency_au_nal)
689 {
690 GstHarness *h = gst_harness_new ("h265parse");
691
692 bytestream_set_caps (h, "au", "nal");
693 bytestream_push_first_au_inalign_au (h, FALSE);
694
695 fail_unless_equals_clocktime (gst_harness_query_latency (h), 0);
696
697 gst_harness_teardown (h);
698 }
699
700 GST_END_TEST;
701
GST_START_TEST(test_latency_nal_au)702 GST_START_TEST (test_latency_nal_au)
703 {
704 GstHarness *h = gst_harness_new ("h265parse");
705 GstBuffer *buf;
706
707 bytestream_set_caps (h, "nal", "au");
708 bytestream_push_first_au_inalign_nal (h, FALSE);
709
710 /* special case because we have latency;
711 * the first buffer needs to be pushed out
712 * before we can correctly query the latency */
713 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
714 buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
715 sizeof (h265_128x128_slice_idr_n_lp), 100, 0);
716 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
717
718 /* our input caps declare framerate=30fps, so the latency must be 1/30 sec */
719 fail_unless_equals_clocktime (gst_harness_query_latency (h),
720 gst_util_uint64_scale (GST_SECOND, 1, 30));
721
722 gst_harness_teardown (h);
723 }
724
725 GST_END_TEST;
726
GST_START_TEST(test_latency_au_au)727 GST_START_TEST (test_latency_au_au)
728 {
729 GstHarness *h = gst_harness_new ("h265parse");
730
731 bytestream_set_caps (h, "au", "au");
732 bytestream_push_first_au_inalign_au (h, FALSE);
733
734 fail_unless_equals_clocktime (gst_harness_query_latency (h), 0);
735
736 gst_harness_teardown (h);
737 }
738
739 GST_END_TEST;
740
741 static void
test_discont_outalign_nal(GstHarness * h)742 test_discont_outalign_nal (GstHarness * h)
743 {
744 GstBuffer *buf;
745
746 /* drop the first AU - tested separately */
747 fail_unless (gst_harness_buffers_in_queue (h) > 0);
748 while (gst_harness_buffers_in_queue (h) > 0)
749 pull_and_drop (h);
750
751 /* FIXME: I think the AUD ought to have DISCONT */
752 buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
753 sizeof (h265_128x128_slice_idr_n_lp), 1000, GST_BUFFER_FLAG_DISCONT);
754 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
755 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
756 pull_and_check (h, h265_128x128_slice_idr_n_lp, 1000,
757 GST_BUFFER_FLAG_DISCONT);
758 }
759
760 static void
test_discont_outalign_au(GstHarness * h)761 test_discont_outalign_au (GstHarness * h)
762 {
763 GstBuffer *buf;
764
765 /* drop the first AU - tested separately */
766 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
767 pull_and_drop (h);
768
769 buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
770 sizeof (h265_128x128_slice_idr_n_lp), 1000, GST_BUFFER_FLAG_DISCONT);
771 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
772 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
773 pull_and_check (h, h265_128x128_slice_idr_n_lp, 1000,
774 GST_BUFFER_FLAG_DISCONT);
775 }
776
GST_START_TEST(test_discont_nal_nal)777 GST_START_TEST (test_discont_nal_nal)
778 {
779 GstHarness *h = gst_harness_new ("h265parse");
780
781 bytestream_set_caps (h, "nal", "nal");
782 bytestream_push_first_au_inalign_nal (h, FALSE);
783 test_discont_outalign_nal (h);
784
785 gst_harness_teardown (h);
786 }
787
788 GST_END_TEST;
789
GST_START_TEST(test_discont_au_nal)790 GST_START_TEST (test_discont_au_nal)
791 {
792 GstHarness *h = gst_harness_new ("h265parse");
793
794 bytestream_set_caps (h, "au", "nal");
795 bytestream_push_first_au_inalign_au (h, FALSE);
796 test_discont_outalign_nal (h);
797
798 gst_harness_teardown (h);
799 }
800
801 GST_END_TEST;
802
GST_START_TEST(test_discont_au_au)803 GST_START_TEST (test_discont_au_au)
804 {
805 GstHarness *h = gst_harness_new ("h265parse");
806
807 bytestream_set_caps (h, "au", "au");
808 bytestream_push_first_au_inalign_au (h, FALSE);
809 test_discont_outalign_au (h);
810
811 gst_harness_teardown (h);
812 }
813
814 GST_END_TEST;
815
GST_START_TEST(test_sliced_nal_nal)816 GST_START_TEST (test_sliced_nal_nal)
817 {
818 GstHarness *h = gst_harness_new ("h265parse");
819 GstBuffer *buf;
820
821 bytestream_set_caps (h, "nal", "nal");
822 bytestream_push_first_au_inalign_nal (h, TRUE);
823
824 /* drop the header buffers */
825 fail_unless (gst_harness_buffers_in_queue (h) > 2);
826 while (gst_harness_buffers_in_queue (h) > 2)
827 pull_and_drop (h);
828
829 /* but expect 2 slices */
830 pull_and_check (h, h265_128x128_slice_1_idr_n_lp, -1, 0);
831 pull_and_check (h, h265_128x128_slice_2_idr_n_lp, -1, 0);
832
833 /* push some more */
834 buf = wrap_buffer (h265_128x128_slice_1_idr_n_lp,
835 sizeof (h265_128x128_slice_1_idr_n_lp), 100, 0);
836 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
837 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
838 pull_and_check (h, h265_128x128_slice_1_idr_n_lp, 100, 0);
839
840 buf = wrap_buffer (h265_128x128_slice_2_idr_n_lp,
841 sizeof (h265_128x128_slice_2_idr_n_lp), 100, 0);
842 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
843 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
844 pull_and_check (h, h265_128x128_slice_2_idr_n_lp, -1, 0);
845
846 gst_harness_teardown (h);
847 }
848
849 GST_END_TEST;
850
GST_START_TEST(test_sliced_au_nal)851 GST_START_TEST (test_sliced_au_nal)
852 {
853 GstHarness *h = gst_harness_new ("h265parse");
854 GstBuffer *buf;
855
856 bytestream_set_caps (h, "au", "nal");
857 bytestream_push_first_au_inalign_au (h, TRUE);
858
859 /* drop the header buffers */
860 fail_unless (gst_harness_buffers_in_queue (h) > 2);
861 while (gst_harness_buffers_in_queue (h) > 2)
862 pull_and_drop (h);
863
864 /* but expect 2 slices */
865 pull_and_check (h, h265_128x128_slice_1_idr_n_lp, -1, 0);
866 pull_and_check (h, h265_128x128_slice_2_idr_n_lp, -1, 0);
867
868 /* push some more */
869 buf = composite_buffer (100, 0, 2,
870 h265_128x128_slice_1_idr_n_lp, sizeof (h265_128x128_slice_1_idr_n_lp),
871 h265_128x128_slice_2_idr_n_lp, sizeof (h265_128x128_slice_2_idr_n_lp));
872 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
873 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2);
874 pull_and_check (h, h265_128x128_slice_1_idr_n_lp, 100, 0);
875 pull_and_check (h, h265_128x128_slice_2_idr_n_lp, -1, 0);
876
877 gst_harness_teardown (h);
878 }
879
880 GST_END_TEST;
881
GST_START_TEST(test_sliced_nal_au)882 GST_START_TEST (test_sliced_nal_au)
883 {
884 GstHarness *h = gst_harness_new ("h265parse");
885 GstBuffer *buf;
886
887 bytestream_set_caps (h, "nal", "au");
888 bytestream_push_first_au_inalign_nal (h, TRUE);
889
890 /* nal -> au has latency; we need to start the next AU to get output */
891 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
892
893
894 /* push some more */
895 buf = wrap_buffer (h265_128x128_slice_1_idr_n_lp,
896 sizeof (h265_128x128_slice_1_idr_n_lp), 100, 0);
897 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
898
899 /* now we can see the initial AU on the output */
900 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
901 pull_and_check_composite (h, 10, 0, 5,
902 h265_128x128_sliced_vps, sizeof (h265_128x128_sliced_vps),
903 h265_128x128_sliced_sps, sizeof (h265_128x128_sliced_sps),
904 h265_128x128_sliced_pps, sizeof (h265_128x128_sliced_pps),
905 h265_128x128_slice_1_idr_n_lp, sizeof (h265_128x128_slice_1_idr_n_lp),
906 h265_128x128_slice_2_idr_n_lp, sizeof (h265_128x128_slice_2_idr_n_lp));
907
908 buf = wrap_buffer (h265_128x128_slice_2_idr_n_lp,
909 sizeof (h265_128x128_slice_2_idr_n_lp), 100, 0);
910 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
911 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
912
913 buf = wrap_buffer (h265_128x128_slice_1_idr_n_lp,
914 sizeof (h265_128x128_slice_1_idr_n_lp), 200, 0);
915 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
916
917 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
918 pull_and_check_composite (h, 100, 0, 2,
919 h265_128x128_slice_1_idr_n_lp, sizeof (h265_128x128_slice_1_idr_n_lp),
920 h265_128x128_slice_2_idr_n_lp, sizeof (h265_128x128_slice_2_idr_n_lp));
921
922 gst_harness_teardown (h);
923 }
924
925 GST_END_TEST;
926
GST_START_TEST(test_sliced_au_au)927 GST_START_TEST (test_sliced_au_au)
928 {
929 GstHarness *h = gst_harness_new ("h265parse");
930 GstBuffer *buf;
931
932 bytestream_set_caps (h, "au", "au");
933 bytestream_push_first_au_inalign_au (h, TRUE);
934
935 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
936 pull_and_check_composite (h, 10, 0, 5,
937 h265_128x128_sliced_vps, sizeof (h265_128x128_sliced_vps),
938 h265_128x128_sliced_sps, sizeof (h265_128x128_sliced_sps),
939 h265_128x128_sliced_pps, sizeof (h265_128x128_sliced_pps),
940 h265_128x128_slice_1_idr_n_lp, sizeof (h265_128x128_slice_1_idr_n_lp),
941 h265_128x128_slice_2_idr_n_lp, sizeof (h265_128x128_slice_2_idr_n_lp));
942
943 /* push some more */
944 buf = composite_buffer (100, 0, 2,
945 h265_128x128_slice_1_idr_n_lp, sizeof (h265_128x128_slice_1_idr_n_lp),
946 h265_128x128_slice_2_idr_n_lp, sizeof (h265_128x128_slice_2_idr_n_lp));
947 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
948 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
949 pull_and_check_composite (h, 100, 0, 2,
950 h265_128x128_slice_1_idr_n_lp, sizeof (h265_128x128_slice_1_idr_n_lp),
951 h265_128x128_slice_2_idr_n_lp, sizeof (h265_128x128_slice_2_idr_n_lp));
952
953 gst_harness_teardown (h);
954 }
955
956 GST_END_TEST;
957
GST_START_TEST(test_parse_skip_to_4bytes_sc)958 GST_START_TEST (test_parse_skip_to_4bytes_sc)
959 {
960 GstHarness *h;
961 GstBuffer *buf1, *buf2;
962 const guint8 initial_bytes[] = { 0x00, 0x00, 0x00, 0x00, 0x01, h265_vps[4] };
963 GstMapInfo map;
964
965 h = gst_harness_new ("h265parse");
966
967 gst_harness_set_caps_str (h, "video/x-h265, stream-format=byte-stream",
968 "video/x-h265, stream-format=byte-stream, alignment=nal");
969
970 /* padding bytes, four bytes start code and 1 of the two identification
971 * bytes. */
972 buf1 = wrap_buffer (initial_bytes, sizeof (initial_bytes), 100, 0);
973
974 /* The second contains the an VPS, starting from second NAL identification
975 * byte and is followed by an SPS, IDR to ensure that the NAL end can be
976 * found */
977 buf2 = composite_buffer (100, 0, 4, h265_vps + 5, sizeof (h265_vps) - 5,
978 h265_sps, sizeof (h265_sps), h265_pps, sizeof (h265_pps),
979 h265_idr, sizeof (h265_idr));
980
981 fail_unless_equals_int (gst_harness_push (h, buf1), GST_FLOW_OK);
982 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
983
984 fail_unless_equals_int (gst_harness_push (h, buf2), GST_FLOW_OK);
985 /* The parser will deliver VPS, SPS, PPS as it now have complete cpas */
986 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 3);
987
988 buf1 = gst_harness_pull (h);
989 gst_buffer_map (buf1, &map, GST_MAP_READ);
990 fail_unless_equals_int (gst_buffer_get_size (buf1), sizeof (h265_vps));
991 gst_buffer_unmap (buf1, &map);
992 gst_buffer_unref (buf1);
993
994 gst_harness_teardown (h);
995 }
996
997 GST_END_TEST;
998
GST_START_TEST(test_parse_sc_with_half_header)999 GST_START_TEST (test_parse_sc_with_half_header)
1000 {
1001 GstHarness *h;
1002 GstBuffer *buf1, *buf2;
1003 GstMapInfo map;
1004
1005 h = gst_harness_new ("h265parse");
1006
1007 gst_harness_set_caps_str (h, "video/x-h265, stream-format=byte-stream",
1008 "video/x-h265, stream-format=byte-stream, alignment=nal");
1009
1010 buf1 = composite_buffer (100, 0, 4, h265_vps, sizeof (h265_vps),
1011 h265_sps, sizeof (h265_sps), h265_pps, sizeof (h265_pps), h265_idr, 5);
1012 buf2 = wrap_buffer (h265_idr + 5, sizeof (h265_idr) - 5, 100, 0);
1013
1014 fail_unless_equals_int (gst_harness_push (h, buf1), GST_FLOW_OK);
1015 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
1016
1017 fail_unless_equals_int (gst_harness_push (h, buf2), GST_FLOW_OK);
1018 /* The parser will deliver VPS, SPS, PPS as it now have complete cpas */
1019 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 3);
1020
1021 buf1 = gst_harness_pull (h);
1022 gst_buffer_map (buf1, &map, GST_MAP_READ);
1023 fail_unless_equals_int (gst_buffer_get_size (buf1), sizeof (h265_vps));
1024 gst_buffer_unmap (buf1, &map);
1025 gst_buffer_unref (buf1);
1026
1027 gst_harness_teardown (h);
1028 }
1029
1030 GST_END_TEST;
1031
1032
1033
1034 /* nal->au has latency, but EOS should force the last AU out */
GST_START_TEST(test_drain)1035 GST_START_TEST (test_drain)
1036 {
1037 GstHarness *h = gst_harness_new ("h265parse");
1038
1039 bytestream_set_caps (h, "nal", "au");
1040 bytestream_push_first_au_inalign_nal (h, FALSE);
1041
1042 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
1043
1044 gst_harness_push_event (h, gst_event_new_eos ());
1045
1046 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
1047 pull_and_drop (h);
1048
1049 gst_harness_teardown (h);
1050 }
1051
1052 GST_END_TEST;
1053
1054
1055 static Suite *
h265parse_harnessed_suite(void)1056 h265parse_harnessed_suite (void)
1057 {
1058 Suite *s = suite_create ("h265parse");
1059 TCase *tc_chain = tcase_create ("general");
1060
1061 suite_add_tcase (s, tc_chain);
1062 tcase_add_test (tc_chain, test_flow_nal_nal);
1063 tcase_add_test (tc_chain, test_flow_au_nal);
1064 tcase_add_test (tc_chain, test_flow_nal_au);
1065 tcase_add_test (tc_chain, test_flow_au_au);
1066
1067 tcase_add_test (tc_chain, test_headers_nal_nal);
1068 tcase_add_test (tc_chain, test_headers_au_nal);
1069 tcase_add_test (tc_chain, test_headers_au_au);
1070
1071 tcase_add_test (tc_chain, test_latency_nal_nal);
1072 tcase_add_test (tc_chain, test_latency_au_nal);
1073 tcase_add_test (tc_chain, test_latency_nal_au);
1074 tcase_add_test (tc_chain, test_latency_au_au);
1075
1076 tcase_add_test (tc_chain, test_discont_nal_nal);
1077 tcase_add_test (tc_chain, test_discont_au_nal);
1078 tcase_add_test (tc_chain, test_discont_au_au);
1079
1080 tcase_add_test (tc_chain, test_sliced_nal_nal);
1081 tcase_add_test (tc_chain, test_sliced_au_nal);
1082 tcase_add_test (tc_chain, test_sliced_nal_au);
1083 tcase_add_test (tc_chain, test_sliced_au_au);
1084
1085 tcase_add_test (tc_chain, test_parse_skip_to_4bytes_sc);
1086 tcase_add_test (tc_chain, test_parse_sc_with_half_header);
1087
1088 tcase_add_test (tc_chain, test_drain);
1089
1090 return s;
1091 }
1092
1093 int
main(int argc,char ** argv)1094 main (int argc, char **argv)
1095 {
1096 int nf = 0;
1097
1098 Suite *s;
1099
1100 gst_check_init (&argc, &argv);
1101
1102 /* init test context */
1103 ctx_factory = "h265parse";
1104 ctx_sink_template = &sinktemplate_bs_au;
1105 ctx_src_template = &srctemplate;
1106 /* no timing info to parse */
1107 ctx_headers[0].data = h265_vps;
1108 ctx_headers[0].size = sizeof (h265_vps);
1109 ctx_headers[1].data = h265_sps;
1110 ctx_headers[1].size = sizeof (h265_sps);
1111 ctx_headers[2].data = h265_pps;
1112 ctx_headers[2].size = sizeof (h265_pps);
1113 ctx_verify_buffer = verify_buffer_bs_au;
1114
1115 /* discard initial vps/sps/pps buffers */
1116 ctx_discard = 0;
1117 /* no timing info to parse */
1118 ctx_no_metadata = TRUE;
1119 ctx_codec_data = FALSE;
1120
1121 ctx_suite = "h265parse_to_bs_au";
1122 s = h265parse_suite ();
1123 nf += gst_check_run_suite (s, ctx_suite, __FILE__ "_to_bs_au.c");
1124
1125 ctx_suite = "h265parse_harnessed";
1126 s = h265parse_harnessed_suite ();
1127 nf += gst_check_run_suite (s, ctx_suite, __FILE__ "_harnessed.c");
1128
1129 return nf;
1130 }
1131