[pulseaudio-discuss] [PATCH 3/3] resampler: Add optional libavresample resampler

Peter Meerwald pmeerw at pmeerw.net
Mon Aug 4 05:40:14 PDT 2014


see https://libav.org/doxygen/master/group__lavr.html

Signed-off-by: Peter Meerwald <pmeerw at pmeerw.net>
Signed-off-by: poljar (Damir Jelić) <poljarinho at gmail.com>
---
 configure.ac                   |  17 +++++
 src/Makefile.am                |   6 ++
 src/pulsecore/resampler.c      |  14 +++-
 src/pulsecore/resampler.h      |   2 +
 src/pulsecore/resampler/lavr.c | 160 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 198 insertions(+), 1 deletion(-)
 create mode 100644 src/pulsecore/resampler/lavr.c

diff --git a/configure.ac b/configure.ac
index cf63eca..578508b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1124,6 +1124,21 @@ AS_IF([test "x$enable_soxr" = "xyes" && test "x$HAVE_SOXR" = "x0"],
 AM_CONDITIONAL([HAVE_SOXR], [test "x$HAVE_SOXR" = x1])
 AS_IF([test "x$HAVE_SOXR" = "x1"], AC_DEFINE([HAVE_SOXR], 1, [Have soxr]))
 
+#### libavresample support (optional) ####
+
+AC_ARG_ENABLE([libavresample],
+   AS_HELP_STRING([--disable-libavresample],[Disable optional libavresample support]))
+
+AS_IF([test "x$enable_libavresample" != "xno"],
+    [PKG_CHECK_MODULES(LIBAVRESAMPLE, libavresample, HAVE_LIBAVRESAMPLE=1, HAVE_LIBAVRESAMPLE=0)],
+    HAVE_LIBAVRESAMPLE=0)
+
+AS_IF([test "x$enable_libavresample" = "xyes" && test "x$HAVE_LIBAVRESAMPLE" = "x0"],
+    [AC_MSG_ERROR([*** libavresample not found])])
+
+AM_CONDITIONAL([HAVE_LIBAVRESAMPLE], [test "x$HAVE_LIBAVRESAMPLE" = x1])
+AS_IF([test "x$HAVE_LIBAVRESAMPLE" = "x1"], AC_DEFINE([HAVE_LIBAVRESAMPLE], 1, [Have libavresample]))
+
 #### Xen support (optional) ####
 
 AC_ARG_ENABLE([xen],
@@ -1461,6 +1476,7 @@ AS_IF([test "x$HAVE_ORC" = "xyes"], ENABLE_ORC=yes, ENABLE_ORC=no)
 AS_IF([test "x$HAVE_ADRIAN_EC" = "x1"], ENABLE_ADRIAN_EC=yes, ENABLE_ADRIAN_EC=no)
 AS_IF([test "x$HAVE_SPEEX" = "x1"], ENABLE_SPEEX=yes, ENABLE_SPEEX=no)
 AS_IF([test "x$HAVE_SOXR" = "x1"], ENABLE_SOXR=yes, ENABLE_SOXR=no)
+AS_IF([test "x$HAVE_LIBAVRESAMPLE" = "x1"], ENABLE_LIBAVRESAMPLE=yes, ENABLE_LIBAVRESAMPLE=no)
 AS_IF([test "x$HAVE_WEBRTC" = "x1"], ENABLE_WEBRTC=yes, ENABLE_WEBRTC=no)
 AS_IF([test "x$HAVE_TDB" = "x1"], ENABLE_TDB=yes, ENABLE_TDB=no)
 AS_IF([test "x$HAVE_GDBM" = "x1"], ENABLE_GDBM=yes, ENABLE_GDBM=no)
@@ -1518,6 +1534,7 @@ echo "
     Enable Adrian echo canceller:  ${ENABLE_ADRIAN_EC}
     Enable speex (resampler, AEC): ${ENABLE_SPEEX}
     Enable soxr:                   ${ENABLE_SOXR}
+    Enable libavresample:          ${ENABLE_LIBAVRESAMPLE}
     Enable WebRTC echo canceller:  ${ENABLE_WEBRTC}
     Enable gcov coverage:          ${ENABLE_GCOV}
     Enable unit tests:             ${ENABLE_TESTS}
diff --git a/src/Makefile.am b/src/Makefile.am
index 9df52df..e333e8a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -998,6 +998,12 @@ libpulsecore_ at PA_MAJORMINOR@_la_CFLAGS += $(SOXR_CFLAGS)
 libpulsecore_ at PA_MAJORMINOR@_la_LIBADD += $(SOXR_LIBS)
 endif
 
+if HAVE_LIBAVRESAMPLE
+libpulsecore_ at PA_MAJORMINOR@_la_SOURCES += pulsecore/resampler/lavr.c
+libpulsecore_ at PA_MAJORMINOR@_la_CFLAGS += $(LIBAVRESAMPLE_CFLAGS)
+libpulsecore_ at PA_MAJORMINOR@_la_LIBADD += $(LIBAVRESAMPLE_LIBS)
+endif
+
 # We split the foreign code off to not be annoyed by warnings we don't care about
 noinst_LTLIBRARIES += libpulsecore-foreign.la
 
diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index e366be6..f477613 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -122,6 +122,11 @@ static int (* const init_table[])(pa_resampler *r) = {
 #else
     [PA_RESAMPLER_SOXR]                    = NULL,
 #endif
+#ifdef HAVE_LIBAVRESAMPLE
+    [PA_RESAMPLER_LAVR]                    = pa_resampler_lavr_init,
+#else
+    [PA_RESAMPLER_LAVR]                    = NULL,
+#endif
 };
 
 static bool speex_is_fixed_point(void);
@@ -169,6 +174,7 @@ static pa_resample_method_t fix_method(
             }
                                      /* Else fall through */
         case PA_RESAMPLER_SOXR:
+        case PA_RESAMPLER_LAVR:
         case PA_RESAMPLER_FFMPEG:
             if (flags & PA_RESAMPLER_VARIABLE_RATE) {
                 pa_log_info("Resampler '%s' cannot do variable rate, reverting to resampler 'auto'.", pa_resample_method_to_string(method));
@@ -613,7 +619,8 @@ static const char * const resample_methods[] = {
     "auto",
     "copy",
     "peaks",
-    "soxr"
+    "soxr",
+    "lavr"
 };
 
 const char *pa_resample_method_to_string(pa_resample_method_t m) {
@@ -646,6 +653,11 @@ int pa_resample_method_supported(pa_resample_method_t m) {
         return 0;
 #endif
 
+#ifndef HAVE_LIBAVRESAMPLE
+    if (m == PA_RESAMPLER_LAVR)
+        return 0;
+#endif
+
     return 1;
 }
 
diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h
index 1d248e2..19e8743 100644
--- a/src/pulsecore/resampler.h
+++ b/src/pulsecore/resampler.h
@@ -62,6 +62,7 @@ typedef enum pa_resample_method {
     PA_RESAMPLER_COPY,
     PA_RESAMPLER_PEAKS,
     PA_RESAMPLER_SOXR,
+    PA_RESAMPLER_LAVR,
     PA_RESAMPLER_MAX
 } pa_resample_method_t;
 
@@ -162,6 +163,7 @@ const pa_sample_spec* pa_resampler_output_sample_spec(pa_resampler *r);
 
 /* Implementation specific init functions */
 int pa_resampler_ffmpeg_init(pa_resampler *r);
+int pa_resampler_lavr_init(pa_resampler *r);
 int pa_resampler_libsamplerate_init(pa_resampler *r);
 int pa_resampler_peaks_init(pa_resampler *r);
 int pa_resampler_speex_init(pa_resampler *r);
diff --git a/src/pulsecore/resampler/lavr.c b/src/pulsecore/resampler/lavr.c
new file mode 100644
index 0000000..7236ca3
--- /dev/null
+++ b/src/pulsecore/resampler/lavr.c
@@ -0,0 +1,160 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2013 Damir Jelić
+
+  PulseAudio 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.
+
+  PulseAudio 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
+  General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with PulseAudio; 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 <libavresample/avresample.h>
+#include <libavutil/opt.h>
+#include <libavutil/samplefmt.h>
+
+#include "pulsecore/resampler.h"
+
+static unsigned lavr_resample(pa_resampler *r, const pa_memchunk *input,
+                          unsigned in_n_frames, pa_memchunk *output,
+                          unsigned *out_n_frames) {
+    AVAudioResampleContext *state;
+    uint8_t *out;
+    uint8_t *in;
+    unsigned out_samples;
+
+    pa_assert(r);
+    pa_assert(input);
+    pa_assert(output);
+    pa_assert(out_n_frames);
+
+    state = r->impl.data;
+
+    out_samples = *out_n_frames;
+    in = pa_memblock_acquire_chunk(input);
+    out = pa_memblock_acquire_chunk(output);
+
+    out_samples = avresample_convert(state, &out, 0, out_samples, &in, 0, in_n_frames);
+
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(output->memblock);
+
+    *out_n_frames = out_samples;
+
+    return 0;
+}
+
+static void lavr_udpate_rates(pa_resampler *r) {
+    AVAudioResampleContext *state;
+    pa_assert(r);
+
+    state = r->impl.data;
+
+    avresample_close(state);
+
+    av_opt_set_int(state, "in_sample_rate", r->i_ss.rate, 0);
+    av_opt_set_int(state, "out_sample_rate", r->o_ss.rate, 0);
+
+    avresample_open(state);
+}
+
+static void lavr_reset(pa_resampler *r) {
+    AVAudioResampleContext *state;
+    pa_assert(r);
+
+    state = r->impl.data;
+    avresample_close(state);
+    avresample_open(state);
+}
+
+static void lavr_free(pa_resampler *r) {
+    AVAudioResampleContext *state;
+    pa_assert(r);
+
+    state = r->impl.data;
+    avresample_free(&state);
+}
+
+int pa_resampler_lavr_init(pa_resampler *r) {
+    AVAudioResampleContext *state;
+    int channel_map;
+    int format;
+    pa_assert(r);
+
+    if (!(state = avresample_alloc_context()))
+        return -1;
+
+    pa_log_debug("%d", r->o_ss.channels);
+    switch (r->o_ss.channels) {
+        case 1:
+            channel_map = AV_CH_LAYOUT_MONO;
+            break;
+        case 2:
+            channel_map = AV_CH_LAYOUT_STEREO;
+            break;
+        case 3:
+            channel_map = AV_CH_LAYOUT_2POINT1;
+            break;
+        case 4:
+            channel_map = AV_CH_LAYOUT_4POINT0;
+            break;
+        case 5:
+            channel_map = AV_CH_LAYOUT_5POINT0;
+            break;
+        case 6:
+            channel_map = AV_CH_LAYOUT_5POINT1;
+            break;
+        case 7:
+            channel_map = AV_CH_LAYOUT_6POINT1;
+            break;
+        case 8:
+            channel_map = AV_CH_LAYOUT_7POINT1;
+            break;
+        default:
+            pa_assert_not_reached();
+    }
+
+    switch (r->work_format) {
+        case PA_SAMPLE_S16NE:
+            format = AV_SAMPLE_FMT_S16;
+            break;
+
+        case PA_SAMPLE_FLOAT32NE:
+            format = AV_SAMPLE_FMT_FLT;
+            break;
+
+        default:
+            pa_assert_not_reached();
+    }
+    av_opt_set_int(state, "in_channel_layout", channel_map, 0);
+    av_opt_set_int(state, "out_channel_layout", channel_map, 0);
+    av_opt_set_int(state, "in_sample_rate", r->i_ss.rate, 0);
+    av_opt_set_int(state, "out_sample_rate", r->o_ss.rate, 0);
+    av_opt_set_int(state, "in_sample_fmt", format, 0);
+    av_opt_set_int(state, "out_sample_fmt", format, 0);
+
+    if (avresample_open(state) < 0)
+        return -1;
+
+    r->impl.free = lavr_free;
+    r->impl.reset = lavr_reset;
+    r->impl.update_rates = lavr_udpate_rates;
+    r->impl.resample = lavr_resample;
+    r->impl.data = state;
+
+    return 0;
+}
-- 
1.9.1



More information about the pulseaudio-discuss mailing list