Commit b0012de4 authored by Nicolas George's avatar Nicolas George

lavfi/buffersrc: implement flags.

The PUSH flags is necessary for efficient scheduling;
otherwise there is no feedback when adding frames to
closed paths.

The NO_CHECK_FORMAT is a small optimization that does
not cost much to implement.

The KEEP_REF flag maps to the add/write distinction in
the fork's API.
parent cb2bd914
...@@ -75,14 +75,23 @@ typedef struct { ...@@ -75,14 +75,23 @@ typedef struct {
return AVERROR(EINVAL);\ return AVERROR(EINVAL);\
} }
int av_buffersrc_add_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags) int av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame)
{ {
return av_buffersrc_add_frame(ctx, frame); return av_buffersrc_add_frame_flags(ctx, (AVFrame *)frame,
AV_BUFFERSRC_FLAG_KEEP_REF);
} }
int av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame) int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame)
{ {
AVFrame *copy; return av_buffersrc_add_frame_flags(ctx, frame, 0);
}
static int av_buffersrc_add_frame_internal(AVFilterContext *ctx,
AVFrame *frame, int flags);
int av_buffersrc_add_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags)
{
AVFrame *copy = NULL;
int ret = 0; int ret = 0;
int64_t layout = frame->channel_layout; int64_t layout = frame->channel_layout;
...@@ -91,22 +100,25 @@ int av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame) ...@@ -91,22 +100,25 @@ int av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame)
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
if (!(flags & AV_BUFFERSRC_FLAG_KEEP_REF) || !frame)
return av_buffersrc_add_frame_internal(ctx, frame, flags);
if (!(copy = av_frame_alloc())) if (!(copy = av_frame_alloc()))
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
ret = av_frame_ref(copy, frame); ret = av_frame_ref(copy, frame);
if (ret >= 0) if (ret >= 0)
ret = av_buffersrc_add_frame(ctx, copy); ret = av_buffersrc_add_frame_internal(ctx, copy, flags);
av_frame_free(&copy); av_frame_free(&copy);
return ret; return ret;
} }
int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame) static int av_buffersrc_add_frame_internal(AVFilterContext *ctx,
AVFrame *frame, int flags)
{ {
BufferSourceContext *s = ctx->priv; BufferSourceContext *s = ctx->priv;
AVFrame *copy; AVFrame *copy;
int ret; int ret;
int64_t layout;
if (!frame) { if (!frame) {
s->eof = 1; s->eof = 1;
...@@ -114,6 +126,8 @@ int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame) ...@@ -114,6 +126,8 @@ int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame)
} else if (s->eof) } else if (s->eof)
return AVERROR(EINVAL); return AVERROR(EINVAL);
if (!(flags & AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT)) {
switch (ctx->outputs[0]->type) { switch (ctx->outputs[0]->type) {
case AVMEDIA_TYPE_VIDEO: case AVMEDIA_TYPE_VIDEO:
CHECK_VIDEO_PARAM_CHANGE(ctx, s, frame->width, frame->height, CHECK_VIDEO_PARAM_CHANGE(ctx, s, frame->width, frame->height,
...@@ -122,17 +136,13 @@ int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame) ...@@ -122,17 +136,13 @@ int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame)
case AVMEDIA_TYPE_AUDIO: case AVMEDIA_TYPE_AUDIO:
CHECK_AUDIO_PARAM_CHANGE(ctx, s, frame->sample_rate, frame->channel_layout, CHECK_AUDIO_PARAM_CHANGE(ctx, s, frame->sample_rate, frame->channel_layout,
frame->format); frame->format);
layout = frame->channel_layout;
if (layout && av_get_channel_layout_nb_channels(layout) != av_frame_get_channels(frame)) {
av_log(0, AV_LOG_ERROR, "Layout indicates a different number of channels than actually present\n");
return AVERROR(EINVAL);
}
break; break;
default: default:
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
}
if (!av_fifo_space(s->fifo) && if (!av_fifo_space(s->fifo) &&
(ret = av_fifo_realloc2(s->fifo, av_fifo_size(s->fifo) + (ret = av_fifo_realloc2(s->fifo, av_fifo_size(s->fifo) +
sizeof(copy))) < 0) sizeof(copy))) < 0)
...@@ -148,6 +158,10 @@ int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame) ...@@ -148,6 +158,10 @@ int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame)
return ret; return ret;
} }
if ((flags & AV_BUFFERSRC_FLAG_PUSH))
if ((ret = ctx->output_pads[0].request_frame(ctx->outputs[0])) < 0)
return ret;
return 0; return 0;
} }
......
...@@ -35,16 +35,25 @@ enum { ...@@ -35,16 +35,25 @@ enum {
*/ */
AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT = 1, AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT = 1,
#if FF_API_AVFILTERBUFFER
/** /**
* Do not copy buffer data. * Ignored
*/ */
AV_BUFFERSRC_FLAG_NO_COPY = 2, AV_BUFFERSRC_FLAG_NO_COPY = 2,
#endif
/** /**
* Immediately push the frame to the output. * Immediately push the frame to the output.
*/ */
AV_BUFFERSRC_FLAG_PUSH = 4, AV_BUFFERSRC_FLAG_PUSH = 4,
/**
* Keep a reference to the frame.
* If the frame if reference-counted, create a new reference; otherwise
* copy the frame data.
*/
AV_BUFFERSRC_FLAG_KEEP_REF = 8,
}; };
/** /**
...@@ -91,6 +100,9 @@ int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf); ...@@ -91,6 +100,9 @@ int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf);
* copied. * copied.
* *
* @return 0 on success, a negative AVERROR on error * @return 0 on success, a negative AVERROR on error
*
* This function is equivalent to av_buffersrc_add_frame_flags() with the
* AV_BUFFERSRC_FLAG_KEEP_REF flag.
*/ */
int av_buffersrc_write_frame(AVFilterContext *s, const AVFrame *frame); int av_buffersrc_write_frame(AVFilterContext *s, const AVFrame *frame);
...@@ -108,11 +120,20 @@ int av_buffersrc_write_frame(AVFilterContext *s, const AVFrame *frame); ...@@ -108,11 +120,20 @@ int av_buffersrc_write_frame(AVFilterContext *s, const AVFrame *frame);
* @note the difference between this function and av_buffersrc_write_frame() is * @note the difference between this function and av_buffersrc_write_frame() is
* that av_buffersrc_write_frame() creates a new reference to the input frame, * that av_buffersrc_write_frame() creates a new reference to the input frame,
* while this function takes ownership of the reference passed to it. * while this function takes ownership of the reference passed to it.
*
* This function is equivalent to av_buffersrc_add_frame_flags() without the
* AV_BUFFERSRC_FLAG_KEEP_REF flag.
*/ */
int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame); int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame);
/** /**
* Add frame data to buffer_src. XXX * Add a frame to the buffer source.
*
* By default, if the frame is reference-counted, this function will take
* ownership of the reference(s) and reset the frame. This can be controled
* using the flags.
*
* If this function returns an error, the input frame is not touched.
* *
* @param buffer_src pointer to a buffer source context * @param buffer_src pointer to a buffer source context
* @param frame a frame, or NULL to mark EOF * @param frame a frame, or NULL to mark EOF
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment