1 /* GStreamer
2 *
3 * unit test for spectrum
4 *
5 * Copyright (C) <2007> Stefan Kost <ensonic@users.sf.net>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 #include <gst/audio/audio.h>
24 #include <gst/check/gstcheck.h>
25
26 gboolean have_eos = FALSE;
27
28 /* For ease of programming we use globals to keep refs for our floating
29 * src and sink pads we create; otherwise we always have to do get_pad,
30 * get_peer, and then remove references in every test function */
31 GstPad *mysrcpad, *mysinkpad;
32
33 #define SPECT_CAPS_TEMPLATE_STRING \
34 "audio/x-raw, " \
35 " rate = (int) [ 1, MAX ], " \
36 " channels = (int) [ 1, MAX ], " \
37 " layout = (string) interleaved, " \
38 " format = (string) { " \
39 GST_AUDIO_NE(S16) ", " \
40 GST_AUDIO_NE(S32) ", " \
41 GST_AUDIO_NE(F32) ", " \
42 GST_AUDIO_NE(F64) " }"
43
44 #define SPECT_CAPS_STRING_S16 \
45 "audio/x-raw, " \
46 "rate = (int) 44100, " \
47 "channels = (int) 1, " \
48 "layout = (string) interleaved, " \
49 "format = (string) " GST_AUDIO_NE(S16)
50
51 #define SPECT_CAPS_STRING_S32 \
52 "audio/x-raw, " \
53 "rate = (int) 44100, " \
54 "channels = (int) 1, " \
55 "layout = (string) interleaved, " \
56 "format = (string) " GST_AUDIO_NE(S32)
57
58 #define SPECT_CAPS_STRING_F32 \
59 "audio/x-raw, " \
60 " rate = (int) 44100, " \
61 " channels = (int) 1, " \
62 " layout = (string) interleaved, " \
63 " format = (string) " GST_AUDIO_NE(F32)
64
65 #define SPECT_CAPS_STRING_F64 \
66 "audio/x-raw, " \
67 " rate = (int) 44100, " \
68 " channels = (int) 1, " \
69 " layout = (string) interleaved, " \
70 " format = (string) " GST_AUDIO_NE(F64)
71
72 #define SPECT_BANDS 256
73
74 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
75 GST_PAD_SINK,
76 GST_PAD_ALWAYS,
77 GST_STATIC_CAPS (SPECT_CAPS_TEMPLATE_STRING)
78 );
79 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
80 GST_PAD_SRC,
81 GST_PAD_ALWAYS,
82 GST_STATIC_CAPS (SPECT_CAPS_TEMPLATE_STRING)
83 );
84
85 /* takes over reference for outcaps */
86 static GstElement *
setup_spectrum(const gchar * caps_str)87 setup_spectrum (const gchar * caps_str)
88 {
89 GstElement *spectrum;
90 GstCaps *caps;
91
92 GST_DEBUG ("setup_spectrum");
93 spectrum = gst_check_setup_element ("spectrum");
94 mysrcpad = gst_check_setup_src_pad (spectrum, &srctemplate);
95 mysinkpad = gst_check_setup_sink_pad (spectrum, &sinktemplate);
96 gst_pad_set_active (mysrcpad, TRUE);
97 gst_pad_set_active (mysinkpad, TRUE);
98
99 caps = gst_caps_from_string (caps_str);
100 gst_check_setup_events (mysrcpad, spectrum, caps, GST_FORMAT_TIME);
101 gst_caps_unref (caps);
102
103 return spectrum;
104 }
105
106 static void
cleanup_spectrum(GstElement * spectrum)107 cleanup_spectrum (GstElement * spectrum)
108 {
109 GST_DEBUG ("cleanup_spectrum");
110
111 gst_pad_set_active (mysrcpad, FALSE);
112 gst_pad_set_active (mysinkpad, FALSE);
113 gst_check_teardown_src_pad (spectrum);
114 gst_check_teardown_sink_pad (spectrum);
115 gst_check_teardown_element (spectrum);
116
117 g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL);
118 g_list_free (buffers);
119 buffers = NULL;
120 }
121
122
GST_START_TEST(test_int16)123 GST_START_TEST (test_int16)
124 {
125 GstElement *spectrum;
126 GstBuffer *inbuffer, *outbuffer;
127 GstBus *bus;
128 GstMessage *message;
129 const GstStructure *structure;
130 int i, j;
131 gint16 *data;
132 GstMapInfo map;
133 const GValue *list, *value;
134 GstClockTime endtime;
135 gfloat level;
136
137 spectrum = setup_spectrum (SPECT_CAPS_STRING_S16);
138 g_object_set (spectrum, "post-messages", TRUE, "interval", GST_SECOND / 100,
139 "bands", SPECT_BANDS, "threshold", -80, NULL);
140
141 fail_unless (gst_element_set_state (spectrum,
142 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
143 "could not set to playing");
144
145 /* create a 1 sec buffer with an 11025 Hz sine wave */
146 inbuffer = gst_buffer_new_allocate (NULL, 44100 * sizeof (gint16), 0);
147 gst_buffer_map (inbuffer, &map, GST_MAP_WRITE);
148 data = (gint16 *) map.data;
149 for (j = 0; j < 44100; j += 4) {
150 *data = 0;
151 ++data;
152 *data = 32767;
153 ++data;
154 *data = 0;
155 ++data;
156 *data = -32767;
157 ++data;
158 }
159 gst_buffer_unmap (inbuffer, &map);
160 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
161
162 /* create a bus to get the spectrum message on */
163 bus = gst_bus_new ();
164 ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
165 gst_element_set_bus (spectrum, bus);
166 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
167
168 /* pushing gives away my reference ... */
169 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
170 /* ... but it ends up being collected on the global buffer list */
171 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
172 fail_unless_equals_int (g_list_length (buffers), 1);
173 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
174 fail_unless (inbuffer == outbuffer);
175
176 message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
177 ASSERT_OBJECT_REFCOUNT (message, "message", 1);
178
179 fail_unless (message != NULL);
180 fail_unless (GST_MESSAGE_SRC (message) == GST_OBJECT (spectrum));
181 fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT);
182 structure = gst_message_get_structure (message);
183 fail_if (structure == NULL);
184 fail_unless_equals_string ((char *) gst_structure_get_name (structure),
185 "spectrum");
186 fail_unless (gst_structure_get_clock_time (structure, "endtime", &endtime));
187
188 list = gst_structure_get_value (structure, "magnitude");
189 for (i = 0; i < SPECT_BANDS; ++i) {
190 value = gst_value_list_get_value (list, i);
191 level = g_value_get_float (value);
192 GST_DEBUG ("band[%3d] is %.2f", i, level);
193 /* Only the bands in the middle should have a level above 60 */
194 fail_if ((i == SPECT_BANDS / 2 || i == SPECT_BANDS / 2 - 1)
195 && level < -20.0);
196 fail_if ((i != SPECT_BANDS / 2 && i != SPECT_BANDS / 2 - 1)
197 && level > -20.0);
198 }
199 fail_unless_equals_int (g_list_length (buffers), 1);
200 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
201 fail_unless (inbuffer == outbuffer);
202
203 /* clean up */
204 /* flush current messages,and future state change messages */
205 gst_bus_set_flushing (bus, TRUE);
206
207 /* message has a ref to the element */
208 ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 2);
209 gst_message_unref (message);
210 ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 1);
211
212 gst_element_set_bus (spectrum, NULL);
213 ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
214 gst_object_unref (bus);
215 fail_unless (gst_element_set_state (spectrum,
216 GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
217 ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 1);
218 cleanup_spectrum (spectrum);
219 }
220
221 GST_END_TEST;
222
GST_START_TEST(test_int32)223 GST_START_TEST (test_int32)
224 {
225 GstElement *spectrum;
226 GstBuffer *inbuffer, *outbuffer;
227 GstBus *bus;
228 GstMessage *message;
229 const GstStructure *structure;
230 int i, j;
231 gint32 *data;
232 GstMapInfo map;
233 const GValue *list, *value;
234 GstClockTime endtime;
235 gfloat level;
236
237 spectrum = setup_spectrum (SPECT_CAPS_STRING_S32);
238 g_object_set (spectrum, "post-messages", TRUE, "interval", GST_SECOND / 100,
239 "bands", SPECT_BANDS, "threshold", -80, NULL);
240
241 fail_unless (gst_element_set_state (spectrum,
242 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
243 "could not set to playing");
244
245 /* create a 1 sec buffer with an 11025 Hz sine wave */
246 inbuffer = gst_buffer_new_allocate (NULL, 44100 * sizeof (gint32), 0);
247 gst_buffer_map (inbuffer, &map, GST_MAP_WRITE);
248 data = (gint32 *) map.data;
249 for (j = 0; j < 44100; j += 4) {
250 *data = 0;
251 ++data;
252 *data = 2147483647;
253 ++data;
254 *data = 0;
255 ++data;
256 *data = -2147483647;
257 ++data;
258 }
259 gst_buffer_unmap (inbuffer, &map);
260 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
261
262 /* create a bus to get the spectrum message on */
263 bus = gst_bus_new ();
264 ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
265 gst_element_set_bus (spectrum, bus);
266 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
267
268 /* pushing gives away my reference ... */
269 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
270 /* ... but it ends up being collected on the global buffer list */
271 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
272 fail_unless_equals_int (g_list_length (buffers), 1);
273 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
274 fail_unless (inbuffer == outbuffer);
275
276 message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
277 ASSERT_OBJECT_REFCOUNT (message, "message", 1);
278
279 fail_unless (message != NULL);
280 fail_unless (GST_MESSAGE_SRC (message) == GST_OBJECT (spectrum));
281 fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT);
282 structure = gst_message_get_structure (message);
283 fail_if (structure == NULL);
284 fail_unless_equals_string ((char *) gst_structure_get_name (structure),
285 "spectrum");
286 fail_unless (gst_structure_get_clock_time (structure, "endtime", &endtime));
287
288 list = gst_structure_get_value (structure, "magnitude");
289 for (i = 0; i < SPECT_BANDS; ++i) {
290 value = gst_value_list_get_value (list, i);
291 level = g_value_get_float (value);
292 GST_DEBUG ("band[%3d] is %.2f", i, level);
293 /* Only the bands in the middle should have a level above 60 */
294 fail_if ((i == SPECT_BANDS / 2 || i == SPECT_BANDS / 2 - 1)
295 && level < -20.0);
296 fail_if ((i != SPECT_BANDS / 2 && i != SPECT_BANDS / 2 - 1)
297 && level > -20.0);
298 }
299 fail_unless_equals_int (g_list_length (buffers), 1);
300 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
301 fail_unless (inbuffer == outbuffer);
302
303 /* clean up */
304 /* flush current messages,and future state change messages */
305 gst_bus_set_flushing (bus, TRUE);
306
307 /* message has a ref to the element */
308 ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 2);
309 gst_message_unref (message);
310 ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 1);
311
312 gst_element_set_bus (spectrum, NULL);
313 ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
314 gst_object_unref (bus);
315 fail_unless (gst_element_set_state (spectrum,
316 GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
317 ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 1);
318 cleanup_spectrum (spectrum);
319 }
320
321 GST_END_TEST;
322
GST_START_TEST(test_float32)323 GST_START_TEST (test_float32)
324 {
325 GstElement *spectrum;
326 GstBuffer *inbuffer, *outbuffer;
327 GstBus *bus;
328 GstMessage *message;
329 const GstStructure *structure;
330 int i, j;
331 gfloat *data;
332 GstMapInfo map;
333 const GValue *list, *value;
334 GstClockTime endtime;
335 gfloat level;
336
337 spectrum = setup_spectrum (SPECT_CAPS_STRING_F32);
338 g_object_set (spectrum, "post-messages", TRUE, "interval", GST_SECOND / 100,
339 "bands", SPECT_BANDS, "threshold", -80, NULL);
340
341 fail_unless (gst_element_set_state (spectrum,
342 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
343 "could not set to playing");
344
345 /* create a 1 sec buffer with an 11025 Hz sine wave */
346 inbuffer = gst_buffer_new_allocate (NULL, 44100 * sizeof (gfloat), 0);
347 gst_buffer_map (inbuffer, &map, GST_MAP_WRITE);
348 data = (gfloat *) map.data;
349 for (j = 0; j < 44100; j += 4) {
350 *data = 0.0;
351 ++data;
352 *data = 1.0;
353 ++data;
354 *data = 0.0;
355 ++data;
356 *data = -1.0;
357 ++data;
358 }
359 gst_buffer_unmap (inbuffer, &map);
360 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
361
362 /* create a bus to get the spectrum message on */
363 bus = gst_bus_new ();
364 ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
365 gst_element_set_bus (spectrum, bus);
366 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
367
368 /* pushing gives away my reference ... */
369 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
370 /* ... but it ends up being collected on the global buffer list */
371 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
372 fail_unless_equals_int (g_list_length (buffers), 1);
373 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
374 fail_unless (inbuffer == outbuffer);
375
376 message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
377 ASSERT_OBJECT_REFCOUNT (message, "message", 1);
378
379 fail_unless (message != NULL);
380 fail_unless (GST_MESSAGE_SRC (message) == GST_OBJECT (spectrum));
381 fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT);
382 structure = gst_message_get_structure (message);
383 fail_if (structure == NULL);
384 fail_unless_equals_string ((char *) gst_structure_get_name (structure),
385 "spectrum");
386 fail_unless (gst_structure_get_clock_time (structure, "endtime", &endtime));
387
388 list = gst_structure_get_value (structure, "magnitude");
389 for (i = 0; i < SPECT_BANDS; ++i) {
390 value = gst_value_list_get_value (list, i);
391 level = g_value_get_float (value);
392 GST_DEBUG ("band[%3d] is %.2f", i, level);
393 /* Only the bands in the middle should have a level above 60 */
394 fail_if ((i == SPECT_BANDS / 2 || i == SPECT_BANDS / 2 - 1)
395 && level < -20.0);
396 fail_if ((i != SPECT_BANDS / 2 && i != SPECT_BANDS / 2 - 1)
397 && level > -20.0);
398 }
399 fail_unless_equals_int (g_list_length (buffers), 1);
400 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
401 fail_unless (inbuffer == outbuffer);
402
403 /* clean up */
404 /* flush current messages,and future state change messages */
405 gst_bus_set_flushing (bus, TRUE);
406
407 /* message has a ref to the element */
408 ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 2);
409 gst_message_unref (message);
410 ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 1);
411
412 gst_element_set_bus (spectrum, NULL);
413 ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
414 gst_object_unref (bus);
415 fail_unless (gst_element_set_state (spectrum,
416 GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
417 ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 1);
418 cleanup_spectrum (spectrum);
419 }
420
421 GST_END_TEST;
422
GST_START_TEST(test_float64)423 GST_START_TEST (test_float64)
424 {
425 GstElement *spectrum;
426 GstBuffer *inbuffer, *outbuffer;
427 GstBus *bus;
428 GstMessage *message;
429 const GstStructure *structure;
430 int i, j;
431 gdouble *data;
432 GstMapInfo map;
433 const GValue *list, *value;
434 GstClockTime endtime;
435 gfloat level;
436
437 spectrum = setup_spectrum (SPECT_CAPS_STRING_F64);
438 g_object_set (spectrum, "post-messages", TRUE, "interval", GST_SECOND / 100,
439 "bands", SPECT_BANDS, "threshold", -80, NULL);
440
441 fail_unless (gst_element_set_state (spectrum,
442 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
443 "could not set to playing");
444
445 /* create a 1 sec buffer with an 11025 Hz sine wave */
446 inbuffer = gst_buffer_new_allocate (NULL, 44100 * sizeof (gdouble), 0);
447 gst_buffer_map (inbuffer, &map, GST_MAP_WRITE);
448 data = (gdouble *) map.data;
449 for (j = 0; j < 44100; j += 4) {
450 *data = 0.0;
451 ++data;
452 *data = 1.0;
453 ++data;
454 *data = 0.0;
455 ++data;
456 *data = -1.0;
457 ++data;
458 }
459 gst_buffer_unmap (inbuffer, &map);
460 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
461
462 /* create a bus to get the spectrum message on */
463 bus = gst_bus_new ();
464 ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
465 gst_element_set_bus (spectrum, bus);
466 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
467
468 /* pushing gives away my reference ... */
469 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
470 /* ... but it ends up being collected on the global buffer list */
471 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
472 fail_unless_equals_int (g_list_length (buffers), 1);
473 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
474 fail_unless (inbuffer == outbuffer);
475
476 message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
477 ASSERT_OBJECT_REFCOUNT (message, "message", 1);
478
479 fail_unless (message != NULL);
480 fail_unless (GST_MESSAGE_SRC (message) == GST_OBJECT (spectrum));
481 fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT);
482 structure = gst_message_get_structure (message);
483 fail_if (structure == NULL);
484 fail_unless_equals_string ((char *) gst_structure_get_name (structure),
485 "spectrum");
486 fail_unless (gst_structure_get_clock_time (structure, "endtime", &endtime));
487
488 list = gst_structure_get_value (structure, "magnitude");
489 for (i = 0; i < SPECT_BANDS; ++i) {
490 value = gst_value_list_get_value (list, i);
491 level = g_value_get_float (value);
492 GST_DEBUG ("band[%3d] is %.2f", i, level);
493 /* Only the bands in the middle should have a level above 60 */
494 fail_if ((i == SPECT_BANDS / 2 || i == SPECT_BANDS / 2 - 1)
495 && level < -20.0);
496 fail_if ((i != SPECT_BANDS / 2 && i != SPECT_BANDS / 2 - 1)
497 && level > -20.0);
498 }
499 fail_unless_equals_int (g_list_length (buffers), 1);
500 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
501 fail_unless (inbuffer == outbuffer);
502
503 /* clean up */
504 /* flush current messages,and future state change messages */
505 gst_bus_set_flushing (bus, TRUE);
506
507 /* message has a ref to the element */
508 ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 2);
509 gst_message_unref (message);
510 ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 1);
511
512 gst_element_set_bus (spectrum, NULL);
513 ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
514 gst_object_unref (bus);
515 fail_unless (gst_element_set_state (spectrum,
516 GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
517 ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 1);
518 cleanup_spectrum (spectrum);
519 }
520
521 GST_END_TEST;
522
523
524 static Suite *
spectrum_suite(void)525 spectrum_suite (void)
526 {
527 Suite *s = suite_create ("spectrum");
528 TCase *tc_chain = tcase_create ("general");
529
530 suite_add_tcase (s, tc_chain);
531 tcase_add_test (tc_chain, test_int16);
532 tcase_add_test (tc_chain, test_int32);
533 tcase_add_test (tc_chain, test_float32);
534 tcase_add_test (tc_chain, test_float64);
535
536 return s;
537 }
538
539 GST_CHECK_MAIN (spectrum);
540