mirror of
https://gitee.com/openharmony/third_party_ffmpeg
synced 2024-11-25 12:19:52 +00:00
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.
This commit is contained in:
parent
2e81bb5e92
commit
3560089e12
@ -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, \
|
||||
|
@ -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;
|
||||
AVFilterBufferRef *picref;
|
||||
|
||||
if (buf->picref)
|
||||
avfilter_unref_buffer(buf->picref);
|
||||
buf->picref = NULL;
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user