[vlc-devel] [PATCH] audio_filter: introduce libavresample based filter
Luca Barbato
lu_zero at gentoo.org
Tue Jun 5 14:36:34 CEST 2012
It supports mid-stream frame, channel map and format changes.
---
configure.ac | 26 +++
modules/LIST | 1 +
modules/audio_filter/Modules.am | 1 +
modules/audio_filter/resampler/avresample.c | 237 +++++++++++++++++++++++++++
4 files changed, 265 insertions(+), 0 deletions(-)
create mode 100644 modules/audio_filter/resampler/avresample.c
diff --git a/configure.ac b/configure.ac
index 15cdc6c..b373ec3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2479,6 +2479,32 @@ then
fi
dnl
+dnl avresample sound resampling and conversion plugin
+dnl
+
+AC_ARG_ENABLE(avresample,
+ AS_HELP_STRING([--enable-avresample],[libavresample sound resampling and conversion plugin (default auto)]))
+if test "${enable_avresample}" != "no"
+then
+ PKG_CHECK_MODULES(SWRESAMPLE,[libavresample libavutil],
+ [
+ VLC_SAVE_FLAGS
+ CPPFLAGS="${CPPFLAGS} ${SWRESAMPLE_CFLAGS}"
+ CFLAGS="${CFLAGS} ${SWRESAMPLE_CFLAGS}"
+ AC_CHECK_HEADERS([libavresample/avresample.h libavutil/audioconvert.h])
+ VLC_ADD_PLUGIN([avresample])
+ VLC_ADD_LIBS([avresample],[$SWRESAMPLE_LIBS])
+ VLC_ADD_CFLAGS([avresample],[$SWRESAMPLE_CFLAGS])
+ AS_IF([test "${ac_cv_ld_bsymbolic}" != "no"], [
+ VLC_ADD_LIBS([avresample],[-Wl,-Bsymbolic])
+ ])
+ VLC_RESTORE_FLAGS
+ ],[
+ AC_MSG_WARN([${SWRESAMPLE_PKG_ERRORS}. avresample not found.])
+ ])
+fi
+
+dnl
dnl postproc plugin
dnl
diff --git a/modules/LIST b/modules/LIST
index 85f93a4..9bec6bc 100644
--- a/modules/LIST
+++ b/modules/LIST
@@ -61,6 +61,7 @@ $Id$
* avcodec: libavcodec audio/video decoder
* avformat: libavformat demuxer
* avi: AVI file stream demuxer
+ * avresample_resampler: libavresample resampler
* ball: Augmented reality ball video filter module
* bandlimited_resampler: Bandlimited interpolation audio resampler
* blend: a picture filter that blends two pictures
diff --git a/modules/audio_filter/Modules.am b/modules/audio_filter/Modules.am
index 913c228..2696564 100644
--- a/modules/audio_filter/Modules.am
+++ b/modules/audio_filter/Modules.am
@@ -65,6 +65,7 @@ SOURCES_bandlimited_resampler = \
resampler/bandlimited.c resampler/bandlimited.h
SOURCES_ugly_resampler = resampler/ugly.c
SOURCES_samplerate = resampler/src.c
+SOURCES_avresample = resampler/avresample.c
libvlc_LTLIBRARIES += \
libugly_resampler_plugin.la
diff --git a/modules/audio_filter/resampler/avresample.c b/modules/audio_filter/resampler/avresample.c
new file mode 100644
index 0000000..6bcd153
--- /dev/null
+++ b/modules/audio_filter/resampler/avresample.c
@@ -0,0 +1,237 @@
+/*****************************************************************************
+ * avresample.c : libavresample audio resampler
+ *****************************************************************************
+ * Copyright © 2012 Luca Barbato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_aout.h>
+#include <vlc_filter.h>
+
+#include <libavutil/opt.h>
+#include <libavutil/error.h>
+#include <libavutil/samplefmt.h>
+#include <libavutil/mathematics.h>
+#include <libavutil/audioconvert.h>
+#include <libavresample/avresample.h>
+
+static int Open (vlc_object_t *);
+static void Close (vlc_object_t *);
+
+/*
+ * Keep track of input parameters, they could change midstream
+ */
+
+struct avr_sys_t
+{
+ int16_t in_channel_map;
+ unsigned int in_sample_rate;
+ vlc_fourcc_t in_sample_format;
+
+ AVAudioResampleContext *avr;
+};
+
+vlc_module_begin ()
+ set_description (N_("avresample resampler"))
+ set_shortname (N_("avresample resampler"))
+ set_category (CAT_AUDIO)
+ set_subcategory (SUBCAT_AUDIO_MISC)
+ set_capability ("audio filter", 10)
+ set_callbacks (Open, Close)
+ add_submodule ()
+ set_capability ("audio resampler", 10)
+ set_callbacks (Open, Close)
+vlc_module_end ()
+
+static block_t *Resample (filter_t *, block_t *);
+
+static enum AVSampleFormat GetAvutilAudioFormat (vlc_fourcc_t codec)
+{
+ switch(codec) {
+ case VLC_CODEC_U8 : return AV_SAMPLE_FMT_U8;
+ case VLC_CODEC_S32N: return AV_SAMPLE_FMT_S32;
+ case VLC_CODEC_FL32: return AV_SAMPLE_FMT_FLT;
+ case VLC_CODEC_FL64: return AV_SAMPLE_FMT_DBL;
+ case VLC_CODEC_S16N: return AV_SAMPLE_FMT_S16;
+ }
+ return AV_SAMPLE_FMT_NONE;
+}
+
+static int ConfigureResample(filter_t *f)
+{
+ int ret;
+ struct avr_sys_t *sys = (struct avr_sys_t *)f->p_sys;
+ AVAudioResampleContext *s = sys->avr;
+
+ int64_t out_channel_layout =
+ av_get_default_channel_layout (
+ aout_FormatNbChannels (&f->fmt_out.audio));
+ int64_t in_channel_layout =
+ av_get_default_channel_layout (
+ aout_FormatNbChannels (&f->fmt_in.audio));
+
+ enum AVSampleFormat out_sample_format =
+ GetAvutilAudioFormat (f->fmt_out.audio.i_format);
+
+ enum AVSampleFormat in_sample_format =
+ GetAvutilAudioFormat (f->fmt_in.audio.i_format);
+
+ if (in_sample_format == AV_SAMPLE_FMT_NONE)
+ {
+ msg_Err (f, "unsupported input format");
+ return VLC_EGENERIC;
+ }
+
+ if (out_sample_format == AV_SAMPLE_FMT_NONE)
+ {
+ msg_Err (f, "unsupported output format");
+ return VLC_EGENERIC;
+ }
+
+ av_opt_set_int (s, "in_channel_layout", in_channel_layout, 0);
+ av_opt_set_int (s, "in_sample_fmt", in_sample_format, 0);
+ av_opt_set_int (s, "in_sample_rate", f->fmt_in.audio.i_rate, 0);
+
+ av_opt_set_int (s, "out_channel_layout", out_channel_layout, 0);
+ av_opt_set_int (s, "out_sample_fmt", out_sample_format, 0);
+ av_opt_set_int (s, "out_sample_rate", f->fmt_out.audio.i_rate, 0);
+
+ if (av_get_bytes_per_sample (in_sample_format) <= 2 &&
+ av_get_bytes_per_sample (out_sample_format) <= 2)
+ av_opt_set_int (s, "internal_sample_fmt", AV_SAMPLE_FMT_S16P, 0);
+
+ if ((ret = avresample_open (s)))
+ {
+ char errbuf[128];
+ av_strerror (ret, errbuf, sizeof(errbuf));
+ msg_Err (f, "cannot initialise resampler: %s", errbuf);
+ return VLC_EGENERIC;
+ }
+
+ sys->in_sample_format = f->fmt_in.audio.i_format;
+ sys->in_sample_rate = f->fmt_in.audio.i_rate;
+ sys->in_channel_map = f->fmt_in.audio.i_physical_channels;
+
+ return VLC_SUCCESS;
+}
+
+static void Close (vlc_object_t *obj)
+{
+ filter_t *filter = (filter_t *)obj;
+ struct avr_sys_t *sys = (struct avr_sys_t *) filter->p_sys;
+ AVAudioResampleContext *s = sys->avr;
+
+ avresample_close (s);
+ avresample_free (&s);
+
+ free(sys);
+ filter->p_sys = NULL;
+}
+
+static int Open (vlc_object_t *obj)
+{
+ int ret;
+ filter_t *f = (filter_t *)obj;
+ struct avr_sys_t *s = f->p_sys = malloc (sizeof (struct avr_sys_t));
+
+ if (unlikely(s == NULL))
+ {
+ msg_Err (obj, "cannot create resampler context");
+ return VLC_EGENERIC;
+ }
+
+ s->avr = avresample_alloc_context();
+
+ if (unlikely (s->avr == NULL))
+ {
+ msg_Err (obj, "cannot create resampler context");
+ free (s);
+ return VLC_EGENERIC;
+ }
+
+ ret = ConfigureResample(f);
+
+ if (unlikely (ret != VLC_SUCCESS))
+ {
+ Close(obj);
+ return VLC_EGENERIC;
+ }
+
+ f->pf_audio_filter = Resample;
+ return VLC_SUCCESS;
+}
+
+static block_t *Resample (filter_t *f, block_t *in)
+{
+ int ret;
+ block_t *out = NULL;
+ struct avr_sys_t *sys = (struct avr_sys_t *) f->p_sys;
+ AVAudioResampleContext *s = sys->avr;
+ int out_size, out_linesize;
+ const size_t framesize = f->fmt_out.audio.i_bytes_per_frame;
+ int nb_samples = in->i_nb_samples;
+
+ if (unlikely (
+ sys->in_sample_rate != f->fmt_in.audio.i_rate ||
+ sys->in_sample_format != f->fmt_in.audio.i_format ||
+ sys->in_channel_map != f->fmt_in.audio.i_physical_channels))
+ {
+ avresample_close (s);
+
+ ret = ConfigureResample (f);
+
+ if (unlikely (ret != VLC_SUCCESS))
+ goto error;
+ }
+
+ out_size = av_samples_get_buffer_size (&out_linesize,
+ f->fmt_out.audio.i_physical_channels,
+ nb_samples,
+ GetAvutilAudioFormat (f->fmt_out.audio.i_format), 0);
+
+ out = block_Alloc (out_size);
+
+ if (unlikely(out == NULL))
+ goto error;
+
+ ret = avresample_convert (s, (void **)&out->p_buffer, out_linesize, nb_samples,
+ (void **)&in->p_buffer, in->i_buffer, in->i_nb_samples);
+
+ if (ret < 0)
+ {
+ char errbuf[128];
+ av_strerror (ret, errbuf, sizeof(errbuf));
+ msg_Err (f, "cannot resample: %s", errbuf);
+ block_Release (out);
+ out = NULL;
+ goto error;
+ }
+
+ out->i_nb_samples = ret;
+ out->i_buffer = ret * framesize;
+ out->i_pts = in->i_pts;
+ out->i_length = ret * CLOCK_FREQ / f->fmt_out.audio.i_rate;
+
+error:
+ block_Release (in);
+ return out;
+}
--
1.7.8.rc1
More information about the vlc-devel
mailing list