• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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