1 /*
2 * GStreamer
3 *
4 * unit test for aacparse
5 *
6 * Copyright (C) 2008 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/gstcheck.h>
27 #include <gst/check/check.h>
28 #include "parser.h"
29
30 #define SRC_CAPS_CDATA "audio/mpeg, mpegversion=(int)4, framed=(boolean)false, codec_data=(buffer)1190"
31 #define SRC_CAPS_TMPL "audio/mpeg, framed=(boolean)false, mpegversion=(int){2,4}"
32 #define SRC_CAPS_RAW "audio/mpeg, mpegversion=(int)4, framed=(boolean)true, stream-format=(string)raw, rate=(int)48000, channels=(int)2, codec_data=(buffer)1190"
33
34 #define SINK_CAPS \
35 "audio/mpeg, framed=(boolean)true"
36 #define SINK_CAPS_MPEG2 \
37 "audio/mpeg, framed=(boolean)true, mpegversion=2, rate=48000, channels=2"
38 #define SINK_CAPS_MPEG4 \
39 "audio/mpeg, framed=(boolean)true, mpegversion=4, rate=96000, channels=2"
40 #define SINK_CAPS_TMPL "audio/mpeg, framed=(boolean)true, mpegversion=(int){2,4}"
41
42 GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
43 GST_PAD_SINK,
44 GST_PAD_ALWAYS,
45 GST_STATIC_CAPS (SINK_CAPS_TMPL)
46 );
47
48 GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
49 GST_PAD_SRC,
50 GST_PAD_ALWAYS,
51 GST_STATIC_CAPS (SRC_CAPS_TMPL)
52 );
53
54 /* some data */
55 static guint8 adif_header[] = {
56 'A', 'D', 'I', 'F'
57 };
58
59 static guint8 adts_frame_mpeg2[] = {
60 0xff, 0xf9, 0x4c, 0x80, 0x01, 0xff, 0xfc, 0x21, 0x10, 0xd3, 0x20, 0x0c,
61 0x32, 0x00, 0xc7
62 };
63
64 static guint8 adts_frame_mpeg4[] = {
65 0xff, 0xf1, 0x4c, 0x80, 0x01, 0xff, 0xfc, 0x21, 0x10, 0xd3, 0x20, 0x0c,
66 0x32, 0x00, 0xc7
67 };
68
69 static guint8 garbage_frame[] = {
70 0xff, 0xff, 0xff, 0xff, 0xff
71 };
72
73 static guint8 raw_frame_short[] = {
74 0x27, 0x00, 0x03, 0x20, 0x64, 0x1c
75 };
76
77 /*
78 * Test if the parser pushes data with ADIF header properly and detects the
79 * stream to MPEG4 properly.
80 */
GST_START_TEST(test_parse_adif_normal)81 GST_START_TEST (test_parse_adif_normal)
82 {
83 GstParserTest ptest;
84
85 /* ADIF header */
86 gst_parser_test_init (&ptest, adif_header, sizeof (adif_header), 1);
87 /* well, no garbage, followed by random data */
88 ptest.series[2].size = 100;
89 ptest.series[2].num = 3;
90 /* and we do not really expect output frames */
91 ptest.framed = FALSE;
92 /* Check that the negotiated caps are as expected */
93 /* For ADIF parser assumes that data is always version 4 */
94 ptest.sink_caps =
95 gst_caps_from_string (SINK_CAPS_MPEG4 ", stream-format=(string)adif");
96
97 gst_parser_test_run (&ptest, NULL);
98
99 gst_caps_unref (ptest.sink_caps);
100 }
101
102 GST_END_TEST;
103
104
GST_START_TEST(test_parse_adts_normal)105 GST_START_TEST (test_parse_adts_normal)
106 {
107 gst_parser_test_normal (adts_frame_mpeg4, sizeof (adts_frame_mpeg4));
108 }
109
110 GST_END_TEST;
111
112
GST_START_TEST(test_parse_adts_drain_single)113 GST_START_TEST (test_parse_adts_drain_single)
114 {
115 gst_parser_test_drain_single (adts_frame_mpeg4, sizeof (adts_frame_mpeg4));
116 }
117
118 GST_END_TEST;
119
120
GST_START_TEST(test_parse_adts_drain_garbage)121 GST_START_TEST (test_parse_adts_drain_garbage)
122 {
123 gst_parser_test_drain_garbage (adts_frame_mpeg4, sizeof (adts_frame_mpeg4),
124 garbage_frame, sizeof (garbage_frame));
125 }
126
127 GST_END_TEST;
128
129
GST_START_TEST(test_parse_adts_split)130 GST_START_TEST (test_parse_adts_split)
131 {
132 gst_parser_test_split (adts_frame_mpeg4, sizeof (adts_frame_mpeg4));
133 }
134
135 GST_END_TEST;
136
137
GST_START_TEST(test_parse_adts_skip_garbage)138 GST_START_TEST (test_parse_adts_skip_garbage)
139 {
140 gst_parser_test_skip_garbage (adts_frame_mpeg4, sizeof (adts_frame_mpeg4),
141 garbage_frame, sizeof (garbage_frame));
142 }
143
144 GST_END_TEST;
145
146
147 /*
148 * Test if the src caps are set according to stream format (MPEG version).
149 */
GST_START_TEST(test_parse_adts_detect_mpeg_version)150 GST_START_TEST (test_parse_adts_detect_mpeg_version)
151 {
152 gst_parser_test_output_caps (adts_frame_mpeg2, sizeof (adts_frame_mpeg2),
153 NULL,
154 SINK_CAPS_MPEG2
155 ", stream-format=(string)adts, level=(string)2, profile=(string)lc");
156 }
157
158 GST_END_TEST;
159
160 /*
161 * Test if the parser correctly handles short raw frames and doesn't
162 * concatenate them.
163 */
GST_START_TEST(test_parse_raw_short)164 GST_START_TEST (test_parse_raw_short)
165 {
166 GstHarness *h = gst_harness_new ("aacparse");
167 GstBuffer *in_buf;
168
169 g_object_set (h->element, "disable-passthrough", TRUE, NULL);
170 gst_harness_set_src_caps_str (h, SRC_CAPS_RAW);
171
172 in_buf = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
173 raw_frame_short, sizeof raw_frame_short, 0, sizeof raw_frame_short,
174 NULL, NULL);
175
176 gst_harness_push (h, gst_buffer_ref (in_buf));
177 fail_unless_equals_int (gst_harness_buffers_received (h), 1);
178
179 gst_harness_push (h, in_buf);
180 fail_unless_equals_int (gst_harness_buffers_received (h), 2);
181
182 gst_harness_push_event (h, gst_event_new_eos ());
183 fail_unless_equals_int (gst_harness_buffers_received (h), 2);
184
185 gst_harness_teardown (h);
186 }
187
188 GST_END_TEST;
189
190 #define structure_get_int(s,f) \
191 (g_value_get_int(gst_structure_get_value(s,f)))
192 #define fail_unless_structure_field_int_equals(s,field,num) \
193 fail_unless_equals_int (structure_get_int(s,field), num)
194 /*
195 * Test if the parser handles raw stream and codec_data info properly.
196 */
GST_START_TEST(test_parse_handle_codec_data)197 GST_START_TEST (test_parse_handle_codec_data)
198 {
199 GstCaps *caps;
200 GstStructure *s;
201 const gchar *stream_format;
202
203 /* Push random data. It should get through since the parser should be
204 * initialized because it got codec_data in the caps */
205 caps = gst_parser_test_get_output_caps (NULL, 100, SRC_CAPS_CDATA);
206 fail_unless (caps != NULL);
207
208 /* Check that the negotiated caps are as expected */
209 /* When codec_data is present, parser assumes that data is version 4 */
210 GST_LOG ("aac output caps: %" GST_PTR_FORMAT, caps);
211 s = gst_caps_get_structure (caps, 0);
212 fail_unless (gst_structure_has_name (s, "audio/mpeg"));
213 fail_unless_structure_field_int_equals (s, "mpegversion", 4);
214 fail_unless_structure_field_int_equals (s, "channels", 2);
215 fail_unless_structure_field_int_equals (s, "rate", 48000);
216 fail_unless (gst_structure_has_field (s, "codec_data"));
217 fail_unless (gst_structure_has_field (s, "stream-format"));
218 stream_format = gst_structure_get_string (s, "stream-format");
219 fail_unless (strcmp (stream_format, "raw") == 0);
220
221 gst_caps_unref (caps);
222 }
223
224 GST_END_TEST;
225
GST_START_TEST(test_parse_proxy_constraints)226 GST_START_TEST (test_parse_proxy_constraints)
227 {
228 GstCaps *caps, *resultcaps;
229 GstElement *parse, *filter;
230 GstPad *sinkpad;
231 GstStructure *s;
232
233 parse = gst_element_factory_make ("aacparse", NULL);
234 filter = gst_element_factory_make ("capsfilter", NULL);
235
236 /* constraint on rate and version */
237 caps = gst_caps_from_string ("audio/mpeg,mpegversion=2,rate=44100");
238 g_object_set (filter, "caps", caps, NULL);
239 gst_caps_unref (caps);
240
241 gst_element_link (parse, filter);
242
243 sinkpad = gst_element_get_static_pad (parse, "sink");
244 caps = gst_pad_query_caps (sinkpad, NULL);
245 GST_LOG ("caps %" GST_PTR_FORMAT, caps);
246
247 fail_unless (gst_caps_get_size (caps) == 1);
248
249 /* getcaps should proxy the rate constraint */
250 s = gst_caps_get_structure (caps, 0);
251 fail_unless (gst_structure_has_name (s, "audio/mpeg"));
252 fail_unless_structure_field_int_equals (s, "rate", 44100);
253 gst_caps_unref (caps);
254
255 /* should accept without the constraint */
256 caps = gst_caps_from_string ("audio/mpeg,mpegversion=2");
257 resultcaps = gst_pad_query_caps (sinkpad, caps);
258 fail_if (gst_caps_is_empty (resultcaps));
259 gst_caps_unref (resultcaps);
260 gst_caps_unref (caps);
261
262 /* should not accept with conflicting version */
263 caps = gst_caps_from_string ("audio/mpeg,mpegversion=4");
264 resultcaps = gst_pad_query_caps (sinkpad, caps);
265 fail_unless (gst_caps_is_empty (resultcaps));
266 gst_caps_unref (resultcaps);
267 gst_caps_unref (caps);
268
269 gst_object_unref (sinkpad);
270
271 gst_object_unref (filter);
272 gst_object_unref (parse);
273 }
274
275 GST_END_TEST;
276
277 static Suite *
aacparse_suite(void)278 aacparse_suite (void)
279 {
280 Suite *s = suite_create ("aacparse");
281 TCase *tc_chain = tcase_create ("general");
282
283 /* init test context */
284 ctx_factory = "aacparse";
285 ctx_sink_template = &sinktemplate;
286 ctx_src_template = &srctemplate;
287
288 suite_add_tcase (s, tc_chain);
289 /* ADIF tests */
290 tcase_add_test (tc_chain, test_parse_adif_normal);
291
292 /* ADTS tests */
293 tcase_add_test (tc_chain, test_parse_adts_normal);
294 tcase_add_test (tc_chain, test_parse_adts_drain_single);
295 tcase_add_test (tc_chain, test_parse_adts_drain_garbage);
296 tcase_add_test (tc_chain, test_parse_adts_split);
297 tcase_add_test (tc_chain, test_parse_adts_skip_garbage);
298 tcase_add_test (tc_chain, test_parse_adts_detect_mpeg_version);
299
300 /* Raw tests */
301 tcase_add_test (tc_chain, test_parse_raw_short);
302
303 /* Other tests */
304 tcase_add_test (tc_chain, test_parse_handle_codec_data);
305
306 /* caps tests */
307 tcase_add_test (tc_chain, test_parse_proxy_constraints);
308
309 return s;
310 }
311
312
313 /*
314 * TODO:
315 * - Both push- and pull-modes need to be tested
316 * * Pull-mode & EOS
317 */
318 GST_CHECK_MAIN (aacparse);
319