• 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 #include <gst/check/check.h>
27 #include <gst/video/video.h>
28 #include "parser.h"
29 
30 #define SRC_CAPS_TMPL   "video/x-h264, parsed=(boolean)false"
31 #define SINK_CAPS_TMPL  "video/x-h264, parsed=(boolean)true"
32 
33 GstStaticPadTemplate sinktemplate_bs_nal = GST_STATIC_PAD_TEMPLATE ("sink",
34     GST_PAD_SINK,
35     GST_PAD_ALWAYS,
36     GST_STATIC_CAPS (SINK_CAPS_TMPL
37         ", stream-format = (string) byte-stream, alignment = (string) nal")
38     );
39 
40 GstStaticPadTemplate sinktemplate_bs_au = GST_STATIC_PAD_TEMPLATE ("sink",
41     GST_PAD_SINK,
42     GST_PAD_ALWAYS,
43     GST_STATIC_CAPS (SINK_CAPS_TMPL
44         ", stream-format = (string) byte-stream, alignment = (string) au")
45     );
46 
47 GstStaticPadTemplate sinktemplate_avc_au = GST_STATIC_PAD_TEMPLATE ("sink",
48     GST_PAD_SINK,
49     GST_PAD_ALWAYS,
50     GST_STATIC_CAPS (SINK_CAPS_TMPL
51         ", stream-format = (string) avc, alignment = (string) au")
52     );
53 
54 GstStaticPadTemplate sinktemplate_avc3_au = GST_STATIC_PAD_TEMPLATE ("sink",
55     GST_PAD_SINK,
56     GST_PAD_ALWAYS,
57     GST_STATIC_CAPS (SINK_CAPS_TMPL
58         ", stream-format = (string) avc3, alignment = (string) au")
59     );
60 
61 GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
62     GST_PAD_SRC,
63     GST_PAD_ALWAYS,
64     GST_STATIC_CAPS (SRC_CAPS_TMPL)
65     );
66 
67 /* some data */
68 
69 /* AUD */
70 static guint8 h264_aud[] = {
71   0x00, 0x00, 0x00, 0x01, 0x09, 0xf0
72 };
73 
74 
75 /* SPS */
76 static guint8 h264_sps[] = {
77   0x00, 0x00, 0x00, 0x01, 0x67, 0x4d, 0x40, 0x15,
78   0xec, 0xa4, 0xbf, 0x2e, 0x02, 0x20, 0x00, 0x00,
79   0x03, 0x00, 0x2e, 0xe6, 0xb2, 0x80, 0x01, 0xe2,
80   0xc5, 0xb2, 0xc0
81 };
82 
83 /* PPS */
84 static guint8 h264_pps[] = {
85   0x00, 0x00, 0x00, 0x01, 0x68, 0xeb, 0xec, 0xb2
86 };
87 
88 /* SEI buffering_period() message */
89 static guint8 h264_sei_buffering_period[] = {
90   0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x01, 0xc0
91 };
92 
93 /* combines to this codec-data */
94 static guint8 h264_avc_codec_data[] = {
95   0x01, 0x4d, 0x40, 0x15, 0xff, 0xe1, 0x00, 0x17,
96   0x67, 0x4d, 0x40, 0x15, 0xec, 0xa4, 0xbf, 0x2e,
97   0x02, 0x20, 0x00, 0x00, 0x03, 0x00, 0x2e, 0xe6,
98   0xb2, 0x80, 0x01, 0xe2, 0xc5, 0xb2, 0xc0, 0x01,
99   0x00, 0x04, 0x68, 0xeb, 0xec, 0xb2
100 };
101 
102 /* codec-data for avc3 where there are no SPS/PPS in the codec_data */
103 static guint8 h264_avc3_codec_data[] = {
104   0x01,                         /* config version, always == 1 */
105   0x4d,                         /* profile */
106   0x40,                         /* profile compatibility */
107   0x15, 0xff,                   /* 6 reserved bits, lengthSizeMinusOne */
108   0xe0,                         /* 3 reserved bits, numSPS */
109   0x00                          /* numPPS */
110 };
111 
112 static guint8 *h264_codec_data = NULL;
113 static guint8 h264_codec_data_size = 0;
114 
115 
116 /* keyframes all around */
117 static guint8 h264_idrframe[] = {
118   0x00, 0x00, 0x00, 0x01, 0x65, 0x88, 0x84, 0x00,
119   0x10, 0xff, 0xfe, 0xf6, 0xf0, 0xfe, 0x05, 0x36,
120   0x56, 0x04, 0x50, 0x96, 0x7b, 0x3f, 0x53, 0xe1
121 };
122 
123 /* truncated nal */
124 static guint8 garbage_frame[] = {
125   0x00, 0x00, 0x00, 0x01, 0x05
126 };
127 
128 /* context to tweak tests */
129 static const gchar *ctx_suite;
130 static gboolean ctx_codec_data;
131 
132 static gboolean
verify_buffer(buffer_verify_data_s * vdata,GstBuffer * buffer)133 verify_buffer (buffer_verify_data_s * vdata, GstBuffer * buffer)
134 {
135   if (vdata->discard) {
136     /* check separate header NALs */
137     gint i = vdata->buffer_counter;
138     guint ofs;
139     gboolean aud;
140 
141     /* SEI with start code prefix with 2 0-bytes */
142     ofs = i == 2;
143     aud = i == 0;
144     fail_unless (i <= 3);
145 
146     if (aud) {
147       fail_unless (gst_buffer_get_size (buffer) == sizeof (h264_aud));
148       fail_unless (gst_buffer_memcmp (buffer, 0, h264_aud,
149               gst_buffer_get_size (buffer)) == 0);
150       vdata->discard++;
151     } else {
152       i -= 1;
153 
154       fail_unless (gst_buffer_get_size (buffer) == ctx_headers[i].size - ofs);
155       fail_unless (gst_buffer_memcmp (buffer, 0, ctx_headers[i].data + ofs,
156               gst_buffer_get_size (buffer)) == 0);
157     }
158   } else {
159     GstMapInfo map;
160 
161     gst_buffer_map (buffer, &map, GST_MAP_READ);
162     fail_unless (map.size > 4);
163     /* only need to check avc and bs-to-nal output case */
164     if (GST_READ_UINT24_BE (map.data) == 0x01) {
165       /* in bs-to-nal, a leading 0x00 is stripped from output */
166       fail_unless (gst_buffer_get_size (buffer) ==
167           vdata->data_to_verify_size - 1);
168       fail_unless (gst_buffer_memcmp (buffer, 0, vdata->data_to_verify + 1,
169               vdata->data_to_verify_size - 1) == 0);
170       gst_buffer_unmap (buffer, &map);
171       return TRUE;
172     } else if (GST_READ_UINT32_BE (map.data) == 0x01) {
173       gboolean aud = FALSE;
174       aud = vdata->buffer_counter % 2;
175       if (aud) {
176         fail_unless (gst_buffer_get_size (buffer) == sizeof (h264_aud));
177         fail_unless (gst_buffer_memcmp (buffer, 0, h264_aud,
178                 gst_buffer_get_size (buffer)) == 0);
179         gst_buffer_unmap (buffer, &map);
180         return TRUE;
181       }
182 
183       /* this is not avc, use default tests from parser.c */
184       gst_buffer_unmap (buffer, &map);
185       return FALSE;
186     }
187     /* header is merged in initial frame */
188     if (vdata->buffer_counter == 0) {
189       guint8 *data = map.data;
190 
191       fail_unless (map.size == vdata->data_to_verify_size +
192           ctx_headers[0].size + ctx_headers[1].size + ctx_headers[2].size);
193       fail_unless (GST_READ_UINT32_BE (data) == ctx_headers[0].size - 4);
194       fail_unless (memcmp (data + 4, ctx_headers[0].data + 4,
195               ctx_headers[0].size - 4) == 0);
196       data += ctx_headers[0].size;
197       fail_unless (GST_READ_UINT32_BE (data) == ctx_headers[1].size - 4);
198       fail_unless (memcmp (data + 4, ctx_headers[1].data + 4,
199               ctx_headers[1].size - 4) == 0);
200       data += ctx_headers[1].size;
201       fail_unless (GST_READ_UINT32_BE (data) == ctx_headers[2].size - 4);
202       fail_unless (memcmp (data + 4, ctx_headers[2].data + 4,
203               ctx_headers[2].size - 4) == 0);
204       data += ctx_headers[2].size;
205       fail_unless (GST_READ_UINT32_BE (data) == vdata->data_to_verify_size - 4);
206       fail_unless (memcmp (data + 4, vdata->data_to_verify + 4,
207               vdata->data_to_verify_size - 4) == 0);
208     } else {
209       fail_unless (GST_READ_UINT32_BE (map.data) == map.size - 4);
210       fail_unless (map.size == vdata->data_to_verify_size);
211       fail_unless (memcmp (map.data + 4, vdata->data_to_verify + 4,
212               map.size - 4) == 0);
213     }
214     gst_buffer_unmap (buffer, &map);
215     return TRUE;
216   }
217 
218   return FALSE;
219 }
220 
221 /* A single access unit comprising of SPS, SEI, PPS and IDR frame */
222 static gboolean
verify_buffer_bs_au(buffer_verify_data_s * vdata,GstBuffer * buffer)223 verify_buffer_bs_au (buffer_verify_data_s * vdata, GstBuffer * buffer)
224 {
225   GstMapInfo map;
226 
227   fail_unless (ctx_sink_template == &sinktemplate_bs_au);
228 
229   gst_buffer_map (buffer, &map, GST_MAP_READ);
230   fail_unless (map.size > 4);
231 
232   if (vdata->buffer_counter == 0) {
233     guint8 *data = map.data;
234 
235     /* AUD, SPS, SEI, PPS */
236     fail_unless (map.size == vdata->data_to_verify_size +
237         sizeof (h264_aud) + ctx_headers[0].size +
238         ctx_headers[1].size + ctx_headers[2].size);
239     fail_unless (memcmp (data, h264_aud, sizeof (h264_aud)) == 0);
240     data += sizeof (h264_aud);
241     fail_unless (memcmp (data, ctx_headers[0].data, ctx_headers[0].size) == 0);
242     data += ctx_headers[0].size;
243     fail_unless (memcmp (data, ctx_headers[1].data, ctx_headers[1].size) == 0);
244     data += ctx_headers[1].size;
245     fail_unless (memcmp (data, ctx_headers[2].data, ctx_headers[2].size) == 0);
246     data += ctx_headers[2].size;
247 
248     /* IDR frame */
249     fail_unless (memcmp (data, vdata->data_to_verify,
250             vdata->data_to_verify_size) == 0);
251   } else {
252     /* IDR frame */
253     guint aud_size = sizeof (h264_aud);
254     fail_unless (map.size == vdata->data_to_verify_size + aud_size);
255     fail_unless (memcmp (map.data, h264_aud, aud_size) == 0);
256     fail_unless (memcmp (map.data + aud_size, vdata->data_to_verify,
257             map.size - aud_size) == 0);
258   }
259 
260   gst_buffer_unmap (buffer, &map);
261   return TRUE;
262 }
263 
GST_START_TEST(test_parse_normal)264 GST_START_TEST (test_parse_normal)
265 {
266   gst_parser_test_normal (h264_idrframe, sizeof (h264_idrframe));
267 }
268 
269 GST_END_TEST;
270 
271 
GST_START_TEST(test_parse_drain_single)272 GST_START_TEST (test_parse_drain_single)
273 {
274   gst_parser_test_drain_single (h264_idrframe, sizeof (h264_idrframe));
275 }
276 
277 GST_END_TEST;
278 
279 
GST_START_TEST(test_parse_drain_garbage)280 GST_START_TEST (test_parse_drain_garbage)
281 {
282   gst_parser_test_drain_garbage (h264_idrframe, sizeof (h264_idrframe),
283       garbage_frame, sizeof (garbage_frame));
284 }
285 
286 GST_END_TEST
GST_START_TEST(test_parse_split)287 GST_START_TEST (test_parse_split)
288 {
289   gst_parser_test_split (h264_idrframe, sizeof (h264_idrframe));
290 }
291 
292 GST_END_TEST;
293 
294 
GST_START_TEST(test_parse_skip_garbage)295 GST_START_TEST (test_parse_skip_garbage)
296 {
297   gst_parser_test_skip_garbage (h264_idrframe, sizeof (h264_idrframe),
298       garbage_frame, sizeof (garbage_frame));
299 }
300 
301 GST_END_TEST;
302 
303 #define structure_get_int(s,f) \
304     (g_value_get_int(gst_structure_get_value(s,f)))
305 #define fail_unless_structure_field_int_equals(s,field,num) \
306     fail_unless_equals_int (structure_get_int(s,field), num)
307 
308 
GST_START_TEST(test_parse_detect_stream)309 GST_START_TEST (test_parse_detect_stream)
310 {
311   GstCaps *caps;
312   GstStructure *s;
313   GstBuffer *buf;
314   const GValue *val;
315 
316   /* parser does not really care that mpeg1 and mpeg2 frame data
317    * should be a bit different */
318   caps = gst_parser_test_get_output_caps (h264_idrframe, sizeof (h264_idrframe),
319       NULL);
320   fail_unless (caps != NULL);
321 
322   /* Check that the negotiated caps are as expected */
323   /* When codec_data is present, parser assumes that data is version 4 */
324   GST_LOG ("h264 output caps: %" GST_PTR_FORMAT, caps);
325   s = gst_caps_get_structure (caps, 0);
326   fail_unless (gst_structure_has_name (s, "video/x-h264"));
327   fail_unless_structure_field_int_equals (s, "width", 32);
328   fail_unless_structure_field_int_equals (s, "height", 24);
329 
330   if (ctx_codec_data) {
331     fail_unless (gst_structure_has_field (s, "codec_data"));
332 
333     /* check codec-data in more detail */
334     val = gst_structure_get_value (s, "codec_data");
335     fail_unless (val != NULL);
336     buf = gst_value_get_buffer (val);
337     fail_unless (buf != NULL);
338     fail_unless (gst_buffer_get_size (buf) == h264_codec_data_size);
339     fail_unless (gst_buffer_memcmp (buf, 0, h264_codec_data,
340             gst_buffer_get_size (buf)) == 0);
341   }
342 
343   gst_caps_unref (caps);
344 }
345 
346 GST_END_TEST;
347 
348 static GstStaticPadTemplate srctemplate_avc_au_and_bs_au =
349     GST_STATIC_PAD_TEMPLATE ("src",
350     GST_PAD_SRC,
351     GST_PAD_ALWAYS,
352     GST_STATIC_CAPS (SRC_CAPS_TMPL
353         ", stream-format = (string) avc, alignment = (string) au; "
354         SRC_CAPS_TMPL
355         ", stream-format = (string) byte-stream, alignment = (string) au")
356     );
357 
GST_START_TEST(test_sink_caps_reordering)358 GST_START_TEST (test_sink_caps_reordering)
359 {
360   /* Upstream can handle avc and byte-stream format (in that preference order)
361    * and downstream requires byte-stream.
362    * Parser reorder upstream's caps to prefer the format requested downstream
363    * and so avoid doing useless conversions. */
364   GstElement *parser;
365   GstPad *sink, *src;
366   GstCaps *src_caps, *sink_caps;
367   GstStructure *s;
368 
369   parser = gst_check_setup_element ("h264parse");
370   fail_unless (parser);
371 
372   src = gst_check_setup_src_pad (parser, &srctemplate_avc_au_and_bs_au);
373   sink = gst_check_setup_sink_pad (parser, &sinktemplate_bs_au);
374 
375   src_caps = gst_pad_get_pad_template_caps (src);
376   sink_caps = gst_pad_peer_query_caps (src, src_caps);
377 
378   /* Sink pad has both format on its sink caps but prefer to use byte-stream */
379   g_assert_cmpuint (gst_caps_get_size (sink_caps), ==, 2);
380 
381   s = gst_caps_get_structure (sink_caps, 0);
382   g_assert_cmpstr (gst_structure_get_name (s), ==, "video/x-h264");
383   g_assert_cmpstr (gst_structure_get_string (s, "alignment"), ==, "au");
384   g_assert_cmpstr (gst_structure_get_string (s, "stream-format"), ==,
385       "byte-stream");
386 
387   s = gst_caps_get_structure (sink_caps, 1);
388   g_assert_cmpstr (gst_structure_get_name (s), ==, "video/x-h264");
389   g_assert_cmpstr (gst_structure_get_string (s, "alignment"), ==, "au");
390   g_assert_cmpstr (gst_structure_get_string (s, "stream-format"), ==, "avc");
391 
392   gst_caps_unref (src_caps);
393   gst_caps_unref (sink_caps);
394   gst_object_unref (src);
395   gst_object_unref (sink);
396   gst_object_unref (parser);
397 }
398 
399 GST_END_TEST;
400 
401 static Suite *
h264parse_suite(void)402 h264parse_suite (void)
403 {
404   Suite *s = suite_create (ctx_suite);
405   TCase *tc_chain = tcase_create ("general");
406 
407   suite_add_tcase (s, tc_chain);
408   tcase_add_test (tc_chain, test_parse_normal);
409   tcase_add_test (tc_chain, test_parse_drain_single);
410   tcase_add_test (tc_chain, test_parse_drain_garbage);
411   tcase_add_test (tc_chain, test_parse_split);
412   tcase_add_test (tc_chain, test_parse_skip_garbage);
413   tcase_add_test (tc_chain, test_parse_detect_stream);
414   tcase_add_test (tc_chain, test_sink_caps_reordering);
415 
416   return s;
417 }
418 
419 static gboolean
verify_buffer_packetized(buffer_verify_data_s * vdata,GstBuffer * buffer)420 verify_buffer_packetized (buffer_verify_data_s * vdata, GstBuffer * buffer)
421 {
422   GstMapInfo map;
423 
424   gst_buffer_map (buffer, &map, GST_MAP_READ);
425 
426   fail_unless (map.size > 4);
427   fail_unless (GST_READ_UINT32_BE (map.data) == 0x01);
428   if (vdata->discard) {
429     /* check separate header NALs */
430     guint8 *data;
431     gint size;
432 
433     if (vdata->buffer_counter == 0) {
434       data = h264_aud;
435       size = sizeof (h264_aud);
436       vdata->discard++;
437     } else if (vdata->buffer_counter == 1) {
438       data = h264_sps;
439       size = sizeof (h264_sps);
440     } else {
441       data = h264_pps;
442       size = sizeof (h264_pps);
443     }
444 
445     fail_unless (map.size == size);
446     fail_unless (memcmp (map.data + 4, data + 4, size - 4) == 0);
447   } else {
448     guint8 *data;
449     gint size;
450     gboolean aud = vdata->buffer_counter % 2;
451     if (aud) {
452       data = h264_aud;
453       size = sizeof (h264_aud);
454     } else {
455       data = (gpointer) vdata->data_to_verify;
456       size = map.size;
457     }
458 
459     fail_unless (map.size == size);
460     fail_unless (memcmp (map.data + 4, data + 4, size - 4) == 0);
461   }
462   gst_buffer_unmap (buffer, &map);
463 
464   return TRUE;
465 }
466 
GST_START_TEST(test_parse_packetized)467 GST_START_TEST (test_parse_packetized)
468 {
469   guint8 *frame;
470   GstCaps *caps;
471   GstBuffer *cdata;
472   GstStructure *s;
473   gchar *desc;
474 
475   /* make AVC frame */
476   frame = g_malloc (sizeof (h264_idrframe));
477   GST_WRITE_UINT32_BE (frame, sizeof (h264_idrframe) - 4);
478   memcpy (frame + 4, h264_idrframe + 4, sizeof (h264_idrframe) - 4);
479 
480   /* some caps messing */
481   caps = gst_caps_from_string (SRC_CAPS_TMPL);
482   cdata =
483       gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, h264_codec_data,
484       h264_codec_data_size, 0, h264_codec_data_size, NULL, NULL);
485   gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, cdata,
486       "stream-format", G_TYPE_STRING, "avc", NULL);
487   gst_buffer_unref (cdata);
488   desc = gst_caps_to_string (caps);
489   gst_caps_unref (caps);
490 
491   caps = gst_parser_test_get_output_caps (frame, sizeof (h264_idrframe), desc);
492   g_free (desc);
493   g_free (frame);
494 
495   /* minor caps checks */
496   GST_LOG ("h264 output caps: %" GST_PTR_FORMAT, caps);
497   s = gst_caps_get_structure (caps, 0);
498   fail_unless (gst_structure_has_name (s, "video/x-h264"));
499   fail_unless_structure_field_int_equals (s, "width", 32);
500   fail_unless_structure_field_int_equals (s, "height", 24);
501 
502   gst_caps_unref (caps);
503 }
504 
505 GST_END_TEST;
506 
507 static Suite *
h264parse_packetized_suite(void)508 h264parse_packetized_suite (void)
509 {
510   Suite *s = suite_create (ctx_suite);
511   TCase *tc_chain = tcase_create ("general");
512 
513   suite_add_tcase (s, tc_chain);
514   tcase_add_test (tc_chain, test_parse_packetized);
515 
516   return s;
517 }
518 
GST_START_TEST(test_parse_sei_closedcaptions)519 GST_START_TEST (test_parse_sei_closedcaptions)
520 {
521   GstVideoCaptionMeta *cc;
522   GstHarness *h;
523   GstBuffer *buf;
524 
525   const guint8 cc_sei_plus_idr[] = {
526     0x00, 0x00, 0x00, 0x4b, 0x06, 0x04, 0x47, 0xb5, 0x00, 0x31, 0x47, 0x41,
527     0x39, 0x34, 0x03, 0xd4,
528     0xff, 0xfc, 0x80, 0x80, 0xfd, 0x80, 0x80, 0xfa, 0x00, 0x00, 0xfa, 0x00,
529     0x00, 0xfa, 0x00, 0x00,
530     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
531     0xfa, 0x00, 0x00, 0xfa,
532     0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
533     0x00, 0x00, 0xfa, 0x00,
534     0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00,
535     0x00, 0xff, 0x80,
536     /* IDR frame (doesn't necessarily match caps) */
537     0x00, 0x00, 0x00, 0x14, 0x65, 0x88, 0x84, 0x00,
538     0x10, 0xff, 0xfe, 0xf6, 0xf0, 0xfe, 0x05, 0x36,
539     0x56, 0x04, 0x50, 0x96, 0x7b, 0x3f, 0x53, 0xe1
540   };
541   const gsize cc_sei_plus_idr_size = sizeof (cc_sei_plus_idr);
542 
543   h = gst_harness_new ("h264parse");
544 
545   gst_harness_set_src_caps_str (h,
546       "video/x-h264, stream-format=(string)avc, alignment=(string)au,"
547       " codec_data=(buffer)014d4015ffe10017674d4015eca4bf2e0220000003002ee6b28001e2c5b2c001000468ebecb2,"
548       " width=(int)32, height=(int)24, framerate=(fraction)30/1,"
549       " pixel-aspect-ratio=(fraction)1/1");
550 
551   buf = gst_buffer_new_and_alloc (cc_sei_plus_idr_size);
552   gst_buffer_fill (buf, 0, cc_sei_plus_idr, cc_sei_plus_idr_size);
553   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
554 
555   buf = gst_harness_pull (h);
556   cc = gst_buffer_get_video_caption_meta (buf);
557   fail_unless (cc != NULL);
558   fail_unless_equals_int (cc->caption_type, GST_VIDEO_CAPTION_TYPE_CEA708_RAW);
559   fail_unless_equals_int (cc->size, 60);
560   fail_unless_equals_int (cc->data[0], 0xfc);
561   fail_unless_equals_int (cc->data[3], 0xfd);
562   gst_buffer_unref (buf);
563 
564   gst_harness_teardown (h);
565 }
566 
567 GST_END_TEST;
568 
569 /*
570  * TODO:
571  *   - Both push- and pull-modes need to be tested
572  *      * Pull-mode & EOS
573  */
574 
575 int
main(int argc,char ** argv)576 main (int argc, char **argv)
577 {
578   int nf = 0;
579 
580   Suite *s;
581   SRunner *sr;
582 
583   gst_check_init (&argc, &argv);
584 
585   /* globabl init test context */
586   ctx_factory = "h264parse";
587   ctx_sink_template = &sinktemplate_bs_nal;
588   ctx_src_template = &srctemplate;
589   ctx_headers[0].data = h264_sps;
590   ctx_headers[0].size = sizeof (h264_sps);
591   ctx_headers[1].data = h264_sei_buffering_period;
592   ctx_headers[1].size = sizeof (h264_sei_buffering_period);
593   ctx_headers[2].data = h264_pps;
594   ctx_headers[2].size = sizeof (h264_pps);
595   ctx_verify_buffer = verify_buffer;
596   ctx_frame_generated = TRUE;
597   /* discard initial sps/pps buffers */
598   ctx_discard = 3;
599   /* no timing info to parse */
600   ctx_no_metadata = TRUE;
601   ctx_codec_data = FALSE;
602 
603   h264_codec_data = h264_avc_codec_data;
604   h264_codec_data_size = sizeof (h264_avc_codec_data);
605 
606   ctx_suite = "h264parse_to_bs_nal";
607   s = h264parse_suite ();
608   nf += gst_check_run_suite (s, ctx_suite, __FILE__ "_to_bs_nal.c");
609 
610   /* setup and tweak to handle bs au output */
611   ctx_suite = "h264parse_to_bs_au";
612   ctx_sink_template = &sinktemplate_bs_au;
613   ctx_verify_buffer = verify_buffer_bs_au;
614   ctx_discard = 0;
615   ctx_frame_generated = FALSE;
616 
617   s = h264parse_suite ();
618   nf += gst_check_run_suite (s, ctx_suite, __FILE__ "_to_bs_au.c");
619 
620   /* setup and tweak to handle avc au output */
621   ctx_suite = "h264parse_to_avc_au";
622   ctx_sink_template = &sinktemplate_avc_au;
623   ctx_verify_buffer = verify_buffer;
624   ctx_discard = 0;
625   ctx_codec_data = TRUE;
626 
627   s = h264parse_suite ();
628   sr = srunner_create (s);
629   srunner_run_all (sr, CK_NORMAL);
630   nf += srunner_ntests_failed (sr);
631   srunner_free (sr);
632 
633   /* setup and tweak to handle avc3 au output */
634   h264_codec_data = h264_avc3_codec_data;
635   h264_codec_data_size = sizeof (h264_avc3_codec_data);
636   ctx_suite = "h264parse_to_avc3_au";
637   ctx_sink_template = &sinktemplate_avc3_au;
638   ctx_discard = 0;
639   ctx_codec_data = TRUE;
640 
641   s = h264parse_suite ();
642   nf += gst_check_run_suite (s, ctx_suite, __FILE__ "_to_avc3_au.c");
643 
644   /* setup and tweak to handle avc packetized input */
645   h264_codec_data = h264_avc_codec_data;
646   h264_codec_data_size = sizeof (h264_avc_codec_data);
647   ctx_suite = "h264parse_packetized";
648   /* turn into separate byte stream NALs */
649   ctx_sink_template = &sinktemplate_bs_nal;
650   /* and ignore inserted codec-data NALs */
651   ctx_discard = 2;
652   ctx_frame_generated = TRUE;
653   /* no more config headers */
654   ctx_headers[0].data = NULL;
655   ctx_headers[1].data = NULL;
656   ctx_headers[2].data = NULL;
657   ctx_headers[0].size = 0;
658   ctx_headers[1].size = 0;
659   ctx_headers[2].size = 0;
660   /* and need adapter buffer check */
661   ctx_verify_buffer = verify_buffer_packetized;
662 
663   s = h264parse_packetized_suite ();
664   nf += gst_check_run_suite (s, ctx_suite, __FILE__ "_packetized.c");
665 
666   {
667     TCase *tc_chain = tcase_create ("general");
668 
669     s = suite_create ("h264parse");
670     suite_add_tcase (s, tc_chain);
671     tcase_add_test (tc_chain, test_parse_sei_closedcaptions);
672     nf += gst_check_run_suite (s, "h264parse", __FILE__);
673   }
674 
675   return nf;
676 }
677