1 /* GStreamer
2  *
3  * unit test for audiodynamic
4  *
5  * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
6  *
7  * Greatly based on the audiopanorama unit test
8  * Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
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/audio/audio.h>
27 #include <gst/base/gstbasetransform.h>
28 #include <gst/check/gstcheck.h>
29 
30 gboolean have_eos = FALSE;
31 
32 /* For ease of programming we use globals to keep refs for our floating
33  * src and sink pads we create; otherwise we always have to do get_pad,
34  * get_peer, and then remove references in every test function */
35 GstPad *mysrcpad, *mysinkpad;
36 
37 
38 #define DYNAMIC_CAPS_STRING    \
39     "audio/x-raw, "                     \
40     "channels = (int) 1, "              \
41     "rate = (int) 44100, "              \
42     "layout = (string) interleaved, "   \
43     "format = (string) " GST_AUDIO_NE(S16)
44 
45 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
46     GST_PAD_SINK,
47     GST_PAD_ALWAYS,
48     GST_STATIC_CAPS ("audio/x-raw, "
49         "channels = (int) 1, "
50         "rate = (int) [ 1,  MAX ], "
51         "layout = (string) interleaved, "
52         "format = (string)" GST_AUDIO_NE (S16)));
53 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
54     GST_PAD_SRC,
55     GST_PAD_ALWAYS,
56     GST_STATIC_CAPS ("audio/x-raw, "
57         "channels = (int) 1, "
58         "rate = (int) [ 1,  MAX ], "
59         "layout = (string) interleaved, "
60         "format = (string) " GST_AUDIO_NE (S16)));
61 
62 static GstElement *
setup_dynamic(void)63 setup_dynamic (void)
64 {
65   GstElement *dynamic;
66 
67   GST_DEBUG ("setup_dynamic");
68   dynamic = gst_check_setup_element ("audiodynamic");
69   mysrcpad = gst_check_setup_src_pad (dynamic, &srctemplate);
70   mysinkpad = gst_check_setup_sink_pad (dynamic, &sinktemplate);
71   gst_pad_set_active (mysrcpad, TRUE);
72   gst_pad_set_active (mysinkpad, TRUE);
73 
74   return dynamic;
75 }
76 
77 static void
cleanup_dynamic(GstElement * dynamic)78 cleanup_dynamic (GstElement * dynamic)
79 {
80   GST_DEBUG ("cleanup_dynamic");
81 
82   g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL);
83   g_list_free (buffers);
84   buffers = NULL;
85 
86   gst_pad_set_active (mysrcpad, FALSE);
87   gst_pad_set_active (mysinkpad, FALSE);
88   gst_check_teardown_src_pad (dynamic);
89   gst_check_teardown_sink_pad (dynamic);
90   gst_check_teardown_element (dynamic);
91 }
92 
GST_START_TEST(test_passthrough)93 GST_START_TEST (test_passthrough)
94 {
95   GstElement *dynamic;
96   GstBuffer *inbuffer, *outbuffer;
97   GstCaps *caps;
98   gint16 in[6] = { 24576, -16384, 256, -128, 0, -24576 };
99   gint16 res[6];
100 
101   dynamic = setup_dynamic ();
102   fail_unless (gst_element_set_state (dynamic,
103           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
104       "could not set to playing");
105 
106   inbuffer =
107       gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, in, 12, 0, 12,
108       NULL, NULL);
109   fail_unless (gst_buffer_memcmp (inbuffer, 0, in, 12) == 0);
110   caps = gst_caps_from_string (DYNAMIC_CAPS_STRING);
111   gst_check_setup_events (mysrcpad, dynamic, caps, GST_FORMAT_TIME);
112   gst_caps_unref (caps);
113   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
114 
115   /* pushing gives away my reference ... */
116   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
117   /* ... but it ends up being collected on the global buffer list */
118   fail_unless_equals_int (g_list_length (buffers), 1);
119   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
120 
121   fail_unless (gst_buffer_extract (outbuffer, 0, res, 12) == 12);
122   GST_INFO
123       ("expected %+5d %+5d %+5d %+5d %+5d %+5d real %+5d %+5d %+5d %+5d %+5d %+5d",
124       in[0], in[1], in[2], in[3], in[4], in[5], res[0], res[1], res[2], res[3],
125       res[4], res[5]);
126   fail_unless (gst_buffer_memcmp (outbuffer, 0, in, 12) == 0);
127 
128   /* cleanup */
129   cleanup_dynamic (dynamic);
130 }
131 
132 GST_END_TEST;
133 
GST_START_TEST(test_compress_hard_50_50)134 GST_START_TEST (test_compress_hard_50_50)
135 {
136   GstElement *dynamic;
137   GstBuffer *inbuffer, *outbuffer;
138   GstCaps *caps;
139   gint16 in[8] = { -30000, 24576, -16384, 256, -128, 0, -24576, 30000 };
140   gint16 res[8];
141 
142   dynamic = setup_dynamic ();
143   g_object_set (G_OBJECT (dynamic), "mode", 0, NULL);
144   g_object_set (G_OBJECT (dynamic), "characteristics", 0, NULL);
145   g_object_set (G_OBJECT (dynamic), "ratio", 0.5, NULL);
146   g_object_set (G_OBJECT (dynamic), "threshold", 0.5, NULL);
147   fail_unless (gst_element_set_state (dynamic,
148           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
149       "could not set to playing");
150 
151   inbuffer = gst_buffer_new_and_alloc (16);
152   gst_buffer_fill (inbuffer, 0, in, 16);
153   fail_unless (gst_buffer_memcmp (inbuffer, 0, in, 16) == 0);
154   caps = gst_caps_from_string (DYNAMIC_CAPS_STRING);
155   gst_check_setup_events (mysrcpad, dynamic, caps, GST_FORMAT_TIME);
156   gst_caps_unref (caps);
157   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
158 
159   /* pushing gives away my reference ... */
160   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
161   /* ... and puts a new buffer on the global list */
162   fail_unless_equals_int (g_list_length (buffers), 1);
163   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
164 
165   fail_unless (gst_buffer_extract (outbuffer, 0, res, 16) == 16);
166 
167   fail_unless (res[0] > in[0]);
168   fail_unless (res[1] < in[1]);
169   fail_unless (res[2] == in[2]);
170   fail_unless (res[3] == in[3]);
171   fail_unless (res[4] == in[4]);
172   fail_unless (res[5] == in[5]);
173   fail_unless (res[6] > in[6]);
174   fail_unless (res[7] < in[7]);
175 
176   /* cleanup */
177   cleanup_dynamic (dynamic);
178 }
179 
180 GST_END_TEST;
181 
GST_START_TEST(test_compress_soft_50_50)182 GST_START_TEST (test_compress_soft_50_50)
183 {
184   GstElement *dynamic;
185   GstBuffer *inbuffer, *outbuffer;
186   GstCaps *caps;
187   gint16 in[8] = { -30000, 24576, -16384, 256, -128, 0, -24576, 30000 };
188   gint16 res[8];
189 
190   dynamic = setup_dynamic ();
191   g_object_set (G_OBJECT (dynamic), "mode", 0, NULL);
192   g_object_set (G_OBJECT (dynamic), "characteristics", 1, NULL);
193   g_object_set (G_OBJECT (dynamic), "ratio", 0.5, NULL);
194   g_object_set (G_OBJECT (dynamic), "threshold", 0.5, NULL);
195   fail_unless (gst_element_set_state (dynamic,
196           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
197       "could not set to playing");
198 
199   inbuffer = gst_buffer_new_and_alloc (16);
200   gst_buffer_fill (inbuffer, 0, in, 16);
201   fail_unless (gst_buffer_memcmp (inbuffer, 0, in, 16) == 0);
202   caps = gst_caps_from_string (DYNAMIC_CAPS_STRING);
203   gst_check_setup_events (mysrcpad, dynamic, caps, GST_FORMAT_TIME);
204   gst_caps_unref (caps);
205   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
206 
207   /* pushing gives away my reference ... */
208   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
209   /* ... and puts a new buffer on the global list */
210   fail_unless_equals_int (g_list_length (buffers), 1);
211   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
212 
213   fail_unless (gst_buffer_extract (outbuffer, 0, res, 16) == 16);
214 
215   fail_unless (res[0] > in[0]);
216   fail_unless (res[1] < in[1]);
217   fail_unless (res[2] == in[2]);
218   fail_unless (res[3] == in[3]);
219   fail_unless (res[4] == in[4]);
220   fail_unless (res[5] == in[5]);
221   fail_unless (res[6] > in[6]);
222   fail_unless (res[7] < in[7]);
223 
224   /* cleanup */
225   cleanup_dynamic (dynamic);
226 }
227 
228 GST_END_TEST;
229 
GST_START_TEST(test_compress_hard_100_50)230 GST_START_TEST (test_compress_hard_100_50)
231 {
232   GstElement *dynamic;
233   GstBuffer *inbuffer, *outbuffer;
234   GstCaps *caps;
235   gint16 in[8] = { -30000, 24576, -16384, 256, -128, 0, -24576, 30000 };
236   gint16 res[8];
237 
238   dynamic = setup_dynamic ();
239   g_object_set (G_OBJECT (dynamic), "mode", 0, NULL);
240   g_object_set (G_OBJECT (dynamic), "characteristics", 0, NULL);
241   g_object_set (G_OBJECT (dynamic), "ratio", 0.5, NULL);
242   g_object_set (G_OBJECT (dynamic), "threshold", 1.0, NULL);
243   fail_unless (gst_element_set_state (dynamic,
244           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
245       "could not set to playing");
246 
247   inbuffer = gst_buffer_new_and_alloc (16);
248   gst_buffer_fill (inbuffer, 0, in, 16);
249   fail_unless (gst_buffer_memcmp (inbuffer, 0, in, 16) == 0);
250   caps = gst_caps_from_string (DYNAMIC_CAPS_STRING);
251   gst_check_setup_events (mysrcpad, dynamic, caps, GST_FORMAT_TIME);
252   gst_caps_unref (caps);
253   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
254 
255   /* pushing gives away my reference ... */
256   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
257   /* ... and puts a new buffer on the global list */
258   fail_unless_equals_int (g_list_length (buffers), 1);
259   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
260 
261   fail_unless (gst_buffer_extract (outbuffer, 0, res, 16) == 16);
262 
263   fail_unless (res[0] == in[0]);
264   fail_unless (res[1] == in[1]);
265   fail_unless (res[2] == in[2]);
266   fail_unless (res[3] == in[3]);
267   fail_unless (res[4] == in[4]);
268   fail_unless (res[5] == in[5]);
269   fail_unless (res[6] == in[6]);
270   fail_unless (res[7] == in[7]);
271 
272   /* cleanup */
273   cleanup_dynamic (dynamic);
274 }
275 
276 GST_END_TEST;
277 
278 
GST_START_TEST(test_expand_hard_50_200)279 GST_START_TEST (test_expand_hard_50_200)
280 {
281   GstElement *dynamic;
282   GstBuffer *inbuffer, *outbuffer;
283   GstCaps *caps;
284   gint16 in[8] = { -30000, 24576, -16383, 256, -128, 0, -24576, 30000 };
285   gint16 res[8];
286 
287   dynamic = setup_dynamic ();
288   g_object_set (G_OBJECT (dynamic), "mode", 1, NULL);
289   g_object_set (G_OBJECT (dynamic), "characteristics", 0, NULL);
290   g_object_set (G_OBJECT (dynamic), "ratio", 2.0, NULL);
291   g_object_set (G_OBJECT (dynamic), "threshold", 0.5, NULL);
292   fail_unless (gst_element_set_state (dynamic,
293           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
294       "could not set to playing");
295 
296   inbuffer = gst_buffer_new_and_alloc (16);
297   gst_buffer_fill (inbuffer, 0, in, 16);
298   fail_unless (gst_buffer_memcmp (inbuffer, 0, in, 16) == 0);
299   caps = gst_caps_from_string (DYNAMIC_CAPS_STRING);
300   gst_check_setup_events (mysrcpad, dynamic, caps, GST_FORMAT_TIME);
301   gst_caps_unref (caps);
302   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
303 
304   /* pushing gives away my reference ... */
305   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
306   /* ... and puts a new buffer on the global list */
307   fail_unless_equals_int (g_list_length (buffers), 1);
308   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
309 
310   fail_unless (gst_buffer_extract (outbuffer, 0, res, 16) == 16);
311 
312   fail_unless (res[0] == in[0]);
313   fail_unless (res[1] == in[1]);
314   fail_unless (res[2] > in[2]);
315   fail_unless (res[3] < in[3]);
316   fail_unless (res[4] > in[4]);
317   fail_unless (res[5] == in[5]);
318   fail_unless (res[6] == in[6]);
319   fail_unless (res[7] == in[7]);
320 
321   /* cleanup */
322   cleanup_dynamic (dynamic);
323 }
324 
325 GST_END_TEST;
326 
GST_START_TEST(test_expand_soft_50_200)327 GST_START_TEST (test_expand_soft_50_200)
328 {
329   GstElement *dynamic;
330   GstBuffer *inbuffer, *outbuffer;
331   GstCaps *caps;
332   gint16 in[8] = { -30000, 24576, -16383, 256, -128, 0, -24576, 30000 };
333   gint16 res[8];
334 
335   dynamic = setup_dynamic ();
336   g_object_set (G_OBJECT (dynamic), "mode", 1, NULL);
337   g_object_set (G_OBJECT (dynamic), "characteristics", 1, NULL);
338   g_object_set (G_OBJECT (dynamic), "ratio", 2.0, NULL);
339   g_object_set (G_OBJECT (dynamic), "threshold", 0.5, NULL);
340   fail_unless (gst_element_set_state (dynamic,
341           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
342       "could not set to playing");
343 
344   inbuffer = gst_buffer_new_and_alloc (16);
345   gst_buffer_fill (inbuffer, 0, in, 16);
346   fail_unless (gst_buffer_memcmp (inbuffer, 0, in, 16) == 0);
347   caps = gst_caps_from_string (DYNAMIC_CAPS_STRING);
348   gst_check_setup_events (mysrcpad, dynamic, caps, GST_FORMAT_TIME);
349   gst_caps_unref (caps);
350   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
351 
352   /* pushing gives away my reference ... */
353   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
354   /* ... and puts a new buffer on the global list */
355   fail_unless_equals_int (g_list_length (buffers), 1);
356   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
357 
358   fail_unless (gst_buffer_extract (outbuffer, 0, res, 16) == 16);
359 
360   fail_unless (res[0] == in[0]);
361   fail_unless (res[1] == in[1]);
362   fail_unless (res[2] > in[2]);
363   fail_unless (res[3] < in[3]);
364   fail_unless (res[4] > in[4]);
365   fail_unless (res[5] == in[5]);
366   fail_unless (res[6] == in[6]);
367   fail_unless (res[7] == in[7]);
368 
369   /* cleanup */
370   cleanup_dynamic (dynamic);
371 }
372 
373 GST_END_TEST;
374 
GST_START_TEST(test_expand_hard_0_200)375 GST_START_TEST (test_expand_hard_0_200)
376 {
377   GstElement *dynamic;
378   GstBuffer *inbuffer, *outbuffer;
379   GstCaps *caps;
380   gint16 in[8] = { -30000, 24576, -16383, 256, -128, 0, -24576, 30000 };
381   gint16 res[8];
382 
383   dynamic = setup_dynamic ();
384   g_object_set (G_OBJECT (dynamic), "mode", 1, NULL);
385   g_object_set (G_OBJECT (dynamic), "characteristics", 0, NULL);
386   g_object_set (G_OBJECT (dynamic), "ratio", 2.0, NULL);
387   g_object_set (G_OBJECT (dynamic), "threshold", 0.0, NULL);
388   fail_unless (gst_element_set_state (dynamic,
389           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
390       "could not set to playing");
391 
392   inbuffer = gst_buffer_new_and_alloc (16);
393   gst_buffer_fill (inbuffer, 0, in, 16);
394   fail_unless (gst_buffer_memcmp (inbuffer, 0, in, 16) == 0);
395   caps = gst_caps_from_string (DYNAMIC_CAPS_STRING);
396   gst_check_setup_events (mysrcpad, dynamic, caps, GST_FORMAT_TIME);
397   gst_caps_unref (caps);
398   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
399 
400   /* pushing gives away my reference ... */
401   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
402   /* ... and puts a new buffer on the global list */
403   fail_unless_equals_int (g_list_length (buffers), 1);
404   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
405 
406   fail_unless (gst_buffer_extract (outbuffer, 0, res, 16) == 16);
407 
408   fail_unless (res[0] == in[0]);
409   fail_unless (res[1] == in[1]);
410   fail_unless (res[2] == in[2]);
411   fail_unless (res[3] == in[3]);
412   fail_unless (res[4] == in[4]);
413   fail_unless (res[5] == in[5]);
414   fail_unless (res[6] == in[6]);
415   fail_unless (res[7] == in[7]);
416 
417   /* cleanup */
418   cleanup_dynamic (dynamic);
419 }
420 
421 GST_END_TEST;
422 
423 static Suite *
dynamic_suite(void)424 dynamic_suite (void)
425 {
426   Suite *s = suite_create ("dynamic");
427   TCase *tc_chain = tcase_create ("general");
428 
429   suite_add_tcase (s, tc_chain);
430   tcase_add_test (tc_chain, test_passthrough);
431   tcase_add_test (tc_chain, test_compress_hard_50_50);
432   tcase_add_test (tc_chain, test_compress_soft_50_50);
433   tcase_add_test (tc_chain, test_compress_hard_100_50);
434   tcase_add_test (tc_chain, test_expand_hard_50_200);
435   tcase_add_test (tc_chain, test_expand_soft_50_200);
436   tcase_add_test (tc_chain, test_expand_hard_0_200);
437   return s;
438 }
439 
440 GST_CHECK_MAIN (dynamic);
441