forked from FFmpeg/FFmpeg
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.
This commit is contained in:
parent
cb2bd91413
commit
b0012de420
2 changed files with 52 additions and 17 deletions
|
@ -75,14 +75,23 @@ typedef struct {
|
||||||
return AVERROR(EINVAL);\
|
return AVERROR(EINVAL);\
|
||||||
}
|
}
|
||||||
|
|
||||||
int av_buffersrc_add_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags)
|
|
||||||
{
|
|
||||||
return av_buffersrc_add_frame(ctx, frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
int av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame)
|
int av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame)
|
||||||
{
|
{
|
||||||
AVFrame *copy;
|
return av_buffersrc_add_frame_flags(ctx, (AVFrame *)frame,
|
||||||
|
AV_BUFFERSRC_FLAG_KEEP_REF);
|
||||||
|
}
|
||||||
|
|
||||||
|
int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame)
|
||||||
|
{
|
||||||
|
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)
|
||||||
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(©);
|
av_frame_free(©);
|
||||||
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)
|
||||||
} 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)
|
||||||
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)
|
||||||
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 {
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
* 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);
|
||||||
* @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
|
||||||
|
|
Loading…
Add table
Reference in a new issue