[FFmpeg-devel] [PATCH 2/4] lavfi/aresample: use libswresample.

Stefano Sabatini stefasab at gmail.com
Tue Jan 31 15:49:35 CET 2012


On date Tuesday 2012-01-31 08:31:46 +0100, Clément Bœsch encoded:
> ---
>  configure                  |    1 +
>  libavfilter/Makefile       |    2 +-
>  libavfilter/af_aresample.c |  282 +++++---------------------------------------
>  3 files changed, 32 insertions(+), 253 deletions(-)
> 
> diff --git a/configure b/configure
> index 348342d..b4e433c 100755
> --- a/configure
> +++ b/configure
> @@ -1649,6 +1649,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/Makefile b/libavfilter/Makefile
> index 01a1316..ff0ba75 100644
> --- a/libavfilter/Makefile
> +++ b/libavfilter/Makefile
> @@ -5,7 +5,7 @@ FFLIBS = avutil
>  
>  FFLIBS-$(CONFIG_ACONVERT_FILTER)             += avcodec
>  FFLIBS-$(CONFIG_AMOVIE_FILTER)               += avformat avcodec
> -FFLIBS-$(CONFIG_ARESAMPLE_FILTER)            += avcodec
> +FFLIBS-$(CONFIG_ARESAMPLE_FILTER)            += swresample
>  FFLIBS-$(CONFIG_MOVIE_FILTER)                += avformat avcodec
>  FFLIBS-$(CONFIG_PAN_FILTER)                  += swresample
>  FFLIBS-$(CONFIG_SCALE_FILTER)                += swscale
> diff --git a/libavfilter/af_aresample.c b/libavfilter/af_aresample.c
> index cd9d80e..cde9adf 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,24 @@ 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;
> -
> -        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));
> -    }
> -
> -    avfilter_filter_samples(outlink, avfilter_ref_buffer(aresample->outsamplesref, ~0));

> +    AResampleContext *aresample = inlink->dst->priv;
> +    const int n_in  = insamplesref->audio->nb_samples;
> +    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);
> +
> +    n_out = swr_convert(aresample->swr, outsamplesref->data, n_out,
> +                                 (void *)insamplesref->data, n_in);
> +
> +    avfilter_copy_buffer_ref_props(outsamplesref, insamplesref);
> +    outsamplesref->audio->sample_rate = outlink->sample_rate;
> +    outsamplesref->audio->nb_samples  = n_out;
> +    outsamplesref->pts = av_rescale(outlink->sample_rate, insamplesref->pts,
> +                                    inlink ->sample_rate);
> +
> +    avfilter_filter_samples(outlink, outsamplesref);
>      avfilter_unref_buffer(insamplesref);
>  }
>  
> @@ -333,7 +112,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",

Looks good, and very nice simplification, a FATE test would be very
nice at this point for testing libswr and audio lavfi (but we still
need to implement -af in ffmpeg before).
-- 
FFmpeg = Free Faithful Minimal Picky Elfic Gadget


More information about the ffmpeg-devel mailing list