1 /*
2 * GStreamer
3 *
4 * unit test for h264parse
5 *
6 * Copyright (C) 2011 Nokia Corporation. All rights reserved.
7 *
8 * Contact: Stefan Kost <stefan.kost@nokia.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 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <gst/check/check.h>
31 #include <gst/video/video.h>
32 #include "gst-libs/gst/codecparsers/gsth264parser.h"
33 #include "parser.h"
34
35 #define SRC_CAPS_TMPL "video/x-h264, parsed=(boolean)false"
36 #define SINK_CAPS_TMPL "video/x-h264, parsed=(boolean)true"
37
38 GstStaticPadTemplate sinktemplate_bs_nal = GST_STATIC_PAD_TEMPLATE ("sink",
39 GST_PAD_SINK,
40 GST_PAD_ALWAYS,
41 GST_STATIC_CAPS (SINK_CAPS_TMPL
42 ", stream-format = (string) byte-stream, alignment = (string) nal")
43 );
44
45 GstStaticPadTemplate sinktemplate_bs_au = GST_STATIC_PAD_TEMPLATE ("sink",
46 GST_PAD_SINK,
47 GST_PAD_ALWAYS,
48 GST_STATIC_CAPS (SINK_CAPS_TMPL
49 ", stream-format = (string) byte-stream, alignment = (string) au")
50 );
51
52 GstStaticPadTemplate sinktemplate_avc_au = GST_STATIC_PAD_TEMPLATE ("sink",
53 GST_PAD_SINK,
54 GST_PAD_ALWAYS,
55 GST_STATIC_CAPS (SINK_CAPS_TMPL
56 ", stream-format = (string) avc, alignment = (string) au")
57 );
58
59 GstStaticPadTemplate sinktemplate_avc3_au = GST_STATIC_PAD_TEMPLATE ("sink",
60 GST_PAD_SINK,
61 GST_PAD_ALWAYS,
62 GST_STATIC_CAPS (SINK_CAPS_TMPL
63 ", stream-format = (string) avc3, alignment = (string) au")
64 );
65
66 GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
67 GST_PAD_SRC,
68 GST_PAD_ALWAYS,
69 GST_STATIC_CAPS (SRC_CAPS_TMPL)
70 );
71
72 /* some data */
73
74 /* AUD */
75 static guint8 h264_aud[] = {
76 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0
77 };
78
79
80 /* SPS */
81 static guint8 h264_sps[] = {
82 0x00, 0x00, 0x00, 0x01, 0x67, 0x4d, 0x40, 0x15,
83 0xec, 0xa4, 0xbf, 0x2e, 0x02, 0x20, 0x00, 0x00,
84 0x03, 0x00, 0x2e, 0xe6, 0xb2, 0x80, 0x01, 0xe2,
85 0xc5, 0xb2, 0xc0
86 };
87
88 /* PPS */
89 static guint8 h264_pps[] = {
90 0x00, 0x00, 0x00, 0x01, 0x68, 0xeb, 0xec, 0xb2
91 };
92
93 /* SEI buffering_period() message */
94 static guint8 h264_sei_buffering_period[] = {
95 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x01, 0xc0
96 };
97
98 /* Content light level information SEI message */
99 static guint8 h264_sei_clli[] = {
100 0x00, 0x00, 0x00, 0x01, 0x06, 0x90, 0x04, 0x03, 0xe8, 0x01, 0x90, 0x80
101 };
102
103 /* Mastering display colour volume information SEI message */
104 static guint8 h264_sei_mdcv[] = {
105 0x00, 0x00, 0x00, 0x01, 0x06, 0x89, 0x18, 0x84,
106 0xd0, 0x3e, 0x80, 0x33, 0x90, 0x86, 0xc4, 0x1d,
107 0x4c, 0x0b, 0xb8, 0x3d, 0x13, 0x40, 0x42, 0x00,
108 0x98, 0x96, 0x80, 0x00, 0x00, 0x03, 0x00, 0x01,
109 0x80
110 };
111
112 /* combines to this codec-data */
113 static guint8 h264_avc_codec_data[] = {
114 0x01, 0x4d, 0x40, 0x15, 0xff, 0xe1, 0x00, 0x17,
115 0x67, 0x4d, 0x40, 0x15, 0xec, 0xa4, 0xbf, 0x2e,
116 0x02, 0x20, 0x00, 0x00, 0x03, 0x00, 0x2e, 0xe6,
117 0xb2, 0x80, 0x01, 0xe2, 0xc5, 0xb2, 0xc0, 0x01,
118 0x00, 0x04, 0x68, 0xeb, 0xec, 0xb2
119 };
120
121 /* codec-data for avc3 where there are no SPS/PPS in the codec_data */
122 static guint8 h264_avc3_codec_data[] = {
123 0x01, /* config version, always == 1 */
124 0x4d, /* profile */
125 0x40, /* profile compatibility */
126 0x15, 0xff, /* 6 reserved bits, lengthSizeMinusOne */
127 0xe0, /* 3 reserved bits, numSPS */
128 0x00 /* numPPS */
129 };
130
131 static guint8 *h264_codec_data = NULL;
132 static guint8 h264_codec_data_size = 0;
133
134
135 /* keyframes all around */
136 static guint8 h264_idrframe[] = {
137 0x00, 0x00, 0x00, 0x01, 0x65, 0x88, 0x84, 0x00,
138 0x10, 0xff, 0xfe, 0xf6, 0xf0, 0xfe, 0x05, 0x36,
139 0x56, 0x04, 0x50, 0x96, 0x7b, 0x3f, 0x53, 0xe1
140 };
141
142 /* truncated nal */
143 static guint8 garbage_frame[] = {
144 0x00, 0x00, 0x00, 0x01, 0x05
145 };
146
147 /* context to tweak tests */
148 static const gchar *ctx_suite;
149 static gboolean ctx_codec_data;
150 static gboolean ctx_hdr_sei;
151
152 #define SPS_LEN 3
153 #define SPS_CONSTRAINT_SET_FLAG_0 1 << 7
154 #define SPS_CONSTRAINT_SET_FLAG_1 (1 << 6)
155 #define SPS_CONSTRAINT_SET_FLAG_2 (1 << 5)
156 #define SPS_CONSTRAINT_SET_FLAG_3 (1 << 4)
157 #define SPS_CONSTRAINT_SET_FLAG_4 (1 << 3)
158 #define SPS_CONSTRAINT_SET_FLAG_5 (1 << 2)
159
160 static void
fill_h264_sps(guint8 * sps,guint8 profile_idc,guint constraint_set_flags,guint level_idc)161 fill_h264_sps (guint8 * sps, guint8 profile_idc, guint constraint_set_flags,
162 guint level_idc)
163 {
164 memset (sps, 0x0, SPS_LEN);
165 /*
166 * * Bit 0:7 - Profile indication
167 * * Bit 8 - constraint_set0_flag
168 * * Bit 9 - constraint_set1_flag
169 * * Bit 10 - constraint_set2_flag
170 * * Bit 11 - constraint_set3_flag
171 * * Bit 12 - constraint_set4_flag
172 * * Bit 13 - constraint_set5_flag
173 * * Bit 14:15 - Reserved
174 * * Bit 16:24 - Level indication
175 * */
176 sps[0] = profile_idc;
177 sps[1] |= constraint_set_flags;
178 sps[2] = level_idc;
179 }
180
181 static gboolean
verify_buffer(buffer_verify_data_s * vdata,GstBuffer * buffer)182 verify_buffer (buffer_verify_data_s * vdata, GstBuffer * buffer)
183 {
184 if (vdata->discard) {
185 /* check separate header NALs */
186 gint i = vdata->buffer_counter;
187 gboolean aud;
188
189 /* SEI with start code prefix with 2 0-bytes */
190 aud = i == 0;
191 fail_unless (i <= 3);
192
193 if (aud) {
194 fail_unless (gst_buffer_get_size (buffer) == sizeof (h264_aud));
195 fail_unless (gst_buffer_memcmp (buffer, 0, h264_aud,
196 gst_buffer_get_size (buffer)) == 0);
197 vdata->discard++;
198 } else {
199 i -= 1;
200
201 fail_unless (gst_buffer_get_size (buffer) == ctx_headers[i].size);
202 fail_unless (gst_buffer_memcmp (buffer, 0, ctx_headers[i].data,
203 gst_buffer_get_size (buffer)) == 0);
204 }
205 } else {
206 GstMapInfo map;
207
208 gst_buffer_map (buffer, &map, GST_MAP_READ);
209 fail_unless (map.size > 4);
210 /* only need to check avc and bs-to-nal output case */
211 if (GST_READ_UINT24_BE (map.data) == 0x01) {
212 /* in bs-to-nal, a leading 0x00 is stripped from output */
213 fail_unless (gst_buffer_get_size (buffer) ==
214 vdata->data_to_verify_size - 1);
215 fail_unless (gst_buffer_memcmp (buffer, 0, vdata->data_to_verify + 1,
216 vdata->data_to_verify_size - 1) == 0);
217 gst_buffer_unmap (buffer, &map);
218 return TRUE;
219 } else if (GST_READ_UINT32_BE (map.data) == 0x01) {
220 gboolean aud = FALSE;
221 aud = vdata->buffer_counter % 2;
222 if (aud) {
223 fail_unless (gst_buffer_get_size (buffer) == sizeof (h264_aud));
224 fail_unless (gst_buffer_memcmp (buffer, 0, h264_aud,
225 gst_buffer_get_size (buffer)) == 0);
226 gst_buffer_unmap (buffer, &map);
227 return TRUE;
228 }
229
230 /* this is not avc, use default tests from parser.c */
231 gst_buffer_unmap (buffer, &map);
232 return FALSE;
233 }
234 /* header is merged in initial frame */
235 if (vdata->buffer_counter == 0) {
236 guint8 *data = map.data;
237
238 fail_unless (map.size == vdata->data_to_verify_size +
239 ctx_headers[0].size + ctx_headers[1].size + ctx_headers[2].size);
240 fail_unless (GST_READ_UINT32_BE (data) == ctx_headers[0].size - 4);
241 fail_unless (memcmp (data + 4, ctx_headers[0].data + 4,
242 ctx_headers[0].size - 4) == 0);
243 data += ctx_headers[0].size;
244 fail_unless (GST_READ_UINT32_BE (data) == ctx_headers[1].size - 4);
245 fail_unless (memcmp (data + 4, ctx_headers[1].data + 4,
246 ctx_headers[1].size - 4) == 0);
247 data += ctx_headers[1].size;
248 fail_unless (GST_READ_UINT32_BE (data) == ctx_headers[2].size - 4);
249 fail_unless (memcmp (data + 4, ctx_headers[2].data + 4,
250 ctx_headers[2].size - 4) == 0);
251 data += ctx_headers[2].size;
252 fail_unless (GST_READ_UINT32_BE (data) == vdata->data_to_verify_size - 4);
253 fail_unless (memcmp (data + 4, vdata->data_to_verify + 4,
254 vdata->data_to_verify_size - 4) == 0);
255 } else {
256 fail_unless (GST_READ_UINT32_BE (map.data) == map.size - 4);
257 fail_unless (map.size == vdata->data_to_verify_size);
258 fail_unless (memcmp (map.data + 4, vdata->data_to_verify + 4,
259 map.size - 4) == 0);
260 }
261 gst_buffer_unmap (buffer, &map);
262 return TRUE;
263 }
264
265 return FALSE;
266 }
267
268 /* A single access unit comprising of SPS, SEI, PPS and IDR frame */
269 static gboolean
verify_buffer_bs_au(buffer_verify_data_s * vdata,GstBuffer * buffer)270 verify_buffer_bs_au (buffer_verify_data_s * vdata, GstBuffer * buffer)
271 {
272 GstMapInfo map;
273
274 fail_unless (ctx_sink_template == &sinktemplate_bs_au);
275
276 /* Currently the parser can only predict DTS when dealing with raw data.
277 * Ensure that this behavior is being checked here. */
278 GST_DEBUG ("PTS: %" GST_TIME_FORMAT " DTS: %" GST_TIME_FORMAT,
279 GST_TIME_ARGS (GST_BUFFER_PTS (buffer)),
280 GST_TIME_ARGS (GST_BUFFER_DTS (buffer)));
281 fail_if (GST_BUFFER_PTS_IS_VALID (buffer));
282 fail_unless (GST_BUFFER_DTS_IS_VALID (buffer));
283
284 gst_buffer_map (buffer, &map, GST_MAP_READ);
285 fail_unless (map.size > 4);
286
287 if (vdata->buffer_counter == 0) {
288 guint8 *data = map.data;
289
290 /* AUD, SPS, SEI, PPS */
291 fail_unless (map.size == vdata->data_to_verify_size +
292 sizeof (h264_aud) + ctx_headers[0].size +
293 ctx_headers[1].size + ctx_headers[2].size);
294 fail_unless (memcmp (data, h264_aud, sizeof (h264_aud)) == 0);
295 data += sizeof (h264_aud);
296 fail_unless (memcmp (data, ctx_headers[0].data, ctx_headers[0].size) == 0);
297 data += ctx_headers[0].size;
298 fail_unless (memcmp (data, ctx_headers[1].data, ctx_headers[1].size) == 0);
299 data += ctx_headers[1].size;
300 fail_unless (memcmp (data, ctx_headers[2].data, ctx_headers[2].size) == 0);
301 data += ctx_headers[2].size;
302
303 /* IDR frame */
304 fail_unless (memcmp (data, vdata->data_to_verify,
305 vdata->data_to_verify_size) == 0);
306 } else {
307 /* IDR frame */
308 guint aud_size = sizeof (h264_aud);
309 fail_unless (map.size == vdata->data_to_verify_size + aud_size);
310 fail_unless (memcmp (map.data, h264_aud, aud_size) == 0);
311 fail_unless (memcmp (map.data + aud_size, vdata->data_to_verify,
312 map.size - aud_size) == 0);
313 }
314
315 gst_buffer_unmap (buffer, &map);
316 return TRUE;
317 }
318
319 static void
verify_h264parse_compatible_caps(guint profile_idc,guint constraint_set_flags,const char * profile)320 verify_h264parse_compatible_caps (guint profile_idc, guint constraint_set_flags,
321 const char *profile)
322 {
323 GstHarness *h;
324 GstBuffer *buf;
325 gchar *sink_caps_str;
326 guint8 *frame_sps;
327 guint frame_sps_len;
328 GstCaps *caps;
329
330 h = gst_harness_new ("h264parse");
331
332 sink_caps_str = g_strdup_printf ("video/x-h264"
333 ", parsed=(boolean)true"
334 ", stream-format=(string){ avc, avc3, byte-stream }"
335 ", alignment=(string){ au, nal }" ", profile=(string)%s", profile);
336
337 /* create and modify sps to the given profile */
338 frame_sps_len = sizeof (h264_sps);
339 frame_sps = g_malloc (frame_sps_len);
340 memcpy (frame_sps, h264_sps, frame_sps_len);
341 fill_h264_sps (&frame_sps[5], profile_idc, constraint_set_flags, 0);
342
343 /* set the peer pad (ie decoder) to the given profile to check the compatibility with the sps */
344 gst_harness_set_caps_str (h, "video/x-h264", sink_caps_str);
345 g_free (sink_caps_str);
346
347
348 /* push sps buffer */
349 buf = gst_buffer_new_and_alloc (frame_sps_len);
350 gst_buffer_fill (buf, 0, frame_sps, frame_sps_len);
351 g_free (frame_sps);
352 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
353 fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
354
355 /* check that the caps have been negociated correctly */
356 fail_unless (caps = gst_pad_get_current_caps (h->sinkpad));
357 gst_caps_unref (caps);
358
359 gst_harness_teardown (h);
360 }
361
GST_START_TEST(test_parse_normal)362 GST_START_TEST (test_parse_normal)
363 {
364 gst_parser_test_normal (h264_idrframe, sizeof (h264_idrframe));
365 }
366
367 GST_END_TEST;
368
369
GST_START_TEST(test_parse_drain_single)370 GST_START_TEST (test_parse_drain_single)
371 {
372 gst_parser_test_drain_single (h264_idrframe, sizeof (h264_idrframe));
373 }
374
375 GST_END_TEST;
376
377
GST_START_TEST(test_parse_drain_garbage)378 GST_START_TEST (test_parse_drain_garbage)
379 {
380 gst_parser_test_drain_garbage (h264_idrframe, sizeof (h264_idrframe),
381 garbage_frame, sizeof (garbage_frame));
382 }
383
384 GST_END_TEST;
385
GST_START_TEST(test_parse_split)386 GST_START_TEST (test_parse_split)
387 {
388 gst_parser_test_split (h264_idrframe, sizeof (h264_idrframe));
389 }
390
391 GST_END_TEST;
392
393
GST_START_TEST(test_parse_skip_garbage)394 GST_START_TEST (test_parse_skip_garbage)
395 {
396 gst_parser_test_skip_garbage (h264_idrframe, sizeof (h264_idrframe),
397 garbage_frame, sizeof (garbage_frame));
398 }
399
400 GST_END_TEST;
401
402 #define structure_get_int(s,f) \
403 (g_value_get_int(gst_structure_get_value(s,f)))
404 #define fail_unless_structure_field_int_equals(s,field,num) \
405 fail_unless_equals_int (structure_get_int(s,field), num)
406
407 #define structure_get_string(s,f) \
408 (g_value_get_string(gst_structure_get_value(s,f)))
409 #define fail_unless_structure_field_string_equals(s,field,name) \
410 fail_unless_equals_string (structure_get_string(s,field), name)
411
GST_START_TEST(test_parse_detect_stream)412 GST_START_TEST (test_parse_detect_stream)
413 {
414 GstCaps *caps;
415 GstStructure *s;
416 GstBuffer *buf;
417 const GValue *val;
418
419 /* parser does not really care that mpeg1 and mpeg2 frame data
420 * should be a bit different */
421 caps = gst_parser_test_get_output_caps (h264_idrframe, sizeof (h264_idrframe),
422 NULL);
423 fail_unless (caps != NULL);
424
425 /* Check that the negotiated caps are as expected */
426 /* When codec_data is present, parser assumes that data is version 4 */
427 GST_LOG ("h264 output caps: %" GST_PTR_FORMAT, caps);
428 s = gst_caps_get_structure (caps, 0);
429 fail_unless (gst_structure_has_name (s, "video/x-h264"));
430 fail_unless_structure_field_int_equals (s, "width", 32);
431 fail_unless_structure_field_int_equals (s, "height", 24);
432 fail_unless_structure_field_string_equals (s, "profile", "main");
433 fail_unless_structure_field_string_equals (s, "level", "2.1");
434
435 if (ctx_codec_data) {
436 fail_unless (gst_structure_has_field (s, "codec_data"));
437
438 /* check codec-data in more detail */
439 val = gst_structure_get_value (s, "codec_data");
440 fail_unless (val != NULL);
441 buf = gst_value_get_buffer (val);
442 fail_unless (buf != NULL);
443 fail_unless (gst_buffer_get_size (buf) == h264_codec_data_size);
444 fail_unless (gst_buffer_memcmp (buf, 0, h264_codec_data,
445 gst_buffer_get_size (buf)) == 0);
446 }
447
448 gst_caps_unref (caps);
449 }
450
451 GST_END_TEST;
452
GST_START_TEST(test_parse_detect_stream_with_hdr_sei)453 GST_START_TEST (test_parse_detect_stream_with_hdr_sei)
454 {
455 GstCaps *caps;
456 GstStructure *s;
457 GstBuffer *buf;
458 const GValue *val;
459 guint8 *h264_idr_plus_sei;
460 gsize h264_idr_plus_sei_size;
461
462 h264_idr_plus_sei_size =
463 sizeof (h264_sei_clli) + sizeof (h264_sei_mdcv) + sizeof (h264_idrframe);
464 h264_idr_plus_sei = malloc (h264_idr_plus_sei_size);
465
466 memcpy (h264_idr_plus_sei, h264_sei_clli, sizeof (h264_sei_clli));
467 memcpy (h264_idr_plus_sei + sizeof (h264_sei_clli), h264_sei_mdcv,
468 sizeof (h264_sei_mdcv));
469 memcpy (h264_idr_plus_sei + sizeof (h264_sei_clli) + sizeof (h264_sei_mdcv),
470 h264_idrframe, sizeof (h264_idrframe));
471
472 /* parser does not really care that mpeg1 and mpeg2 frame data
473 * should be a bit different */
474 caps =
475 gst_parser_test_get_output_caps (h264_idr_plus_sei,
476 h264_idr_plus_sei_size, NULL);
477 fail_unless (caps != NULL);
478
479 /* Check that the negotiated caps are as expected */
480 /* When codec_data is present, parser assumes that data is version 4 */
481 GST_LOG ("h264 output caps: %" GST_PTR_FORMAT, caps);
482 s = gst_caps_get_structure (caps, 0);
483 fail_unless (gst_structure_has_name (s, "video/x-h264"));
484 fail_unless_structure_field_int_equals (s, "width", 32);
485 fail_unless_structure_field_int_equals (s, "height", 24);
486 fail_unless_structure_field_string_equals (s, "profile", "main");
487 fail_unless_structure_field_string_equals (s, "level", "2.1");
488
489 fail_unless_structure_field_string_equals (s, "mastering-display-info",
490 "7500:3000:34000:16000:13200:34500:15635:16450:10000000:1");
491 fail_unless_structure_field_string_equals (s, "content-light-level",
492 "1000:400");
493 if (ctx_codec_data) {
494 fail_unless (gst_structure_has_field (s, "codec_data"));
495
496 /* check codec-data in more detail */
497 val = gst_structure_get_value (s, "codec_data");
498 fail_unless (val != NULL);
499 buf = gst_value_get_buffer (val);
500 fail_unless (buf != NULL);
501 fail_unless (gst_buffer_get_size (buf) == h264_codec_data_size);
502 fail_unless (gst_buffer_memcmp (buf, 0, h264_codec_data,
503 gst_buffer_get_size (buf)) == 0);
504 }
505 g_free (h264_idr_plus_sei);
506 gst_caps_unref (caps);
507 }
508
509 GST_END_TEST;
510
511 static GstStaticPadTemplate srctemplate_avc_au_and_bs_au =
512 GST_STATIC_PAD_TEMPLATE ("src",
513 GST_PAD_SRC,
514 GST_PAD_ALWAYS,
515 GST_STATIC_CAPS (SRC_CAPS_TMPL
516 ", stream-format = (string) avc, alignment = (string) au; "
517 SRC_CAPS_TMPL
518 ", stream-format = (string) byte-stream, alignment = (string) au")
519 );
520
GST_START_TEST(test_sink_caps_reordering)521 GST_START_TEST (test_sink_caps_reordering)
522 {
523 /* Upstream can handle avc and byte-stream format (in that preference order)
524 * and downstream requires byte-stream.
525 * Parser reorder upstream's caps to prefer the format requested downstream
526 * and so avoid doing useless conversions. */
527 GstElement *parser;
528 GstPad *sink, *src;
529 GstCaps *src_caps, *sink_caps;
530 GstStructure *s;
531
532 parser = gst_check_setup_element ("h264parse");
533 fail_unless (parser);
534
535 src = gst_check_setup_src_pad (parser, &srctemplate_avc_au_and_bs_au);
536 sink = gst_check_setup_sink_pad (parser, &sinktemplate_bs_au);
537
538 src_caps = gst_pad_get_pad_template_caps (src);
539 sink_caps = gst_pad_peer_query_caps (src, src_caps);
540
541 /* Sink pad has both format on its sink caps but prefer to use byte-stream */
542 g_assert_cmpuint (gst_caps_get_size (sink_caps), ==, 2);
543
544 s = gst_caps_get_structure (sink_caps, 0);
545 g_assert_cmpstr (gst_structure_get_name (s), ==, "video/x-h264");
546 g_assert_cmpstr (gst_structure_get_string (s, "alignment"), ==, "au");
547 g_assert_cmpstr (gst_structure_get_string (s, "stream-format"), ==,
548 "byte-stream");
549
550 s = gst_caps_get_structure (sink_caps, 1);
551 g_assert_cmpstr (gst_structure_get_name (s), ==, "video/x-h264");
552 g_assert_cmpstr (gst_structure_get_string (s, "alignment"), ==, "au");
553 g_assert_cmpstr (gst_structure_get_string (s, "stream-format"), ==, "avc");
554
555 gst_caps_unref (src_caps);
556 gst_caps_unref (sink_caps);
557 gst_object_unref (src);
558 gst_object_unref (sink);
559 gst_object_unref (parser);
560 }
561
562 GST_END_TEST;
563
GST_START_TEST(test_parse_compatible_caps)564 GST_START_TEST (test_parse_compatible_caps)
565 {
566 verify_h264parse_compatible_caps (GST_H264_PROFILE_BASELINE, 0, "extended");
567
568 verify_h264parse_compatible_caps (GST_H264_PROFILE_BASELINE,
569 SPS_CONSTRAINT_SET_FLAG_1, "baseline");
570 verify_h264parse_compatible_caps (GST_H264_PROFILE_BASELINE,
571 SPS_CONSTRAINT_SET_FLAG_1, "main");
572 verify_h264parse_compatible_caps (GST_H264_PROFILE_BASELINE,
573 SPS_CONSTRAINT_SET_FLAG_1, "high");
574 verify_h264parse_compatible_caps (GST_H264_PROFILE_BASELINE,
575 SPS_CONSTRAINT_SET_FLAG_1, "high-10");
576 verify_h264parse_compatible_caps (GST_H264_PROFILE_BASELINE,
577 SPS_CONSTRAINT_SET_FLAG_1, "high-4:2:2");
578 verify_h264parse_compatible_caps (GST_H264_PROFILE_BASELINE,
579 SPS_CONSTRAINT_SET_FLAG_1, "high-4:4:4");
580
581 verify_h264parse_compatible_caps (GST_H264_PROFILE_MAIN, 0, "high");
582 verify_h264parse_compatible_caps (GST_H264_PROFILE_MAIN, 0, "high-10");
583 verify_h264parse_compatible_caps (GST_H264_PROFILE_MAIN, 0, "high-4:2:2");
584 verify_h264parse_compatible_caps (GST_H264_PROFILE_MAIN, 0, "high-4:4:4");
585
586 verify_h264parse_compatible_caps (GST_H264_PROFILE_EXTENDED,
587 SPS_CONSTRAINT_SET_FLAG_0, "baseline");
588
589 verify_h264parse_compatible_caps (GST_H264_PROFILE_EXTENDED,
590 SPS_CONSTRAINT_SET_FLAG_0 | SPS_CONSTRAINT_SET_FLAG_1,
591 "constrained-baseline");
592 verify_h264parse_compatible_caps (GST_H264_PROFILE_EXTENDED,
593 SPS_CONSTRAINT_SET_FLAG_0 | SPS_CONSTRAINT_SET_FLAG_1, "baseline");
594 verify_h264parse_compatible_caps (GST_H264_PROFILE_EXTENDED,
595 SPS_CONSTRAINT_SET_FLAG_0 | SPS_CONSTRAINT_SET_FLAG_1, "main");
596 verify_h264parse_compatible_caps (GST_H264_PROFILE_EXTENDED,
597 SPS_CONSTRAINT_SET_FLAG_0 | SPS_CONSTRAINT_SET_FLAG_1, "high");
598 verify_h264parse_compatible_caps (GST_H264_PROFILE_EXTENDED,
599 SPS_CONSTRAINT_SET_FLAG_0 | SPS_CONSTRAINT_SET_FLAG_1, "high-10");
600 verify_h264parse_compatible_caps (GST_H264_PROFILE_EXTENDED,
601 SPS_CONSTRAINT_SET_FLAG_0 | SPS_CONSTRAINT_SET_FLAG_1, "high-4:2:2");
602 verify_h264parse_compatible_caps (GST_H264_PROFILE_EXTENDED,
603 SPS_CONSTRAINT_SET_FLAG_0 | SPS_CONSTRAINT_SET_FLAG_1, "high-4:4:4");
604
605 verify_h264parse_compatible_caps (GST_H264_PROFILE_EXTENDED,
606 SPS_CONSTRAINT_SET_FLAG_1, "main");
607 verify_h264parse_compatible_caps (GST_H264_PROFILE_EXTENDED,
608 SPS_CONSTRAINT_SET_FLAG_1, "high");
609 verify_h264parse_compatible_caps (GST_H264_PROFILE_EXTENDED,
610 SPS_CONSTRAINT_SET_FLAG_1, "high-10");
611 verify_h264parse_compatible_caps (GST_H264_PROFILE_EXTENDED,
612 SPS_CONSTRAINT_SET_FLAG_1, "high-4:2:2");
613 verify_h264parse_compatible_caps (GST_H264_PROFILE_EXTENDED,
614 SPS_CONSTRAINT_SET_FLAG_1, "high-4:4:4");
615
616 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH, 0, "high-10");
617 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH, 0, "high-4:2:2");
618 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH, 0, "high-4:4:4");
619
620 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH,
621 SPS_CONSTRAINT_SET_FLAG_1, "main");
622 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH,
623 SPS_CONSTRAINT_SET_FLAG_1, "high-10");
624 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH,
625 SPS_CONSTRAINT_SET_FLAG_1, "high-4:2:2");
626 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH,
627 SPS_CONSTRAINT_SET_FLAG_1, "high-4:4:4");
628
629 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH10, 0, "high-4:2:2");
630 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH10, 0, "high-4:4:4");
631 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH10,
632 SPS_CONSTRAINT_SET_FLAG_1, "main");
633 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH10,
634 SPS_CONSTRAINT_SET_FLAG_1, "high");
635 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH10,
636 SPS_CONSTRAINT_SET_FLAG_1, "high-4:2:2");
637 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH10,
638 SPS_CONSTRAINT_SET_FLAG_1, "high-4:4:4");
639
640 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH10,
641 SPS_CONSTRAINT_SET_FLAG_3, "high-10");
642 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH10,
643 SPS_CONSTRAINT_SET_FLAG_3, "high-4:2:2");
644 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH10,
645 SPS_CONSTRAINT_SET_FLAG_3, "high-4:4:4");
646 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH10,
647 SPS_CONSTRAINT_SET_FLAG_3, "high-4:2:2-intra");
648 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH10,
649 SPS_CONSTRAINT_SET_FLAG_3, "high-4:4:4-intra");
650
651 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH_422, 0, "high-4:2:2");
652 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH_422, 0, "high-4:4:4");
653
654 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH_422,
655 SPS_CONSTRAINT_SET_FLAG_1, "main");
656 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH_422,
657 SPS_CONSTRAINT_SET_FLAG_1, "high");
658 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH_422,
659 SPS_CONSTRAINT_SET_FLAG_1, "high-10");
660 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH_422,
661 SPS_CONSTRAINT_SET_FLAG_1, "high-4:4:4");
662
663 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH_422,
664 SPS_CONSTRAINT_SET_FLAG_3, "high-4:2:2");
665 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH_422,
666 SPS_CONSTRAINT_SET_FLAG_3, "high-4:4:4");
667 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH_422,
668 SPS_CONSTRAINT_SET_FLAG_3, "high-4:2:2-intra");
669 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH_422,
670 SPS_CONSTRAINT_SET_FLAG_3, "high-4:4:4-intra");
671
672 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH_444,
673 SPS_CONSTRAINT_SET_FLAG_1, "main");
674 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH_444,
675 SPS_CONSTRAINT_SET_FLAG_1, "high");
676 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH_444,
677 SPS_CONSTRAINT_SET_FLAG_1, "high-10");
678 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH_444,
679 SPS_CONSTRAINT_SET_FLAG_1, "high-4:2:2");
680
681 verify_h264parse_compatible_caps (GST_H264_PROFILE_HIGH_444,
682 SPS_CONSTRAINT_SET_FLAG_3, "high-4:4:4");
683 }
684
685 GST_END_TEST;
686
687 static Suite *
h264parse_suite(void)688 h264parse_suite (void)
689 {
690 Suite *s = suite_create (ctx_suite);
691 TCase *tc_chain = tcase_create ("general");
692
693 suite_add_tcase (s, tc_chain);
694 tcase_add_test (tc_chain, test_parse_normal);
695 tcase_add_test (tc_chain, test_parse_drain_single);
696 tcase_add_test (tc_chain, test_parse_drain_garbage);
697 tcase_add_test (tc_chain, test_parse_split);
698 tcase_add_test (tc_chain, test_parse_skip_garbage);
699 tcase_add_test (tc_chain, test_parse_detect_stream);
700 if (ctx_hdr_sei)
701 tcase_add_test (tc_chain, test_parse_detect_stream_with_hdr_sei);
702 tcase_add_test (tc_chain, test_sink_caps_reordering);
703
704 return s;
705 }
706
707 static gboolean
verify_buffer_packetized(buffer_verify_data_s * vdata,GstBuffer * buffer)708 verify_buffer_packetized (buffer_verify_data_s * vdata, GstBuffer * buffer)
709 {
710 GstMapInfo map;
711
712 gst_buffer_map (buffer, &map, GST_MAP_READ);
713
714 fail_unless (map.size > 4);
715 fail_unless (GST_READ_UINT32_BE (map.data) == 0x01);
716 if (vdata->discard) {
717 /* check separate header NALs */
718 guint8 *data;
719 gint size;
720
721 if (vdata->buffer_counter == 0) {
722 data = h264_aud;
723 size = sizeof (h264_aud);
724 vdata->discard++;
725 } else if (vdata->buffer_counter == 1) {
726 data = h264_sps;
727 size = sizeof (h264_sps);
728 } else {
729 data = h264_pps;
730 size = sizeof (h264_pps);
731 }
732
733 fail_unless (map.size == size);
734 fail_unless (memcmp (map.data + 4, data + 4, size - 4) == 0);
735 } else {
736 guint8 *data;
737 gint size;
738 gboolean aud = vdata->buffer_counter % 2;
739 if (aud) {
740 data = h264_aud;
741 size = sizeof (h264_aud);
742 } else {
743 data = (gpointer) vdata->data_to_verify;
744 size = map.size;
745 }
746
747 fail_unless (map.size == size);
748 fail_unless (memcmp (map.data + 4, data + 4, size - 4) == 0);
749 }
750 gst_buffer_unmap (buffer, &map);
751
752 return TRUE;
753 }
754
GST_START_TEST(test_parse_packetized)755 GST_START_TEST (test_parse_packetized)
756 {
757 guint8 *frame;
758 GstCaps *caps;
759 GstBuffer *cdata;
760 GstStructure *s;
761 gchar *desc;
762
763 /* make AVC frame */
764 frame = g_malloc (sizeof (h264_idrframe));
765 GST_WRITE_UINT32_BE (frame, sizeof (h264_idrframe) - 4);
766 memcpy (frame + 4, h264_idrframe + 4, sizeof (h264_idrframe) - 4);
767
768 /* some caps messing */
769 caps = gst_caps_from_string (SRC_CAPS_TMPL);
770 cdata =
771 gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, h264_codec_data,
772 h264_codec_data_size, 0, h264_codec_data_size, NULL, NULL);
773 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, cdata,
774 "stream-format", G_TYPE_STRING, "avc", NULL);
775 gst_buffer_unref (cdata);
776 desc = gst_caps_to_string (caps);
777 gst_caps_unref (caps);
778
779 caps = gst_parser_test_get_output_caps (frame, sizeof (h264_idrframe), desc);
780 g_free (desc);
781 g_free (frame);
782
783 /* minor caps checks */
784 GST_LOG ("h264 output caps: %" GST_PTR_FORMAT, caps);
785 s = gst_caps_get_structure (caps, 0);
786 fail_unless (gst_structure_has_name (s, "video/x-h264"));
787 fail_unless_structure_field_int_equals (s, "width", 32);
788 fail_unless_structure_field_int_equals (s, "height", 24);
789
790 gst_caps_unref (caps);
791 }
792
793 GST_END_TEST;
794
795 static Suite *
h264parse_packetized_suite(void)796 h264parse_packetized_suite (void)
797 {
798 Suite *s = suite_create (ctx_suite);
799 TCase *tc_chain = tcase_create ("general");
800
801 suite_add_tcase (s, tc_chain);
802 tcase_add_test (tc_chain, test_parse_packetized);
803
804 return s;
805 }
806
807 /* These were generated using pipeline:
808 * gst-launch-1.0 videotestsrc num-buffers=2 pattern=green \
809 * ! video/x-raw,width=128,height=128 \
810 * ! openh264enc num-slices=2 \
811 * ! fakesink dump=1
812 */
813
814 /* codec-data */
815 static guint8 h264_slicing_codec_data[] = {
816 0x01, 0x42, 0xc0, 0x0b, 0xff, 0xe1, 0x00, 0x0e,
817 0x67, 0x42, 0xc0, 0x0b, 0x8c, 0x8d, 0x41, 0x02,
818 0x24, 0x03, 0xc2, 0x21, 0x1a, 0x80, 0x01, 0x00,
819 0x04, 0x68, 0xce, 0x3c, 0x80
820 };
821
822 /* SPS */
823 static guint8 h264_slicing_sps[] = {
824 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x0b,
825 0x8c, 0x8d, 0x41, 0x02, 0x24, 0x03, 0xc2, 0x21,
826 0x1a, 0x80
827 };
828
829 /* PPS */
830 static guint8 h264_slicing_pps[] = {
831 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x3c, 0x80
832 };
833
834 /* IDR Slice 1 */
835 static guint8 h264_idr_slice_1[] = {
836 0x00, 0x00, 0x00, 0x01, 0x65, 0xb8, 0x00, 0x04,
837 0x00, 0x00, 0x11, 0xff, 0xff, 0xf8, 0x22, 0x8a,
838 0x1f, 0x1c, 0x00, 0x04, 0x0a, 0x63, 0x80, 0x00,
839 0x81, 0xec, 0x9a, 0x93, 0x93, 0x93, 0x93, 0x93,
840 0x93, 0xad, 0x57, 0x5d, 0x75, 0xd7, 0x5d, 0x75,
841 0xd7, 0x5d, 0x75, 0xd7, 0x5d, 0x75, 0xd7, 0x5d,
842 0x75, 0xd7, 0x5d, 0x78
843 };
844
845 /* IDR Slice 2 */
846 static guint8 h264_idr_slice_2[] = {
847 0x00, 0x00, 0x00, 0x01, 0x65, 0x04, 0x2e, 0x00,
848 0x01, 0x00, 0x00, 0x04, 0x7f, 0xff, 0xfe, 0x08,
849 0xa2, 0x87, 0xc7, 0x00, 0x01, 0x02, 0x98, 0xe0,
850 0x00, 0x20, 0x7b, 0x26, 0xa4, 0xe4, 0xe4, 0xe4,
851 0xe4, 0xe4, 0xeb, 0x55, 0xd7, 0x5d, 0x75, 0xd7,
852 0x5d, 0x75, 0xd7, 0x5d, 0x75, 0xd7, 0x5d, 0x75,
853 0xd7, 0x5d, 0x75, 0xd7, 0x5e
854 };
855
856 /* P Slice 1 */
857 static guint8 h264_slice_1[] = {
858 0x00, 0x00, 0x00, 0x01, 0x61, 0xe0, 0x00, 0x40,
859 0x00, 0x9c, 0x82, 0x3c, 0x10, 0xc0
860 };
861
862 /* P Slice 2 */
863 static guint8 h264_slice_2[] = {
864 0x00, 0x00, 0x00, 0x01, 0x61, 0x04, 0x38, 0x00,
865 0x10, 0x00, 0x27, 0x20, 0x8f, 0x04, 0x30
866 };
867
868 static inline GstBuffer *
wrap_buffer(const guint8 * buf,gsize size,GstClockTime pts,GstBufferFlags flags)869 wrap_buffer (const guint8 * buf, gsize size, GstClockTime pts,
870 GstBufferFlags flags)
871 {
872 GstBuffer *buffer;
873
874 buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
875 (gpointer) buf, size, 0, size, NULL, NULL);
876 GST_BUFFER_PTS (buffer) = pts;
877 GST_BUFFER_FLAGS (buffer) |= flags;
878
879 return buffer;
880 }
881
882 static inline GstBuffer *
composite_buffer(GstClockTime pts,GstBufferFlags flags,gint count,...)883 composite_buffer (GstClockTime pts, GstBufferFlags flags, gint count, ...)
884 {
885 va_list vl;
886 gint i;
887 const guint8 *data;
888 gsize size;
889 GstBuffer *buffer;
890
891 va_start (vl, count);
892
893 buffer = gst_buffer_new ();
894 for (i = 0; i < count; i++) {
895 data = va_arg (vl, guint8 *);
896 size = va_arg (vl, gsize);
897
898 buffer = gst_buffer_append (buffer, wrap_buffer (data, size, 0, 0));
899 }
900 GST_BUFFER_PTS (buffer) = pts;
901 GST_BUFFER_FLAGS (buffer) |= flags;
902
903 va_end (vl);
904
905 return buffer;
906 }
907
908 #define pull_and_check_full(h, data, size, pts, flags) \
909 { \
910 GstBuffer *b = gst_harness_pull (h); \
911 gst_check_buffer_data (b, data, size); \
912 fail_unless_equals_clocktime (GST_BUFFER_PTS (b), pts); \
913 if (flags) \
914 fail_unless (GST_BUFFER_FLAG_IS_SET (b, flags)); \
915 gst_buffer_unref (b); \
916 }
917
918 #define pull_and_check(h, data, pts, flags) \
919 pull_and_check_full (h, data, sizeof (data), pts, flags)
920
921 #define pull_and_drop(h) \
922 G_STMT_START { \
923 GstBuffer *b = gst_harness_pull (h); \
924 gst_buffer_unref (b); \
925 } G_STMT_END;
926
GST_START_TEST(test_parse_sliced_nal_nal)927 GST_START_TEST (test_parse_sliced_nal_nal)
928 {
929 GstHarness *h = gst_harness_new ("h264parse");
930 GstBuffer *buf;
931
932 gst_harness_set_caps_str (h,
933 "video/x-h264,stream-format=byte-stream,alignment=nal,parsed=false,framerate=30/1",
934 "video/x-h264,stream-format=byte-stream,alignment=nal,parsed=true");
935
936 buf = wrap_buffer (h264_slicing_sps, sizeof (h264_slicing_sps), 10, 0);
937 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
938
939 buf = wrap_buffer (h264_slicing_pps, sizeof (h264_slicing_pps), 10, 0);
940 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
941
942 /* parser must have inserted AUD before the headers, with the same PTS */
943 pull_and_check (h, h264_aud, 10, 0);
944
945 /* drop the header buffers */
946 while ((buf = gst_harness_try_pull (h)))
947 gst_buffer_unref (buf);
948
949 /* reported latency must be zero */
950 fail_unless_equals_clocktime (gst_harness_query_latency (h), 0);
951
952 /* test some flow with 2 slices.
953 * 1st slice gets the input PTS, second gets NONE */
954 buf = wrap_buffer (h264_idr_slice_1, sizeof (h264_idr_slice_1), 100, 0);
955 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
956 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
957 pull_and_check (h, h264_idr_slice_1, 100, 0);
958
959 buf = wrap_buffer (h264_idr_slice_2, sizeof (h264_idr_slice_2), 100, 0);
960 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
961 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
962 pull_and_check (h, h264_idr_slice_2, -1, 0);
963
964 buf = wrap_buffer (h264_idr_slice_1, sizeof (h264_idr_slice_1), 200, 0);
965 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
966 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2);
967 pull_and_check (h, h264_aud, 200, 0);
968 pull_and_check (h, h264_idr_slice_1, 200, 0);
969
970 buf = wrap_buffer (h264_idr_slice_2, sizeof (h264_idr_slice_2), 200, 0);
971 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
972 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
973 pull_and_check (h, h264_idr_slice_2, -1, 0);
974
975 buf = wrap_buffer (h264_idr_slice_1, sizeof (h264_idr_slice_1), 250, 0);
976 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
977 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2);
978 pull_and_check (h, h264_aud, 250, 0);
979 pull_and_check (h, h264_idr_slice_1, 250, 0);
980
981 /* 1st slice starts a new AU, even though the previous one is incomplete.
982 * DISCONT must also be propagated */
983 buf = wrap_buffer (h264_idr_slice_1, sizeof (h264_idr_slice_1), 400,
984 GST_BUFFER_FLAG_DISCONT);
985 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
986 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2);
987 pull_and_check (h, h264_aud, 400, 0);
988 pull_and_check (h, h264_idr_slice_1, 400, GST_BUFFER_FLAG_DISCONT);
989
990 gst_harness_teardown (h);
991 }
992
993 GST_END_TEST;
994
GST_START_TEST(test_parse_sliced_au_nal)995 GST_START_TEST (test_parse_sliced_au_nal)
996 {
997 GstHarness *h = gst_harness_new ("h264parse");
998 GstBuffer *buf;
999
1000 gst_harness_set_caps_str (h,
1001 "video/x-h264,stream-format=byte-stream,alignment=au,parsed=false,framerate=30/1",
1002 "video/x-h264,stream-format=byte-stream,alignment=nal,parsed=true");
1003
1004 /* push the whole AU in a single buffer */
1005 buf = composite_buffer (100, 0, 4,
1006 h264_slicing_sps, sizeof (h264_slicing_sps),
1007 h264_slicing_pps, sizeof (h264_slicing_pps),
1008 h264_idr_slice_1, sizeof (h264_idr_slice_1),
1009 h264_idr_slice_2, sizeof (h264_idr_slice_2));
1010 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1011
1012 /* parser must have inserted AUD before the headers, with the same PTS */
1013 pull_and_check (h, h264_aud, 100, 0);
1014
1015 /* drop the headers */
1016 fail_unless (gst_harness_buffers_in_queue (h) > 2);
1017 while (gst_harness_buffers_in_queue (h) > 2)
1018 pull_and_drop (h);
1019
1020 /* reported latency must be zero */
1021 fail_unless_equals_clocktime (gst_harness_query_latency (h), 0);
1022
1023 /* 1st slice here doens't have a PTS
1024 * because it was present in the first header NAL */
1025 pull_and_check (h, h264_idr_slice_1, -1, 0);
1026 pull_and_check (h, h264_idr_slice_2, -1, 0);
1027
1028 /* new AU. we expect AUD to be inserted and 1st slice to have the same PTS */
1029 buf = composite_buffer (200, 0, 2,
1030 h264_idr_slice_1, sizeof (h264_idr_slice_1),
1031 h264_idr_slice_2, sizeof (h264_idr_slice_2));
1032 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1033 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 3);
1034 pull_and_check (h, h264_aud, 200, 0);
1035 pull_and_check (h, h264_idr_slice_1, 200, 0);
1036 pull_and_check (h, h264_idr_slice_2, -1, 0);
1037
1038 /* DISCONT must be propagated */
1039 buf = composite_buffer (400, GST_BUFFER_FLAG_DISCONT, 2,
1040 h264_idr_slice_1, sizeof (h264_idr_slice_1),
1041 h264_idr_slice_2, sizeof (h264_idr_slice_2));
1042 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1043 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 3);
1044 pull_and_check (h, h264_aud, 400, 0);
1045 pull_and_check (h, h264_idr_slice_1, 400, GST_BUFFER_FLAG_DISCONT);
1046 pull_and_check (h, h264_idr_slice_2, -1, 0);
1047
1048 gst_harness_teardown (h);
1049 }
1050
1051 GST_END_TEST;
1052
GST_START_TEST(test_parse_sliced_nal_au)1053 GST_START_TEST (test_parse_sliced_nal_au)
1054 {
1055 GstHarness *h = gst_harness_new ("h264parse");
1056 GstBuffer *buf;
1057
1058 gst_harness_set_caps_str (h,
1059 "video/x-h264,stream-format=byte-stream,alignment=nal,parsed=false,framerate=30/1",
1060 "video/x-h264,stream-format=byte-stream,alignment=au,parsed=true");
1061
1062 buf = wrap_buffer (h264_slicing_sps, sizeof (h264_slicing_sps), 100, 0);
1063 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1064
1065 buf = wrap_buffer (h264_slicing_pps, sizeof (h264_slicing_pps), 100, 0);
1066 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1067
1068 buf = wrap_buffer (h264_idr_slice_1, sizeof (h264_idr_slice_1), 100, 0);
1069 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1070
1071 buf = wrap_buffer (h264_idr_slice_2, sizeof (h264_idr_slice_2), 100, 0);
1072 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1073
1074 /* no output yet, it will be pushed as soon as
1075 * the parser recognizes the new AU */
1076 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
1077
1078 buf = wrap_buffer (h264_idr_slice_1, sizeof (h264_idr_slice_1), 200, 0);
1079 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1080
1081 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
1082
1083 {
1084 GstMapInfo info;
1085
1086 buf = composite_buffer (100, 0, 5,
1087 h264_aud, sizeof (h264_aud),
1088 h264_slicing_sps, sizeof (h264_slicing_sps),
1089 h264_slicing_pps, sizeof (h264_slicing_pps),
1090 h264_idr_slice_1, sizeof (h264_idr_slice_1),
1091 h264_idr_slice_2, sizeof (h264_idr_slice_2));
1092 gst_buffer_map (buf, &info, GST_MAP_READ);
1093
1094 pull_and_check_full (h, info.data, info.size, 100, 0);
1095
1096 gst_buffer_unmap (buf, &info);
1097 gst_buffer_unref (buf);
1098 }
1099
1100 /* reported latency must be 1 frame (@ 30fps because of sink pad caps) */
1101 fail_unless_equals_clocktime (gst_harness_query_latency (h),
1102 gst_util_uint64_scale (GST_SECOND, 1, 30));
1103
1104 gst_harness_teardown (h);
1105 }
1106
1107 GST_END_TEST;
1108
GST_START_TEST(test_parse_sliced_sps_pps_sps)1109 GST_START_TEST (test_parse_sliced_sps_pps_sps)
1110 {
1111 GstHarness *h = gst_harness_new ("h264parse");
1112 GstBuffer *buf;
1113
1114 gst_harness_set_caps_str (h,
1115 "video/x-h264,stream-format=byte-stream,alignment=nal,parsed=false,framerate=30/1",
1116 "video/x-h264,stream-format=byte-stream,alignment=au,parsed=true");
1117
1118 buf = wrap_buffer (h264_slicing_sps, sizeof (h264_slicing_sps), 100, 0);
1119 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1120
1121 buf = wrap_buffer (h264_slicing_pps, sizeof (h264_slicing_pps), 100, 0);
1122 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1123
1124 buf = wrap_buffer (h264_idr_slice_1, sizeof (h264_idr_slice_1), 100, 0);
1125 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1126
1127 /* no output yet, it will be pushed as soon as
1128 * the parser recognizes the new AU */
1129 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
1130
1131 buf = wrap_buffer (h264_slicing_sps, sizeof (h264_slicing_sps), 200, 0);
1132 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1133
1134 /* no PP, just a SPS here is valid */
1135
1136 buf = wrap_buffer (h264_idr_slice_1, sizeof (h264_idr_slice_1), 200, 0);
1137 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1138
1139 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
1140
1141 buf = wrap_buffer (h264_idr_slice_1, sizeof (h264_idr_slice_1), 300, 0);
1142 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1143
1144 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2);
1145
1146 {
1147 GstMapInfo info;
1148
1149 buf = composite_buffer (100, 0, 4,
1150 h264_aud, sizeof (h264_aud),
1151 h264_slicing_sps, sizeof (h264_slicing_sps),
1152 h264_slicing_pps, sizeof (h264_slicing_pps),
1153 h264_idr_slice_1, sizeof (h264_idr_slice_1));
1154 gst_buffer_map (buf, &info, GST_MAP_READ);
1155
1156 pull_and_check_full (h, info.data, info.size, 100, 0);
1157
1158 gst_buffer_unmap (buf, &info);
1159 gst_buffer_unref (buf);
1160
1161 buf = composite_buffer (200, 0, 3,
1162 h264_aud, sizeof (h264_aud),
1163 h264_slicing_sps, sizeof (h264_slicing_sps),
1164 h264_idr_slice_1, sizeof (h264_idr_slice_1));
1165 gst_buffer_map (buf, &info, GST_MAP_READ);
1166
1167 pull_and_check_full (h, info.data, info.size, 200, 0);
1168
1169 gst_buffer_unmap (buf, &info);
1170 gst_buffer_unref (buf);
1171 }
1172
1173 gst_harness_teardown (h);
1174 }
1175
1176 GST_END_TEST;
1177
1178
1179 static Suite *
h264parse_sliced_suite(void)1180 h264parse_sliced_suite (void)
1181 {
1182 Suite *s = suite_create (ctx_suite);
1183 TCase *tc_chain = tcase_create ("general");
1184
1185 suite_add_tcase (s, tc_chain);
1186 tcase_add_test (tc_chain, test_parse_sliced_nal_nal);
1187 tcase_add_test (tc_chain, test_parse_sliced_au_nal);
1188 tcase_add_test (tc_chain, test_parse_sliced_nal_au);
1189 tcase_add_test (tc_chain, test_parse_sliced_sps_pps_sps);
1190
1191 return s;
1192 }
1193
1194
GST_START_TEST(test_parse_sei_closedcaptions)1195 GST_START_TEST (test_parse_sei_closedcaptions)
1196 {
1197 GstVideoCaptionMeta *cc;
1198 GstHarness *h;
1199 GstBuffer *buf;
1200
1201 const guint8 cc_sei_plus_idr[] = {
1202 0x00, 0x00, 0x00, 0x4b, 0x06, 0x04, 0x47, 0xb5, 0x00, 0x31, 0x47, 0x41,
1203 0x39, 0x34, 0x03, 0xd4,
1204 0xff, 0xfc, 0x80, 0x80, 0xfd, 0x80, 0x80, 0xfa, 0x00, 0x00, 0xfa, 0x00,
1205 0x00, 0xfa, 0x00, 0x00,
1206 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1207 0xfa, 0x00, 0x00, 0xfa,
1208 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
1209 0x00, 0x00, 0xfa, 0x00,
1210 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00,
1211 0x00, 0xff, 0x80,
1212 /* IDR frame (doesn't necessarily match caps) */
1213 0x00, 0x00, 0x00, 0x14, 0x65, 0x88, 0x84, 0x00,
1214 0x10, 0xff, 0xfe, 0xf6, 0xf0, 0xfe, 0x05, 0x36,
1215 0x56, 0x04, 0x50, 0x96, 0x7b, 0x3f, 0x53, 0xe1
1216 };
1217 const gsize cc_sei_plus_idr_size = sizeof (cc_sei_plus_idr);
1218
1219 h = gst_harness_new ("h264parse");
1220
1221 gst_harness_set_src_caps_str (h,
1222 "video/x-h264, stream-format=(string)avc, alignment=(string)au,"
1223 " codec_data=(buffer)014d4015ffe10017674d4015eca4bf2e0220000003002ee6b28001e2c5b2c001000468ebecb2,"
1224 " width=(int)32, height=(int)24, framerate=(fraction)30/1,"
1225 " pixel-aspect-ratio=(fraction)1/1");
1226
1227 buf = gst_buffer_new_and_alloc (cc_sei_plus_idr_size);
1228 gst_buffer_fill (buf, 0, cc_sei_plus_idr, cc_sei_plus_idr_size);
1229 fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1230
1231 buf = gst_harness_pull (h);
1232 cc = gst_buffer_get_video_caption_meta (buf);
1233 fail_unless (cc != NULL);
1234 fail_unless_equals_int (cc->caption_type, GST_VIDEO_CAPTION_TYPE_CEA708_RAW);
1235 fail_unless_equals_int (cc->size, 60);
1236 fail_unless_equals_int (cc->data[0], 0xfc);
1237 fail_unless_equals_int (cc->data[3], 0xfd);
1238 gst_buffer_unref (buf);
1239
1240 gst_harness_teardown (h);
1241 }
1242
1243 GST_END_TEST;
1244
GST_START_TEST(test_parse_skip_to_4bytes_sc)1245 GST_START_TEST (test_parse_skip_to_4bytes_sc)
1246 {
1247 GstHarness *h;
1248 GstBuffer *buf1, *buf2;
1249 const guint8 initial_bytes[] = { 0x00, 0x00, 0x00, 0x00, 0x01 };
1250 GstMapInfo map;
1251
1252 h = gst_harness_new ("h264parse");
1253
1254 gst_harness_set_caps_str (h, "video/x-h264, stream-format=byte-stream",
1255 "video/x-h264, stream-format=byte-stream, alignment=nal");
1256
1257 /* padding bytes, four bytes start code. */
1258 buf1 = wrap_buffer (initial_bytes, sizeof (initial_bytes), 100, 0);
1259
1260 /* The second contains the an AUD, starting from NAL identification byte,
1261 * and is followed by SPS, PPS and IDR */
1262 buf2 = composite_buffer (100, 0, 4, h264_aud + 4, sizeof (h264_aud) - 4,
1263 h264_sps, sizeof (h264_sps), h264_pps, sizeof (h264_pps),
1264 h264_idrframe, sizeof (h264_idrframe));
1265
1266 fail_unless_equals_int (gst_harness_push (h, buf1), GST_FLOW_OK);
1267 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
1268
1269 fail_unless_equals_int (gst_harness_push (h, buf2), GST_FLOW_OK);
1270 /* The parser will deliver AUD, SPS, PPS as it now have complete caps */
1271 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 3);
1272
1273 buf1 = gst_harness_pull (h);
1274 gst_buffer_map (buf1, &map, GST_MAP_READ);
1275 fail_unless_equals_int (gst_buffer_get_size (buf1), sizeof (h264_aud));
1276 gst_buffer_unmap (buf1, &map);
1277 gst_buffer_unref (buf1);
1278
1279 gst_harness_teardown (h);
1280 }
1281
1282 GST_END_TEST;
1283
1284 typedef enum
1285 {
1286 PACKETIZED_AU = 0,
1287 /* TODO: packetized with nal alignment if we expect that should work? */
1288 BYTESTREAM_AU,
1289 BYTESTREAM_NAL,
1290 } H264ParseStreamType;
1291
1292 static const gchar *
stream_type_to_caps_str(H264ParseStreamType type)1293 stream_type_to_caps_str (H264ParseStreamType type)
1294 {
1295 switch (type) {
1296 case PACKETIZED_AU:
1297 return "video/x-h264,stream-format=avc,alignment=au";
1298 case BYTESTREAM_AU:
1299 return "video/x-h264,stream-format=byte-stream,alignment=au";
1300 case BYTESTREAM_NAL:
1301 return "video/x-h264,stream-format=byte-stream,alignment=nal";
1302 }
1303
1304 g_assert_not_reached ();
1305
1306 return NULL;
1307 }
1308
1309 static GstMemory *
nalu_to_memory(H264ParseStreamType type,const guint8 * data,gsize size)1310 nalu_to_memory (H264ParseStreamType type, const guint8 * data, gsize size)
1311 {
1312 gpointer dump = g_memdup2 (data, size);
1313
1314 if (type == PACKETIZED_AU) {
1315 guint32 nalu_size;
1316
1317 nalu_size = size - 4;
1318 nalu_size = GUINT32_TO_BE (nalu_size);
1319 memcpy (dump, &nalu_size, sizeof (nalu_size));
1320 }
1321
1322 return gst_memory_new_wrapped (0, dump, size, 0, size, dump, g_free);
1323 }
1324
1325 static GList *
create_aud_test_buffers(H264ParseStreamType type,gboolean inband_aud)1326 create_aud_test_buffers (H264ParseStreamType type, gboolean inband_aud)
1327 {
1328 GList *list = NULL;
1329 GstBuffer *buf = NULL;
1330
1331 #define APPEND_NALU_TO_BUFFER(type,nalu,end_of_au) G_STMT_START { \
1332 if (!buf) { \
1333 buf = gst_buffer_new (); \
1334 } \
1335 gst_buffer_append_memory (buf, nalu_to_memory (type, nalu, \
1336 sizeof (nalu))); \
1337 if (type == BYTESTREAM_NAL || end_of_au) { \
1338 list = g_list_append (list, buf); \
1339 buf = NULL; \
1340 } \
1341 } G_STMT_END
1342
1343 if (inband_aud)
1344 APPEND_NALU_TO_BUFFER (type, h264_aud, FALSE);
1345
1346 APPEND_NALU_TO_BUFFER (type, h264_slicing_sps, FALSE);
1347 APPEND_NALU_TO_BUFFER (type, h264_slicing_pps, FALSE);
1348 APPEND_NALU_TO_BUFFER (type, h264_idr_slice_1, FALSE);
1349 APPEND_NALU_TO_BUFFER (type, h264_idr_slice_2, TRUE);
1350
1351 if (inband_aud)
1352 APPEND_NALU_TO_BUFFER (type, h264_aud, FALSE);
1353
1354 APPEND_NALU_TO_BUFFER (type, h264_slice_1, FALSE);
1355 APPEND_NALU_TO_BUFFER (type, h264_slice_2, TRUE);
1356
1357 #undef APPEND_NALU_TO_BUFFER
1358
1359 return list;
1360 }
1361
1362 static void
check_aud_insertion(gboolean inband_aud,H264ParseStreamType in_type,H264ParseStreamType out_type)1363 check_aud_insertion (gboolean inband_aud, H264ParseStreamType in_type,
1364 H264ParseStreamType out_type)
1365 {
1366 GstHarness *h;
1367 GList *in_buffers = NULL;
1368 GList *expected_buffers = NULL;
1369 GList *result_buffers = NULL;
1370 GList *iter, *walk;
1371 GstCaps *in_caps, *out_caps;
1372 gboolean aud_in_output;
1373 GstBuffer *buf;
1374
1375 h = gst_harness_new ("h264parse");
1376
1377 in_caps = gst_caps_from_string (stream_type_to_caps_str (in_type));
1378 if (in_type == PACKETIZED_AU) {
1379 GstBuffer *cdata_buf = gst_buffer_new_memdup (h264_slicing_codec_data,
1380 sizeof (h264_slicing_codec_data));
1381 gst_caps_set_simple (in_caps,
1382 "codec_data", GST_TYPE_BUFFER, cdata_buf, NULL);
1383 gst_buffer_unref (cdata_buf);
1384 }
1385
1386 out_caps = gst_caps_from_string (stream_type_to_caps_str (out_type));
1387
1388 gst_harness_set_caps (h, in_caps, out_caps);
1389
1390 in_buffers = create_aud_test_buffers (in_type, inband_aud);
1391
1392 if (out_type == BYTESTREAM_AU || out_type == BYTESTREAM_NAL) {
1393 /* In case of byte-stream output, parse will insert AUD always */
1394 aud_in_output = TRUE;
1395 } else if (inband_aud) {
1396 /* Parse will not drop AUD in any case */
1397 aud_in_output = TRUE;
1398 } else {
1399 /* Cases where input bitstream doesn't contain AUD and output format is
1400 * packetized. In this case parse will not insert AUD */
1401 aud_in_output = FALSE;
1402 }
1403
1404 expected_buffers = create_aud_test_buffers (out_type, aud_in_output);
1405
1406 for (iter = in_buffers; iter; iter = g_list_next (iter)) {
1407 buf = (GstBuffer *) iter->data;
1408 fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buf)),
1409 GST_FLOW_OK);
1410 }
1411
1412 /* EOS for pending buffers to be drained if any */
1413 gst_harness_push_event (h, gst_event_new_eos ());
1414
1415 while ((buf = gst_harness_try_pull (h)))
1416 result_buffers = g_list_append (result_buffers, buf);
1417
1418 fail_unless_equals_int (g_list_length (result_buffers),
1419 g_list_length (expected_buffers));
1420
1421 for (iter = expected_buffers, walk = result_buffers; iter && walk;
1422 iter = g_list_next (iter), walk = g_list_next (walk)) {
1423 GstBuffer *buf1, *buf2;
1424 GstMapInfo map1, map2;
1425
1426 buf1 = (GstBuffer *) iter->data;
1427 buf2 = (GstBuffer *) walk->data;
1428
1429 gst_buffer_map (buf1, &map1, GST_MAP_READ);
1430 gst_buffer_map (buf2, &map2, GST_MAP_READ);
1431
1432 fail_unless_equals_int (map1.size, map2.size);
1433 fail_unless (memcmp (map1.data, map2.data, map1.size) == 0);
1434 gst_buffer_unmap (buf1, &map1);
1435 gst_buffer_unmap (buf2, &map2);
1436 }
1437
1438 g_list_free_full (in_buffers, (GDestroyNotify) gst_buffer_unref);
1439 g_list_free_full (expected_buffers, (GDestroyNotify) gst_buffer_unref);
1440 g_list_free_full (result_buffers, (GDestroyNotify) gst_buffer_unref);
1441
1442 gst_harness_teardown (h);
1443 }
1444
GST_START_TEST(test_parse_aud_insert)1445 GST_START_TEST (test_parse_aud_insert)
1446 {
1447 gboolean inband_aud[] = {
1448 TRUE, FALSE
1449 };
1450 H264ParseStreamType stream_types[] = {
1451 PACKETIZED_AU, BYTESTREAM_AU, BYTESTREAM_NAL
1452 };
1453 guint i, j, k;
1454
1455 for (i = 0; i < G_N_ELEMENTS (inband_aud); i++) {
1456 for (j = 0; j < G_N_ELEMENTS (stream_types); j++) {
1457 for (k = 0; k < G_N_ELEMENTS (stream_types); k++) {
1458 check_aud_insertion (inband_aud[i], stream_types[j], stream_types[k]);
1459 }
1460 }
1461 }
1462 }
1463
1464 GST_END_TEST;
1465
1466 /*
1467 * TODO:
1468 * - Both push- and pull-modes need to be tested
1469 * * Pull-mode & EOS
1470 */
1471
1472 int
main(int argc,char ** argv)1473 main (int argc, char **argv)
1474 {
1475 int nf = 0;
1476
1477 Suite *s;
1478 SRunner *sr;
1479
1480 gst_check_init (&argc, &argv);
1481
1482 /* globabl init test context */
1483 ctx_factory = "h264parse";
1484 ctx_sink_template = &sinktemplate_bs_nal;
1485 ctx_src_template = &srctemplate;
1486 ctx_headers[0].data = h264_sps;
1487 ctx_headers[0].size = sizeof (h264_sps);
1488 ctx_headers[1].data = h264_sei_buffering_period;
1489 ctx_headers[1].size = sizeof (h264_sei_buffering_period);
1490 ctx_headers[2].data = h264_pps;
1491 ctx_headers[2].size = sizeof (h264_pps);
1492 ctx_verify_buffer = verify_buffer;
1493 ctx_frame_generated = TRUE;
1494 /* discard initial sps/pps buffers */
1495 ctx_discard = 3;
1496 /* no timing info to parse */
1497 ctx_no_metadata = TRUE;
1498 ctx_codec_data = FALSE;
1499 ctx_hdr_sei = FALSE;
1500
1501 h264_codec_data = h264_avc_codec_data;
1502 h264_codec_data_size = sizeof (h264_avc_codec_data);
1503
1504 ctx_suite = "h264parse_to_bs_nal";
1505 s = h264parse_suite ();
1506 nf += gst_check_run_suite (s, ctx_suite, __FILE__ "_to_bs_nal.c");
1507
1508 /* setup and tweak to handle bs au output */
1509 ctx_suite = "h264parse_to_bs_au";
1510 ctx_sink_template = &sinktemplate_bs_au;
1511 ctx_verify_buffer = verify_buffer_bs_au;
1512 ctx_discard = 0;
1513 ctx_frame_generated = FALSE;
1514 ctx_hdr_sei = TRUE;
1515 s = h264parse_suite ();
1516 nf += gst_check_run_suite (s, ctx_suite, __FILE__ "_to_bs_au.c");
1517
1518 /* setup and tweak to handle avc au output */
1519 ctx_suite = "h264parse_to_avc_au";
1520 ctx_sink_template = &sinktemplate_avc_au;
1521 ctx_verify_buffer = verify_buffer;
1522 ctx_discard = 0;
1523 ctx_codec_data = TRUE;
1524 ctx_hdr_sei = FALSE;
1525
1526 s = h264parse_suite ();
1527 sr = srunner_create (s);
1528 srunner_run_all (sr, CK_NORMAL);
1529 nf += srunner_ntests_failed (sr);
1530 srunner_free (sr);
1531
1532 /* setup and tweak to handle avc3 au output */
1533 h264_codec_data = h264_avc3_codec_data;
1534 h264_codec_data_size = sizeof (h264_avc3_codec_data);
1535 ctx_suite = "h264parse_to_avc3_au";
1536 ctx_sink_template = &sinktemplate_avc3_au;
1537 ctx_discard = 0;
1538 ctx_codec_data = TRUE;
1539
1540 s = h264parse_suite ();
1541 nf += gst_check_run_suite (s, ctx_suite, __FILE__ "_to_avc3_au.c");
1542
1543 /* setup and tweak to handle avc packetized input */
1544 h264_codec_data = h264_avc_codec_data;
1545 h264_codec_data_size = sizeof (h264_avc_codec_data);
1546 ctx_suite = "h264parse_packetized";
1547 /* turn into separate byte stream NALs */
1548 ctx_sink_template = &sinktemplate_bs_nal;
1549 /* and ignore inserted codec-data NALs */
1550 ctx_discard = 2;
1551 ctx_frame_generated = TRUE;
1552 /* no more config headers */
1553 ctx_headers[0].data = NULL;
1554 ctx_headers[1].data = NULL;
1555 ctx_headers[2].data = NULL;
1556 ctx_headers[0].size = 0;
1557 ctx_headers[1].size = 0;
1558 ctx_headers[2].size = 0;
1559 /* and need adapter buffer check */
1560 ctx_verify_buffer = verify_buffer_packetized;
1561
1562 s = h264parse_packetized_suite ();
1563 nf += gst_check_run_suite (s, ctx_suite, __FILE__ "_packetized.c");
1564
1565 ctx_suite = "h264parse_sliced";
1566 s = h264parse_sliced_suite ();
1567 nf += gst_check_run_suite (s, ctx_suite, __FILE__ "_sliced.c");
1568
1569 {
1570 TCase *tc_chain = tcase_create ("general");
1571
1572 s = suite_create ("h264parse");
1573 suite_add_tcase (s, tc_chain);
1574 tcase_add_test (tc_chain, test_parse_sei_closedcaptions);
1575 tcase_add_test (tc_chain, test_parse_compatible_caps);
1576 tcase_add_test (tc_chain, test_parse_skip_to_4bytes_sc);
1577 tcase_add_test (tc_chain, test_parse_aud_insert);
1578 nf += gst_check_run_suite (s, "h264parse", __FILE__);
1579 }
1580
1581 return nf;
1582 }
1583