From 9de731e9d0f415ce8c5dc1c9079490964c244867 Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Sun, 23 Sep 2012 20:45:49 +0200 Subject: lavfi/sink_buffer: implement libav compatibility API. Implement av_buffersink_read() and av_buffersink_read_samples() for ffmpeg's version of buffersink. With this change, avconv linked against ffmpeg's libraries passes the same number of tests whether it uses ffbuffersink or buffersink_old. --- libavfilter/buffersink.c | 6 +-- libavfilter/internal.h | 4 ++ libavfilter/sink_buffer.c | 114 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 115 insertions(+), 9 deletions(-) (limited to 'libavfilter') diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c index 2e84fb4507..5cd0924666 100644 --- a/libavfilter/buffersink.c +++ b/libavfilter/buffersink.c @@ -59,7 +59,7 @@ static int start_frame(AVFilterLink *link, AVFilterBufferRef *buf) return 0; } -int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf) +int ff_buffersink_read_compat(AVFilterContext *ctx, AVFilterBufferRef **buf) { BufferSinkContext *s = ctx->priv; AVFilterLink *link = ctx->inputs[0]; @@ -100,8 +100,8 @@ static int read_from_fifo(AVFilterContext *ctx, AVFilterBufferRef **pbuf, } -int av_buffersink_read_samples(AVFilterContext *ctx, AVFilterBufferRef **pbuf, - int nb_samples) +int ff_buffersink_read_samples_compat(AVFilterContext *ctx, AVFilterBufferRef **pbuf, + int nb_samples) { BufferSinkContext *s = ctx->priv; AVFilterLink *link = ctx->inputs[0]; diff --git a/libavfilter/internal.h b/libavfilter/internal.h index c217883319..e82f04dbb9 100644 --- a/libavfilter/internal.h +++ b/libavfilter/internal.h @@ -365,4 +365,8 @@ AVFilterBufferRef *ff_copy_buffer_ref(AVFilterLink *outlink, #define FF_INLINK_IDX(link) ((int)((link)->dstpad - (link)->dst->input_pads)) #define FF_OUTLINK_IDX(link) ((int)((link)->srcpad - (link)->src->output_pads)) +int ff_buffersink_read_compat(AVFilterContext *ctx, AVFilterBufferRef **buf); +int ff_buffersink_read_samples_compat(AVFilterContext *ctx, AVFilterBufferRef **pbuf, + int nb_samples); + #endif /* AVFILTER_INTERNAL_H */ diff --git a/libavfilter/sink_buffer.c b/libavfilter/sink_buffer.c index 8c52c5c93b..83e43cf396 100644 --- a/libavfilter/sink_buffer.c +++ b/libavfilter/sink_buffer.c @@ -23,10 +23,12 @@ * buffer sink */ +#include "libavutil/audioconvert.h" #include "libavutil/avassert.h" #include "libavutil/fifo.h" #include "avfilter.h" #include "buffersink.h" +#include "audio.h" #include "internal.h" AVBufferSinkParams *av_buffersink_params_alloc(void) @@ -96,12 +98,10 @@ static av_cold void common_uninit(AVFilterContext *ctx) } } -static int end_frame(AVFilterLink *inlink) +static int add_buffer_ref(AVFilterContext *ctx, AVFilterBufferRef *ref) { - AVFilterContext *ctx = inlink->dst; - BufferSinkContext *buf = inlink->dst->priv; + BufferSinkContext *buf = ctx->priv; - av_assert1(inlink->cur_buf); if (av_fifo_space(buf->fifo) < sizeof(AVFilterBufferRef *)) { /* realloc fifo size */ if (av_fifo_realloc2(buf->fifo, av_fifo_size(buf->fifo) * 2) < 0) { @@ -113,8 +113,19 @@ static int end_frame(AVFilterLink *inlink) } /* cache frame */ - av_fifo_generic_write(buf->fifo, - &inlink->cur_buf, sizeof(AVFilterBufferRef *), NULL); + av_fifo_generic_write(buf->fifo, &ref, sizeof(AVFilterBufferRef *), NULL); + return 0; +} + +static int end_frame(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + BufferSinkContext *buf = inlink->dst->priv; + int ret; + + av_assert1(inlink->cur_buf); + if ((ret = add_buffer_ref(ctx, inlink->cur_buf)) < 0) + return ret; inlink->cur_buf = NULL; if (buf->warning_limit && av_fifo_size(buf->fifo) / sizeof(AVFilterBufferRef *) >= buf->warning_limit) { @@ -348,3 +359,94 @@ AVFilter avfilter_asink_abuffersink = { { .name = NULL }}, .outputs = (const AVFilterPad[]) {{ .name = NULL }}, }; + +/* Libav compatibility API */ + +extern AVFilter avfilter_vsink_buffer; +extern AVFilter avfilter_asink_abuffer; + +int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf) +{ + AVFilterBufferRef *tbuf; + int ret; + + if (ctx->filter-> inputs[0].start_frame == + avfilter_vsink_buffer. inputs[0].start_frame || + ctx->filter-> inputs[0].filter_samples == + avfilter_asink_abuffer.inputs[0].filter_samples) + return ff_buffersink_read_compat(ctx, buf); + av_assert0(ctx->filter-> inputs[0].end_frame == + avfilter_vsink_ffbuffersink. inputs[0].end_frame || + ctx->filter-> inputs[0].filter_samples == + avfilter_asink_ffabuffersink.inputs[0].filter_samples); + + ret = av_buffersink_get_buffer_ref(ctx, &tbuf, + buf ? 0 : AV_BUFFERSINK_FLAG_PEEK); + if (!buf) + return ret >= 0; + if (ret < 0) + return ret; + *buf = tbuf; + return 0; +} + +int av_buffersink_read_samples(AVFilterContext *ctx, AVFilterBufferRef **buf, + int nb_samples) +{ + BufferSinkContext *sink = ctx->priv; + int ret = 0, have_samples = 0, need_samples; + AVFilterBufferRef *tbuf, *in_buf; + AVFilterLink *link = ctx->inputs[0]; + int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout); + + if (ctx->filter-> inputs[0].filter_samples == + avfilter_asink_abuffer.inputs[0].filter_samples) + return ff_buffersink_read_samples_compat(ctx, buf, nb_samples); + av_assert0(ctx->filter-> inputs[0].filter_samples == + avfilter_asink_ffabuffersink.inputs[0].filter_samples); + + tbuf = ff_get_audio_buffer(link, AV_PERM_WRITE, nb_samples); + if (!tbuf) + return AVERROR(ENOMEM); + + while (have_samples < nb_samples) { + ret = av_buffersink_get_buffer_ref(ctx, &in_buf, + AV_BUFFERSINK_FLAG_PEEK); + if (ret < 0) { + if (ret == AVERROR_EOF && have_samples) { + nb_samples = have_samples; + ret = 0; + } + break; + } + + need_samples = FFMIN(in_buf->audio->nb_samples, + nb_samples - have_samples); + av_samples_copy(tbuf->extended_data, in_buf->extended_data, + have_samples, 0, need_samples, + nb_channels, in_buf->format); + have_samples += need_samples; + if (need_samples < in_buf->audio->nb_samples) { + in_buf->audio->nb_samples -= need_samples; + av_samples_copy(in_buf->extended_data, in_buf->extended_data, + 0, need_samples, in_buf->audio->nb_samples, + nb_channels, in_buf->format); + } else { + av_buffersink_get_buffer_ref(ctx, &in_buf, 0); + avfilter_unref_buffer(in_buf); + } + } + tbuf->audio->nb_samples = have_samples; + + if (ret < 0) { + av_assert0(!av_fifo_size(sink->fifo)); + if (have_samples) + add_buffer_ref(ctx, tbuf); + else + avfilter_unref_buffer(tbuf); + return ret; + } + + *buf = tbuf; + return 0; +} -- cgit v1.2.3