Added gst-plugins-base-subtitles0.10-0.10.34 for Meego Harmattan 1.2
[mafwsubrenderer] / gst-plugins-base-subtitles0.10 / tests / check / elements / audiorate.c
1 /* GStreamer unit tests for audiorate
2  *
3  * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <gst/check/gstcheck.h>
26
27 /* helper element to insert additional buffers overlapping with previous ones */
28 static gdouble injector_inject_probability = 0.0;
29
30 typedef GstElement TestInjector;
31 typedef GstElementClass TestInjectorClass;
32
33 GType test_injector_get_type (void);
34 GST_BOILERPLATE (TestInjector, test_injector, GstElement, GST_TYPE_ELEMENT);
35
36 #define INJECTOR_CAPS \
37   "audio/x-raw-float, "                                  \
38     "rate = (int) [ 1, MAX ], "                          \
39     "channels = (int) [ 1, 8 ], "                        \
40     "endianness = (int) BYTE_ORDER, "                    \
41     "width = (int) 32;"                                  \
42   "audio/x-raw-int, "                                    \
43     "rate = (int) [ 1, MAX ], "                          \
44     "channels = (int) [ 1, 8 ], "                        \
45     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
46     "width = (int) { 8, 16, 32 }, "                      \
47     "depth = (int) [ 1, 32 ], "                          \
48     "signed = (boolean) { true, false }"
49
50 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
51     GST_PAD_SRC,
52     GST_PAD_ALWAYS,
53     GST_STATIC_CAPS (INJECTOR_CAPS));
54
55 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
56     GST_PAD_SINK,
57     GST_PAD_ALWAYS,
58     GST_STATIC_CAPS (INJECTOR_CAPS));
59
60 static void
61 test_injector_base_init (gpointer g_class)
62 {
63   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
64
65   gst_element_class_add_pad_template (element_class,
66       gst_static_pad_template_get (&src_template));
67   gst_element_class_add_pad_template (element_class,
68       gst_static_pad_template_get (&sink_template));
69 }
70
71 static void
72 test_injector_class_init (TestInjectorClass * klass)
73 {
74   /* nothing to do here */
75 }
76
77 static GstFlowReturn
78 test_injector_chain (GstPad * pad, GstBuffer * buf)
79 {
80   GstFlowReturn ret;
81   GstPad *srcpad;
82
83   srcpad =
84       gst_element_get_static_pad (GST_ELEMENT (GST_PAD_PARENT (pad)), "src");
85
86   /* since we're increasing timestamp/offsets, push this one first */
87   GST_LOG (" passing buffer   [t=%" GST_TIME_FORMAT "-%" GST_TIME_FORMAT
88       "], offset=%" G_GINT64_FORMAT ", offset_end=%" G_GINT64_FORMAT,
89       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
90       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)),
91       GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf));
92
93   gst_buffer_ref (buf);
94
95   ret = gst_pad_push (srcpad, buf);
96
97   if (g_random_double () < injector_inject_probability) {
98     GstBuffer *ibuf;
99
100     ibuf = gst_buffer_copy (buf);
101
102     if (GST_BUFFER_OFFSET_IS_VALID (buf) &&
103         GST_BUFFER_OFFSET_END_IS_VALID (buf)) {
104       guint64 delta;
105
106       delta = GST_BUFFER_OFFSET_END (buf) - GST_BUFFER_OFFSET (buf);
107       GST_BUFFER_OFFSET (ibuf) += delta / 4;
108       GST_BUFFER_OFFSET_END (ibuf) += delta / 4;
109     } else {
110       GST_BUFFER_OFFSET (ibuf) = GST_BUFFER_OFFSET_NONE;
111       GST_BUFFER_OFFSET_END (ibuf) = GST_BUFFER_OFFSET_NONE;
112     }
113
114     if (GST_BUFFER_TIMESTAMP_IS_VALID (buf) &&
115         GST_BUFFER_DURATION_IS_VALID (buf)) {
116       GstClockTime delta;
117
118       delta = GST_BUFFER_DURATION (buf);
119       GST_BUFFER_TIMESTAMP (ibuf) += delta / 4;
120     } else {
121       GST_BUFFER_TIMESTAMP (ibuf) = GST_CLOCK_TIME_NONE;
122       GST_BUFFER_DURATION (ibuf) = GST_CLOCK_TIME_NONE;
123     }
124
125     if (GST_BUFFER_TIMESTAMP_IS_VALID (ibuf) ||
126         GST_BUFFER_OFFSET_IS_VALID (ibuf)) {
127       GST_LOG ("injecting buffer [t=%" GST_TIME_FORMAT "-%" GST_TIME_FORMAT
128           "], offset=%" G_GINT64_FORMAT ", offset_end=%" G_GINT64_FORMAT,
129           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (ibuf)),
130           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (ibuf) +
131               GST_BUFFER_DURATION (ibuf)), GST_BUFFER_OFFSET (ibuf),
132           GST_BUFFER_OFFSET_END (ibuf));
133
134       if (gst_pad_push (srcpad, ibuf) != GST_FLOW_OK) {
135         /* ignore return value */
136       }
137     } else {
138       GST_WARNING ("couldn't inject buffer, no incoming timestamps or offsets");
139       gst_buffer_unref (ibuf);
140     }
141   }
142
143   gst_buffer_unref (buf);
144
145   return ret;
146 }
147
148 static void
149 test_injector_init (TestInjector * injector, TestInjectorClass * klass)
150 {
151   GstPad *pad;
152
153   pad = gst_pad_new_from_static_template (&sink_template, "sink");
154   gst_pad_set_chain_function (pad, test_injector_chain);
155   gst_pad_set_getcaps_function (pad, gst_pad_proxy_getcaps);
156   gst_pad_set_setcaps_function (pad, gst_pad_proxy_setcaps);
157   gst_element_add_pad (GST_ELEMENT (injector), pad);
158
159   pad = gst_pad_new_from_static_template (&src_template, "src");
160   gst_pad_set_getcaps_function (pad, gst_pad_proxy_getcaps);
161   gst_pad_set_setcaps_function (pad, gst_pad_proxy_setcaps);
162   gst_element_add_pad (GST_ELEMENT (injector), pad);
163 }
164
165 static gboolean
166 probe_cb (GstPad * pad, GstBuffer * buf, gdouble * drop_probability)
167 {
168   if (g_random_double () < *drop_probability) {
169     GST_LOG ("dropping buffer [t=%" GST_TIME_FORMAT "-%" GST_TIME_FORMAT "], "
170         "offset=%" G_GINT64_FORMAT ", offset_end=%" G_GINT64_FORMAT,
171         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
172         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)),
173         GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf));
174     return FALSE;               /* drop buffer */
175   }
176
177   return TRUE;                  /* don't drop buffer */
178 }
179
180 static void
181 got_buf (GstElement * fakesink, GstBuffer * buf, GstPad * pad, GList ** p_bufs)
182 {
183   *p_bufs = g_list_append (*p_bufs, gst_buffer_ref (buf));
184 }
185
186 static void
187 do_perfect_stream_test (guint rate, guint width, gdouble drop_probability,
188     gdouble inject_probability)
189 {
190   GstElement *pipe, *src, *conv, *filter, *injector, *audiorate, *sink;
191   GstMessage *msg;
192   GstCaps *caps;
193   GstPad *srcpad;
194   GList *l, *bufs = NULL;
195   GstClockTime next_time = GST_CLOCK_TIME_NONE;
196   guint64 next_offset = GST_BUFFER_OFFSET_NONE;
197
198   caps = gst_caps_new_simple ("audio/x-raw-int", "rate", G_TYPE_INT,
199       rate, "width", G_TYPE_INT, width, NULL);
200
201   GST_INFO ("-------- drop=%.0f%% caps = %" GST_PTR_FORMAT " ---------- ",
202       drop_probability * 100.0, caps);
203
204   g_assert (drop_probability >= 0.0 && drop_probability <= 1.0);
205   g_assert (inject_probability >= 0.0 && inject_probability <= 1.0);
206   g_assert (width > 0 && (width % 8) == 0);
207
208   pipe = gst_pipeline_new ("pipeline");
209   fail_unless (pipe != NULL);
210
211   src = gst_element_factory_make ("audiotestsrc", "audiotestsrc");
212   fail_unless (src != NULL);
213
214   g_object_set (src, "num-buffers", 100, NULL);
215
216   conv = gst_element_factory_make ("audioconvert", "audioconvert");
217   fail_unless (conv != NULL);
218
219   filter = gst_element_factory_make ("capsfilter", "capsfilter");
220   fail_unless (filter != NULL);
221
222   g_object_set (filter, "caps", caps, NULL);
223
224   injector_inject_probability = inject_probability;
225
226   injector = GST_ELEMENT (g_object_new (test_injector_get_type (), NULL));
227
228   srcpad = gst_element_get_static_pad (injector, "src");
229   fail_unless (srcpad != NULL);
230   gst_pad_add_buffer_probe (srcpad, G_CALLBACK (probe_cb), &drop_probability);
231   gst_object_unref (srcpad);
232
233   audiorate = gst_element_factory_make ("audiorate", "audiorate");
234   fail_unless (audiorate != NULL);
235
236   sink = gst_element_factory_make ("fakesink", "fakesink");
237   fail_unless (sink != NULL);
238
239   g_object_set (sink, "signal-handoffs", TRUE, NULL);
240
241   g_signal_connect (sink, "handoff", G_CALLBACK (got_buf), &bufs);
242
243   gst_bin_add_many (GST_BIN (pipe), src, conv, filter, injector, audiorate,
244       sink, NULL);
245   gst_element_link_many (src, conv, filter, injector, audiorate, sink, NULL);
246
247   fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PLAYING),
248       GST_STATE_CHANGE_ASYNC);
249
250   fail_unless_equals_int (gst_element_get_state (pipe, NULL, NULL, -1),
251       GST_STATE_CHANGE_SUCCESS);
252
253   msg = gst_bus_poll (GST_ELEMENT_BUS (pipe),
254       GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
255   fail_unless_equals_string (GST_MESSAGE_TYPE_NAME (msg), "eos");
256
257   for (l = bufs; l != NULL; l = l->next) {
258     GstBuffer *buf = GST_BUFFER (l->data);
259     guint num_samples;
260
261     fail_unless (GST_BUFFER_TIMESTAMP_IS_VALID (buf));
262     fail_unless (GST_BUFFER_DURATION_IS_VALID (buf));
263     fail_unless (GST_BUFFER_OFFSET_IS_VALID (buf));
264     fail_unless (GST_BUFFER_OFFSET_END_IS_VALID (buf));
265
266     GST_LOG ("buffer: ts=%" GST_TIME_FORMAT ", end_ts=%" GST_TIME_FORMAT
267         " off=%" G_GINT64_FORMAT ", end_off=%" G_GINT64_FORMAT,
268         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
269         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)),
270         GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf));
271
272     if (GST_CLOCK_TIME_IS_VALID (next_time)) {
273       fail_unless_equals_uint64 (next_time, GST_BUFFER_TIMESTAMP (buf));
274     }
275     if (next_offset != GST_BUFFER_OFFSET_NONE) {
276       fail_unless_equals_uint64 (next_offset, GST_BUFFER_OFFSET (buf));
277     }
278
279     /* check buffer size for sanity */
280     fail_unless_equals_int (GST_BUFFER_SIZE (buf) % (width / 8), 0);
281
282     /* check there is actually as much data as there should be */
283     num_samples = GST_BUFFER_OFFSET_END (buf) - GST_BUFFER_OFFSET (buf);
284     fail_unless_equals_int (GST_BUFFER_SIZE (buf), num_samples * (width / 8));
285
286     next_time = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);
287     next_offset = GST_BUFFER_OFFSET_END (buf);
288   }
289
290   gst_message_unref (msg);
291   gst_element_set_state (pipe, GST_STATE_NULL);
292   gst_object_unref (pipe);
293
294   g_list_foreach (bufs, (GFunc) gst_mini_object_unref, NULL);
295   g_list_free (bufs);
296
297   gst_caps_unref (caps);
298 }
299
300 static const guint rates[] = { 8000, 11025, 16000, 22050, 32000, 44100,
301   48000, 3333, 33333, 66666, 9999
302 };
303
304 GST_START_TEST (test_perfect_stream_drop0)
305 {
306   guint i;
307
308   for (i = 0; i < G_N_ELEMENTS (rates); ++i) {
309     do_perfect_stream_test (rates[i], 8, 0.0, 0.0);
310     do_perfect_stream_test (rates[i], 16, 0.0, 0.0);
311   }
312 }
313
314 GST_END_TEST;
315
316 GST_START_TEST (test_perfect_stream_drop10)
317 {
318   guint i;
319
320   for (i = 0; i < G_N_ELEMENTS (rates); ++i) {
321     do_perfect_stream_test (rates[i], 8, 0.10, 0.0);
322     do_perfect_stream_test (rates[i], 16, 0.10, 0.0);
323   }
324 }
325
326 GST_END_TEST;
327
328 GST_START_TEST (test_perfect_stream_drop50)
329 {
330   guint i;
331
332   for (i = 0; i < G_N_ELEMENTS (rates); ++i) {
333     do_perfect_stream_test (rates[i], 8, 0.50, 0.0);
334     do_perfect_stream_test (rates[i], 16, 0.50, 0.0);
335   }
336 }
337
338 GST_END_TEST;
339
340 GST_START_TEST (test_perfect_stream_drop90)
341 {
342   guint i;
343
344   for (i = 0; i < G_N_ELEMENTS (rates); ++i) {
345     do_perfect_stream_test (rates[i], 8, 0.90, 0.0);
346     do_perfect_stream_test (rates[i], 16, 0.90, 0.0);
347   }
348 }
349
350 GST_END_TEST;
351
352 GST_START_TEST (test_perfect_stream_inject10)
353 {
354   guint i;
355
356   for (i = 0; i < G_N_ELEMENTS (rates); ++i) {
357     do_perfect_stream_test (rates[i], 8, 0.0, 0.10);
358     do_perfect_stream_test (rates[i], 16, 0.0, 0.10);
359   }
360 }
361
362 GST_END_TEST;
363
364 GST_START_TEST (test_perfect_stream_inject90)
365 {
366   guint i;
367
368   for (i = 0; i < G_N_ELEMENTS (rates); ++i) {
369     do_perfect_stream_test (rates[i], 8, 0.0, 0.90);
370     do_perfect_stream_test (rates[i], 16, 0.0, 0.90);
371   }
372 }
373
374 GST_END_TEST;
375
376 GST_START_TEST (test_perfect_stream_drop45_inject25)
377 {
378   guint i;
379
380   for (i = 0; i < G_N_ELEMENTS (rates); ++i) {
381     do_perfect_stream_test (rates[i], 8, 0.45, 0.25);
382     do_perfect_stream_test (rates[i], 16, 0.45, 0.25);
383   }
384 }
385
386 GST_END_TEST;
387
388 /* TODO: also do all tests with channels=1 and channels=2 */
389
390 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
391     GST_PAD_SRC,
392     GST_PAD_ALWAYS,
393     GST_STATIC_CAPS ("audio/x-raw-float,channels=1,rate=44100,width=32")
394     );
395
396 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
397     GST_PAD_SINK,
398     GST_PAD_ALWAYS,
399     GST_STATIC_CAPS ("audio/x-raw-float,channels=1,rate=44100,width=32")
400     );
401
402 GST_START_TEST (test_large_discont)
403 {
404   GstElement *audiorate;
405   GstCaps *caps;
406   GstPad *srcpad, *sinkpad;
407   GstBuffer *buf;
408
409   audiorate = gst_check_setup_element ("audiorate");
410   caps = gst_caps_new_simple ("audio/x-raw-float",
411       "channels", G_TYPE_INT, 1,
412       "rate", G_TYPE_INT, 44100, "width", G_TYPE_INT, 32, NULL);
413
414   srcpad = gst_check_setup_src_pad (audiorate, &srctemplate, caps);
415   sinkpad = gst_check_setup_sink_pad (audiorate, &sinktemplate, caps);
416
417   gst_pad_set_active (srcpad, TRUE);
418   gst_pad_set_active (sinkpad, TRUE);
419
420   fail_unless (gst_element_set_state (audiorate,
421           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
422       "failed to set audiorate playing");
423
424   buf = gst_buffer_new_and_alloc (4);
425   gst_buffer_set_caps (buf, caps);
426   GST_BUFFER_TIMESTAMP (buf) = 0;
427   gst_pad_push (srcpad, buf);
428
429   fail_unless_equals_int (g_list_length (buffers), 1);
430
431   buf = gst_buffer_new_and_alloc (4);
432   gst_buffer_set_caps (buf, caps);
433   GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND;
434   gst_pad_push (srcpad, buf);
435   /* Now we should have 3 more buffers: the one we injected, plus _two_ filler
436    * buffers, because the gap is > 1 second (but less than 2 seconds) */
437   fail_unless_equals_int (g_list_length (buffers), 4);
438
439   gst_element_set_state (audiorate, GST_STATE_NULL);
440   gst_caps_unref (caps);
441
442   gst_check_teardown_sink_pad (audiorate);
443   gst_check_teardown_src_pad (audiorate);
444
445   gst_object_unref (audiorate);
446 }
447
448 GST_END_TEST;
449
450 static Suite *
451 audiorate_suite (void)
452 {
453   Suite *s = suite_create ("audiorate");
454   TCase *tc_chain = tcase_create ("general");
455
456   suite_add_tcase (s, tc_chain);
457
458   tcase_add_test (tc_chain, test_perfect_stream_drop0);
459   tcase_add_test (tc_chain, test_perfect_stream_drop10);
460   tcase_add_test (tc_chain, test_perfect_stream_drop50);
461   tcase_add_test (tc_chain, test_perfect_stream_drop90);
462   tcase_add_test (tc_chain, test_perfect_stream_inject10);
463   tcase_add_test (tc_chain, test_perfect_stream_inject90);
464   tcase_add_test (tc_chain, test_perfect_stream_drop45_inject25);
465   tcase_add_test (tc_chain, test_large_discont);
466
467   return s;
468 }
469
470 GST_CHECK_MAIN (audiorate);