[FFmpeg-devel] [PATCH] lavfi: use libswr in af_aresample.

Clément Bœsch ubitux at gmail.com
Sat Jan 21 21:10:39 CET 2012


---
Question: is there any need of flushing? (is the number of output samples exact
enough?)
---
 configure                  |    1 +
 libavfilter/af_aresample.c |  272 ++++----------------------------------------
 2 files changed, 23 insertions(+), 250 deletions(-)

diff --git a/configure b/configure
index 3bace2b..18e617d 100755
--- a/configure
+++ b/configure
@@ -1639,6 +1639,7 @@ udp_protocol_deps="network"
 
 # filters
 amovie_filter_deps="avcodec avformat"
+aresample_filter_deps="swresample"
 ass_filter_deps="libass"
 blackframe_filter_deps="gpl"
 boxblur_filter_deps="gpl"
diff --git a/libavfilter/af_aresample.c b/libavfilter/af_aresample.c
index cd9d80e..0fdc1dd 100644
--- a/libavfilter/af_aresample.c
+++ b/libavfilter/af_aresample.c
@@ -24,20 +24,14 @@
  * resampling audio filter
  */
 
-#include "libavutil/eval.h"
-#include "libavcodec/avcodec.h"
+#include "libswresample/swresample.h"
 #include "avfilter.h"
 #include "internal.h"
 
 typedef struct {
-    struct AVResampleContext *resample;
     int out_rate;
     double ratio;
-    AVFilterBufferRef *outsamplesref;
-    int unconsumed_nb_samples,
-        max_cached_nb_samples;
-    int16_t *cached_data[8],
-            *resampled_data[8];
+    struct SwrContext *swr;
 } AResampleContext;
 
 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
@@ -58,23 +52,12 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
 static av_cold void uninit(AVFilterContext *ctx)
 {
     AResampleContext *aresample = ctx->priv;
-    if (aresample->outsamplesref) {
-        int nb_channels =
-            av_get_channel_layout_nb_channels(
-                aresample->outsamplesref->audio->channel_layout);
-        avfilter_unref_buffer(aresample->outsamplesref);
-        while (nb_channels--) {
-            av_freep(&(aresample->cached_data[nb_channels]));
-            av_freep(&(aresample->resampled_data[nb_channels]));
-        }
-    }
-
-    if (aresample->resample)
-        av_resample_close(aresample->resample);
+    swr_free(&aresample->swr);
 }
 
 static int config_output(AVFilterLink *outlink)
 {
+    int ret;
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = ctx->inputs[0];
     AResampleContext *aresample = ctx->priv;
@@ -85,9 +68,16 @@ static int config_output(AVFilterLink *outlink)
         outlink->sample_rate = aresample->out_rate;
     outlink->time_base = (AVRational) {1, aresample->out_rate};
 
-    //TODO: make the resampling parameters configurable
-    aresample->resample = av_resample_init(aresample->out_rate, inlink->sample_rate,
-                                           16, 10, 0, 0.8);
+    //TODO: make the resampling parameters (filter size, phrase shift, linear, cutoff) configurable
+    aresample->swr = swr_alloc_set_opts(aresample->swr,
+                                        inlink->channel_layout, inlink->format, aresample->out_rate,
+                                        inlink->channel_layout, inlink->format, inlink->sample_rate,
+                                        0, ctx);
+    if (!aresample->swr)
+        return AVERROR(ENOMEM);
+    ret = swr_init(aresample->swr);
+    if (ret < 0)
+        return ret;
 
     aresample->ratio = (double)outlink->sample_rate / inlink->sample_rate;
 
@@ -96,235 +86,18 @@ static int config_output(AVFilterLink *outlink)
     return 0;
 }
 
-static int query_formats(AVFilterContext *ctx)
-{
-    AVFilterFormats *formats = NULL;
-
-    avfilter_add_format(&formats, AV_SAMPLE_FMT_S16);
-    if (!formats)
-        return AVERROR(ENOMEM);
-    avfilter_set_common_sample_formats(ctx, formats);
-
-    formats = avfilter_make_all_channel_layouts();
-    if (!formats)
-        return AVERROR(ENOMEM);
-    avfilter_set_common_channel_layouts(ctx, formats);
-
-    formats = avfilter_make_all_packing_formats();
-    if (!formats)
-        return AVERROR(ENOMEM);
-    avfilter_set_common_packing_formats(ctx, formats);
-
-    return 0;
-}
-
-static void deinterleave(int16_t **outp, int16_t *in,
-                         int nb_channels, int nb_samples)
-{
-    int16_t *out[8];
-    memcpy(out, outp, nb_channels * sizeof(int16_t*));
-
-    switch (nb_channels) {
-    case 2:
-        while (nb_samples--) {
-            *out[0]++ = *in++;
-            *out[1]++ = *in++;
-        }
-        break;
-    case 3:
-        while (nb_samples--) {
-            *out[0]++ = *in++;
-            *out[1]++ = *in++;
-            *out[2]++ = *in++;
-        }
-        break;
-    case 4:
-        while (nb_samples--) {
-            *out[0]++ = *in++;
-            *out[1]++ = *in++;
-            *out[2]++ = *in++;
-            *out[3]++ = *in++;
-        }
-        break;
-    case 5:
-        while (nb_samples--) {
-            *out[0]++ = *in++;
-            *out[1]++ = *in++;
-            *out[2]++ = *in++;
-            *out[3]++ = *in++;
-            *out[4]++ = *in++;
-        }
-        break;
-    case 6:
-        while (nb_samples--) {
-            *out[0]++ = *in++;
-            *out[1]++ = *in++;
-            *out[2]++ = *in++;
-            *out[3]++ = *in++;
-            *out[4]++ = *in++;
-            *out[5]++ = *in++;
-        }
-        break;
-    case 8:
-        while (nb_samples--) {
-            *out[0]++ = *in++;
-            *out[1]++ = *in++;
-            *out[2]++ = *in++;
-            *out[3]++ = *in++;
-            *out[4]++ = *in++;
-            *out[5]++ = *in++;
-            *out[6]++ = *in++;
-            *out[7]++ = *in++;
-        }
-        break;
-    }
-}
-
-static void interleave(int16_t *out, int16_t **inp,
-        int nb_channels, int nb_samples)
-{
-    int16_t *in[8];
-    memcpy(in, inp, nb_channels * sizeof(int16_t*));
-
-    switch (nb_channels) {
-    case 2:
-        while (nb_samples--) {
-            *out++ = *in[0]++;
-            *out++ = *in[1]++;
-        }
-        break;
-    case 3:
-        while (nb_samples--) {
-            *out++ = *in[0]++;
-            *out++ = *in[1]++;
-            *out++ = *in[2]++;
-        }
-        break;
-    case 4:
-        while (nb_samples--) {
-            *out++ = *in[0]++;
-            *out++ = *in[1]++;
-            *out++ = *in[2]++;
-            *out++ = *in[3]++;
-        }
-        break;
-    case 5:
-        while (nb_samples--) {
-            *out++ = *in[0]++;
-            *out++ = *in[1]++;
-            *out++ = *in[2]++;
-            *out++ = *in[3]++;
-            *out++ = *in[4]++;
-        }
-        break;
-    case 6:
-        while (nb_samples--) {
-            *out++ = *in[0]++;
-            *out++ = *in[1]++;
-            *out++ = *in[2]++;
-            *out++ = *in[3]++;
-            *out++ = *in[4]++;
-            *out++ = *in[5]++;
-        }
-        break;
-    case 8:
-        while (nb_samples--) {
-            *out++ = *in[0]++;
-            *out++ = *in[1]++;
-            *out++ = *in[2]++;
-            *out++ = *in[3]++;
-            *out++ = *in[4]++;
-            *out++ = *in[5]++;
-            *out++ = *in[6]++;
-            *out++ = *in[7]++;
-        }
-        break;
-    }
-}
-
 static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref)
 {
-    AResampleContext *aresample  = inlink->dst->priv;
-    AVFilterLink * const outlink = inlink->dst->outputs[0];
-    int i,
-        in_nb_samples            = insamplesref->audio->nb_samples,
-        cached_nb_samples        = in_nb_samples + aresample->unconsumed_nb_samples,
-        requested_out_nb_samples = aresample->ratio * cached_nb_samples,
-        nb_channels              =
-            av_get_channel_layout_nb_channels(inlink->channel_layout);
-
-    if (cached_nb_samples > aresample->max_cached_nb_samples) {
-        for (i = 0; i < nb_channels; i++) {
-            aresample->cached_data[i]    =
-                av_realloc(aresample->cached_data[i], cached_nb_samples * sizeof(int16_t));
-            aresample->resampled_data[i] =
-                av_realloc(aresample->resampled_data[i],
-                           FFALIGN(sizeof(int16_t) * requested_out_nb_samples, 16));
-
-            if (aresample->cached_data[i] == NULL || aresample->resampled_data[i] == NULL)
-                return;
-        }
-        aresample->max_cached_nb_samples = cached_nb_samples;
-
-        if (aresample->outsamplesref)
-            avfilter_unref_buffer(aresample->outsamplesref);
-
-        aresample->outsamplesref =
-            avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, requested_out_nb_samples);
-        outlink->out_buf = aresample->outsamplesref;
-    }
-
-    avfilter_copy_buffer_ref_props(aresample->outsamplesref, insamplesref);
-    aresample->outsamplesref->audio->sample_rate = outlink->sample_rate;
-    aresample->outsamplesref->pts =
-        av_rescale(outlink->sample_rate, insamplesref->pts, inlink->sample_rate);
-
-    /* av_resample() works with planar audio buffers */
-    if (!inlink->planar && nb_channels > 1) {
-        int16_t *out[8];
-        for (i = 0; i < nb_channels; i++)
-            out[i] = aresample->cached_data[i] + aresample->unconsumed_nb_samples;
+    AResampleContext *aresample = inlink->dst->priv;
+    const int n_in  = insamplesref->audio->nb_samples;
+    const int n_out = n_in * aresample->ratio;
+    AVFilterLink *const outlink = inlink->dst->outputs[0];
+    AVFilterBufferRef *outsamplesref = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, n_out);
 
-        deinterleave(out, (int16_t *)insamplesref->data[0],
-                     nb_channels, in_nb_samples);
-    } else {
-        for (i = 0; i < nb_channels; i++)
-            memcpy(aresample->cached_data[i] + aresample->unconsumed_nb_samples,
-                   insamplesref->data[i],
-                   in_nb_samples * sizeof(int16_t));
-    }
-
-    for (i = 0; i < nb_channels; i++) {
-        int consumed_nb_samples;
-        const int is_last = i+1 == nb_channels;
-
-        aresample->outsamplesref->audio->nb_samples =
-            av_resample(aresample->resample,
-                        aresample->resampled_data[i], aresample->cached_data[i],
-                        &consumed_nb_samples,
-                        cached_nb_samples,
-                        requested_out_nb_samples, is_last);
-
-        /* move unconsumed data back to the beginning of the cache */
-        aresample->unconsumed_nb_samples = cached_nb_samples - consumed_nb_samples;
-        memmove(aresample->cached_data[i],
-                aresample->cached_data[i] + consumed_nb_samples,
-                aresample->unconsumed_nb_samples * sizeof(int16_t));
-    }
-
-
-    /* copy resampled data to the output samplesref */
-    if (!inlink->planar && nb_channels > 1) {
-        interleave((int16_t *)aresample->outsamplesref->data[0],
-                   aresample->resampled_data,
-                   nb_channels, aresample->outsamplesref->audio->nb_samples);
-    } else {
-        for (i = 0; i < nb_channels; i++)
-            memcpy(aresample->outsamplesref->data[i], aresample->resampled_data[i],
-                   aresample->outsamplesref->audio->nb_samples * sizeof(int16_t));
-    }
+    swr_convert(aresample->swr, outsamplesref->data, n_out,
+                         (void *)insamplesref->data, n_in);
 
-    avfilter_filter_samples(outlink, avfilter_ref_buffer(aresample->outsamplesref, ~0));
+    avfilter_filter_samples(outlink, outsamplesref);
     avfilter_unref_buffer(insamplesref);
 }
 
@@ -333,7 +106,6 @@ AVFilter avfilter_af_aresample = {
     .description   = NULL_IF_CONFIG_SMALL("Resample audio data."),
     .init          = init,
     .uninit        = uninit,
-    .query_formats = query_formats,
     .priv_size     = sizeof(AResampleContext),
 
     .inputs    = (const AVFilterPad[]) {{ .name      = "default",
-- 
1.7.8.4



More information about the ffmpeg-devel mailing list