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.
This commit is contained in:
		@@ -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,7 +100,7 @@ static int read_from_fifo(AVFilterContext *ctx, AVFilterBufferRef **pbuf,
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int av_buffersink_read_samples(AVFilterContext *ctx, AVFilterBufferRef **pbuf,
 | 
			
		||||
int ff_buffersink_read_samples_compat(AVFilterContext *ctx, AVFilterBufferRef **pbuf,
 | 
			
		||||
                                      int nb_samples)
 | 
			
		||||
{
 | 
			
		||||
    BufferSinkContext *s = ctx->priv;
 | 
			
		||||
 
 | 
			
		||||
@@ -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 */
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user