From: Andy Wingo Date: Fri, 9 Apr 2004 12:39:30 +0000 (+0000) Subject: gst/audioconvert/bufferframesconvert.c: New element to convert buffer-frames for... X-Git-Tag: BRANCH-GSTREAMER-0_8-ROOT~1278 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=92fe387eea5fe5c617695399704e0f4136cd0fed;p=platform%2Fupstream%2Fgst-plugins-base.git gst/audioconvert/bufferframesconvert.c: New element to convert buffer-frames for float streams. Not working nicely yet. Original commit message from CVS: 2004-04-09 Andy Wingo * gst/audioconvert/bufferframesconvert.c: New element to convert buffer-frames for float streams. Not working nicely yet. * gst/audioconvert/plugin.h: * gst/audioconvert/plugin.c: New files. * gst/audioconvert/Makefile.am: Build the new files. * gst/audioconvert/gstaudioconvert.c: Initialize via plugin.[ch]. --- diff --git a/gst/audioconvert/Makefile.am b/gst/audioconvert/Makefile.am index 9b83fe10d..fff3c2724 100644 --- a/gst/audioconvert/Makefile.am +++ b/gst/audioconvert/Makefile.am @@ -1,7 +1,7 @@ plugin_LTLIBRARIES = libgstaudioconvert.la -libgstaudioconvert_la_SOURCES = gstaudioconvert.c +libgstaudioconvert_la_SOURCES = gstaudioconvert.c bufferframesconvert.c plugin.c plugin.h libgstaudioconvert_la_CFLAGS = $(GST_CFLAGS) libgstaudioconvert_la_LIBADD = libgstaudioconvert_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) diff --git a/gst/audioconvert/bufferframesconvert.c b/gst/audioconvert/bufferframesconvert.c new file mode 100644 index 000000000..402f3e7c9 --- /dev/null +++ b/gst/audioconvert/bufferframesconvert.c @@ -0,0 +1,349 @@ +/* GStreamer buffer-frames conversion plugin + * Copyright (C) 2004 Andy Wingo + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "plugin.h" + +#define GSTPLUGIN_TYPE_BUFFER_FRAMES_CONVERT \ + (gstplugin_buffer_frames_convert_get_type()) +#define BUFFER_FRAMES_CONVERT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSTPLUGIN_TYPE_BUFFER_FRAMES_CONVERT, BufferFramesConvert)) + +typedef struct _BufferFramesConvert BufferFramesConvert; +typedef struct _BufferFramesConvertClass BufferFramesConvertClass; + +struct _BufferFramesConvert +{ + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + gint in_buffer_samples; + gint out_buffer_samples; + + gboolean passthrough; + GstBuffer *buf_out; + gint64 offset; + gint samples_out_remaining; +}; + +struct _BufferFramesConvertClass +{ + GstElementClass parent_class; +}; + +static GstElementDetails details = { + "buffer-frames conversion", + "Filter/Converter/Audio", + "Convert between different values of the buffer-frames stream property", + "Andy Wingo " +}; + +static GstStaticPadTemplate sink_static_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-float," + "rate = (int) [ 1, MAX ]," + "channels = (int) [ 1, MAX ]," + "endianness = (int) BYTE_ORDER," + "width = (int) 32," "buffer-frames = (int) [ 0, MAX ]") + ); + +static GstStaticPadTemplate src_static_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-float," + "rate = (int) [ 1, MAX ]," + "channels = (int) [ 1, MAX ]," + "endianness = (int) BYTE_ORDER," + "width = (int) 32," "buffer-frames = (int) [ 0, MAX ]") + ); + +static void buffer_frames_convert_class_init (BufferFramesConvertClass * klass); +static void buffer_frames_convert_base_init (BufferFramesConvertClass * klass); +static void buffer_frames_convert_init (BufferFramesConvert * this); + +static GstElementStateReturn buffer_frames_convert_change_state (GstElement * + element); + +static GstCaps *buffer_frames_convert_getcaps (GstPad * pad); +static GstPadLinkReturn buffer_frames_convert_link (GstPad * pad, + const GstCaps * caps); + +static void buffer_frames_convert_chain (GstPad * sinkpad, GstData * _data); + +static GstElementClass *parent_class = NULL; + +GType +gstplugin_buffer_frames_convert_get_type (void) +{ + static GType buffer_frames_convert_type = 0; + + if (!buffer_frames_convert_type) { + static const GTypeInfo buffer_frames_convert_info = { + sizeof (BufferFramesConvertClass), + (GBaseInitFunc) buffer_frames_convert_base_init, + NULL, + (GClassInitFunc) buffer_frames_convert_class_init, + NULL, + NULL, + sizeof (BufferFramesConvert), + 0, + (GInstanceInitFunc) buffer_frames_convert_init, + }; + + buffer_frames_convert_type = + g_type_register_static (GST_TYPE_ELEMENT, "GstBufferFramesConvert", + &buffer_frames_convert_info, 0); + } + return buffer_frames_convert_type; +} + +static void +buffer_frames_convert_base_init (BufferFramesConvertClass * klass) +{ + GstElementClass *eclass = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_details (eclass, &details); + gst_element_class_add_pad_template + (eclass, gst_static_pad_template_get (&src_static_template)); + gst_element_class_add_pad_template + (eclass, gst_static_pad_template_get (&sink_static_template)); +} + +static void +buffer_frames_convert_class_init (BufferFramesConvertClass * klass) +{ + GstElementClass *eclass = (GstElementClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + eclass->change_state = buffer_frames_convert_change_state; +} + +static void +buffer_frames_convert_init (BufferFramesConvert * this) +{ + this->sinkpad = gst_pad_new_from_template + (gst_static_pad_template_get (&sink_static_template), "sink"); + gst_element_add_pad (GST_ELEMENT (this), this->sinkpad); + gst_pad_set_link_function (this->sinkpad, buffer_frames_convert_link); + gst_pad_set_getcaps_function (this->sinkpad, buffer_frames_convert_getcaps); + gst_pad_set_chain_function (this->sinkpad, buffer_frames_convert_chain); + + this->srcpad = gst_pad_new_from_template + (gst_static_pad_template_get (&src_static_template), "src"); + gst_element_add_pad (GST_ELEMENT (this), this->srcpad); + gst_pad_set_link_function (this->srcpad, buffer_frames_convert_link); + gst_pad_set_getcaps_function (this->srcpad, buffer_frames_convert_getcaps); + + this->in_buffer_samples = -1; + this->out_buffer_samples = -1; + + this->buf_out = NULL; + this->samples_out_remaining = 0; +} + +static GstElementStateReturn +buffer_frames_convert_change_state (GstElement * element) +{ + BufferFramesConvert *this = (BufferFramesConvert *) element; + + switch (GST_STATE_TRANSITION (element)) { + case GST_STATE_READY_TO_PAUSED: + this->offset = 0; + break; + + case GST_STATE_PAUSED_TO_READY: + if (this->buf_out) + gst_buffer_unref (this->buf_out); + this->buf_out = NULL; + this->samples_out_remaining = 0; + break; + + default: + break; + } + + if (parent_class->change_state) + return parent_class->change_state (element); + return GST_STATE_SUCCESS; +} + +static GstCaps * +buffer_frames_convert_getcaps (GstPad * pad) +{ + BufferFramesConvert *this; + GstPad *otherpad; + GstCaps *ret; + int i; + + this = BUFFER_FRAMES_CONVERT (GST_OBJECT_PARENT (pad)); + + otherpad = pad == this->srcpad ? this->sinkpad : this->srcpad; + ret = gst_pad_get_allowed_caps (otherpad); + + for (i = 0; i < gst_caps_get_size (ret); i++) + gst_structure_set (gst_caps_get_structure (ret, i), + "buffer-frames", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL); + + GST_DEBUG ("allowed caps %" GST_PTR_FORMAT, ret); + + return ret; +} + +static GstPadLinkReturn +buffer_frames_convert_link (GstPad * pad, const GstCaps * caps) +{ + BufferFramesConvert *this; + GstCaps *othercaps; + GstPad *otherpad; + GstPadLinkReturn ret; + GstStructure *sinkstructure, *srcstructure; + gint numchannels; + + this = BUFFER_FRAMES_CONVERT (GST_OBJECT_PARENT (pad)); + + otherpad = pad == this->srcpad ? this->sinkpad : this->srcpad; + + /* first try to act as a passthrough */ + ret = gst_pad_try_set_caps (otherpad, caps); + if (GST_PAD_LINK_SUCCESSFUL (ret)) { + this->passthrough = TRUE; + return ret; + } + + /* then try to set unfixed buffer-frames */ + othercaps = gst_caps_copy (caps); + gst_caps_set_simple (othercaps, "buffer-frames", GST_TYPE_INT_RANGE, 0, + G_MAXINT, NULL); + ret = gst_pad_try_set_caps_nonfixed (otherpad, othercaps); + if (GST_PAD_LINK_FAILED (ret)) + return ret; + + /* it's ok, let's record our data */ + sinkstructure = + gst_caps_get_structure (pad == this->sinkpad ? caps : othercaps, 0); + srcstructure = + gst_caps_get_structure (pad == this->srcpad ? caps : othercaps, 0); + gst_structure_get_int (sinkstructure, "buffer-frames", + &this->in_buffer_samples); + gst_structure_get_int (srcstructure, "buffer-frames", + &this->out_buffer_samples); + + gst_structure_get_int (sinkstructure, "channels", &numchannels); + this->in_buffer_samples *= numchannels; + this->out_buffer_samples *= numchannels; + + if (this->out_buffer_samples == 0) + this->passthrough = TRUE; + + return GST_PAD_LINK_OK; +} + +static void +buffer_frames_convert_chain (GstPad * pad, GstData * _data) +{ + BufferFramesConvert *this; + GstBuffer *buf_in, *buf_out; + gfloat *data_in; + gfloat *data_out; + gint i, samples_in, samples_in_remaining, samples_out_remaining, + out_buffer_samples; + + this = (BufferFramesConvert *) GST_OBJECT_PARENT (pad); + + if (this->passthrough) { + gst_pad_push (this->srcpad, _data); + return; + } + + buf_in = (GstBuffer *) _data; + data_in = (gfloat *) GST_BUFFER_DATA (buf_in); + samples_in = samples_in_remaining = + GST_BUFFER_SIZE (buf_in) / sizeof (gfloat); + out_buffer_samples = this->out_buffer_samples; + + /* deal with any leftover buffer */ + if (this->buf_out) { + samples_out_remaining = this->samples_out_remaining; + buf_out = this->buf_out; + data_out = (gfloat *) GST_BUFFER_DATA (buf_out); + data_out += out_buffer_samples - samples_out_remaining; + + i = MIN (samples_out_remaining, samples_in_remaining); + samples_in_remaining -= i; + samples_out_remaining -= i; + while (i--) + *(data_out++) = *(data_in++); + + if (!samples_out_remaining) { + this->buf_out = NULL; + this->samples_out_remaining = 0; + gst_pad_push (this->srcpad, (GstData *) buf_out); + } else { + /* we used up the incoming samples, but didn't fill our buffer */ + this->samples_out_remaining = samples_out_remaining; + gst_buffer_unref (buf_in); + return; + } + } + + /* use a fast subbuffer while we can */ + while (samples_in_remaining > out_buffer_samples) { + buf_out = gst_buffer_create_sub (buf_in, + (samples_in - samples_in_remaining) * sizeof (gfloat), + out_buffer_samples * sizeof (gfloat)); + data_in += out_buffer_samples; + samples_in_remaining -= out_buffer_samples; + gst_pad_push (this->srcpad, (GstData *) buf_out); + } + + /* if there's an event coming next, just push what we have */ + if (this->in_buffer_samples && samples_in != this->in_buffer_samples + && samples_in_remaining) { + buf_out = + gst_buffer_create_sub (buf_in, + (samples_in - samples_in_remaining) * sizeof (gfloat), + samples_in_remaining * sizeof (gfloat)); + gst_pad_push (this->srcpad, (GstData *) buf_out); + } else { + /* otherwise make a leftover buffer if it's necessary */ + if (samples_in_remaining) { + buf_out = + gst_pad_alloc_buffer (this->srcpad, 0, + out_buffer_samples * sizeof (gfloat)); + data_out = (gfloat *) GST_BUFFER_DATA (buf_out); + this->buf_out = buf_out; + this->samples_out_remaining = out_buffer_samples - samples_in_remaining; + while (samples_in_remaining--) + *(data_out++) = *(data_in++); + } + } + + gst_buffer_unref (buf_in); +} diff --git a/gst/audioconvert/gstaudioconvert.c b/gst/audioconvert/gstaudioconvert.c index f15c34acb..d1c9a30e5 100644 --- a/gst/audioconvert/gstaudioconvert.c +++ b/gst/audioconvert/gstaudioconvert.c @@ -38,6 +38,7 @@ #include #include +#include "plugin.h" GST_DEBUG_CATEGORY_STATIC (audio_convert_debug); #define GST_CAT_DEFAULT (audio_convert_debug) @@ -100,7 +101,6 @@ static GstElementDetails audio_convert_details = { }; /* type functions */ -static GType gst_audio_convert_get_type (void); static void gst_audio_convert_base_init (gpointer g_class); static void gst_audio_convert_class_init (GstAudioConvertClass * klass); static void gst_audio_convert_init (GstAudioConvert * audio_convert); @@ -421,7 +421,6 @@ gst_audio_convert_link (GstPad * pad, const GstCaps * caps) } GST_DEBUG_OBJECT (this, "negotiated pad to %" GST_PTR_FORMAT, caps); - GST_DEBUG_OBJECT (this, "negotiated otherpad to %" GST_PTR_FORMAT, othercaps); return GST_PAD_LINK_OK; } @@ -635,7 +634,6 @@ gst_audio_convert_buffer_to_default_format (GstAudioConvert * this, in = (gfloat *) GST_BUFFER_DATA (buf); out = (gint32 *) GST_BUFFER_DATA (ret); - /* increment `in' via the for, cause CLAMP duplicates the first arg */ for (i = buf->size / sizeof (float); i > 0; i--) { *in *= 2147483647.0f + .5; *out = (gint32) CLAMP ((gint64) * in, -2147483648ll, 2147483647ll); @@ -781,21 +779,3 @@ gst_audio_convert_channels (GstAudioConvert * this, GstBuffer * buf) gst_buffer_unref (buf); return ret; } - -/*** PLUGIN DETAILS ***********************************************************/ - -static gboolean -plugin_init (GstPlugin * plugin) -{ - if (!gst_element_register (plugin, "audioconvert", GST_RANK_PRIMARY, - GST_TYPE_AUDIO_CONVERT)) - return FALSE; - - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "gstaudioconvert", - "Convert audio to different formats", - plugin_init, VERSION, "LGPL", GST_PACKAGE, GST_ORIGIN) diff --git a/gst/audioconvert/plugin.c b/gst/audioconvert/plugin.c new file mode 100644 index 000000000..aeb1b9686 --- /dev/null +++ b/gst/audioconvert/plugin.c @@ -0,0 +1,44 @@ +/* GStreamer audio conversion plugin + * Copyright (C) 2004 Andy Wingo + * + * plugin.c: the stubs for the audioconvert plugin + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "plugin.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_element_register (plugin, "audioconvert", + GST_RANK_PRIMARY, gst_audio_convert_get_type ()) || + !gst_element_register (plugin, "buffer-frames-convert", + GST_RANK_NONE, gstplugin_buffer_frames_convert_get_type ())) + return FALSE; + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "gstaudioconvert", + "Convert audio to different formats", + plugin_init, VERSION, "LGPL", GST_PACKAGE, GST_ORIGIN) diff --git a/gst/audioconvert/plugin.h b/gst/audioconvert/plugin.h new file mode 100644 index 000000000..5ef836835 --- /dev/null +++ b/gst/audioconvert/plugin.h @@ -0,0 +1,36 @@ +/* GStreamer buffer-frames conversion plugin + * Copyright (C) 2004 Andy Wingo + * + * plugin.h: the stubs for the buffer-frames-convert plugin + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_PLUGIN_BUFFERFRAMESCONVERT_H__ +#define __GST_PLUGIN_BUFFERFRAMESCONVERT_H__ + + +#include + +G_BEGIN_DECLS + +GType gst_audio_convert_get_type (void); +GType gstplugin_buffer_frames_convert_get_type (void); + +G_END_DECLS + +#endif /* __GST_PLUGIN_BUFFERFRAMESCONVERT_H__ */