[FFmpeg-devel] [PATCH 3/5] lavfi: add asrc_abuffer - audio source buffer filter

Stefano Sabatini stefano.sabatini-lala at poste.it
Sat Aug 20 12:44:56 CEST 2011


On date Wednesday 2011-08-17 21:37:04 +0300, Mina Nagy Zaki encoded:
> Replaced strsep() with strtok_r() and used a macro for format parsing.
> 

> From c18348b5c747a3220ef050fcd4181013311a5c9c Mon Sep 17 00:00:00 2001
> From: Mina Nagy Zaki <mnzaki at gmail.com>
> Date: Mon, 1 Aug 2011 11:33:26 +0300
> Subject: [PATCH 03/13] lavfi: add asrc_abuffer - audio source buffer filter
> 
> Originally based on code by Stefano Sabatini and S. N. Hemanth
> ---
>  doc/filters.texi           |   44 ++++++
>  libavfilter/Makefile       |    2 +
>  libavfilter/allfilters.c   |    1 +
>  libavfilter/asrc_abuffer.c |  362 ++++++++++++++++++++++++++++++++++++++++++++
>  libavfilter/asrc_abuffer.h |   81 ++++++++++
>  5 files changed, 490 insertions(+), 0 deletions(-)
>  create mode 100644 libavfilter/asrc_abuffer.c
>  create mode 100644 libavfilter/asrc_abuffer.h
[...]
> +static inline void log_input_change(void *ctx, AVFilterLink *link, AVFilterBufferRef *ref)
> +{
> +    char old_layout_str[16], new_layout_str[16];
> +    av_get_channel_layout_string(old_layout_str, sizeof(old_layout_str),
> +                                 -1, link->channel_layout);
> +    av_get_channel_layout_string(new_layout_str, sizeof(new_layout_str),
> +                                 -1, ref->audio->channel_layout);
> +    av_log(ctx, AV_LOG_INFO,

> +           "Audio input format changed: "
> +           "%s:%s:%li -> %s:%s:%u, normalizing\n",

weird %li -> %u, we should use the same type everywhere

> +           av_get_sample_fmt_name(link->format),
> +           old_layout_str, link->sample_rate,
> +           av_get_sample_fmt_name(ref->format),
> +           new_layout_str, ref->audio->sample_rate);
> +}
> +
> +int av_asrc_buffer_add_audio_buffer_ref(AVFilterContext *ctx,
> +                                        AVFilterBufferRef *samplesref,
> +                                        int av_unused flags)
> +{
> +    ABufferSourceContext *abuffer = ctx->priv;
> +    AVFilterLink *link;
> +    int ret, logged = 0;
> +
> +    if (av_fifo_space(abuffer->fifo) < sizeof(samplesref)) {
> +        av_log(ctx, AV_LOG_ERROR,
> +               "Buffering limit reached. Please consume some available frames "
> +               "before adding new ones.\n");
> +        return AVERROR(EINVAL);
> +    }
> +
> +    // Normalize input
> +
> +    link = ctx->outputs[0];
> +    if (samplesref->audio->sample_rate != link->sample_rate) {
> +
> +        log_input_change(ctx, link, samplesref);
> +        logged = 1;
> +
> +        abuffer->sample_rate = samplesref->audio->sample_rate;
> +
> +        if (!abuffer->aresample) {
> +            ret = insert_filter(abuffer, link, &abuffer->aresample, "aresample");
> +            if (ret < 0) return ret;
> +        } else {
> +            link = abuffer->aresample->outputs[0];
> +            if (samplesref->audio->sample_rate == link->sample_rate)
> +                remove_filter(&abuffer->aresample);
> +            else
> +                if ((ret = reconfigure_filter(abuffer, abuffer->aresample)) < 0)
> +                    return ret;
> +        }
> +    }
> +
> +    link = ctx->outputs[0];
> +    if (samplesref->format                != link->format         ||
> +        samplesref->audio->channel_layout != link->channel_layout ||
> +        samplesref->audio->planar         != link->planar) {
> +
> +        if (!logged) log_input_change(ctx, link, samplesref);
> +
> +        abuffer->sample_format  = samplesref->format;
> +        abuffer->channel_layout = samplesref->audio->channel_layout;
> +        abuffer->packing_format = samplesref->audio->planar;
> +
> +        if (!abuffer->aconvert) {
> +            ret = insert_filter(abuffer, link, &abuffer->aconvert, "aconvert");
> +            if (ret < 0) return ret;
> +        } else {
> +            link = abuffer->aconvert->outputs[0];
> +            if (samplesref->format                == link->format         &&
> +                samplesref->audio->channel_layout == link->channel_layout &&
> +                samplesref->audio->planar         == link->planar
> +               )
> +                remove_filter(&abuffer->aconvert);
> +            else
> +                if ((ret = reconfigure_filter(abuffer, abuffer->aconvert)) < 0)
> +                    return ret;
> +        }
> +    }
> +
> +    if (sizeof(samplesref) != av_fifo_generic_write(abuffer->fifo, &samplesref,
> +                                                    sizeof(samplesref), NULL)) {
> +        av_log(ctx, AV_LOG_ERROR, "Error while writing to FIFO\n");
> +        return AVERROR(EINVAL);
> +    }
> +
> +    return 0;
> +}
> +
> +int av_asrc_buffer_add_samples(AVFilterContext *ctx,
> +                               uint8_t *data[8], int linesize[8],
> +                               int nb_samples, int sample_rate,
> +                               int sample_fmt, int64_t channel_layout, int planar,
> +                               int64_t pts, int av_unused flags)
> +{
> +    AVFilterBufferRef *samplesref;
> +
> +    samplesref = avfilter_get_audio_buffer_ref_from_arrays(
> +                     data, linesize, AV_PERM_WRITE,
> +                     nb_samples,
> +                     sample_fmt, channel_layout, planar);
> +    if (!samplesref)
> +        return AVERROR(ENOMEM);
> +
> +    samplesref->buf->free  = buf_free;
> +    samplesref->pts = pts;
> +    samplesref->audio->sample_rate = sample_rate;
> +
> +    return av_asrc_buffer_add_audio_buffer_ref(ctx, samplesref, 0);
> +}
> +
> +int av_asrc_buffer_add_buffer(AVFilterContext *ctx,
> +                              uint8_t *buf, int buf_size, int sample_rate,
> +                              int sample_fmt, int64_t channel_layout, int planar,
> +                              int64_t pts, int av_unused flags)
> +{
> +    uint8_t *data[8];
> +    int linesize[8];
> +    int nb_channels = av_get_channel_layout_nb_channels(channel_layout),
> +        nb_samples  = buf_size / nb_channels / av_get_bytes_per_sample(sample_fmt);
> +
> +    av_samples_fill_arrays(data, linesize,
> +                           buf, nb_channels, nb_samples,
> +                           sample_fmt, planar, 16);
> +
> +    return av_asrc_buffer_add_samples(ctx,
> +                                      data, linesize, nb_samples,
> +                                      sample_rate,
> +                                      sample_fmt, channel_layout, planar,
> +                                      pts, flags);
> +}
> +
> +static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
> +{
> +    ABufferSourceContext *abuffer = ctx->priv;
> +    char *arg = NULL, *ptr, chlayout_str[16];
> +    int ret;
> +
> +    arg = strtok_r(args, ":", &ptr);
> +
> +#define ADD_FORMATS(fmt_name)                                           \
> +    if (!arg) goto arg_fail;                                            \
> +    if ((ret = ff_parse_##fmt_name(&abuffer->fmt_name, arg, ctx)) < 0)  \
> +        return ret;                                                     \
> +    if (*args)                                                          \
> +        arg = strtok_r(NULL, ":", &ptr)
> +
> +    ADD_FORMATS(sample_rate);
> +    ADD_FORMATS(sample_format);
> +    ADD_FORMATS(channel_layout);
> +    ADD_FORMATS(packing_format);

Nit: ADD_FORMAT

> +
> +    abuffer->fifo = av_fifo_alloc(FIFO_SIZE*sizeof(AVFilterBufferRef*));
> +    if (!abuffer->fifo) {
> +        av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo, filter init failed.\n");
> +        return AVERROR(ENOMEM);
> +    }
> +
> +    av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str),
> +                                 -1, abuffer->channel_layout);
> +    av_log(ctx, AV_LOG_INFO, "format:%s layout:%s rate:%d\n",
> +           av_get_sample_fmt_name(abuffer->sample_format), chlayout_str,
> +           abuffer->sample_rate);
> +
> +    return 0;
> +

> +arg_fail:
> +    av_log(ctx, AV_LOG_ERROR, "Please provide the required arguments "
> +                              "sample_rate:sample_fmt:channel_layout:packing\n");
> +    return AVERROR(EINVAL);

Nit: Invalid arguments provided, they must be of the form "..." 

[...]

Looks fine otherwise, going to apply in a few days.
-- 
FFmpeg = Fiendish and Fabulous Merciful Powered Ecletic Gorilla


More information about the ffmpeg-devel mailing list