[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