[FFmpeg-devel] [PATCH 2/2] lavfi/sink_buffer: implement libav compatibility API.
Nicolas George
nicolas.george at normalesup.org
Wed Sep 26 19:06:26 CEST 2012
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.
Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
---
libavfilter/buffersink.c | 6 +--
libavfilter/internal.h | 4 ++
libavfilter/sink_buffer.c | 114 ++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 115 insertions(+), 9 deletions(-)
With this change applied, incompatible_fork_abi is no longer needed and we
can consider dropping the other implementation of buffersink at any time.
diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c
index 2e84fb4..5cd0924 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 c217883..e82f04d 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 8c52c5c..83e43cf 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;
+}
--
1.7.10.4
More information about the ffmpeg-devel
mailing list