| /* GStreamer unit tests for the interleave element | |
| * Copyright (C) 2008 Sebastian Dröge <slomo@circular-chaos.org> | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Library General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Library General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Library General Public | |
| * License along with this library; if not, write to the | |
| * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, | |
| * Boston, MA 02110-1301, USA. | |
| */ | |
| #ifdef HAVE_CONFIG_H | |
| # include "config.h" | |
| #endif | |
| #include <stdio.h> | |
| #include <gst/audio/audio.h> | |
| #include <gst/check/gstcheck.h> | |
| #include <gst/audio/audio.h> | |
| GST_START_TEST (test_create_and_unref) | |
| { | |
| GstElement *deinterleave; | |
| deinterleave = gst_element_factory_make ("deinterleave", NULL); | |
| fail_unless (deinterleave != NULL); | |
| gst_element_set_state (deinterleave, GST_STATE_NULL); | |
| gst_object_unref (deinterleave); | |
| } | |
| GST_END_TEST; | |
| static GstPad *mysrcpad, **mysinkpads; | |
| static gint nsinkpads; | |
| static GstBus *bus; | |
| static GstElement *deinterleave; | |
| static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", | |
| GST_PAD_SINK, | |
| GST_PAD_ALWAYS, | |
| GST_STATIC_CAPS ("audio/x-raw, " | |
| "format = (string) " GST_AUDIO_NE (F32) ", " | |
| "channels = (int) 1, layout = (string) {interleaved, non-interleaved}, rate = (int) {32000, 48000}")); | |
| static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", | |
| GST_PAD_SRC, | |
| GST_PAD_ALWAYS, | |
| GST_STATIC_CAPS ("audio/x-raw, " | |
| "format = (string) " GST_AUDIO_NE (F32) ", " | |
| "channels = (int) { 2, 3 }, layout = (string) interleaved, rate = (int) {32000, 48000}")); | |
| #define CAPS_32khz \ | |
| "audio/x-raw, " \ | |
| "format = (string) "GST_AUDIO_NE (F32) ", " \ | |
| "channels = (int) 2, layout = (string) interleaved, " \ | |
| "rate = (int) 32000" | |
| #define CAPS_48khz \ | |
| "audio/x-raw, " \ | |
| "format = (string) "GST_AUDIO_NE (F32) ", " \ | |
| "channels = (int) 2, layout = (string) interleaved, " \ | |
| "rate = (int) 48000" | |
| #define CAPS_48khz_3CH \ | |
| "audio/x-raw, " \ | |
| "format = (string) "GST_AUDIO_NE (F32) ", " \ | |
| "channels = (int) 3, layout = (string) interleaved, " \ | |
| "rate = (int) 48000" | |
| static GstFlowReturn | |
| deinterleave_chain_func (GstPad * pad, GstObject * parent, GstBuffer * buffer) | |
| { | |
| gint i; | |
| GstMapInfo map; | |
| gfloat *indata; | |
| fail_unless (GST_IS_BUFFER (buffer)); | |
| gst_buffer_map (buffer, &map, GST_MAP_READ); | |
| indata = (gfloat *) map.data; | |
| fail_unless_equals_int (map.size, 48000 * sizeof (gfloat)); | |
| fail_unless (indata != NULL); | |
| if (strcmp (GST_PAD_NAME (pad), "sink0") == 0) { | |
| for (i = 0; i < 48000; i++) | |
| fail_unless_equals_float (indata[i], -1.0); | |
| } else if (strcmp (GST_PAD_NAME (pad), "sink1") == 0) { | |
| for (i = 0; i < 48000; i++) | |
| fail_unless_equals_float (indata[i], 1.0); | |
| } else { | |
| g_assert_not_reached (); | |
| } | |
| gst_buffer_unmap (buffer, &map); | |
| gst_buffer_unref (buffer); | |
| return GST_FLOW_OK; | |
| } | |
| static void | |
| deinterleave_pad_added (GstElement * src, GstPad * pad, gpointer data) | |
| { | |
| gchar *name; | |
| gint link = GPOINTER_TO_INT (data); | |
| if (nsinkpads >= link) | |
| return; | |
| name = g_strdup_printf ("sink%d", nsinkpads); | |
| mysinkpads[nsinkpads] = | |
| gst_pad_new_from_static_template (&sinktemplate, name); | |
| g_free (name); | |
| fail_if (mysinkpads[nsinkpads] == NULL); | |
| gst_pad_set_chain_function (mysinkpads[nsinkpads], deinterleave_chain_func); | |
| fail_unless (gst_pad_link (pad, mysinkpads[nsinkpads]) == GST_PAD_LINK_OK); | |
| gst_pad_set_active (mysinkpads[nsinkpads], TRUE); | |
| nsinkpads++; | |
| } | |
| GST_START_TEST (test_2_channels) | |
| { | |
| GstPad *sinkpad; | |
| gint i; | |
| GstBuffer *inbuf; | |
| GstCaps *caps; | |
| gfloat *indata; | |
| GstMapInfo map; | |
| guint64 channel_mask = 0; | |
| mysinkpads = g_new0 (GstPad *, 2); | |
| nsinkpads = 0; | |
| deinterleave = gst_element_factory_make ("deinterleave", NULL); | |
| fail_unless (deinterleave != NULL); | |
| mysrcpad = gst_pad_new_from_static_template (&srctemplate, "src"); | |
| fail_unless (mysrcpad != NULL); | |
| gst_pad_set_active (mysrcpad, TRUE); | |
| caps = gst_caps_from_string (CAPS_48khz); | |
| channel_mask |= | |
| G_GUINT64_CONSTANT (1) << GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; | |
| channel_mask |= | |
| G_GUINT64_CONSTANT (1) << GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; | |
| gst_caps_set_simple (caps, "channel-mask", GST_TYPE_BITMASK, channel_mask, | |
| NULL); | |
| gst_check_setup_events (mysrcpad, deinterleave, caps, GST_FORMAT_TIME); | |
| sinkpad = gst_element_get_static_pad (deinterleave, "sink"); | |
| fail_unless (sinkpad != NULL); | |
| fail_unless (gst_pad_link (mysrcpad, sinkpad) == GST_PAD_LINK_OK); | |
| g_object_unref (sinkpad); | |
| g_signal_connect (deinterleave, "pad-added", | |
| G_CALLBACK (deinterleave_pad_added), GINT_TO_POINTER (2)); | |
| bus = gst_bus_new (); | |
| gst_element_set_bus (deinterleave, bus); | |
| fail_unless (gst_element_set_state (deinterleave, | |
| GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); | |
| inbuf = gst_buffer_new_and_alloc (2 * 48000 * sizeof (gfloat)); | |
| inbuf = gst_buffer_make_writable (inbuf); | |
| gst_buffer_map (inbuf, &map, GST_MAP_WRITE); | |
| indata = (gfloat *) map.data; | |
| for (i = 0; i < 2 * 48000; i += 2) { | |
| indata[i] = -1.0; | |
| indata[i + 1] = 1.0; | |
| } | |
| gst_buffer_unmap (inbuf, &map); | |
| fail_unless (gst_pad_push (mysrcpad, inbuf) == GST_FLOW_OK); | |
| fail_unless (gst_element_set_state (deinterleave, | |
| GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); | |
| for (i = 0; i < nsinkpads; i++) | |
| g_object_unref (mysinkpads[i]); | |
| g_free (mysinkpads); | |
| mysinkpads = NULL; | |
| g_object_unref (deinterleave); | |
| gst_bus_set_flushing (bus, TRUE); | |
| g_object_unref (bus); | |
| gst_caps_unref (caps); | |
| gst_object_unref (mysrcpad); | |
| } | |
| GST_END_TEST; | |
| GST_START_TEST (test_2_channels_1_linked) | |
| { | |
| GstPad *sinkpad; | |
| gint i; | |
| GstBuffer *inbuf; | |
| GstCaps *caps; | |
| gfloat *indata; | |
| GstMapInfo map; | |
| guint64 channel_mask = 0; | |
| nsinkpads = 0; | |
| mysinkpads = g_new0 (GstPad *, 2); | |
| deinterleave = gst_element_factory_make ("deinterleave", NULL); | |
| fail_unless (deinterleave != NULL); | |
| mysrcpad = gst_pad_new_from_static_template (&srctemplate, "src"); | |
| fail_unless (mysrcpad != NULL); | |
| gst_pad_set_active (mysrcpad, TRUE); | |
| caps = gst_caps_from_string (CAPS_48khz); | |
| channel_mask |= | |
| G_GUINT64_CONSTANT (1) << GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; | |
| channel_mask |= | |
| G_GUINT64_CONSTANT (1) << GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; | |
| gst_caps_set_simple (caps, "channel-mask", GST_TYPE_BITMASK, channel_mask, | |
| NULL); | |
| gst_check_setup_events (mysrcpad, deinterleave, caps, GST_FORMAT_TIME); | |
| sinkpad = gst_element_get_static_pad (deinterleave, "sink"); | |
| fail_unless (sinkpad != NULL); | |
| fail_unless (gst_pad_link (mysrcpad, sinkpad) == GST_PAD_LINK_OK); | |
| g_object_unref (sinkpad); | |
| g_signal_connect (deinterleave, "pad-added", | |
| G_CALLBACK (deinterleave_pad_added), GINT_TO_POINTER (1)); | |
| bus = gst_bus_new (); | |
| gst_element_set_bus (deinterleave, bus); | |
| fail_unless (gst_element_set_state (deinterleave, | |
| GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); | |
| inbuf = gst_buffer_new_and_alloc (2 * 48000 * sizeof (gfloat)); | |
| inbuf = gst_buffer_make_writable (inbuf); | |
| gst_buffer_map (inbuf, &map, GST_MAP_WRITE); | |
| indata = (gfloat *) map.data; | |
| for (i = 0; i < 2 * 48000; i += 2) { | |
| indata[i] = -1.0; | |
| indata[i + 1] = 1.0; | |
| } | |
| gst_buffer_unmap (inbuf, &map); | |
| fail_unless (gst_pad_push (mysrcpad, inbuf) == GST_FLOW_OK); | |
| fail_unless (gst_element_set_state (deinterleave, | |
| GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); | |
| for (i = 0; i < nsinkpads; i++) | |
| g_object_unref (mysinkpads[i]); | |
| g_free (mysinkpads); | |
| mysinkpads = NULL; | |
| g_object_unref (deinterleave); | |
| gst_bus_set_flushing (bus, TRUE); | |
| g_object_unref (bus); | |
| gst_caps_unref (caps); | |
| gst_object_unref (mysrcpad); | |
| } | |
| GST_END_TEST; | |
| GST_START_TEST (test_2_channels_caps_change) | |
| { | |
| GstPad *sinkpad; | |
| GstCaps *caps, *caps2; | |
| GstCaps *ret_caps; | |
| gint i; | |
| GstBuffer *inbuf; | |
| gfloat *indata; | |
| GstMapInfo map; | |
| guint64 channel_mask; | |
| nsinkpads = 0; | |
| mysinkpads = g_new0 (GstPad *, 2); | |
| deinterleave = gst_element_factory_make ("deinterleave", NULL); | |
| fail_unless (deinterleave != NULL); | |
| mysrcpad = gst_pad_new_from_static_template (&srctemplate, "src"); | |
| fail_unless (mysrcpad != NULL); | |
| gst_pad_set_active (mysrcpad, TRUE); | |
| caps = gst_caps_from_string (CAPS_48khz); | |
| channel_mask = 0; | |
| channel_mask |= | |
| G_GUINT64_CONSTANT (1) << GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; | |
| channel_mask |= | |
| G_GUINT64_CONSTANT (1) << GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; | |
| gst_caps_set_simple (caps, "channel-mask", GST_TYPE_BITMASK, channel_mask, | |
| NULL); | |
| sinkpad = gst_element_get_static_pad (deinterleave, "sink"); | |
| fail_unless (sinkpad != NULL); | |
| fail_unless (gst_pad_link (mysrcpad, sinkpad) == GST_PAD_LINK_OK); | |
| g_object_unref (sinkpad); | |
| ret_caps = gst_pad_peer_query_caps (mysrcpad, caps); | |
| fail_if (gst_caps_is_empty (ret_caps)); | |
| fail_unless (gst_pad_peer_query_accept_caps (mysrcpad, caps)); | |
| gst_caps_unref (ret_caps); | |
| gst_check_setup_events (mysrcpad, deinterleave, caps, GST_FORMAT_TIME); | |
| g_signal_connect (deinterleave, "pad-added", | |
| G_CALLBACK (deinterleave_pad_added), GINT_TO_POINTER (2)); | |
| bus = gst_bus_new (); | |
| gst_element_set_bus (deinterleave, bus); | |
| fail_unless (gst_element_set_state (deinterleave, | |
| GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); | |
| inbuf = gst_buffer_new_and_alloc (2 * 48000 * sizeof (gfloat)); | |
| inbuf = gst_buffer_make_writable (inbuf); | |
| gst_buffer_map (inbuf, &map, GST_MAP_WRITE); | |
| indata = (gfloat *) map.data; | |
| for (i = 0; i < 2 * 48000; i += 2) { | |
| indata[i] = -1.0; | |
| indata[i + 1] = 1.0; | |
| } | |
| gst_buffer_unmap (inbuf, &map); | |
| fail_unless (gst_pad_push (mysrcpad, inbuf) == GST_FLOW_OK); | |
| caps2 = gst_caps_from_string (CAPS_32khz); | |
| channel_mask = 0; | |
| channel_mask |= | |
| G_GUINT64_CONSTANT (1) << GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; | |
| channel_mask |= | |
| G_GUINT64_CONSTANT (1) << GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; | |
| gst_caps_set_simple (caps2, "channel-mask", GST_TYPE_BITMASK, channel_mask, | |
| NULL); | |
| ret_caps = gst_pad_peer_query_caps (mysrcpad, caps2); | |
| fail_if (gst_caps_is_empty (ret_caps)); | |
| fail_unless (gst_pad_peer_query_accept_caps (mysrcpad, caps2)); | |
| gst_caps_unref (ret_caps); | |
| gst_pad_set_caps (mysrcpad, caps2); | |
| inbuf = gst_buffer_new_and_alloc (2 * 48000 * sizeof (gfloat)); | |
| inbuf = gst_buffer_make_writable (inbuf); | |
| gst_buffer_map (inbuf, &map, GST_MAP_WRITE); | |
| indata = (gfloat *) map.data; | |
| for (i = 0; i < 2 * 48000; i += 2) { | |
| indata[i] = -1.0; | |
| indata[i + 1] = 1.0; | |
| } | |
| gst_buffer_unmap (inbuf, &map); | |
| /* Should work fine because the caps changed in a compatible way */ | |
| fail_unless (gst_pad_push (mysrcpad, inbuf) == GST_FLOW_OK); | |
| gst_caps_unref (caps2); | |
| caps2 = gst_caps_from_string (CAPS_48khz_3CH); | |
| channel_mask = 0; | |
| channel_mask |= | |
| G_GUINT64_CONSTANT (1) << GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; | |
| channel_mask |= | |
| G_GUINT64_CONSTANT (1) << GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; | |
| channel_mask |= | |
| G_GUINT64_CONSTANT (1) << GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER; | |
| gst_caps_set_simple (caps2, "channel-mask", GST_TYPE_BITMASK, channel_mask, | |
| NULL); | |
| ret_caps = gst_pad_peer_query_caps (mysrcpad, caps2); | |
| fail_unless (gst_caps_is_empty (ret_caps)); | |
| gst_caps_unref (ret_caps); | |
| fail_if (gst_pad_peer_query_accept_caps (mysrcpad, caps2)); | |
| gst_pad_set_caps (mysrcpad, caps2); | |
| inbuf = gst_buffer_new_and_alloc (3 * 48000 * sizeof (gfloat)); | |
| inbuf = gst_buffer_make_writable (inbuf); | |
| gst_buffer_map (inbuf, &map, GST_MAP_WRITE); | |
| indata = (gfloat *) map.data; | |
| for (i = 0; i < 3 * 48000; i += 3) { | |
| indata[i] = -1.0; | |
| indata[i + 1] = 1.0; | |
| indata[i + 2] = 0.0; | |
| } | |
| gst_buffer_unmap (inbuf, &map); | |
| /* Should break because the caps changed in an incompatible way */ | |
| fail_if (gst_pad_push (mysrcpad, inbuf) == GST_FLOW_OK); | |
| fail_unless (gst_element_set_state (deinterleave, | |
| GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); | |
| for (i = 0; i < nsinkpads; i++) | |
| g_object_unref (mysinkpads[i]); | |
| g_free (mysinkpads); | |
| mysinkpads = NULL; | |
| g_object_unref (deinterleave); | |
| gst_bus_set_flushing (bus, TRUE); | |
| g_object_unref (bus); | |
| gst_caps_unref (caps); | |
| gst_caps_unref (caps2); | |
| gst_object_unref (mysrcpad); | |
| } | |
| GST_END_TEST; | |
| #define SAMPLES_PER_BUFFER 10 | |
| #define NUM_CHANNELS 8 | |
| #define SAMPLE_RATE 44100 | |
| static guint pads_created; | |
| static void | |
| set_channel_positions (GstCaps * caps, int channels, | |
| GstAudioChannelPosition * channelpositions) | |
| { | |
| int c; | |
| guint64 channel_mask = 0; | |
| for (c = 0; c < channels; c++) | |
| channel_mask |= G_GUINT64_CONSTANT (1) << channelpositions[c]; | |
| gst_caps_set_simple (caps, "channel-mask", GST_TYPE_BITMASK, channel_mask, | |
| NULL); | |
| } | |
| static void | |
| src_handoff_float32_8ch (GstElement * src, GstBuffer * buf, GstPad * pad, | |
| gpointer user_data) | |
| { | |
| gfloat *data, *p; | |
| guint size, i, c; | |
| size = sizeof (gfloat) * SAMPLES_PER_BUFFER * NUM_CHANNELS; | |
| data = p = (gfloat *) g_malloc (size); | |
| for (i = 0; i < SAMPLES_PER_BUFFER; ++i) { | |
| for (c = 0; c < NUM_CHANNELS; ++c) { | |
| *p = (gfloat) ((i * NUM_CHANNELS) + c); | |
| ++p; | |
| } | |
| } | |
| if (gst_buffer_n_memory (buf)) { | |
| gst_buffer_replace_memory_range (buf, 0, -1, | |
| gst_memory_new_wrapped (0, data, size, 0, size, data, g_free)); | |
| } else { | |
| gst_buffer_insert_memory (buf, 0, | |
| gst_memory_new_wrapped (0, data, size, 0, size, data, g_free)); | |
| } | |
| GST_BUFFER_OFFSET (buf) = 0; | |
| GST_BUFFER_TIMESTAMP (buf) = 0; | |
| } | |
| static GstPadProbeReturn | |
| src_event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer userdata) | |
| { | |
| GstAudioChannelPosition layout[NUM_CHANNELS]; | |
| GstCaps *caps; | |
| guint i; | |
| if ((info->type & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) | |
| && GST_EVENT_TYPE (info->data) == GST_EVENT_STREAM_START) { | |
| gst_pad_remove_probe (pad, info->id); | |
| caps = gst_caps_new_simple ("audio/x-raw", | |
| "format", G_TYPE_STRING, GST_AUDIO_NE (F32), | |
| "channels", G_TYPE_INT, NUM_CHANNELS, | |
| "layout", G_TYPE_STRING, "interleaved", | |
| "rate", G_TYPE_INT, SAMPLE_RATE, NULL); | |
| for (i = 0; i < NUM_CHANNELS; ++i) | |
| layout[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT + i; | |
| set_channel_positions (caps, NUM_CHANNELS, layout); | |
| gst_pad_set_caps (pad, caps); | |
| gst_caps_unref (caps); | |
| } | |
| return GST_PAD_PROBE_OK; | |
| } | |
| static GstPadProbeReturn | |
| float_buffer_check_probe (GstPad * pad, GstPadProbeInfo * info, | |
| gpointer userdata) | |
| { | |
| GstMapInfo map; | |
| gfloat *data; | |
| guint padnum, numpads; | |
| guint num, i; | |
| GstCaps *caps; | |
| GstStructure *s; | |
| GstAudioChannelPosition *pos; | |
| gint channels; | |
| GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER (info); | |
| GstAudioInfo audio_info; | |
| guint pad_id = GPOINTER_TO_UINT (userdata); | |
| fail_unless_equals_int (sscanf (GST_PAD_NAME (pad), "src_%u", &padnum), 1); | |
| numpads = pads_created; | |
| /* Check caps */ | |
| caps = gst_pad_get_current_caps (pad); | |
| fail_unless (caps != NULL); | |
| s = gst_caps_get_structure (caps, 0); | |
| fail_unless (gst_structure_get_int (s, "channels", &channels)); | |
| fail_unless_equals_int (channels, 1); | |
| gst_audio_info_init (&audio_info); | |
| fail_unless (gst_audio_info_from_caps (&audio_info, caps)); | |
| pos = audio_info.position; | |
| fail_unless (pos != NULL | |
| && pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT + pad_id); | |
| gst_caps_unref (caps); | |
| gst_buffer_map (buffer, &map, GST_MAP_READ); | |
| data = (gfloat *) map.data; | |
| num = map.size / sizeof (gfloat); | |
| /* Check buffer content */ | |
| for (i = 0; i < num; ++i) { | |
| guint val, rest; | |
| val = (guint) data[i]; | |
| GST_LOG ("%s[%u]: %8f", GST_PAD_NAME (pad), i, data[i]); | |
| /* can't use the modulo operator in the assertion statement, since due to | |
| * the way it gets expanded it would be interpreted as a printf operator | |
| * in the failure case, which will result in segfaults */ | |
| rest = val % numpads; | |
| /* check that the first channel is on pad src0, the second on src1 etc. */ | |
| fail_unless_equals_int (rest, padnum); | |
| } | |
| gst_buffer_unmap (buffer, &map); | |
| return GST_PAD_PROBE_OK; /* don't drop data */ | |
| } | |
| static void | |
| pad_added_setup_data_check_float32_8ch_cb (GstElement * deinterleave, | |
| GstPad * pad, GstElement * pipeline) | |
| { | |
| GstElement *queue, *sink; | |
| GstPad *sinkpad; | |
| queue = gst_element_factory_make ("queue", NULL); | |
| fail_unless (queue != NULL); | |
| sink = gst_element_factory_make ("fakesink", NULL); | |
| fail_unless (sink != NULL); | |
| gst_bin_add_many (GST_BIN (pipeline), queue, sink, NULL); | |
| gst_element_link_pads_full (queue, "src", sink, "sink", | |
| GST_PAD_LINK_CHECK_NOTHING); | |
| sinkpad = gst_element_get_static_pad (queue, "sink"); | |
| fail_unless_equals_int (gst_pad_link (pad, sinkpad), GST_PAD_LINK_OK); | |
| gst_object_unref (sinkpad); | |
| gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, float_buffer_check_probe, | |
| GUINT_TO_POINTER (pads_created), NULL); | |
| gst_element_set_state (sink, GST_STATE_PLAYING); | |
| gst_element_set_state (queue, GST_STATE_PLAYING); | |
| GST_LOG ("new pad: %s", GST_PAD_NAME (pad)); | |
| ++pads_created; | |
| } | |
| static GstElement * | |
| make_fake_src_8chans_float32 (void) | |
| { | |
| GstElement *src; | |
| GstPad *pad; | |
| src = gst_element_factory_make ("fakesrc", "src"); | |
| fail_unless (src != NULL, "failed to create fakesrc element"); | |
| g_object_set (src, "num-buffers", 1, NULL); | |
| g_object_set (src, "signal-handoffs", TRUE, NULL); | |
| g_signal_connect (src, "handoff", G_CALLBACK (src_handoff_float32_8ch), NULL); | |
| pad = gst_element_get_static_pad (src, "src"); | |
| gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, src_event_probe, | |
| NULL, NULL); | |
| gst_object_unref (pad); | |
| return src; | |
| } | |
| GST_START_TEST (test_8_channels_float32) | |
| { | |
| GstElement *pipeline, *src, *deinterleave; | |
| GstMessage *msg; | |
| pipeline = (GstElement *) gst_pipeline_new ("pipeline"); | |
| fail_unless (pipeline != NULL, "failed to create pipeline"); | |
| src = make_fake_src_8chans_float32 (); | |
| deinterleave = gst_element_factory_make ("deinterleave", "deinterleave"); | |
| fail_unless (deinterleave != NULL, "failed to create deinterleave element"); | |
| g_object_set (deinterleave, "keep-positions", TRUE, NULL); | |
| gst_bin_add_many (GST_BIN (pipeline), src, deinterleave, NULL); | |
| fail_unless (gst_element_link (src, deinterleave), | |
| "failed to link src <=> deinterleave"); | |
| g_signal_connect (deinterleave, "pad-added", | |
| G_CALLBACK (pad_added_setup_data_check_float32_8ch_cb), pipeline); | |
| pads_created = 0; | |
| gst_element_set_state (pipeline, GST_STATE_PLAYING); | |
| msg = gst_bus_poll (GST_ELEMENT_BUS (pipeline), GST_MESSAGE_EOS, -1); | |
| gst_message_unref (msg); | |
| fail_unless_equals_int (pads_created, NUM_CHANNELS); | |
| gst_element_set_state (pipeline, GST_STATE_NULL); | |
| gst_object_unref (pipeline); | |
| } | |
| GST_END_TEST; | |
| static Suite * | |
| deinterleave_suite (void) | |
| { | |
| Suite *s = suite_create ("deinterleave"); | |
| TCase *tc_chain = tcase_create ("general"); | |
| suite_add_tcase (s, tc_chain); | |
| tcase_set_timeout (tc_chain, 180); | |
| tcase_add_test (tc_chain, test_create_and_unref); | |
| tcase_add_test (tc_chain, test_2_channels); | |
| tcase_add_test (tc_chain, test_2_channels_1_linked); | |
| tcase_add_test (tc_chain, test_2_channels_caps_change); | |
| tcase_add_test (tc_chain, test_8_channels_float32); | |
| return s; | |
| } | |
| GST_CHECK_MAIN (deinterleave); |