diff options
author | Edward Hervey <bilboed@bilboed.com> | 2007-11-15 10:09:21 +0000 |
---|---|---|
committer | Edward Hervey <bilboed@bilboed.com> | 2007-11-15 10:09:21 +0000 |
commit | 74caaae3793a83b35ff82d7b8157cc2f949d04fc (patch) | |
tree | ba37545bb8f3d56b8bba2182a9246973e75c103b | |
parent | a892f18f58ede22341be5b117e564cdfeae9d7df (diff) |
ext/ffmpeg/: Added new ffaudioresample element using the ffmpeg resampling code.
Original commit message from CVS:
* ext/ffmpeg/Makefile.am:
* ext/ffmpeg/gstffmpeg.c: (plugin_init):
* ext/ffmpeg/gstffmpeg.h:
* ext/ffmpeg/gstffmpegaudioresample.c:
(gst_ffmpegaudioresample_base_init),
(gst_ffmpegaudioresample_class_init),
(gst_ffmpegaudioresample_init), (gst_ffmpegaudioresample_finalize),
(gst_ffmpegaudioresample_transform_caps),
(gst_ffmpegaudioresample_transform_size),
(gst_ffmpegaudioresample_get_unit_size),
(gst_ffmpegaudioresample_set_caps),
(gst_ffmpegaudioresample_transform),
(gst_ffmpegaudioresample_register):
Added new ffaudioresample element using the ffmpeg resampling code.
It's (way) faster than audioresample, doesn't introduce latency, but
might cause a little bit of 'clicking'.
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | ext/ffmpeg/Makefile.am | 3 | ||||
-rw-r--r-- | ext/ffmpeg/gstffmpeg.c | 1 | ||||
-rw-r--r-- | ext/ffmpeg/gstffmpeg.h | 3 | ||||
-rw-r--r-- | ext/ffmpeg/gstffmpegaudioresample.c | 293 |
5 files changed, 318 insertions, 1 deletions
@@ -1,5 +1,24 @@ 2007-11-15 Edward Hervey <bilboed@bilboed.com> + * ext/ffmpeg/Makefile.am: + * ext/ffmpeg/gstffmpeg.c: (plugin_init): + * ext/ffmpeg/gstffmpeg.h: + * ext/ffmpeg/gstffmpegaudioresample.c: + (gst_ffmpegaudioresample_base_init), + (gst_ffmpegaudioresample_class_init), + (gst_ffmpegaudioresample_init), (gst_ffmpegaudioresample_finalize), + (gst_ffmpegaudioresample_transform_caps), + (gst_ffmpegaudioresample_transform_size), + (gst_ffmpegaudioresample_get_unit_size), + (gst_ffmpegaudioresample_set_caps), + (gst_ffmpegaudioresample_transform), + (gst_ffmpegaudioresample_register): + Added new ffaudioresample element using the ffmpeg resampling code. + It's (way) faster than audioresample, doesn't introduce latency, but + might cause a little bit of 'clicking'. + +2007-11-15 Edward Hervey <bilboed@bilboed.com> + * Makefile.am: * autogen.sh: * configure.ac: diff --git a/ext/ffmpeg/Makefile.am b/ext/ffmpeg/Makefile.am index fc3f475..5ee00cf 100644 --- a/ext/ffmpeg/Makefile.am +++ b/ext/ffmpeg/Makefile.am @@ -8,7 +8,8 @@ libgstffmpeg_la_SOURCES = gstffmpeg.c \ gstffmpegcfg.c \ gstffmpegdemux.c \ gstffmpegmux.c \ - gstffmpegdeinterlace.c + gstffmpegdeinterlace.c \ + gstffmpegaudioresample.c # \ # gstffmpegscale.c diff --git a/ext/ffmpeg/gstffmpeg.c b/ext/ffmpeg/gstffmpeg.c index 3d695c4..691af07 100644 --- a/ext/ffmpeg/gstffmpeg.c +++ b/ext/ffmpeg/gstffmpeg.c @@ -149,6 +149,7 @@ plugin_init (GstPlugin * plugin) #if 0 gst_ffmpegcsp_register (plugin); #endif + gst_ffmpegaudioresample_register (plugin); register_protocol (&gstreamer_protocol); diff --git a/ext/ffmpeg/gstffmpeg.h b/ext/ffmpeg/gstffmpeg.h index e0f1c90..459e692 100644 --- a/ext/ffmpeg/gstffmpeg.h +++ b/ext/ffmpeg/gstffmpeg.h @@ -48,7 +48,10 @@ extern gboolean gst_ffmpegdec_register (GstPlugin * plugin); extern gboolean gst_ffmpegenc_register (GstPlugin * plugin); extern gboolean gst_ffmpegmux_register (GstPlugin * plugin); extern gboolean gst_ffmpegcsp_register (GstPlugin * plugin); +#if 0 extern gboolean gst_ffmpegscale_register (GstPlugin * plugin); +#endif +extern gboolean gst_ffmpegaudioresample_register (GstPlugin * plugin); extern gboolean gst_ffmpegdeinterlace_register (GstPlugin * plugin); int gst_ffmpeg_avcodec_open (AVCodecContext *avctx, AVCodec *codec); diff --git a/ext/ffmpeg/gstffmpegaudioresample.c b/ext/ffmpeg/gstffmpegaudioresample.c new file mode 100644 index 0000000..0e8be5c --- /dev/null +++ b/ext/ffmpeg/gstffmpegaudioresample.c @@ -0,0 +1,293 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> + * This file: + * Copyright (C) 2005 Luca Ognibene <luogni@tin.it> + * Copyright (C) 2006 Martin Zlomek <martin.zlomek@itonis.tv> + * + * 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 + +#ifdef HAVE_FFMPEG_UNINSTALLED +#include <avcodec.h> +#else +#include <ffmpeg/avcodec.h> +#endif + +#include <gst/gst.h> +#include <gst/base/gstbasetransform.h> +#include <gst/video/video.h> + +#include "gstffmpeg.h" +#include "gstffmpegcodecmap.h" + +typedef struct _GstFFMpegAudioResample +{ + GstBaseTransform element; + + GstPad *sinkpad, *srcpad; + + gint in_rate, out_rate; + gint in_channels, out_channels; + + ReSampleContext *res; +} GstFFMpegAudioResample; + +typedef struct _GstFFMpegAudioResampleClass +{ + GstBaseTransformClass parent_class; +} GstFFMpegAudioResampleClass; + +#define GST_TYPE_FFMPEGAUDIORESAMPLE \ + (gst_ffmpegaudioresample_get_type()) +#define GST_FFMPEGAUDIORESAMPLE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFMPEGAUDIORESAMPLE,GstFFMpegAudioResample)) +#define GST_FFMPEGAUDIORESAMPLE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFMPEGAUDIORESAMPLE,GstFFMpegAudioResampleClass)) +#define GST_IS_FFMPEGAUDIORESAMPLE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FFMPEGAUDIORESAMPLE)) +#define GST_IS_FFMPEGAUDIORESAMPLE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FFMPEGAUDIORESAMPLE)) + +static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-int, endianness = (int) BYTE_ORDER, signed = (boolean) true, width = (int) 16, depth = (int) 16, channels = (int) { 1 , 2 }, rate = (int) [1, MAX ]") + ); + +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-int, endianness = (int) BYTE_ORDER, signed = (boolean) true, width = (int) 16, depth = (int) 16, channels = (int) [ 1 , 6 ], rate = (int) [1, MAX ]") + ); + +GST_BOILERPLATE (GstFFMpegAudioResample, gst_ffmpegaudioresample, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM); + +static void gst_ffmpegaudioresample_finalize (GObject * object); + +static GstCaps *gst_ffmpegaudioresample_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps); +static gboolean gst_ffmpegaudioresample_transform_size (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, guint size, GstCaps *othercaps, + guint * othersize); +static gboolean gst_ffmpegaudioresample_get_unit_size (GstBaseTransform * trans, + GstCaps * caps, guint * size); +static gboolean gst_ffmpegaudioresample_set_caps (GstBaseTransform * trans, + GstCaps * incaps, GstCaps * outcaps); +static GstFlowReturn gst_ffmpegaudioresample_transform (GstBaseTransform * trans, + GstBuffer * inbuf, GstBuffer * outbuf); + +static void +gst_ffmpegaudioresample_base_init (gpointer g_class) +{ + static GstElementDetails plugin_details = { + "FFMPEG Audio resampling element", + "Filter/Converter/Audio", + "Converts audio from one samplerate to another", + "Edward Hervey <bilboed@bilboed.com>", + }; + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory)); + gst_element_class_set_details (element_class, &plugin_details); +} + +static void +gst_ffmpegaudioresample_class_init (GstFFMpegAudioResampleClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstBaseTransformClass *trans_class = GST_BASE_TRANSFORM_CLASS (klass); + + gobject_class->finalize = gst_ffmpegaudioresample_finalize; + + trans_class->transform_caps = + GST_DEBUG_FUNCPTR (gst_ffmpegaudioresample_transform_caps); + trans_class->get_unit_size = + GST_DEBUG_FUNCPTR (gst_ffmpegaudioresample_get_unit_size); + trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_ffmpegaudioresample_set_caps); + trans_class->transform = GST_DEBUG_FUNCPTR (gst_ffmpegaudioresample_transform); + trans_class->transform_size = GST_DEBUG_FUNCPTR (gst_ffmpegaudioresample_transform_size); + + trans_class->passthrough_on_same_caps = TRUE; +} + +static void +gst_ffmpegaudioresample_init (GstFFMpegAudioResample * resample, GstFFMpegAudioResampleClass * klass) +{ + GstBaseTransform *trans = GST_BASE_TRANSFORM (resample); + + gst_pad_set_bufferalloc_function (trans->sinkpad, NULL); + + resample->res = NULL; +} + +static void +gst_ffmpegaudioresample_finalize (GObject * object) +{ + GstFFMpegAudioResample *resample = GST_FFMPEGAUDIORESAMPLE (object); + + if (resample->res != NULL) + audio_resample_close (resample->res); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static GstCaps * +gst_ffmpegaudioresample_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps) +{ + GstCaps *retcaps; + GstStructure * struc; + + retcaps = gst_caps_copy (caps); + struc = gst_caps_get_structure (retcaps, 0); + gst_structure_set (struc, "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + + GST_LOG_OBJECT (trans, "returning caps %" GST_PTR_FORMAT, + retcaps); + + return retcaps; +} + +static gboolean gst_ffmpegaudioresample_transform_size (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, guint size, GstCaps *othercaps, + guint * othersize) +{ + gint inrate, outrate; + gint inchanns, outchanns; + GstStructure *ins, *outs; + gboolean ret; + guint64 conv; + + ins = gst_caps_get_structure (caps, 0); + outs = gst_caps_get_structure (othercaps, 0); + + /* Get input/output sample rate and channels */ + ret = gst_structure_get_int (ins, "rate", &inrate); + ret &= gst_structure_get_int (ins, "channels", &inchanns); + ret &= gst_structure_get_int (outs, "rate", &outrate); + ret &= gst_structure_get_int (outs, "channels", &outchanns); + + if (!ret) + return FALSE; + + conv = gst_util_uint64_scale(size, outrate * outchanns, + inrate * inchanns); + *othersize = (guint) conv; + + GST_DEBUG_OBJECT (trans, "Transformed size from %d to %d", + size, *othersize); + + return TRUE; +} + +static gboolean +gst_ffmpegaudioresample_get_unit_size (GstBaseTransform * trans, GstCaps * caps, + guint * size) +{ + gint channels; + GstStructure * structure; + gboolean ret; + + g_assert (size); + + structure = gst_caps_get_structure (caps, 0); + ret = gst_structure_get_int (structure, "channels", &channels); + g_return_val_if_fail (ret, FALSE); + + *size = 2 * channels; + + return TRUE; +} + +static gboolean +gst_ffmpegaudioresample_set_caps (GstBaseTransform * trans, GstCaps * incaps, + GstCaps * outcaps) +{ + GstFFMpegAudioResample *resample = GST_FFMPEGAUDIORESAMPLE (trans); + GstStructure *instructure = gst_caps_get_structure (incaps, 0); + GstStructure *outstructure = gst_caps_get_structure (outcaps, 0); + + GST_LOG_OBJECT (resample, "incaps:%"GST_PTR_FORMAT, + incaps); + + GST_LOG_OBJECT (resample, "outcaps:%"GST_PTR_FORMAT, + outcaps); + + if (!gst_structure_get_int (instructure, "channels", &resample->in_channels)) + return FALSE; + if (!gst_structure_get_int (instructure, "rate", &resample->in_rate)) + return FALSE; + + if (!gst_structure_get_int (outstructure, "channels", &resample->out_channels)) + return FALSE; + if (!gst_structure_get_int (outstructure, "rate", &resample->out_rate)) + return FALSE; + + resample->res = audio_resample_init (resample->out_channels, resample->in_channels, + resample->out_rate, resample->in_rate); + if (resample->res == NULL) + return FALSE; + + return TRUE; +} + +static GstFlowReturn +gst_ffmpegaudioresample_transform (GstBaseTransform * trans, GstBuffer * inbuf, + GstBuffer * outbuf) +{ + GstFFMpegAudioResample *resample = GST_FFMPEGAUDIORESAMPLE (trans); + gint nbsamples; + gint ret; + + gst_buffer_copy_metadata (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS); + nbsamples = GST_BUFFER_SIZE (inbuf) / (2 * resample->in_channels); + + GST_LOG_OBJECT (resample, "input buffer duration:%"GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf))); + + GST_DEBUG_OBJECT (resample, "audio_resample(ctx, output:%p [size:%d], input:%p [size:%d], nbsamples:%d", + GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf), + GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf), + nbsamples); + + ret = audio_resample (resample->res, (short *) GST_BUFFER_DATA(outbuf), + (short *) GST_BUFFER_DATA (inbuf), nbsamples); + + GST_DEBUG_OBJECT (resample, "audio_resample returned %d", ret); + + GST_BUFFER_DURATION(outbuf) = gst_util_uint64_scale (ret, GST_SECOND, + resample->out_rate); + + GST_LOG_OBJECT (resample, "Output buffer duration:%"GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf))); + + return GST_FLOW_OK; +} + +gboolean +gst_ffmpegaudioresample_register (GstPlugin * plugin) +{ + return gst_element_register (plugin, "ffaudioresample", + GST_RANK_NONE, GST_TYPE_FFMPEGAUDIORESAMPLE); +} |