summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas George <nicolas.george@normalesup.org>2013-03-10 13:33:18 +0100
committerNicolas George <nicolas.george@normalesup.org>2013-03-10 13:56:17 +0100
commitb0012de420f20d5731b90af1f2a3e7093f2195d9 (patch)
tree2b3fed590dfd42581082e71ccae2c597e5e5d4c3
parentcb2bd91413af28ca9a0202e9b92ee7c1e3d9dd2e (diff)
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.
-rw-r--r--libavfilter/buffersrc.c40
-rw-r--r--libavfilter/buffersrc.h25
2 files changed, 50 insertions, 15 deletions
diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c
index 6c6689b4ca..185018dfd9 100644
--- a/libavfilter/buffersrc.c
+++ b/libavfilter/buffersrc.c
@@ -75,14 +75,23 @@ typedef struct {
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;
int64_t layout = frame->channel_layout;
@@ -91,22 +100,25 @@ int av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame)
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()))
return AVERROR(ENOMEM);
ret = av_frame_ref(copy, frame);
if (ret >= 0)
- ret = av_buffersrc_add_frame(ctx, copy);
+ ret = av_buffersrc_add_frame_internal(ctx, copy, flags);
av_frame_free(&copy);
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;
AVFrame *copy;
int ret;
- int64_t layout;
if (!frame) {
s->eof = 1;
@@ -114,6 +126,8 @@ int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame)
} else if (s->eof)
return AVERROR(EINVAL);
+ if (!(flags & AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT)) {
+
switch (ctx->outputs[0]->type) {
case AVMEDIA_TYPE_VIDEO:
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:
CHECK_AUDIO_PARAM_CHANGE(ctx, s, frame->sample_rate, frame->channel_layout,
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;
default:
return AVERROR(EINVAL);
}
+ }
+
if (!av_fifo_space(s->fifo) &&
(ret = av_fifo_realloc2(s->fifo, av_fifo_size(s->fifo) +
sizeof(copy))) < 0)
@@ -148,6 +158,10 @@ int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame)
return ret;
}
+ if ((flags & AV_BUFFERSRC_FLAG_PUSH))
+ if ((ret = ctx->output_pads[0].request_frame(ctx->outputs[0])) < 0)
+ return ret;
+
return 0;
}
diff --git a/libavfilter/buffersrc.h b/libavfilter/buffersrc.h
index 3b9fd5282c..66361b3dab 100644
--- a/libavfilter/buffersrc.h
+++ b/libavfilter/buffersrc.h
@@ -35,16 +35,25 @@ enum {
*/
AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT = 1,
+#if FF_API_AVFILTERBUFFER
/**
- * Do not copy buffer data.
+ * Ignored
*/
AV_BUFFERSRC_FLAG_NO_COPY = 2,
+#endif
/**
* Immediately push the frame to the output.
*/
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.
*
* @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);
@@ -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
* that av_buffersrc_write_frame() creates a new reference to the input frame,
* 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);
/**
- * 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 frame a frame, or NULL to mark EOF