diff options
author | Stefano Sabatini <stefano.sabatini-lala@poste.it> | 2011-06-29 17:31:16 +0200 |
---|---|---|
committer | Stefano Sabatini <stefano.sabatini-lala@poste.it> | 2011-08-14 02:04:19 +0200 |
commit | 3560089e1204441f27b43825aaa34e3dfc47dd10 (patch) | |
tree | efd6102b21da2b0131996a204200c35ba1dcfb41 /libavfilter | |
parent | 2e81bb5e92351cc88d88a1c55d21b13532131524 (diff) | |
download | ffmpeg-3560089e1204441f27b43825aaa34e3dfc47dd10.tar.gz |
vsink_buffer: make the buffer cache all the incoming frames
Allow to cache more than one frame (e.g. for filters which return
more than one frame when avfilter_request_frame() is called on them),
and do not discard previously cached frames when a new one is added.
Diffstat (limited to 'libavfilter')
-rw-r--r-- | libavfilter/avfilter.h | 2 | ||||
-rw-r--r-- | libavfilter/vsink_buffer.c | 53 |
2 files changed, 41 insertions, 14 deletions
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index fd660292ae..472406f2b4 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -30,7 +30,7 @@ #define LIBAVFILTER_VERSION_MAJOR 2 #define LIBAVFILTER_VERSION_MINOR 29 -#define LIBAVFILTER_VERSION_MICRO 1 +#define LIBAVFILTER_VERSION_MICRO 2 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ diff --git a/libavfilter/vsink_buffer.c b/libavfilter/vsink_buffer.c index f8140b5e5a..e0f03344f5 100644 --- a/libavfilter/vsink_buffer.c +++ b/libavfilter/vsink_buffer.c @@ -23,14 +23,17 @@ * buffer video sink */ +#include "libavutil/fifo.h" #include "avfilter.h" #include "vsink_buffer.h" typedef struct { - AVFilterBufferRef *picref; ///< cached picref + AVFifoBuffer *fifo; ///< FIFO buffer of video frame references enum PixelFormat *pix_fmts; ///< accepted pixel formats, must be terminated with -1 } BufferSinkContext; +#define FIFO_INIT_SIZE 8 + static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) { BufferSinkContext *buf = ctx->priv; @@ -40,6 +43,12 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) return AVERROR(EINVAL); } + buf->fifo = av_fifo_alloc(FIFO_INIT_SIZE*sizeof(AVFilterBufferRef *)); + if (!buf->fifo) { + av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo\n"); + return AVERROR(ENOMEM); + } + buf->pix_fmts = opaque; return 0; } @@ -47,19 +56,36 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) static av_cold void uninit(AVFilterContext *ctx) { BufferSinkContext *buf = ctx->priv; - - if (buf->picref) - avfilter_unref_buffer(buf->picref); - buf->picref = NULL; + AVFilterBufferRef *picref; + + if (buf->fifo) { + while (av_fifo_size(buf->fifo) >= sizeof(AVFilterBufferRef *)) { + av_fifo_generic_read(buf->fifo, &picref, sizeof(picref), NULL); + avfilter_unref_buffer(picref); + } + av_fifo_free(buf->fifo); + buf->fifo = NULL; + } } static void end_frame(AVFilterLink *inlink) { + AVFilterContext *ctx = inlink->dst; BufferSinkContext *buf = inlink->dst->priv; - if (buf->picref) /* drop the last cached frame */ - avfilter_unref_buffer(buf->picref); - buf->picref = 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) { + av_log(ctx, AV_LOG_ERROR, + "Cannot buffer more frames. Consume some available frames " + "before adding new ones.\n"); + return; + } + } + + /* cache frame */ + av_fifo_generic_write(buf->fifo, + &inlink->cur_buf, sizeof(AVFilterBufferRef *), NULL); } static int query_formats(AVFilterContext *ctx) @@ -79,17 +105,18 @@ int av_vsink_buffer_get_video_buffer_ref(AVFilterContext *ctx, *picref = NULL; /* no picref available, fetch it from the filterchain */ - if (!buf->picref) { + if (!av_fifo_size(buf->fifo)) { if ((ret = avfilter_request_frame(inlink)) < 0) return ret; } - if (!buf->picref) + if (!av_fifo_size(buf->fifo)) return AVERROR(EINVAL); - *picref = buf->picref; - if (!(flags & AV_VSINK_BUF_FLAG_PEEK)) - buf->picref = NULL; + if (flags & AV_VSINK_BUF_FLAG_PEEK) + *picref = (AVFilterBufferRef *)av_fifo_peek2(buf->fifo, 0); + else + av_fifo_generic_read(buf->fifo, picref, sizeof(*picref), NULL); return 0; } |