mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-21 10:55:51 +02:00
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;
|
||||
}
|
||||
|
||||
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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user