From e6f278e0652e2b623956130df0fcff657d1b94a8 Mon Sep 17 00:00:00 2001 From: Leif Johnson Date: Sat, 19 Jul 2003 23:16:25 +0000 Subject: [PATCH] + alterations to the adder for changed float caps Original commit message from CVS: + alterations to the adder for changed float caps --- gst/adder/gstadder.c | 171 +++++++++++++++++++++++-------------------- gst/adder/gstadder.h | 16 ++-- 2 files changed, 95 insertions(+), 92 deletions(-) diff --git a/gst/adder/gstadder.c b/gst/adder/gstadder.c index 859d71f29c..60f1741319 100644 --- a/gst/adder/gstadder.c +++ b/gst/adder/gstadder.c @@ -36,7 +36,7 @@ GstElementDetails adder_details = { "Adder", "Filter/Audio", "LGPL", - "N-to-1 audio adder/mixer", + "Add N audio channels together", VERSION, "Thomas ", "(C) 2001, 2002", @@ -61,7 +61,7 @@ GST_PAD_TEMPLATE_FACTORY (gst_adder_src_template_factory, gst_caps_new ("int_src", "audio/x-raw-int", GST_AUDIO_INT_PAD_TEMPLATE_PROPS), gst_caps_new ("float_src", "audio/x-raw-float", - GST_AUDIO_FLOAT_MONO_PAD_TEMPLATE_PROPS) + GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_PROPS) ); GST_PAD_TEMPLATE_FACTORY (gst_adder_sink_template_factory, @@ -71,7 +71,7 @@ GST_PAD_TEMPLATE_FACTORY (gst_adder_sink_template_factory, gst_caps_new ("int_sink", "audio/x-raw-int", GST_AUDIO_INT_PAD_TEMPLATE_PROPS), gst_caps_new ("float_sink", "audio/x-raw-float", - GST_AUDIO_FLOAT_MONO_PAD_TEMPLATE_PROPS) + GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_PROPS) ); static void gst_adder_class_init (GstAdderClass *klass); @@ -113,12 +113,11 @@ gst_adder_parse_caps (GstAdder *adder, GstCaps *caps) { const gchar *mimetype; GstElement *el = GST_ELEMENT (adder); - + mimetype = gst_caps_get_mime (caps); if (adder->format == GST_ADDER_FORMAT_UNSET) { - /* the caps haven't been set yet at all, - * so we need to go ahead and set all + /* the caps haven't been set yet at all, so we need to go ahead and set all the relevant values. */ if (strcmp (mimetype, "audio/x-raw-int") == 0) { GST_DEBUG ("parse_caps sets adder to format int"); @@ -132,14 +131,13 @@ gst_adder_parse_caps (GstAdder *adder, GstCaps *caps) } else if (strcmp (mimetype, "audio/x-raw-float") == 0) { GST_DEBUG ("parse_caps sets adder to format float"); adder->format = GST_ADDER_FORMAT_FLOAT; - gst_caps_get_float (caps, "intercept", &adder->intercept); - gst_caps_get_float (caps, "slope", &adder->slope); + gst_caps_get_int (caps, "width", &adder->width); gst_caps_get_int (caps, "channels", &adder->channels); - gst_caps_get_int (caps, "rate", &adder->rate); + gst_caps_get_int (caps, "rate", &adder->rate); } } else { - /* otherwise, a previously-linked pad has set all the values. we should - barf if some of the attempted new values don't match. */ + /* otherwise, a previously-linked pad has set all the values. we should barf + if some of the attempted new values don't match. */ if (strcmp (mimetype, "audio/x-raw-int") == 0) { gint width, channels, rate; gboolean is_signed; @@ -171,21 +169,20 @@ gst_adder_parse_caps (GstAdder *adder, GstCaps *caps) return FALSE; } if (adder->is_signed != is_signed) { - gst_element_error (el, - "can't link %ssigned pad with %ssigned adder", + gst_element_error (el, "can't link %ssigned pad with %ssigned adder", adder->is_signed ? "" : "un", is_signed ? "" : "un"); return FALSE; } } else if (strcmp (mimetype, "audio/x-raw-float") == 0) { - gint channels, rate; + gint channels, rate, width; - gst_caps_get_int (caps, "channels", &channels); - gst_caps_get_int (caps, "rate", &rate); + gst_caps_get_int (caps, "width", &width); + gst_caps_get_int (caps, "channels", &channels); + gst_caps_get_int (caps, "rate", &rate); if (adder->format != GST_ADDER_FORMAT_FLOAT) { - gst_element_error (el, - "can't link a non-float pad to a float adder"); + gst_element_error (el, "can't link a non-float pad to a float adder"); return FALSE; } if (adder->channels != channels) { @@ -199,6 +196,11 @@ gst_adder_parse_caps (GstAdder *adder, GstCaps *caps) rate, adder->rate); return FALSE; } + if (adder->width != width) { + gst_element_error (el, "can't link %d bit float pad with %d bit adder", + width, adder->width); + return FALSE; + } } } return TRUE; @@ -212,7 +214,7 @@ gst_adder_link (GstPad *pad, GstCaps *caps) GList *remove = NULL; GSList *channels; GstPad *p; - + g_return_val_if_fail (caps != NULL, GST_PAD_LINK_REFUSED); g_return_val_if_fail (pad != NULL, GST_PAD_LINK_REFUSED); @@ -221,18 +223,17 @@ gst_adder_link (GstPad *pad, GstCaps *caps) if (GST_CAPS_IS_FIXED (caps)) { if (!gst_adder_parse_caps (adder, caps)) return GST_PAD_LINK_REFUSED; - + if (pad == adder->srcpad || gst_pad_try_set_caps (adder->srcpad, caps) > 0) { sinkpads = gst_element_get_pad_list ((GstElement *) adder); while (sinkpads) { p = (GstPad *) sinkpads->data; if (p != pad && p != adder->srcpad) { if (gst_pad_try_set_caps (p, caps) <= 0) { - GST_DEBUG ( - "caps mismatch; unlinking and removing pad %s:%s " + GST_DEBUG ("caps mismatch; unlinking and removing pad %s:%s " "(peer %s:%s)", - GST_DEBUG_PAD_NAME (p), - GST_DEBUG_PAD_NAME (GST_PAD_PEER (p))); + GST_DEBUG_PAD_NAME (p), + GST_DEBUG_PAD_NAME (GST_PAD_PEER (p))); gst_pad_unlink (GST_PAD (GST_PAD_PEER (p)), p); remove = g_list_prepend (remove, p); } @@ -240,8 +241,8 @@ gst_adder_link (GstPad *pad, GstCaps *caps) sinkpads = g_list_next (sinkpads); } while (remove) { - gst_element_remove_pad (GST_ELEMENT (adder), - GST_PAD_CAST (remove->data)); + gst_element_remove_pad (GST_ELEMENT (adder), + GST_PAD_CAST (remove->data)); restart: channels = adder->input_channels; while (channels) { @@ -249,8 +250,8 @@ gst_adder_link (GstPad *pad, GstCaps *caps) channel = (GstAdderInputChannel*) channels->data; if (channel->sinkpad == GST_PAD_CAST (remove->data)) { gst_bytestream_destroy (channel->bytestream); - adder->input_channels = g_slist_remove_link (adder->input_channels, - channels); + adder->input_channels = + g_slist_remove_link (adder->input_channels, channels); adder->numsinkpads--; goto restart; } @@ -268,7 +269,7 @@ gst_adder_link (GstPad *pad, GstCaps *caps) } static void -gst_adder_class_init (GstAdderClass *klass) +gst_adder_class_init (GstAdderClass *klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; @@ -391,23 +392,22 @@ gst_adder_loop (GstElement *element) g_return_if_fail (element != NULL); g_return_if_fail (GST_IS_ADDER (element)); - + adder = GST_ADDER (element); if (adder->bufpool == NULL) { adder->bufpool = gst_pad_get_bufferpool (adder->srcpad); if (adder->bufpool == NULL) { - adder->bufpool = gst_buffer_pool_get_default (GST_ADDER_BUFFER_SIZE, + adder->bufpool = gst_buffer_pool_get_default (GST_ADDER_BUFFER_SIZE, GST_ADDER_NUM_BUFFERS); } } - + /* get new output buffer */ buf_out = gst_buffer_new_from_pool (adder->bufpool, 0, 0); - + if (buf_out == NULL) { - gst_element_error (GST_ELEMENT (adder), - "could not get new output buffer !\n"); + gst_element_error (GST_ELEMENT (adder), "could not get new output buffer"); return; } @@ -429,21 +429,19 @@ gst_adder_loop (GstElement *element) inputs = inputs->next; GST_DEBUG ("looking into channel %p", input); - + if (!GST_PAD_IS_USABLE (input->sinkpad)) { - GST_DEBUG ("adder ignoring pad %s:%s", + GST_DEBUG ("adder ignoring pad %s:%s", GST_DEBUG_PAD_NAME (input->sinkpad)); continue; } - /* Get data from the bytestream of each input channel. - * We need to check for events before passing on the data - * to the output buffer. */ + /* Get data from the bytestream of each input channel. We need to check for + events before passing on the data to the output buffer. */ got_bytes = gst_bytestream_peek_bytes (input->bytestream, &raw_in, GST_BUFFER_SIZE (buf_out)); - /* FIXME we should do something with the data if - * got_bytes is more than zero */ + /* FIXME we should do something with the data if got_bytes > 0 */ if (got_bytes < GST_BUFFER_SIZE(buf_out)) { GstEvent *event = NULL; guint32 waiting; @@ -455,15 +453,15 @@ gst_adder_loop (GstElement *element) switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS: /* if we get an EOS event from one of our sink pads, we assume that - pad's finished handling data. just skip this pad */ + pad's finished handling data. just skip this pad. */ GST_DEBUG ("got an EOS event"); gst_event_unref (event); continue; case GST_EVENT_INTERRUPT: gst_event_unref (event); GST_DEBUG ("got an interrupt event"); - /* we have to call interrupt here, the scheduler will switch out this - * element ASAP or returns TRUE if we need to exit the loop */ + /* we have to call interrupt here, the scheduler will switch out + this element ASAP or returns TRUE if we need to exit the loop */ if (gst_element_interrupt (GST_ELEMENT (adder))) { gst_buffer_unref (buf_out); return; @@ -473,40 +471,55 @@ gst_adder_loop (GstElement *element) } } } else { - /* here's where the data gets copied. this is a little nasty looking - because it's the same code pretty much 3 times, except each time uses - different data types and clamp limits. */ - GST_DEBUG ( - "copying %d bytes from channel %p to output data %p " + /* here's where the data gets copied. */ + + GST_DEBUG ("copying %d bytes from channel %p to output data %p " "in buffer %p", - GST_BUFFER_SIZE (buf_out), input, + GST_BUFFER_SIZE (buf_out), input, GST_BUFFER_DATA (buf_out), buf_out); if (adder->format == GST_ADDER_FORMAT_INT) { - if (adder->width == 16) { + if (adder->width == 32) { + gint32 *in = (gint32 *) raw_in; + gint32 *out = (gint32 *) GST_BUFFER_DATA (buf_out); + for (i = 0; i < GST_BUFFER_SIZE (buf_out) / 4; i++) + out[i] = CLAMP(out[i] + in[i], 0x80000000, 0x7fffffff); + } else if (adder->width == 16) { gint16 *in = (gint16 *) raw_in; - gint16 *out = (gint16 *) GST_BUFFER_DATA (buf_out); + gint16 *out = (gint16 *) GST_BUFFER_DATA (buf_out); for (i = 0; i < GST_BUFFER_SIZE (buf_out) / 2; i++) - out[i] = CLAMP(out[i] + in[i], -32768, 32767); + out[i] = CLAMP(out[i] + in[i], 0x8000, 0x7fff); } else if (adder->width == 8) { gint8 *in = (gint8 *) raw_in; - gint8 *out = (gint8 *) GST_BUFFER_DATA (buf_out); + gint8 *out = (gint8 *) GST_BUFFER_DATA (buf_out); for (i = 0; i < GST_BUFFER_SIZE (buf_out); i++) - out[i] = CLAMP(out[i] + in[i], -128, 127); + out[i] = CLAMP(out[i] + in[i], 0x80, 0x7f); } else { gst_element_error (GST_ELEMENT (adder), - "invalid width (%u) for int format in gstadder\n", + "invalid width (%u) for integer audio in gstadder", adder->width); return; } } else if (adder->format == GST_ADDER_FORMAT_FLOAT) { - gfloat *in = (gfloat *) raw_in; - gfloat *out = (gfloat *) GST_BUFFER_DATA (buf_out); - for (i = 0; i < GST_BUFFER_SIZE (buf_out) / sizeof (gfloat); i++) - out[i] += in[i]; + if (adder->width == 64) { + gdouble *in = (gdouble *) raw_in; + gdouble *out = (gdouble *) GST_BUFFER_DATA (buf_out); + for (i = 0; i < GST_BUFFER_SIZE (buf_out) / sizeof (gdouble); i++) + out[i] = CLAMP(out[i] + in[i], -1.0, 1.0); + } else if (adder->width == 32) { + gfloat *in = (gfloat *) raw_in; + gfloat *out = (gfloat *) GST_BUFFER_DATA (buf_out); + for (i = 0; i < GST_BUFFER_SIZE (buf_out) / sizeof (gfloat); i++) + out[i] = CLAMP(out[i] + in[i], -1.0, 1.0); + } else { + gst_element_error (GST_ELEMENT (adder), + "invalid width (%u) for float audio in gstadder", + adder->width); + return; + } } else { gst_element_error (GST_ELEMENT (adder), - "invalid audio format (%d) in gstadder\n", + "invalid audio format (%d) in gstadder", adder->format); return; } @@ -518,24 +531,18 @@ gst_adder_loop (GstElement *element) } if (adder->format == GST_ADDER_FORMAT_UNSET) { - GstCaps *caps = - - gst_caps_new ("default_adder_caps", - "audio/x-raw-int", - gst_props_new ("width", GST_PROPS_INT (16), - "depth", GST_PROPS_INT (16), - "rate", GST_PROPS_INT (44100), - "channels", GST_PROPS_INT (2), - "endianness", GST_PROPS_INT (G_BYTE_ORDER), - "signed", GST_PROPS_BOOLEAN (TRUE), - NULL)); + GstCaps *caps = + gst_caps_new ("default_adder_caps", + "audio/x-raw-int", + GST_AUDIO_INT_PAD_TEMPLATE_PROPS); if (gst_pad_try_set_caps (adder->srcpad, caps) < 0) { gst_element_error (GST_ELEMENT (adder), - "Couldn't set the default caps, " - "use link_filtered instead"); + "Couldn't set the default caps, " + "use link_filtered instead"); return; } + gst_adder_parse_caps (adder, caps); } @@ -552,6 +559,7 @@ gst_adder_loop (GstElement *element) gst_pad_push (adder->srcpad, buf_out); } + static GstElementStateReturn gst_adder_change_state (GstElement *element) { @@ -589,6 +597,7 @@ gst_adder_change_state (GstElement *element) return GST_STATE_SUCCESS; } + static gboolean plugin_init (GModule *module, GstPlugin *plugin) { @@ -596,17 +605,17 @@ plugin_init (GModule *module, GstPlugin *plugin) factory = gst_element_factory_new ("adder", GST_TYPE_ADDER, &adder_details); g_return_val_if_fail (factory != NULL, FALSE); - + if (! gst_library_load ("gstbytestream")) return FALSE; - - gst_element_factory_add_pad_template (factory, + + gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (gst_adder_src_template_factory)); - gst_element_factory_add_pad_template (factory, + gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (gst_adder_sink_template_factory)); - + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); - + return TRUE; } diff --git a/gst/adder/gstadder.h b/gst/adder/gstadder.h index 2493534542..a1d6f1d9f0 100644 --- a/gst/adder/gstadder.h +++ b/gst/adder/gstadder.h @@ -64,27 +64,21 @@ struct _GstAdder { GstPad *srcpad; GstBufferPool *bufpool; - + /* keep track of the sinkpads */ guint numsinkpads; GSList *input_channels; - /* the next three are valid for both int and float */ + /* the next are valid for both int and float */ GstAdderFormat format; guint rate; guint channels; - - /* the next five are valid only for format == GST_ADDER_FORMAT_INT */ guint width; - guint depth; guint endianness; - guint law; + + /* the next are valid only for format == GST_ADDER_FORMAT_INT */ + guint depth; gboolean is_signed; - - /* the next three are valid only for format == GST_ADDER_FORMAT_FLOAT */ - const gchar *layout; - gfloat slope; - gfloat intercept; /* counters to keep track of timestamps */ gint64 timestamp; -- 2.34.1