diff options
Diffstat (limited to 'gst/audiomixer/gstaudiointerleave.c')
-rw-r--r-- | gst/audiomixer/gstaudiointerleave.c | 902 |
1 files changed, 0 insertions, 902 deletions
diff --git a/gst/audiomixer/gstaudiointerleave.c b/gst/audiomixer/gstaudiointerleave.c deleted file mode 100644 index 90ec363ea..000000000 --- a/gst/audiomixer/gstaudiointerleave.c +++ /dev/null @@ -1,902 +0,0 @@ -/* GStreamer - * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> - * 2000 Wim Taymans <wtay@chello.be> - * 2005 Wim Taymans <wim@fluendo.com> - * 2007 Andy Wingo <wingo at pobox.com> - * 2008 Sebastian Dröge <slomo@circular-chaos.org> - * 2014 Collabora - * Olivier Crete <olivier.crete@collabora.com> - * - * gstaudiointerleave.c: audiointerleave element, N in, one out, - * samples are added - * - * 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. - */ -/** - * SECTION:element-audiointerleave - * @title: audiointerleave - * - */ - -/* FIXME 0.11: suppress warnings for deprecated API such as GValueArray - * with newer GLib versions (>= 2.31.0) */ -#define GLIB_DISABLE_DEPRECATION_WARNINGS - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstaudiointerleave.h" -#include <gst/audio/audio.h> - -#include <string.h> - -#define GST_CAT_DEFAULT gst_audio_interleave_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); - -enum -{ - PROP_PAD_0, - PROP_PAD_CHANNEL -}; - -G_DEFINE_TYPE (GstAudioInterleavePad, gst_audio_interleave_pad, - GST_TYPE_AUDIO_AGGREGATOR_PAD); - -static void -gst_audio_interleave_pad_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstAudioInterleavePad *pad = GST_AUDIO_INTERLEAVE_PAD (object); - - switch (prop_id) { - case PROP_PAD_CHANNEL: - g_value_set_uint (value, pad->channel); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static void -gst_audio_interleave_pad_class_init (GstAudioInterleavePadClass * klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - - gobject_class->get_property = gst_audio_interleave_pad_get_property; - - g_object_class_install_property (gobject_class, - PROP_PAD_CHANNEL, - g_param_spec_uint ("channel", - "Channel number", - "Number of the channel of this pad in the output", 0, G_MAXUINT, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); -} - -static void -gst_audio_interleave_pad_init (GstAudioInterleavePad * pad) -{ -} - -enum -{ - PROP_0, - PROP_CHANNEL_POSITIONS, - PROP_CHANNEL_POSITIONS_FROM_INPUT -}; - -/* elementfactory information */ - -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -#define CAPS \ - GST_AUDIO_CAPS_MAKE ("{ S32LE, U32LE, S16LE, U16LE, S8, U8, F32LE, F64LE }") \ - ", layout = (string) { interleaved, non-interleaved }" -#else -#define CAPS \ - GST_AUDIO_CAPS_MAKE ("{ S32BE, U32BE, S16BE, U16BE, S8, U8, F32BE, F64BE }") \ - ", layout = (string) { interleaved, non-interleaved }" -#endif - -static GstStaticPadTemplate gst_audio_interleave_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink_%u", - GST_PAD_SINK, - GST_PAD_REQUEST, - GST_STATIC_CAPS ("audio/x-raw, " - "rate = (int) [ 1, MAX ], " - "channels = (int) 1, " - "format = (string) " GST_AUDIO_FORMATS_ALL ", " - "layout = (string) {non-interleaved, interleaved}") - ); - -static GstStaticPadTemplate gst_audio_interleave_src_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw, " - "rate = (int) [ 1, MAX ], " - "channels = (int) [ 1, MAX ], " - "format = (string) " GST_AUDIO_FORMATS_ALL ", " - "layout = (string) interleaved") - ); - -static void gst_audio_interleave_child_proxy_init (gpointer g_iface, - gpointer iface_data); - -#define gst_audio_interleave_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstAudioInterleave, gst_audio_interleave, - GST_TYPE_AUDIO_AGGREGATOR, G_IMPLEMENT_INTERFACE (GST_TYPE_CHILD_PROXY, - gst_audio_interleave_child_proxy_init)); - -static void gst_audio_interleave_finalize (GObject * object); -static void gst_audio_interleave_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_audio_interleave_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static gboolean gst_audio_interleave_setcaps (GstAudioInterleave * self, - GstPad * pad, GstCaps * caps); -static GstPad *gst_audio_interleave_request_new_pad (GstElement * element, - GstPadTemplate * temp, const gchar * req_name, const GstCaps * caps); -static void gst_audio_interleave_release_pad (GstElement * element, - GstPad * pad); - -static gboolean gst_audio_interleave_stop (GstAggregator * agg); - -static gboolean -gst_audio_interleave_aggregate_one_buffer (GstAudioAggregator * aagg, - GstAudioAggregatorPad * aaggpad, GstBuffer * inbuf, guint in_offset, - GstBuffer * outbuf, guint out_offset, guint num_samples); - - -static void -__remove_channels (GstCaps * caps) -{ - GstStructure *s; - gint i, size; - - size = gst_caps_get_size (caps); - for (i = 0; i < size; i++) { - s = gst_caps_get_structure (caps, i); - gst_structure_remove_field (s, "channel-mask"); - gst_structure_remove_field (s, "channels"); - } -} - -static void -__set_channels (GstCaps * caps, gint channels) -{ - GstStructure *s; - gint i, size; - - size = gst_caps_get_size (caps); - for (i = 0; i < size; i++) { - s = gst_caps_get_structure (caps, i); - if (channels > 0) - gst_structure_set (s, "channels", G_TYPE_INT, channels, NULL); - else - gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); - } -} - -/* we can only accept caps that we and downstream can handle. - * if we have filtercaps set, use those to constrain the target caps. - */ -static GstCaps * -gst_audio_interleave_sink_getcaps (GstAggregator * agg, GstPad * pad, - GstCaps * filter) -{ - GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (agg); - GstCaps *result = NULL, *peercaps, *sinkcaps; - - GST_OBJECT_LOCK (self); - /* If we already have caps on one of the sink pads return them */ - if (self->sinkcaps) - result = gst_caps_copy (self->sinkcaps); - GST_OBJECT_UNLOCK (self); - - if (result == NULL) { - /* get the downstream possible caps */ - peercaps = gst_pad_peer_query_caps (agg->srcpad, NULL); - - /* get the allowed caps on this sinkpad */ - sinkcaps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); - __remove_channels (sinkcaps); - if (peercaps) { - peercaps = gst_caps_make_writable (peercaps); - __remove_channels (peercaps); - /* if the peer has caps, intersect */ - GST_DEBUG_OBJECT (pad, "intersecting peer and template caps"); - result = gst_caps_intersect (peercaps, sinkcaps); - gst_caps_unref (peercaps); - gst_caps_unref (sinkcaps); - } else { - /* the peer has no caps (or there is no peer), just use the allowed caps - * of this sinkpad. */ - GST_DEBUG_OBJECT (pad, "no peer caps, using sinkcaps"); - result = sinkcaps; - } - __set_channels (result, 1); - } - - if (filter != NULL) { - GstCaps *caps = result; - - GST_LOG_OBJECT (pad, "intersecting filter caps %" GST_PTR_FORMAT " with " - "preliminary result %" GST_PTR_FORMAT, filter, caps); - - result = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST); - gst_caps_unref (caps); - } - - GST_DEBUG_OBJECT (pad, "Returning caps %" GST_PTR_FORMAT, result); - - return result; -} - -static gboolean -gst_audio_interleave_sink_query (GstAggregator * agg, GstAggregatorPad * aggpad, - GstQuery * query) -{ - gboolean res = FALSE; - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_CAPS: - { - GstCaps *filter, *caps; - - gst_query_parse_caps (query, &filter); - caps = gst_audio_interleave_sink_getcaps (agg, GST_PAD (aggpad), filter); - gst_query_set_caps_result (query, caps); - gst_caps_unref (caps); - res = TRUE; - break; - } - default: - res = - GST_AGGREGATOR_CLASS (parent_class)->sink_query (agg, aggpad, query); - break; - } - - return res; -} - -static gint -compare_positions (gconstpointer a, gconstpointer b, gpointer user_data) -{ - const gint i = *(const gint *) a; - const gint j = *(const gint *) b; - const gint *pos = (const gint *) user_data; - - if (pos[i] < pos[j]) - return -1; - else if (pos[i] > pos[j]) - return 1; - else - return 0; -} - -static gboolean -gst_audio_interleave_channel_positions_to_mask (GValueArray * positions, - gint default_ordering_map[64], guint64 * mask) -{ - gint i; - guint channels; - GstAudioChannelPosition *pos; - gboolean ret; - - channels = positions->n_values; - pos = g_new (GstAudioChannelPosition, channels); - - for (i = 0; i < channels; i++) { - GValue *val; - - val = g_value_array_get_nth (positions, i); - pos[i] = g_value_get_enum (val); - } - - /* sort the default ordering map according to the position order */ - for (i = 0; i < channels; i++) { - default_ordering_map[i] = i; - } - g_qsort_with_data (default_ordering_map, channels, - sizeof (*default_ordering_map), compare_positions, pos); - - ret = gst_audio_channel_positions_to_mask (pos, channels, FALSE, mask); - g_free (pos); - - return ret; -} - - -/* Must be called with the object lock held */ - -static guint64 -gst_audio_interleave_get_channel_mask (GstAudioInterleave * self) -{ - guint64 channel_mask = 0; - - if (self->channels <= 64 && - self->channel_positions != NULL && - self->channels == self->channel_positions->n_values) { - if (!gst_audio_interleave_channel_positions_to_mask - (self->channel_positions, self->default_channels_ordering_map, - &channel_mask)) { - GST_WARNING_OBJECT (self, "Invalid channel positions, using NONE"); - channel_mask = 0; - } - } else if (self->channels <= 64) { - GST_WARNING_OBJECT (self, "Using NONE channel positions"); - } - - return channel_mask; -} - - -#define MAKE_FUNC(type) \ -static void interleave_##type (guint##type *out, guint##type *in, \ - guint stride, guint nframes) \ -{ \ - gint i; \ - \ - for (i = 0; i < nframes; i++) { \ - *out = in[i]; \ - out += stride; \ - } \ -} - -MAKE_FUNC (8); -MAKE_FUNC (16); -MAKE_FUNC (32); -MAKE_FUNC (64); - -static void -interleave_24 (guint8 * out, guint8 * in, guint stride, guint nframes) -{ - gint i; - - for (i = 0; i < nframes; i++) { - memcpy (out, in, 3); - out += stride * 3; - in += 3; - } -} - -static void -gst_audio_interleave_set_process_function (GstAudioInterleave * self, - GstAudioInfo * info) -{ - switch (GST_AUDIO_INFO_WIDTH (info)) { - case 8: - self->func = (GstInterleaveFunc) interleave_8; - break; - case 16: - self->func = (GstInterleaveFunc) interleave_16; - break; - case 24: - self->func = (GstInterleaveFunc) interleave_24; - break; - case 32: - self->func = (GstInterleaveFunc) interleave_32; - break; - case 64: - self->func = (GstInterleaveFunc) interleave_64; - break; - default: - g_assert_not_reached (); - break; - } -} - - -/* the first caps we receive on any of the sinkpads will define the caps for all - * the other sinkpads because we can only mix streams with the same caps. - */ -static gboolean -gst_audio_interleave_setcaps (GstAudioInterleave * self, GstPad * pad, - GstCaps * caps) -{ - GstAudioAggregator *aagg = GST_AUDIO_AGGREGATOR (self); - GstAudioInfo info; - GValue *val; - guint channel; - gboolean new = FALSE; - - if (!gst_audio_info_from_caps (&info, caps)) - goto invalid_format; - - GST_OBJECT_LOCK (self); - if (self->sinkcaps && !gst_caps_is_subset (caps, self->sinkcaps)) - goto cannot_change_caps; - - if (!self->sinkcaps) { - GstCaps *sinkcaps = gst_caps_copy (caps); - GstStructure *s = gst_caps_get_structure (sinkcaps, 0); - - gst_structure_remove_field (s, "channel-mask"); - - GST_DEBUG_OBJECT (self, "setting sinkcaps %" GST_PTR_FORMAT, sinkcaps); - - gst_caps_replace (&self->sinkcaps, sinkcaps); - gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (aagg)); - - gst_caps_unref (sinkcaps); - new = TRUE; - } - - if (self->channel_positions_from_input - && GST_AUDIO_INFO_CHANNELS (&info) == 1) { - channel = GST_AUDIO_INTERLEAVE_PAD (pad)->channel; - val = g_value_array_get_nth (self->input_channel_positions, channel); - g_value_set_enum (val, GST_AUDIO_INFO_POSITION (&info, 0)); - } - GST_OBJECT_UNLOCK (self); - - gst_audio_aggregator_set_sink_caps (aagg, GST_AUDIO_AGGREGATOR_PAD (pad), - caps); - - if (!new) - return TRUE; - - GST_INFO_OBJECT (pad, "handle caps change to %" GST_PTR_FORMAT, caps); - - return TRUE; - - /* ERRORS */ -invalid_format: - { - GST_WARNING_OBJECT (self, "invalid format set as caps: %" GST_PTR_FORMAT, - caps); - return FALSE; - } -cannot_change_caps: - { - GST_OBJECT_UNLOCK (self); - GST_WARNING_OBJECT (self, "caps of %" GST_PTR_FORMAT " already set, can't " - "change", self->sinkcaps); - return FALSE; - } -} - -static gboolean -gst_audio_interleave_sink_event (GstAggregator * agg, GstAggregatorPad * aggpad, - GstEvent * event) -{ - GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (agg); - gboolean res = TRUE; - - GST_DEBUG_OBJECT (aggpad, "Got %s event on sink pad", - GST_EVENT_TYPE_NAME (event)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_CAPS: - { - GstCaps *caps; - - gst_event_parse_caps (event, &caps); - res = gst_audio_interleave_setcaps (self, GST_PAD_CAST (aggpad), caps); - gst_event_unref (event); - event = NULL; - break; - } - default: - break; - } - - if (event != NULL) - return GST_AGGREGATOR_CLASS (parent_class)->sink_event (agg, aggpad, event); - - return res; -} - -static GstFlowReturn -gst_audio_interleave_update_src_caps (GstAggregator * agg, GstCaps * caps, - GstCaps ** ret) -{ - GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (agg); - GstStructure *s; - - /* This means that either no caps have been set on the sink pad (if - * sinkcaps is NULL) or that there is no sink pad (if channels == 0). - */ - GST_OBJECT_LOCK (self); - if (self->sinkcaps == NULL || self->channels == 0) { - GST_OBJECT_UNLOCK (self); - return GST_FLOW_NOT_NEGOTIATED; - } - - *ret = gst_caps_copy (self->sinkcaps); - s = gst_caps_get_structure (*ret, 0); - - gst_structure_set (s, "channels", G_TYPE_INT, self->channels, "layout", - G_TYPE_STRING, "interleaved", "channel-mask", GST_TYPE_BITMASK, - gst_audio_interleave_get_channel_mask (self), NULL); - - GST_OBJECT_UNLOCK (self); - - return GST_FLOW_OK; -} - -static gboolean -gst_audio_interleave_negotiated_src_caps (GstAggregator * agg, GstCaps * caps) -{ - GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (agg); - GstAudioAggregator *aagg = GST_AUDIO_AGGREGATOR (self); - - if (!GST_AGGREGATOR_CLASS (parent_class)->negotiated_src_caps (agg, caps)) - return FALSE; - - gst_audio_interleave_set_process_function (self, &aagg->info); - - return TRUE; -} - -static void -gst_audio_interleave_class_init (GstAudioInterleaveClass * klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - GstElementClass *gstelement_class = (GstElementClass *) klass; - GstAggregatorClass *agg_class = (GstAggregatorClass *) klass; - GstAudioAggregatorClass *aagg_class = (GstAudioAggregatorClass *) klass; - - GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "audiointerleave", 0, - "audio interleaving element"); - - gobject_class->set_property = gst_audio_interleave_set_property; - gobject_class->get_property = gst_audio_interleave_get_property; - gobject_class->finalize = gst_audio_interleave_finalize; - - gst_element_class_add_static_pad_template (gstelement_class, - &gst_audio_interleave_src_template); - gst_element_class_add_static_pad_template_with_gtype (gstelement_class, - &gst_audio_interleave_sink_template, GST_TYPE_AUDIO_INTERLEAVE_PAD); - gst_element_class_set_static_metadata (gstelement_class, "AudioInterleave", - "Generic/Audio", "Mixes multiple audio streams", - "Olivier Crete <olivier.crete@collabora.com>"); - - gstelement_class->request_new_pad = - GST_DEBUG_FUNCPTR (gst_audio_interleave_request_new_pad); - gstelement_class->release_pad = - GST_DEBUG_FUNCPTR (gst_audio_interleave_release_pad); - - agg_class->sink_query = GST_DEBUG_FUNCPTR (gst_audio_interleave_sink_query); - agg_class->sink_event = GST_DEBUG_FUNCPTR (gst_audio_interleave_sink_event); - agg_class->stop = gst_audio_interleave_stop; - agg_class->update_src_caps = gst_audio_interleave_update_src_caps; - agg_class->negotiated_src_caps = gst_audio_interleave_negotiated_src_caps; - - aagg_class->aggregate_one_buffer = gst_audio_interleave_aggregate_one_buffer; - aagg_class->convert_buffer = NULL; - - /** - * GstInterleave:channel-positions - * - * Channel positions: This property controls the channel positions - * that are used on the src caps. The number of elements should be - * the same as the number of sink pads and the array should contain - * a valid list of channel positions. The n-th element of the array - * is the position of the n-th sink pad. - * - * These channel positions will only be used if they're valid and the - * number of elements is the same as the number of channels. If this - * is not given a NONE layout will be used. - * - */ - g_object_class_install_property (gobject_class, PROP_CHANNEL_POSITIONS, - g_param_spec_value_array ("channel-positions", "Channel positions", - "Channel positions used on the output", - g_param_spec_enum ("channel-position", "Channel position", - "Channel position of the n-th input", - GST_TYPE_AUDIO_CHANNEL_POSITION, - GST_AUDIO_CHANNEL_POSITION_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS), - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /** - * GstInterleave:channel-positions-from-input - * - * Channel positions from input: If this property is set to %TRUE the channel - * positions will be taken from the input caps if valid channel positions for - * the output can be constructed from them. If this is set to %TRUE setting the - * channel-positions property overwrites this property again. - * - */ - g_object_class_install_property (gobject_class, - PROP_CHANNEL_POSITIONS_FROM_INPUT, - g_param_spec_boolean ("channel-positions-from-input", - "Channel positions from input", - "Take channel positions from the input", TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -} - -static void -gst_audio_interleave_init (GstAudioInterleave * self) -{ - self->input_channel_positions = g_value_array_new (0); - self->channel_positions_from_input = TRUE; - self->channel_positions = self->input_channel_positions; -} - -static void -gst_audio_interleave_finalize (GObject * object) -{ - GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (object); - - if (self->channel_positions - && self->channel_positions != self->input_channel_positions) { - g_value_array_free (self->channel_positions); - self->channel_positions = NULL; - } - - if (self->input_channel_positions) { - g_value_array_free (self->input_channel_positions); - self->input_channel_positions = NULL; - } - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_audio_interleave_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (object); - - switch (prop_id) { - case PROP_CHANNEL_POSITIONS: - g_return_if_fail ( - ((GValueArray *) g_value_get_boxed (value))->n_values > 0); - - if (self->channel_positions && - self->channel_positions != self->input_channel_positions) - g_value_array_free (self->channel_positions); - - self->channel_positions = g_value_dup_boxed (value); - self->channel_positions_from_input = FALSE; - break; - case PROP_CHANNEL_POSITIONS_FROM_INPUT: - self->channel_positions_from_input = g_value_get_boolean (value); - - if (self->channel_positions_from_input) { - if (self->channel_positions && - self->channel_positions != self->input_channel_positions) - g_value_array_free (self->channel_positions); - self->channel_positions = self->input_channel_positions; - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_audio_interleave_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (object); - - switch (prop_id) { - case PROP_CHANNEL_POSITIONS: - g_value_set_boxed (value, self->channel_positions); - break; - case PROP_CHANNEL_POSITIONS_FROM_INPUT: - g_value_set_boolean (value, self->channel_positions_from_input); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -gst_audio_interleave_stop (GstAggregator * agg) -{ - GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (agg); - - if (!GST_AGGREGATOR_CLASS (parent_class)->stop (agg)) - return FALSE; - - gst_caps_replace (&self->sinkcaps, NULL); - - return TRUE; -} - -static GstPad * -gst_audio_interleave_request_new_pad (GstElement * element, - GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps) -{ - GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (element); - GstAudioInterleavePad *newpad; - gchar *pad_name; - gint channel, padnumber; - GValue val = { 0, }; - - /* FIXME: We ignore req_name, this is evil! */ - - GST_OBJECT_LOCK (self); - padnumber = g_atomic_int_add (&self->padcounter, 1); - channel = self->channels++; - if (!self->channel_positions_from_input) - channel = padnumber; - GST_OBJECT_UNLOCK (self); - - pad_name = g_strdup_printf ("sink_%u", padnumber); - newpad = (GstAudioInterleavePad *) - GST_ELEMENT_CLASS (parent_class)->request_new_pad (element, - templ, pad_name, caps); - g_free (pad_name); - if (newpad == NULL) - goto could_not_create; - - newpad->channel = channel; - gst_pad_use_fixed_caps (GST_PAD (newpad)); - - gst_child_proxy_child_added (GST_CHILD_PROXY (element), G_OBJECT (newpad), - GST_OBJECT_NAME (newpad)); - - - g_value_init (&val, GST_TYPE_AUDIO_CHANNEL_POSITION); - g_value_set_enum (&val, GST_AUDIO_CHANNEL_POSITION_NONE); - self->input_channel_positions = - g_value_array_append (self->input_channel_positions, &val); - g_value_unset (&val); - - /* Update the src caps if we already have them */ - gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (self)); - - return GST_PAD_CAST (newpad); - -could_not_create: - { - GST_DEBUG_OBJECT (element, "could not create/add pad"); - return NULL; - } -} - -static void -gst_audio_interleave_release_pad (GstElement * element, GstPad * pad) -{ - GstAudioInterleave *self; - gint position; - GList *l; - - self = GST_AUDIO_INTERLEAVE (element); - - /* Take lock to make sure we're not changing this when processing buffers */ - GST_OBJECT_LOCK (self); - - self->channels--; - - position = GST_AUDIO_INTERLEAVE_PAD (pad)->channel; - g_value_array_remove (self->input_channel_positions, position); - - /* Update channel numbers */ - /* Taken above, GST_OBJECT_LOCK (self); */ - for (l = GST_ELEMENT_CAST (self)->sinkpads; l != NULL; l = l->next) { - GstAudioInterleavePad *ipad = GST_AUDIO_INTERLEAVE_PAD (l->data); - - if (GST_AUDIO_INTERLEAVE_PAD (pad)->channel < ipad->channel) - ipad->channel--; - } - - gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (self)); - GST_OBJECT_UNLOCK (self); - - - GST_DEBUG_OBJECT (self, "release pad %s:%s", GST_DEBUG_PAD_NAME (pad)); - - gst_child_proxy_child_removed (GST_CHILD_PROXY (self), G_OBJECT (pad), - GST_OBJECT_NAME (pad)); - - GST_ELEMENT_CLASS (parent_class)->release_pad (element, pad); -} - - -/* Called with object lock and pad object lock held */ -static gboolean -gst_audio_interleave_aggregate_one_buffer (GstAudioAggregator * aagg, - GstAudioAggregatorPad * aaggpad, GstBuffer * inbuf, guint in_offset, - GstBuffer * outbuf, guint out_offset, guint num_frames) -{ - GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (aagg); - GstAudioInterleavePad *pad = GST_AUDIO_INTERLEAVE_PAD (aaggpad); - GstMapInfo inmap; - GstMapInfo outmap; - gint out_width, in_bpf, out_bpf, out_channels, channel; - guint8 *outdata; - - GST_OBJECT_LOCK (aagg); - GST_OBJECT_LOCK (aaggpad); - - out_width = GST_AUDIO_INFO_WIDTH (&aagg->info) / 8; - in_bpf = GST_AUDIO_INFO_BPF (&aaggpad->info); - out_bpf = GST_AUDIO_INFO_BPF (&aagg->info); - out_channels = GST_AUDIO_INFO_CHANNELS (&aagg->info); - - gst_buffer_map (outbuf, &outmap, GST_MAP_READWRITE); - gst_buffer_map (inbuf, &inmap, GST_MAP_READ); - GST_LOG_OBJECT (pad, "interleaves %u frames on channel %d/%d at offset %u" - " from offset %u", num_frames, pad->channel, out_channels, - out_offset * out_bpf, in_offset * in_bpf); - - if (self->channels > 64) { - channel = pad->channel; - } else { - channel = self->default_channels_ordering_map[pad->channel]; - } - - outdata = outmap.data + (out_offset * out_bpf) + (out_width * channel); - - - self->func (outdata, inmap.data + (in_offset * in_bpf), out_channels, - num_frames); - - - gst_buffer_unmap (inbuf, &inmap); - gst_buffer_unmap (outbuf, &outmap); - - GST_OBJECT_UNLOCK (aaggpad); - GST_OBJECT_UNLOCK (aagg); - - return TRUE; -} - - -/* GstChildProxy implementation */ -static GObject * -gst_audio_interleave_child_proxy_get_child_by_index (GstChildProxy * - child_proxy, guint index) -{ - GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (child_proxy); - GObject *obj = NULL; - - GST_OBJECT_LOCK (self); - obj = g_list_nth_data (GST_ELEMENT_CAST (self)->sinkpads, index); - if (obj) - gst_object_ref (obj); - GST_OBJECT_UNLOCK (self); - - return obj; -} - -static guint -gst_audio_interleave_child_proxy_get_children_count (GstChildProxy * - child_proxy) -{ - guint count = 0; - GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (child_proxy); - - GST_OBJECT_LOCK (self); - count = GST_ELEMENT_CAST (self)->numsinkpads; - GST_OBJECT_UNLOCK (self); - GST_INFO_OBJECT (self, "Children Count: %d", count); - - return count; -} - -static void -gst_audio_interleave_child_proxy_init (gpointer g_iface, gpointer iface_data) -{ - GstChildProxyInterface *iface = g_iface; - - GST_INFO ("intializing child proxy interface"); - iface->get_child_by_index = - gst_audio_interleave_child_proxy_get_child_by_index; - iface->get_children_count = - gst_audio_interleave_child_proxy_get_children_count; -} |