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:
parent
279ae1cd72
commit
9de731e9d0
@ -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;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user