mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-02-10 00:30:14 +00:00
vsrc_buffer: allow buffering arbitrary number of frames.
This commit is contained in:
parent
416fd90ead
commit
95587d29d7
@ -26,10 +26,11 @@
|
|||||||
#include "avfilter.h"
|
#include "avfilter.h"
|
||||||
#include "buffersrc.h"
|
#include "buffersrc.h"
|
||||||
#include "vsrc_buffer.h"
|
#include "vsrc_buffer.h"
|
||||||
|
#include "libavutil/fifo.h"
|
||||||
#include "libavutil/imgutils.h"
|
#include "libavutil/imgutils.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
AVFilterBufferRef *buf;
|
AVFifoBuffer *fifo;
|
||||||
int h, w;
|
int h, w;
|
||||||
enum PixelFormat pix_fmt;
|
enum PixelFormat pix_fmt;
|
||||||
AVRational time_base; ///< time_base to set in the output link
|
AVRational time_base; ///< time_base to set in the output link
|
||||||
@ -46,25 +47,29 @@ int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame,
|
|||||||
int64_t pts, AVRational pixel_aspect)
|
int64_t pts, AVRational pixel_aspect)
|
||||||
{
|
{
|
||||||
BufferSourceContext *c = buffer_filter->priv;
|
BufferSourceContext *c = buffer_filter->priv;
|
||||||
|
AVFilterBufferRef *buf;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (c->buf) {
|
if (!av_fifo_space(c->fifo) &&
|
||||||
av_log(buffer_filter, AV_LOG_ERROR,
|
(ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) +
|
||||||
"Buffering several frames is not supported. "
|
sizeof(buf))) < 0)
|
||||||
"Please consume all available frames before adding a new one.\n"
|
return ret;
|
||||||
);
|
|
||||||
//return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK_PARAM_CHANGE(buffer_filter, c, frame->width, frame->height, frame->format);
|
CHECK_PARAM_CHANGE(buffer_filter, c, frame->width, frame->height, frame->format);
|
||||||
|
|
||||||
c->buf = avfilter_get_video_buffer(buffer_filter->outputs[0], AV_PERM_WRITE,
|
buf = avfilter_get_video_buffer(buffer_filter->outputs[0], AV_PERM_WRITE,
|
||||||
c->w, c->h);
|
c->w, c->h);
|
||||||
av_image_copy(c->buf->data, c->buf->linesize, frame->data, frame->linesize,
|
av_image_copy(buf->data, buf->linesize, frame->data, frame->linesize,
|
||||||
c->pix_fmt, c->w, c->h);
|
c->pix_fmt, c->w, c->h);
|
||||||
|
|
||||||
avfilter_copy_frame_props(c->buf, frame);
|
avfilter_copy_frame_props(buf, frame);
|
||||||
c->buf->pts = pts;
|
buf->pts = pts;
|
||||||
c->buf->video->pixel_aspect = pixel_aspect;
|
buf->video->pixel_aspect = pixel_aspect;
|
||||||
|
|
||||||
|
if ((ret = av_fifo_generic_write(c->fifo, &buf, sizeof(buf), NULL)) < 0) {
|
||||||
|
avfilter_unref_buffer(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -72,18 +77,17 @@ int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame,
|
|||||||
int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf)
|
int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf)
|
||||||
{
|
{
|
||||||
BufferSourceContext *c = s->priv;
|
BufferSourceContext *c = s->priv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (c->buf) {
|
if (!av_fifo_space(c->fifo) &&
|
||||||
av_log(s, AV_LOG_ERROR,
|
(ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) +
|
||||||
"Buffering several frames is not supported. "
|
sizeof(buf))) < 0)
|
||||||
"Please consume all available frames before adding a new one.\n"
|
return ret;
|
||||||
);
|
|
||||||
return AVERROR(EINVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK_PARAM_CHANGE(s, c, buf->video->w, buf->video->h, buf->format);
|
CHECK_PARAM_CHANGE(s, c, buf->video->w, buf->video->h, buf->format);
|
||||||
|
|
||||||
c->buf = buf;
|
if ((ret = av_fifo_generic_write(c->fifo, &buf, sizeof(buf), NULL)) < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -110,6 +114,9 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(c->fifo = av_fifo_alloc(sizeof(AVFilterBufferRef*))))
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
av_log(ctx, AV_LOG_INFO, "w:%d h:%d pixfmt:%s\n", c->w, c->h, av_pix_fmt_descriptors[c->pix_fmt].name);
|
av_log(ctx, AV_LOG_INFO, "w:%d h:%d pixfmt:%s\n", c->w, c->h, av_pix_fmt_descriptors[c->pix_fmt].name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -117,9 +124,13 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
|
|||||||
static av_cold void uninit(AVFilterContext *ctx)
|
static av_cold void uninit(AVFilterContext *ctx)
|
||||||
{
|
{
|
||||||
BufferSourceContext *s = ctx->priv;
|
BufferSourceContext *s = ctx->priv;
|
||||||
if (s->buf)
|
while (av_fifo_size(s->fifo)) {
|
||||||
avfilter_unref_buffer(s->buf);
|
AVFilterBufferRef *buf;
|
||||||
s->buf = NULL;
|
av_fifo_generic_read(s->fifo, &buf, sizeof(buf), NULL);
|
||||||
|
avfilter_unref_buffer(buf);
|
||||||
|
}
|
||||||
|
av_fifo_free(s->fifo);
|
||||||
|
s->fifo = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int query_formats(AVFilterContext *ctx)
|
static int query_formats(AVFilterContext *ctx)
|
||||||
@ -146,18 +157,19 @@ static int config_props(AVFilterLink *link)
|
|||||||
static int request_frame(AVFilterLink *link)
|
static int request_frame(AVFilterLink *link)
|
||||||
{
|
{
|
||||||
BufferSourceContext *c = link->src->priv;
|
BufferSourceContext *c = link->src->priv;
|
||||||
|
AVFilterBufferRef *buf;
|
||||||
|
|
||||||
if (!c->buf) {
|
if (!av_fifo_size(c->fifo)) {
|
||||||
av_log(link->src, AV_LOG_ERROR,
|
av_log(link->src, AV_LOG_ERROR,
|
||||||
"request_frame() called with no available frame!\n");
|
"request_frame() called with no available frame!\n");
|
||||||
//return -1;
|
//return -1;
|
||||||
}
|
}
|
||||||
|
av_fifo_generic_read(c->fifo, &buf, sizeof(buf), NULL);
|
||||||
|
|
||||||
avfilter_start_frame(link, avfilter_ref_buffer(c->buf, ~0));
|
avfilter_start_frame(link, avfilter_ref_buffer(buf, ~0));
|
||||||
avfilter_draw_slice(link, 0, link->h, 1);
|
avfilter_draw_slice(link, 0, link->h, 1);
|
||||||
avfilter_end_frame(link);
|
avfilter_end_frame(link);
|
||||||
avfilter_unref_buffer(c->buf);
|
avfilter_unref_buffer(buf);
|
||||||
c->buf = NULL;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -165,7 +177,7 @@ static int request_frame(AVFilterLink *link)
|
|||||||
static int poll_frame(AVFilterLink *link)
|
static int poll_frame(AVFilterLink *link)
|
||||||
{
|
{
|
||||||
BufferSourceContext *c = link->src->priv;
|
BufferSourceContext *c = link->src->priv;
|
||||||
return !!c->buf;
|
return !!av_fifo_size(c->fifo);
|
||||||
}
|
}
|
||||||
|
|
||||||
AVFilter avfilter_vsrc_buffer = {
|
AVFilter avfilter_vsrc_buffer = {
|
||||||
|
Loading…
Reference in New Issue
Block a user