tests: flacparse: check and compare intended data
[gstreamer-omap:gst-plugins-good.git] / tests / check / elements / flacparse.c
1 /*
2  * GStreamer
3  *
4  * unit test for flacparse
5  *
6  * Copyright (C) 2010 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., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */
25
26 #include <gst/check/gstcheck.h>
27 #include "parser.h"
28
29 #define SRC_CAPS_TMPL  "audio/x-flac, framed=(boolean)false"
30 #define SINK_CAPS_TMPL  "audio/x-flac, framed=(boolean)true"
31
32 GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
33     GST_PAD_SINK,
34     GST_PAD_ALWAYS,
35     GST_STATIC_CAPS (SINK_CAPS_TMPL)
36     );
37
38 GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
39     GST_PAD_SRC,
40     GST_PAD_ALWAYS,
41     GST_STATIC_CAPS (SRC_CAPS_TMPL)
42     );
43
44 /* some data */
45 static guint8 streaminfo_header[] = {
46   0x7f, 0x46, 0x4c, 0x41, 0x43, 0x01, 0x00, 0x00,
47   0x02, 0x66, 0x4c, 0x61, 0x43, 0x00, 0x00, 0x00,
48   0x22, 0x12, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00,
49   0x00, 0x00, 0x00, 0x0a, 0xc4, 0x40, 0xf0, 0x00,
50   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52   0x00, 0x00, 0x00
53 };
54
55 static guint8 comment_header[] = {
56   0x84, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
57   0x00, 0x00, 0x00, 0x00
58 };
59
60 static guint8 flac_frame[] = {
61   0xff, 0xf8, 0xa9, 0x08, 0x00, 0x50, 0x18, 0x06,
62   0x6a, 0x0c, 0xce, 0x13, 0x24, 0x19, 0x68, 0x00,
63   0x46, 0x23, 0x08, 0xca, 0xcb, 0x58, 0x9c, 0x26,
64   0x92, 0x30, 0xa6, 0x29, 0x8a, 0xca, 0xd1, 0x18,
65   0xae, 0x26, 0x5c, 0x90, 0x60, 0xbf, 0x11, 0xad,
66   0x43, 0x02, 0x06, 0x26, 0xbd, 0x35, 0xdd, 0xa3,
67   0x11, 0xa6, 0x4d, 0x18, 0x8c, 0x9a, 0xe4, 0x62,
68   0xd9, 0x23, 0x11, 0x8b, 0xcb, 0x56, 0x55, 0x45,
69   0xc2, 0x18, 0x56, 0xa2, 0xe2, 0xe1, 0x18, 0x99,
70   0x54, 0x98, 0x46, 0x4d, 0x08, 0x70, 0x9a, 0x64,
71   0xc4, 0x18, 0x4f, 0x27, 0x64, 0x31, 0x66, 0x27,
72   0x79, 0x19, 0x3c, 0x8c, 0x8c, 0xa3, 0x44, 0x18,
73   0x23, 0xd2, 0x6b, 0x8b, 0x64, 0x8c, 0x21, 0x84,
74   0xd6, 0x23, 0x13, 0x13, 0x2d, 0x44, 0xca, 0x5a,
75   0x23, 0x09, 0x93, 0x25, 0x18, 0x10, 0x61, 0x38,
76   0xb4, 0x60, 0x8f, 0x2c, 0x8d, 0x26, 0xb4, 0xc9,
77   0xd9, 0x19, 0x19, 0x34, 0xd7, 0x31, 0x06, 0x10,
78   0xc4, 0x30, 0x83, 0x17, 0xe2, 0x0c, 0x2c, 0xc4,
79   0xc8, 0xc9, 0x3c, 0x5e, 0x93, 0x11, 0x8a, 0x62,
80   0x64, 0x8c, 0x26, 0x23, 0x22, 0x30, 0x9a, 0x58,
81   0x86, 0x04, 0x18, 0x4c, 0xab, 0x2b, 0x26, 0x5c,
82   0x46, 0x88, 0xcb, 0xb1, 0x0d, 0x26, 0xbb, 0x5e,
83   0x8c, 0xa7, 0x64, 0x31, 0x3d, 0x31, 0x06, 0x26,
84   0x43, 0x17, 0xa3, 0x08, 0x61, 0x06, 0x17, 0xc4,
85   0x62, 0xec, 0x4d, 0x4b, 0x2e, 0x2d, 0x4a, 0x94,
86   0xa4, 0xc2, 0x31, 0x4c, 0x4c, 0x20, 0xc0, 0x83,
87   0x14, 0x8c, 0x27, 0x8b, 0x31, 0x23, 0x2f, 0x23,
88   0x11, 0x91, 0x94, 0x65, 0x1a, 0x20, 0xc2, 0x18,
89   0x86, 0x51, 0x88, 0x62, 0x7c, 0x43, 0x2e, 0xa3,
90   0x04, 0x18, 0x8c, 0x20, 0xc2, 0xf5, 0xaa, 0x94,
91   0xc2, 0x31, 0x32, 0xd2, 0xb2, 0xa2, 0x30, 0xba,
92   0x10, 0xc2, 0xb5, 0x89, 0xa5, 0x18, 0x10, 0x62,
93   0x9a, 0x10, 0x61, 0x19, 0x72, 0x71, 0x1a, 0xb9,
94   0x0c, 0x23, 0x46, 0x10, 0x62, 0x78, 0x81, 0x82,
95   0x3d, 0x75, 0xea, 0x6b, 0x51, 0x8b, 0x61, 0x06,
96   0x08, 0x62, 0x32, 0x5e, 0x84, 0x18, 0x27, 0x25,
97   0xc2, 0x6a, 0x4b, 0x51, 0x31, 0x34, 0x5e, 0x29,
98   0xa1, 0x3c, 0x4d, 0x26, 0x23, 0x10, 0xc2, 0x6b,
99   0xb1, 0x0d, 0x11, 0xae, 0x46, 0x88, 0x31, 0x35,
100   0xb1, 0x06, 0x08, 0x79, 0x7e, 0x4f, 0x53, 0x23,
101   0x29, 0xa4, 0x30, 0x20, 0x30, 0x23, 0x5a, 0xb2,
102   0xc8, 0x60, 0x9c, 0x93, 0x13, 0x17, 0x92, 0x98,
103   0x46, 0x13, 0x54, 0x53, 0x08, 0xcb, 0x13, 0xa1,
104   0x1a, 0x89, 0xe5, 0x46, 0x08, 0x18, 0x10, 0x30,
105   0x9d, 0x68, 0xc2, 0x1c, 0x46, 0x46, 0xae, 0x62,
106   0x1a, 0x46, 0x4e, 0x4d, 0x34, 0x8c, 0xbd, 0x26,
107   0xc0, 0x40, 0x62, 0xc9, 0xa9, 0x31, 0x74, 0xa8,
108   0x99, 0x52, 0xb0, 0x8c, 0xa9, 0x29, 0x84, 0x61,
109   0x19, 0x54, 0x43, 0x02, 0x06, 0x04, 0x32, 0xe5,
110   0x18, 0x21, 0x91, 0x8b, 0xf2, 0xcc, 0x10, 0x30,
111   0x8e, 0x23, 0xc4, 0x76, 0x43, 0x08, 0x30, 0x83,
112   0x08, 0x62, 0x6c, 0x4e, 0xe2, 0x35, 0x96, 0xd0,
113   0x8e, 0x89, 0x97, 0x42, 0x18, 0x91, 0x84, 0x61,
114   0x3c, 0x26, 0xa5, 0x2c, 0x4e, 0x17, 0x94, 0xb8,
115   0xb5, 0xa4, 0xcb, 0x88, 0xc9, 0x84, 0x18, 0xb9,
116   0x84, 0x19, 0x23, 0x2d, 0xa4, 0x64, 0x62, 0x18,
117   0x86, 0x53, 0x93, 0xcb, 0x30, 0x8f, 0x2f, 0x93,
118   0x55, 0xc4, 0xd7, 0x08, 0x62, 0xb8, 0x46, 0x84,
119   0x68, 0xa3, 0x02, 0xaf, 0x33
120 };
121
122 static guint8 garbage_frame[] = {
123   0xff, 0xff, 0xff, 0xff, 0xff
124 };
125
126
127 GST_START_TEST (test_parse_flac_normal)
128 {
129   gst_parser_test_normal (flac_frame, sizeof (flac_frame));
130 }
131
132 GST_END_TEST;
133
134
135 GST_START_TEST (test_parse_flac_drain_single)
136 {
137   gst_parser_test_drain_single (flac_frame, sizeof (flac_frame));
138 }
139
140 GST_END_TEST;
141
142
143 GST_START_TEST (test_parse_flac_drain_garbage)
144 {
145   /* We always output the after frame garbage too because we
146    * have no way of detecting it
147    */
148 #if 0
149   gst_parser_test_drain_garbage (flac_frame, sizeof (flac_frame),
150       garbage_frame, sizeof (garbage_frame));
151 #endif
152   guint8 frame[sizeof (flac_frame) + sizeof (garbage_frame)];
153
154   memcpy (frame, flac_frame, sizeof (flac_frame));
155   memcpy (frame + sizeof (flac_frame), garbage_frame, sizeof (garbage_frame));
156
157   gst_parser_test_drain_single (frame, sizeof (frame));
158 }
159
160 GST_END_TEST;
161
162
163 GST_START_TEST (test_parse_flac_split)
164 {
165   gst_parser_test_split (flac_frame, sizeof (flac_frame));
166 }
167
168 GST_END_TEST;
169
170
171 GST_START_TEST (test_parse_flac_skip_garbage)
172 {
173   /* We always include the garbage into the frame because
174    * we have no easy way for finding the real end of the
175    * frame. The decoder will later skip the garbage
176    */
177 #if 0
178   gst_parser_test_skip_garbage (flac_frame, sizeof (flac_frame),
179       garbage_frame, sizeof (garbage_frame));
180 #endif
181   guint8 frame[sizeof (flac_frame) + sizeof (garbage_frame)];
182
183   memcpy (frame, flac_frame, sizeof (flac_frame));
184   memcpy (frame + sizeof (flac_frame), garbage_frame, sizeof (garbage_frame));
185
186   gst_parser_test_normal (frame, sizeof (frame));
187 }
188
189 GST_END_TEST;
190
191
192 #define structure_get_int(s,f) \
193     (g_value_get_int(gst_structure_get_value(s,f)))
194 #define fail_unless_structure_field_int_equals(s,field,num) \
195     fail_unless_equals_int (structure_get_int(s,field), num)
196 /*
197  * Test if the parser handles raw stream and codec_data info properly.
198  */
199 GST_START_TEST (test_parse_flac_detect_stream)
200 {
201   GstCaps *caps;
202   GstStructure *s;
203   const GValue *streamheader;
204   GArray *bufarr;
205   gint i;
206
207   /* Push random data. It should get through since the parser should be
208    * initialized because it got codec_data in the caps */
209   caps = gst_parser_test_get_output_caps (flac_frame, sizeof (flac_frame),
210       SRC_CAPS_TMPL);
211   fail_unless (caps != NULL);
212
213   /* Check that the negotiated caps are as expected */
214   /* When codec_data is present, parser assumes that data is version 4 */
215   GST_LOG ("flac output caps: %" GST_PTR_FORMAT, caps);
216   s = gst_caps_get_structure (caps, 0);
217   fail_unless (gst_structure_has_name (s, "audio/x-flac"));
218   fail_unless_structure_field_int_equals (s, "channels", 1);
219   fail_unless_structure_field_int_equals (s, "rate", 44100);
220   fail_unless (gst_structure_has_field (s, "streamheader"));
221   streamheader = gst_structure_get_value (s, "streamheader");
222   fail_unless (G_VALUE_TYPE (streamheader) == GST_TYPE_ARRAY);
223   bufarr = g_value_peek_pointer (streamheader);
224   fail_unless (bufarr->len == 2);
225   for (i = 0; i < bufarr->len; i++) {
226     GstBuffer *buf;
227     GValue *bufval = &g_array_index (bufarr, GValue, i);
228
229     fail_unless (G_VALUE_TYPE (bufval) == GST_TYPE_BUFFER);
230     buf = g_value_peek_pointer (bufval);
231     if (i == 0) {
232       fail_unless (GST_BUFFER_SIZE (buf) == sizeof (streaminfo_header));
233       fail_unless (memcmp (GST_BUFFER_DATA (buf), streaminfo_header,
234               sizeof (streaminfo_header)) == 0);
235     } else if (i == 1) {
236       fail_unless (GST_BUFFER_SIZE (buf) == sizeof (comment_header));
237       fail_unless (memcmp (GST_BUFFER_DATA (buf), comment_header,
238               sizeof (comment_header)) == 0);
239     }
240   }
241
242   gst_caps_unref (caps);
243 }
244
245 GST_END_TEST;
246
247 GST_START_TEST (test_parse_flac_set_index)
248 {
249   GstElement *parse;
250   GstIndex *idx;
251
252   idx = gst_index_factory_make ("memindex");
253   if (idx == NULL)
254     return;
255   parse = gst_element_factory_make ("flacparse", NULL);
256   fail_unless (parse != NULL);
257   gst_object_ref_sink (idx);
258   gst_element_set_index (parse, GST_INDEX (idx));
259   gst_object_unref (idx);
260   gst_object_unref (parse);
261 }
262
263 GST_END_TEST;
264
265 static Suite *
266 flacparse_suite (void)
267 {
268   Suite *s = suite_create ("flacparse");
269   TCase *tc_chain = tcase_create ("general");
270
271   suite_add_tcase (s, tc_chain);
272   tcase_add_test (tc_chain, test_parse_flac_normal);
273   tcase_add_test (tc_chain, test_parse_flac_drain_single);
274   tcase_add_test (tc_chain, test_parse_flac_drain_garbage);
275   tcase_add_test (tc_chain, test_parse_flac_split);
276   tcase_add_test (tc_chain, test_parse_flac_skip_garbage);
277
278   /* Other tests */
279   tcase_add_test (tc_chain, test_parse_flac_detect_stream);
280   tcase_add_test (tc_chain, test_parse_flac_set_index);
281
282   return s;
283 }
284
285
286 /*
287  * TODO:
288  *   - Both push- and pull-modes need to be tested
289  *      * Pull-mode & EOS
290  */
291
292 int
293 main (int argc, char **argv)
294 {
295   int nf;
296
297   Suite *s = flacparse_suite ();
298   SRunner *sr = srunner_create (s);
299
300   gst_check_init (&argc, &argv);
301
302   /* init test context */
303   ctx_factory = "flacparse";
304   ctx_sink_template = &sinktemplate;
305   ctx_src_template = &srctemplate;
306   ctx_discard = 3;
307   ctx_headers[0].data = streaminfo_header;
308   ctx_headers[0].size = sizeof (streaminfo_header);
309   ctx_headers[1].data = comment_header;
310   ctx_headers[1].size = sizeof (comment_header);
311   /* custom offsets, and ts always repeatedly 0 */
312   ctx_no_metadata = TRUE;
313
314   srunner_run_all (sr, CK_NORMAL);
315   nf = srunner_ntests_failed (sr);
316   srunner_free (sr);
317
318   return nf;
319 }