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;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf)
 | 
					int ff_buffersink_read_compat(AVFilterContext *ctx, AVFilterBufferRef **buf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BufferSinkContext *s    = ctx->priv;
 | 
					    BufferSinkContext *s    = ctx->priv;
 | 
				
			||||||
    AVFilterLink      *link = ctx->inputs[0];
 | 
					    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)
 | 
					                                      int nb_samples)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BufferSinkContext *s = ctx->priv;
 | 
					    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_INLINK_IDX(link)  ((int)((link)->dstpad - (link)->dst->input_pads))
 | 
				
			||||||
#define FF_OUTLINK_IDX(link) ((int)((link)->srcpad - (link)->src->output_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 */
 | 
					#endif /* AVFILTER_INTERNAL_H */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,10 +23,12 @@
 | 
				
			|||||||
 * buffer sink
 | 
					 * buffer sink
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "libavutil/audioconvert.h"
 | 
				
			||||||
#include "libavutil/avassert.h"
 | 
					#include "libavutil/avassert.h"
 | 
				
			||||||
#include "libavutil/fifo.h"
 | 
					#include "libavutil/fifo.h"
 | 
				
			||||||
#include "avfilter.h"
 | 
					#include "avfilter.h"
 | 
				
			||||||
#include "buffersink.h"
 | 
					#include "buffersink.h"
 | 
				
			||||||
 | 
					#include "audio.h"
 | 
				
			||||||
#include "internal.h"
 | 
					#include "internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AVBufferSinkParams *av_buffersink_params_alloc(void)
 | 
					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 = ctx->priv;
 | 
				
			||||||
    BufferSinkContext *buf = inlink->dst->priv;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    av_assert1(inlink->cur_buf);
 | 
					 | 
				
			||||||
    if (av_fifo_space(buf->fifo) < sizeof(AVFilterBufferRef *)) {
 | 
					    if (av_fifo_space(buf->fifo) < sizeof(AVFilterBufferRef *)) {
 | 
				
			||||||
        /* realloc fifo size */
 | 
					        /* realloc fifo size */
 | 
				
			||||||
        if (av_fifo_realloc2(buf->fifo, av_fifo_size(buf->fifo) * 2) < 0) {
 | 
					        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 */
 | 
					    /* cache frame */
 | 
				
			||||||
    av_fifo_generic_write(buf->fifo,
 | 
					    av_fifo_generic_write(buf->fifo, &ref, sizeof(AVFilterBufferRef *), NULL);
 | 
				
			||||||
                          &inlink->cur_buf, 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;
 | 
					    inlink->cur_buf = NULL;
 | 
				
			||||||
    if (buf->warning_limit &&
 | 
					    if (buf->warning_limit &&
 | 
				
			||||||
        av_fifo_size(buf->fifo) / sizeof(AVFilterBufferRef *) >= buf->warning_limit) {
 | 
					        av_fifo_size(buf->fifo) / sizeof(AVFilterBufferRef *) >= buf->warning_limit) {
 | 
				
			||||||
@@ -348,3 +359,94 @@ AVFilter avfilter_asink_abuffersink = {
 | 
				
			|||||||
                                  { .name = NULL }},
 | 
					                                  { .name = NULL }},
 | 
				
			||||||
    .outputs   = (const AVFilterPad[]) {{ .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