3 * unit test for audioresample, based on the audioresample unit test
5 * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
6 * Copyright (C) <2006> Tim-Philipp Müller <tim at centricular net>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
26 #include <gst/check/gstcheck.h>
28 #include <gst/audio/audio.h>
30 /* For ease of programming we use globals to keep refs for our floating
31 * src and sink pads we create; otherwise we always have to do get_pad,
32 * get_peer, and then remove references in every test function */
33 static GstPad *mysrcpad, *mysinkpad;
35 #define RESAMPLE_CAPS_FLOAT \
36 "audio/x-raw-float, " \
37 "channels = (int) [ 1, MAX ], " \
38 "rate = (int) [ 1, MAX ], " \
39 "endianness = (int) BYTE_ORDER, " \
40 "width = (int) { 32, 64 }"
42 #define RESAMPLE_CAPS_INT \
44 "channels = (int) [ 1, MAX ], " \
45 "rate = (int) [ 1, MAX ], " \
46 "endianness = (int) BYTE_ORDER, " \
47 "width = (int) 16, " \
48 "depth = (int) 16, " \
49 "signed = (bool) TRUE"
51 #define RESAMPLE_CAPS_TEMPLATE_STRING \
52 RESAMPLE_CAPS_FLOAT " ; " \
55 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
58 GST_STATIC_CAPS (RESAMPLE_CAPS_TEMPLATE_STRING)
60 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
63 GST_STATIC_CAPS (RESAMPLE_CAPS_TEMPLATE_STRING)
67 setup_audioresample (int channels, int inrate, int outrate, int width,
70 GstElement *audioresample;
72 GstStructure *structure;
74 GST_DEBUG ("setup_audioresample");
75 audioresample = gst_check_setup_element ("audioresample");
78 caps = gst_caps_from_string (RESAMPLE_CAPS_FLOAT);
80 caps = gst_caps_from_string (RESAMPLE_CAPS_INT);
81 structure = gst_caps_get_structure (caps, 0);
82 gst_structure_set (structure, "channels", G_TYPE_INT, channels,
83 "rate", G_TYPE_INT, inrate, "width", G_TYPE_INT, width, NULL);
85 gst_structure_set (structure, "depth", G_TYPE_INT, width, NULL);
86 fail_unless (gst_caps_is_fixed (caps));
88 fail_unless (gst_element_set_state (audioresample,
89 GST_STATE_PAUSED) == GST_STATE_CHANGE_SUCCESS,
90 "could not set to paused");
92 mysrcpad = gst_check_setup_src_pad (audioresample, &srctemplate, caps);
93 gst_pad_set_caps (mysrcpad, caps);
94 gst_caps_unref (caps);
97 caps = gst_caps_from_string (RESAMPLE_CAPS_FLOAT);
99 caps = gst_caps_from_string (RESAMPLE_CAPS_INT);
100 structure = gst_caps_get_structure (caps, 0);
101 gst_structure_set (structure, "channels", G_TYPE_INT, channels,
102 "rate", G_TYPE_INT, outrate, "width", G_TYPE_INT, width, NULL);
104 gst_structure_set (structure, "depth", G_TYPE_INT, width, NULL);
105 fail_unless (gst_caps_is_fixed (caps));
107 mysinkpad = gst_check_setup_sink_pad (audioresample, &sinktemplate, caps);
108 /* this installs a getcaps func that will always return the caps we set
110 gst_pad_set_caps (mysinkpad, caps);
111 gst_pad_use_fixed_caps (mysinkpad);
113 gst_pad_set_active (mysinkpad, TRUE);
114 gst_pad_set_active (mysrcpad, TRUE);
116 gst_caps_unref (caps);
118 return audioresample;
122 cleanup_audioresample (GstElement * audioresample)
124 GST_DEBUG ("cleanup_audioresample");
126 fail_unless (gst_element_set_state (audioresample,
127 GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to NULL");
129 gst_pad_set_active (mysrcpad, FALSE);
130 gst_pad_set_active (mysinkpad, FALSE);
131 gst_check_teardown_src_pad (audioresample);
132 gst_check_teardown_sink_pad (audioresample);
133 gst_check_teardown_element (audioresample);
134 gst_check_drop_buffers ();
138 fail_unless_perfect_stream (void)
140 guint64 timestamp = 0L, duration = 0L;
141 guint64 offset = 0L, offset_end = 0L;
146 for (l = buffers; l; l = l->next) {
147 buffer = GST_BUFFER (l->data);
148 ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
149 GST_DEBUG ("buffer timestamp %" G_GUINT64_FORMAT ", duration %"
150 G_GUINT64_FORMAT " offset %" G_GUINT64_FORMAT " offset_end %"
152 GST_BUFFER_TIMESTAMP (buffer),
153 GST_BUFFER_DURATION (buffer),
154 GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET_END (buffer));
156 fail_unless_equals_uint64 (timestamp, GST_BUFFER_TIMESTAMP (buffer));
157 fail_unless_equals_uint64 (offset, GST_BUFFER_OFFSET (buffer));
158 duration = GST_BUFFER_DURATION (buffer);
159 offset_end = GST_BUFFER_OFFSET_END (buffer);
161 timestamp += duration;
163 gst_buffer_unref (buffer);
165 g_list_free (buffers);
169 /* this tests that the output is a perfect stream if the input is */
171 test_perfect_stream_instance (int inrate, int outrate, int samples,
174 GstElement *audioresample;
175 GstBuffer *inbuffer, *outbuffer;
182 audioresample = setup_audioresample (2, inrate, outrate, 16, FALSE);
183 caps = gst_pad_get_negotiated_caps (mysrcpad);
184 fail_unless (gst_caps_is_fixed (caps));
186 fail_unless (gst_element_set_state (audioresample,
187 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
188 "could not set to playing");
190 for (j = 1; j <= numbuffers; ++j) {
192 inbuffer = gst_buffer_new_and_alloc (samples * 4);
193 GST_BUFFER_DURATION (inbuffer) = GST_FRAMES_TO_CLOCK_TIME (samples, inrate);
194 GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_DURATION (inbuffer) * (j - 1);
195 GST_BUFFER_OFFSET (inbuffer) = offset;
197 GST_BUFFER_OFFSET_END (inbuffer) = offset;
199 gst_buffer_set_caps (inbuffer, caps);
201 p = (gint16 *) GST_BUFFER_DATA (inbuffer);
203 /* create a 16 bit signed ramp */
204 for (i = 0; i < samples; ++i) {
205 *p = -32767 + i * (65535 / samples);
207 *p = -32767 + i * (65535 / samples);
211 /* pushing gives away my reference ... */
212 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
213 /* ... but it ends up being collected on the global buffer list */
214 fail_unless_equals_int (g_list_length (buffers), j);
217 /* FIXME: we should make audioresample handle eos by flushing out the last
218 * samples, which will give us one more, small, buffer */
219 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
220 ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
222 fail_unless_perfect_stream ();
225 gst_caps_unref (caps);
226 cleanup_audioresample (audioresample);
230 /* make sure that outgoing buffers are contiguous in timestamp/duration and
233 GST_START_TEST (test_perfect_stream)
235 /* integral scalings */
236 test_perfect_stream_instance (48000, 24000, 500, 20);
237 test_perfect_stream_instance (48000, 12000, 500, 20);
238 test_perfect_stream_instance (12000, 24000, 500, 20);
239 test_perfect_stream_instance (12000, 48000, 500, 20);
241 /* non-integral scalings */
242 test_perfect_stream_instance (44100, 8000, 500, 20);
243 test_perfect_stream_instance (8000, 44100, 500, 20);
246 test_perfect_stream_instance (12345, 54321, 500, 20);
247 test_perfect_stream_instance (101, 99, 500, 20);
252 /* this tests that the output is a correct discontinuous stream
253 * if the input is; ie input drops in time come out the same way */
255 test_discont_stream_instance (int inrate, int outrate, int samples,
258 GstElement *audioresample;
259 GstBuffer *inbuffer, *outbuffer;
266 GST_DEBUG ("inrate:%d outrate:%d samples:%d numbuffers:%d",
267 inrate, outrate, samples, numbuffers);
269 audioresample = setup_audioresample (2, inrate, outrate, 16, FALSE);
270 caps = gst_pad_get_negotiated_caps (mysrcpad);
271 fail_unless (gst_caps_is_fixed (caps));
273 fail_unless (gst_element_set_state (audioresample,
274 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
275 "could not set to playing");
277 for (j = 1; j <= numbuffers; ++j) {
279 inbuffer = gst_buffer_new_and_alloc (samples * 4);
280 GST_BUFFER_DURATION (inbuffer) = samples * GST_SECOND / inrate;
281 /* "drop" half the buffers */
282 ints = GST_BUFFER_DURATION (inbuffer) * 2 * (j - 1);
283 GST_BUFFER_TIMESTAMP (inbuffer) = ints;
284 GST_BUFFER_OFFSET (inbuffer) = (j - 1) * 2 * samples;
285 GST_BUFFER_OFFSET_END (inbuffer) = j * 2 * samples + samples;
287 gst_buffer_set_caps (inbuffer, caps);
289 p = (gint16 *) GST_BUFFER_DATA (inbuffer);
291 /* create a 16 bit signed ramp */
292 for (i = 0; i < samples; ++i) {
293 *p = -32767 + i * (65535 / samples);
295 *p = -32767 + i * (65535 / samples);
299 GST_DEBUG ("Sending Buffer time:%" G_GUINT64_FORMAT " duration:%"
300 G_GINT64_FORMAT " discont:%d offset:%" G_GUINT64_FORMAT " offset_end:%"
301 G_GUINT64_FORMAT, GST_BUFFER_TIMESTAMP (inbuffer),
302 GST_BUFFER_DURATION (inbuffer), GST_BUFFER_IS_DISCONT (inbuffer),
303 GST_BUFFER_OFFSET (inbuffer), GST_BUFFER_OFFSET_END (inbuffer));
304 /* pushing gives away my reference ... */
305 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
307 /* check if the timestamp of the pushed buffer matches the incoming one */
308 outbuffer = g_list_nth_data (buffers, g_list_length (buffers) - 1);
309 fail_if (outbuffer == NULL);
310 fail_unless_equals_uint64 (ints, GST_BUFFER_TIMESTAMP (outbuffer));
311 GST_DEBUG ("Got Buffer time:%" G_GUINT64_FORMAT " duration:%"
312 G_GINT64_FORMAT " discont:%d offset:%" G_GUINT64_FORMAT " offset_end:%"
313 G_GUINT64_FORMAT, GST_BUFFER_TIMESTAMP (outbuffer),
314 GST_BUFFER_DURATION (outbuffer), GST_BUFFER_IS_DISCONT (outbuffer),
315 GST_BUFFER_OFFSET (outbuffer), GST_BUFFER_OFFSET_END (outbuffer));
317 fail_unless (GST_BUFFER_IS_DISCONT (outbuffer),
318 "expected discont for buffer #%d", j);
323 gst_caps_unref (caps);
324 cleanup_audioresample (audioresample);
327 GST_START_TEST (test_discont_stream)
329 /* integral scalings */
330 test_discont_stream_instance (48000, 24000, 5000, 20);
331 test_discont_stream_instance (48000, 12000, 5000, 20);
332 test_discont_stream_instance (12000, 24000, 5000, 20);
333 test_discont_stream_instance (12000, 48000, 5000, 20);
335 /* non-integral scalings */
336 test_discont_stream_instance (44100, 8000, 5000, 20);
337 test_discont_stream_instance (8000, 44100, 5000, 20);
340 test_discont_stream_instance (12345, 54321, 5000, 20);
341 test_discont_stream_instance (101, 99, 5000, 20);
348 GST_START_TEST (test_reuse)
350 GstElement *audioresample;
355 audioresample = setup_audioresample (1, 9343, 48000, 16, FALSE);
356 caps = gst_pad_get_negotiated_caps (mysrcpad);
357 fail_unless (gst_caps_is_fixed (caps));
359 fail_unless (gst_element_set_state (audioresample,
360 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
361 "could not set to playing");
363 newseg = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0);
364 fail_unless (gst_pad_push_event (mysrcpad, newseg) != FALSE);
366 inbuffer = gst_buffer_new_and_alloc (9343 * 4);
367 memset (GST_BUFFER_DATA (inbuffer), 0, GST_BUFFER_SIZE (inbuffer));
368 GST_BUFFER_DURATION (inbuffer) = GST_SECOND;
369 GST_BUFFER_TIMESTAMP (inbuffer) = 0;
370 GST_BUFFER_OFFSET (inbuffer) = 0;
371 gst_buffer_set_caps (inbuffer, caps);
373 /* pushing gives away my reference ... */
374 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
376 /* ... but it ends up being collected on the global buffer list */
377 fail_unless_equals_int (g_list_length (buffers), 1);
379 /* now reset and try again ... */
380 fail_unless (gst_element_set_state (audioresample,
381 GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to NULL");
383 fail_unless (gst_element_set_state (audioresample,
384 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
385 "could not set to playing");
387 newseg = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0);
388 fail_unless (gst_pad_push_event (mysrcpad, newseg) != FALSE);
390 inbuffer = gst_buffer_new_and_alloc (9343 * 4);
391 memset (GST_BUFFER_DATA (inbuffer), 0, GST_BUFFER_SIZE (inbuffer));
392 GST_BUFFER_DURATION (inbuffer) = GST_SECOND;
393 GST_BUFFER_TIMESTAMP (inbuffer) = 0;
394 GST_BUFFER_OFFSET (inbuffer) = 0;
395 gst_buffer_set_caps (inbuffer, caps);
397 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
399 /* ... it also ends up being collected on the global buffer list. If we
400 * now have more than 2 buffers, then audioresample probably didn't clean
401 * up its internal buffer properly and tried to push the remaining samples
402 * when it got the second NEWSEGMENT event */
403 fail_unless_equals_int (g_list_length (buffers), 2);
405 cleanup_audioresample (audioresample);
406 gst_caps_unref (caps);
411 GST_START_TEST (test_shutdown)
413 GstElement *pipeline, *src, *cf1, *ar, *cf2, *sink;
417 /* create pipeline, force audioresample to actually resample */
418 pipeline = gst_pipeline_new (NULL);
420 src = gst_check_setup_element ("audiotestsrc");
421 cf1 = gst_check_setup_element ("capsfilter");
422 ar = gst_check_setup_element ("audioresample");
423 cf2 = gst_check_setup_element ("capsfilter");
424 g_object_set (cf2, "name", "capsfilter2", NULL);
425 sink = gst_check_setup_element ("fakesink");
428 gst_caps_new_simple ("audio/x-raw-int", "rate", G_TYPE_INT, 11025, NULL);
429 g_object_set (cf1, "caps", caps, NULL);
430 gst_caps_unref (caps);
433 gst_caps_new_simple ("audio/x-raw-int", "rate", G_TYPE_INT, 48000, NULL);
434 g_object_set (cf2, "caps", caps, NULL);
435 gst_caps_unref (caps);
437 /* don't want to sync against the clock, the more throughput the better */
438 g_object_set (src, "is-live", FALSE, NULL);
439 g_object_set (sink, "sync", FALSE, NULL);
441 gst_bin_add_many (GST_BIN (pipeline), src, cf1, ar, cf2, sink, NULL);
442 fail_if (!gst_element_link_many (src, cf1, ar, cf2, sink, NULL));
444 /* now, wait until pipeline is running and then shut it down again; repeat */
445 for (i = 0; i < 20; ++i) {
446 gst_element_set_state (pipeline, GST_STATE_PAUSED);
447 gst_element_get_state (pipeline, NULL, NULL, -1);
448 gst_element_set_state (pipeline, GST_STATE_PLAYING);
450 gst_element_set_state (pipeline, GST_STATE_NULL);
453 gst_object_unref (pipeline);
459 live_switch_alloc_only_48000 (GstPad * pad, guint64 offset,
460 guint size, GstCaps * caps, GstBuffer ** buf)
462 GstStructure *structure;
467 structure = gst_caps_get_structure (caps, 0);
468 fail_unless (gst_structure_get_int (structure, "rate", &rate));
469 fail_unless (gst_structure_get_int (structure, "channels", &channels));
472 return GST_FLOW_NOT_NEGOTIATED;
474 desired = gst_caps_copy (caps);
475 gst_caps_set_simple (desired, "rate", G_TYPE_INT, 48000, NULL);
477 *buf = gst_buffer_new_and_alloc (channels * 48000);
478 gst_buffer_set_caps (*buf, desired);
479 gst_caps_unref (desired);
485 live_switch_get_sink_caps (GstPad * pad)
489 result = gst_caps_copy (GST_PAD_CAPS (pad));
491 gst_caps_set_simple (result,
492 "rate", GST_TYPE_INT_RANGE, 48000, G_MAXINT, NULL);
498 live_switch_push (int rate, GstCaps * caps)
504 desired = gst_caps_copy (caps);
505 gst_caps_set_simple (desired, "rate", G_TYPE_INT, rate, NULL);
506 gst_pad_set_caps (mysrcpad, desired);
508 fail_unless (gst_pad_alloc_buffer_and_set_caps (mysrcpad,
509 GST_BUFFER_OFFSET_NONE, rate * 4, desired, &inbuffer) == GST_FLOW_OK);
511 /* When the basetransform hits the non-configured case it always
512 * returns a buffer with exactly the same caps as we requested so the actual
513 * renegotiation (if needed) will be done in the _chain*/
514 fail_unless (inbuffer != NULL);
515 GST_DEBUG ("desired: %" GST_PTR_FORMAT ".... got: %" GST_PTR_FORMAT,
516 desired, GST_BUFFER_CAPS (inbuffer));
517 fail_unless (gst_caps_is_equal (desired, GST_BUFFER_CAPS (inbuffer)));
519 memset (GST_BUFFER_DATA (inbuffer), 0, GST_BUFFER_SIZE (inbuffer));
520 GST_BUFFER_DURATION (inbuffer) = GST_SECOND;
521 GST_BUFFER_TIMESTAMP (inbuffer) = 0;
522 GST_BUFFER_OFFSET (inbuffer) = 0;
524 /* pushing gives away my reference ... */
525 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
527 /* ... but it ends up being collected on the global buffer list */
528 fail_unless_equals_int (g_list_length (buffers), 1);
530 for (l = buffers; l; l = l->next) {
531 GstBuffer *buffer = GST_BUFFER (l->data);
533 gst_buffer_unref (buffer);
536 g_list_free (buffers);
539 gst_caps_unref (desired);
542 GST_START_TEST (test_live_switch)
544 GstElement *audioresample;
548 audioresample = setup_audioresample (4, 48000, 48000, 16, FALSE);
550 /* Let the sinkpad act like something that can only handle things of
551 * rate 48000- and can only allocate buffers for that rate, but if someone
552 * tries to get a buffer with a rate higher then 48000 tries to renegotiate
554 gst_pad_set_bufferalloc_function (mysinkpad, live_switch_alloc_only_48000);
555 gst_pad_set_getcaps_function (mysinkpad, live_switch_get_sink_caps);
557 gst_pad_use_fixed_caps (mysrcpad);
559 caps = gst_pad_get_negotiated_caps (mysrcpad);
560 fail_unless (gst_caps_is_fixed (caps));
562 fail_unless (gst_element_set_state (audioresample,
563 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
564 "could not set to playing");
566 newseg = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0);
567 fail_unless (gst_pad_push_event (mysrcpad, newseg) != FALSE);
569 /* downstream can provide the requested rate, a buffer alloc will be passed
571 live_switch_push (48000, caps);
573 /* Downstream can never accept this rate, buffer alloc isn't passed on */
574 live_switch_push (40000, caps);
576 /* Downstream can provide the requested rate but will re-negotiate */
577 live_switch_push (50000, caps);
579 cleanup_audioresample (audioresample);
580 gst_caps_unref (caps);
585 #ifndef GST_DISABLE_PARSE
587 static GMainLoop *loop;
588 static gint messages = 0;
591 element_message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
595 s = gst_structure_to_string (gst_message_get_structure (message));
596 GST_DEBUG ("Received message: %s", s);
603 eos_message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
605 GST_DEBUG ("Received eos");
606 g_main_loop_quit (loop);
610 test_pipeline (gint width, gboolean fp, gint inrate, gint outrate, gint quality)
612 GstElement *pipeline;
614 GError *error = NULL;
619 ("audiotestsrc num-buffers=10 ! audioconvert ! audio/x-raw-%s,rate=%d,width=%d,channels=2 ! audioresample quality=%d ! audio/x-raw-%s,rate=%d,width=%d ! identity check-imperfect-timestamp=TRUE ! fakesink",
620 (fp) ? "float" : "int", inrate, width, quality, (fp) ? "float" : "int",
623 pipeline = gst_parse_launch (pipe_str, &error);
624 fail_unless (pipeline != NULL, "Error parsing pipeline: %s",
625 error ? error->message : "(invalid error)");
628 bus = gst_element_get_bus (pipeline);
629 fail_if (bus == NULL);
630 gst_bus_add_signal_watch (bus);
631 g_signal_connect (bus, "message::element", (GCallback) element_message_cb,
633 g_signal_connect (bus, "message::eos", (GCallback) eos_message_cb, NULL);
635 gst_element_set_state (pipeline, GST_STATE_PLAYING);
637 /* run until we receive EOS */
638 loop = g_main_loop_new (NULL, FALSE);
640 g_main_loop_run (loop);
642 g_main_loop_unref (loop);
645 gst_element_set_state (pipeline, GST_STATE_NULL);
647 fail_if (messages > 0, "Received imperfect timestamp messages");
648 gst_object_unref (pipeline);
651 GST_START_TEST (test_pipelines)
655 /* Test qualities 0, 5 and 10 */
656 for (quality = 0; quality < 11; quality += 5) {
657 GST_DEBUG ("Checking with quality %d", quality);
659 test_pipeline (8, FALSE, 44100, 48000, quality);
660 test_pipeline (8, FALSE, 48000, 44100, quality);
662 test_pipeline (16, FALSE, 44100, 48000, quality);
663 test_pipeline (16, FALSE, 48000, 44100, quality);
665 test_pipeline (24, FALSE, 44100, 48000, quality);
666 test_pipeline (24, FALSE, 48000, 44100, quality);
668 test_pipeline (32, FALSE, 44100, 48000, quality);
669 test_pipeline (32, FALSE, 48000, 44100, quality);
671 test_pipeline (32, TRUE, 44100, 48000, quality);
672 test_pipeline (32, TRUE, 48000, 44100, quality);
674 test_pipeline (64, TRUE, 44100, 48000, quality);
675 test_pipeline (64, TRUE, 48000, 44100, quality);
681 GST_START_TEST (test_preference_passthrough)
683 GstStateChangeReturn ret;
684 GstElement *pipeline, *src;
690 GError *error = NULL;
693 pipeline = gst_parse_launch ("audiotestsrc num-buffers=1 name=src ! "
694 "audioresample ! audio/x-raw-int,channels=1,width=16,depth=16,"
695 "endianness=BYTE_ORDER,signed=true,rate=8000 ! "
696 "fakesink can-activate-pull=false", &error);
697 fail_unless (pipeline != NULL, "Error parsing pipeline: %s",
698 error ? error->message : "(invalid error)");
700 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
701 fail_unless_equals_int (ret, GST_STATE_CHANGE_ASYNC);
703 /* run until we receive EOS */
704 bus = gst_element_get_bus (pipeline);
705 fail_if (bus == NULL);
706 msg = gst_bus_timed_pop_filtered (bus, -1, GST_MESSAGE_EOS);
707 gst_message_unref (msg);
708 gst_object_unref (bus);
710 src = gst_bin_get_by_name (GST_BIN (pipeline), "src");
711 fail_unless (src != NULL);
712 pad = gst_element_get_static_pad (src, "src");
713 fail_unless (pad != NULL);
714 caps = gst_pad_get_negotiated_caps (pad);
715 GST_LOG ("negotiated audiotestsrc caps: %" GST_PTR_FORMAT, caps);
716 fail_unless (caps != NULL);
717 s = gst_caps_get_structure (caps, 0);
718 fail_unless (gst_structure_get_int (s, "rate", &rate));
719 /* there's no need to resample, audiotestsrc supports any rate, so make
720 * sure audioresample provided upstream with the right caps to negotiate
722 fail_unless_equals_int (rate, 8000);
723 gst_caps_unref (caps);
724 gst_object_unref (pad);
725 gst_object_unref (src);
727 gst_element_set_state (pipeline, GST_STATE_NULL);
728 gst_object_unref (pipeline);
736 _message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
738 GMainLoop *loop = user_data;
740 switch (GST_MESSAGE_TYPE (message)) {
741 case GST_MESSAGE_ERROR:
742 case GST_MESSAGE_WARNING:
743 g_assert_not_reached ();
745 case GST_MESSAGE_EOS:
746 g_main_loop_quit (loop);
758 GstClockTime next_out_ts;
759 guint64 next_out_off;
761 guint64 in_buffer_count, out_buffer_count;
765 fakesink_handoff_cb (GstElement * object, GstBuffer * buffer, GstPad * pad,
768 TimestampDriftCtx *ctx = user_data;
770 ctx->out_buffer_count++;
771 if (ctx->latency == GST_CLOCK_TIME_NONE) {
772 ctx->latency = 1000 - GST_BUFFER_SIZE (buffer) / 8;
775 /* Check if we have a perfectly timestampped stream */
776 if (ctx->next_out_ts != GST_CLOCK_TIME_NONE)
777 fail_unless (ctx->next_out_ts == GST_BUFFER_TIMESTAMP (buffer),
778 "expected timestamp %" GST_TIME_FORMAT " got timestamp %"
779 GST_TIME_FORMAT, GST_TIME_ARGS (ctx->next_out_ts),
780 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
782 /* Check if we have a perfectly offsetted stream */
783 fail_unless (GST_BUFFER_OFFSET_END (buffer) ==
784 GST_BUFFER_OFFSET (buffer) + GST_BUFFER_SIZE (buffer) / 8,
785 "expected offset end %" G_GUINT64_FORMAT " got offset end %"
787 GST_BUFFER_OFFSET (buffer) + GST_BUFFER_SIZE (buffer) / 8,
788 GST_BUFFER_OFFSET_END (buffer));
789 if (ctx->next_out_off != GST_BUFFER_OFFSET_NONE) {
790 fail_unless (GST_BUFFER_OFFSET (buffer) == ctx->next_out_off,
791 "expected offset %" G_GUINT64_FORMAT " got offset %" G_GUINT64_FORMAT,
792 ctx->next_out_off, GST_BUFFER_OFFSET (buffer));
795 if (ctx->in_buffer_count != ctx->out_buffer_count) {
796 GST_INFO ("timestamp %" GST_TIME_FORMAT,
797 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
800 if (ctx->in_ts != GST_CLOCK_TIME_NONE && ctx->in_buffer_count > 1
801 && ctx->in_buffer_count == ctx->out_buffer_count) {
802 fail_unless (GST_BUFFER_TIMESTAMP (buffer) ==
803 ctx->in_ts - gst_util_uint64_scale_round (ctx->latency, GST_SECOND,
805 "expected output timestamp %" GST_TIME_FORMAT " (%" G_GUINT64_FORMAT
806 ") got output timestamp %" GST_TIME_FORMAT " (%" G_GUINT64_FORMAT ")",
807 GST_TIME_ARGS (ctx->in_ts - gst_util_uint64_scale_round (ctx->latency,
809 ctx->in_ts - gst_util_uint64_scale_round (ctx->latency, GST_SECOND,
810 4096), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
811 GST_BUFFER_TIMESTAMP (buffer));
815 GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer);
816 ctx->next_out_off = GST_BUFFER_OFFSET_END (buffer);
820 identity_handoff_cb (GstElement * object, GstBuffer * buffer,
823 TimestampDriftCtx *ctx = user_data;
825 ctx->in_ts = GST_BUFFER_TIMESTAMP (buffer);
826 ctx->in_buffer_count++;
829 GST_START_TEST (test_timestamp_drift)
831 TimestampDriftCtx ctx =
832 { GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE,
833 GST_BUFFER_OFFSET_NONE, 0, 0
835 GstElement *pipeline;
836 GstElement *audiotestsrc, *capsfilter1, *identity, *audioresample,
837 *capsfilter2, *fakesink;
842 pipeline = gst_pipeline_new ("pipeline");
843 fail_unless (pipeline != NULL);
845 audiotestsrc = gst_element_factory_make ("audiotestsrc", "src");
846 fail_unless (audiotestsrc != NULL);
847 g_object_set (G_OBJECT (audiotestsrc), "num-buffers", 10000,
848 "samplesperbuffer", 4000, NULL);
850 capsfilter1 = gst_element_factory_make ("capsfilter", "capsfilter1");
851 fail_unless (capsfilter1 != NULL);
854 ("audio/x-raw-float, channels=1, width=64, rate=16384");
855 g_object_set (G_OBJECT (capsfilter1), "caps", caps, NULL);
856 gst_caps_unref (caps);
858 identity = gst_element_factory_make ("identity", "identity");
859 fail_unless (identity != NULL);
860 g_object_set (G_OBJECT (identity), "sync", FALSE, "signal-handoffs", TRUE,
862 g_signal_connect (identity, "handoff", (GCallback) identity_handoff_cb, &ctx);
864 audioresample = gst_element_factory_make ("audioresample", "resample");
865 fail_unless (audioresample != NULL);
866 capsfilter2 = gst_element_factory_make ("capsfilter", "capsfilter2");
867 fail_unless (capsfilter2 != NULL);
870 ("audio/x-raw-float, channels=1, width=64, rate=4096");
871 g_object_set (G_OBJECT (capsfilter2), "caps", caps, NULL);
872 gst_caps_unref (caps);
874 fakesink = gst_element_factory_make ("fakesink", "sink");
875 fail_unless (fakesink != NULL);
876 g_object_set (G_OBJECT (fakesink), "sync", FALSE, "async", FALSE,
877 "signal-handoffs", TRUE, NULL);
878 g_signal_connect (fakesink, "handoff", (GCallback) fakesink_handoff_cb, &ctx);
881 gst_bin_add_many (GST_BIN (pipeline), audiotestsrc, capsfilter1, identity,
882 audioresample, capsfilter2, fakesink, NULL);
883 fail_unless (gst_element_link_many (audiotestsrc, capsfilter1, identity,
884 audioresample, capsfilter2, fakesink, NULL));
886 loop = g_main_loop_new (NULL, FALSE);
888 bus = gst_element_get_bus (pipeline);
889 gst_bus_add_signal_watch (bus);
890 g_signal_connect (bus, "message", (GCallback) _message_cb, loop);
892 fail_unless (gst_element_set_state (pipeline,
893 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
894 g_main_loop_run (loop);
896 fail_unless (gst_element_set_state (pipeline,
897 GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
898 g_main_loop_unref (loop);
899 gst_object_unref (pipeline);
904 audioresample_suite (void)
906 Suite *s = suite_create ("audioresample");
907 TCase *tc_chain = tcase_create ("general");
909 suite_add_tcase (s, tc_chain);
910 tcase_add_test (tc_chain, test_perfect_stream);
911 tcase_add_test (tc_chain, test_discont_stream);
912 tcase_add_test (tc_chain, test_reuse);
913 tcase_add_test (tc_chain, test_shutdown);
914 tcase_add_test (tc_chain, test_live_switch);
915 tcase_add_test (tc_chain, test_timestamp_drift);
917 #ifndef GST_DISABLE_PARSE
918 tcase_set_timeout (tc_chain, 360);
919 tcase_add_test (tc_chain, test_pipelines);
920 tcase_add_test (tc_chain, test_preference_passthrough);
926 GST_CHECK_MAIN (audioresample);