summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Hervey <bilboed@bilboed.com>2007-11-15 10:09:21 +0000
committerEdward Hervey <bilboed@bilboed.com>2007-11-15 10:09:21 +0000
commit74caaae3793a83b35ff82d7b8157cc2f949d04fc (patch)
treeba37545bb8f3d56b8bba2182a9246973e75c103b
parenta892f18f58ede22341be5b117e564cdfeae9d7df (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--ChangeLog19
-rw-r--r--ext/ffmpeg/Makefile.am3
-rw-r--r--ext/ffmpeg/gstffmpeg.c1
-rw-r--r--ext/ffmpeg/gstffmpeg.h3
-rw-r--r--ext/ffmpeg/gstffmpegaudioresample.c293
5 files changed, 318 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 585b285..8eb3705 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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);
+}