[FFmpeg-devel] [PATCH 2/5] lavfi/buffersrc: add add av_buffersrc_close().

Nicolas George george at nsup.org
Sun Aug 3 15:15:37 CEST 2014


Also deprecate adding a NULL frame to mark EOF.

TODO APIchanges entry, version bump.

Signed-off-by: Nicolas George <george at nsup.org>
---
 libavfilter/buffersrc.c | 40 ++++++++++++++++++++++++++++++----------
 libavfilter/buffersrc.h | 15 +++++++++++++++
 2 files changed, 45 insertions(+), 10 deletions(-)


Note: relying on the frame duration for the end timestamp would be fragile
(no filters update it), and technically an API break.


diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c
index 27d3db0..6d71587 100644
--- a/libavfilter/buffersrc.c
+++ b/libavfilter/buffersrc.c
@@ -63,6 +63,7 @@ typedef struct BufferSourceContext {
     char    *channel_layout_str;
 
     int eof;
+    int64_t eof_pts;
 } BufferSourceContext;
 
 #define CHECK_VIDEO_PARAM_CHANGE(s, c, width, height, format)\
@@ -77,6 +78,27 @@ typedef struct BufferSourceContext {
         return AVERROR(EINVAL);\
     }
 
+static int push_if_flag(AVFilterContext *ctx, int flags)
+{
+    return (flags & AV_BUFFERSRC_FLAG_PUSH) ?
+        ctx->output_pads[0].request_frame(ctx->outputs[0]) : 0;
+}
+
+int av_buffersrc_close(AVFilterContext *ctx, int64_t pts, int flags)
+{
+    BufferSourceContext *s = ctx->priv;
+
+    if (pts == AV_NOPTS_VALUE) {
+        av_log(ctx, AV_LOG_WARNING, "No EOF timestamp\n");
+        /* FIXME use duration for audio */
+        pts = av_rescale_q(ctx->outputs[0]->current_pts,
+                           AV_TIME_BASE_Q, ctx->outputs[0]->time_base) + 1;
+    }
+    s->eof_pts = pts;
+    s->eof = 1;
+    return push_if_flag(ctx, flags);
+}
+
 int attribute_align_arg av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame)
 {
     return av_buffersrc_add_frame_flags(ctx, (AVFrame *)frame,
@@ -125,8 +147,7 @@ static int av_buffersrc_add_frame_internal(AVFilterContext *ctx,
     s->nb_failed_requests = 0;
 
     if (!frame) {
-        s->eof = 1;
-        return 0;
+        return av_buffersrc_close(ctx, AV_NOPTS_VALUE, flags);
     } else if (s->eof)
         return AVERROR(EINVAL);
 
@@ -177,11 +198,7 @@ static int av_buffersrc_add_frame_internal(AVFilterContext *ctx,
         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 push_if_flag(ctx, flags);
 }
 
 #if FF_API_AVFILTERBUFFER
@@ -211,8 +228,7 @@ int av_buffersrc_add_ref(AVFilterContext *ctx, AVFilterBufferRef *buf,
     int ret = 0, planes, i;
 
     if (!buf) {
-        s->eof = 1;
-        return 0;
+        return av_buffersrc_close(ctx, AV_NOPTS_VALUE, flags);
     } else if (s->eof)
         return AVERROR(EINVAL);
 
@@ -487,10 +503,14 @@ static int request_frame(AVFilterLink *link)
 {
     BufferSourceContext *c = link->src->priv;
     AVFrame *frame;
+    int ret;
 
     if (!av_fifo_size(c->fifo)) {
-        if (c->eof)
+        if (c->eof) {
+            if ((ret = ff_filter_link_close(link, c->eof_pts)) < 0)
+                return ret;
             return AVERROR_EOF;
+        }
         c->nb_failed_requests++;
         return AVERROR(EAGAIN);
     }
diff --git a/libavfilter/buffersrc.h b/libavfilter/buffersrc.h
index ea34c04..28ca545 100644
--- a/libavfilter/buffersrc.h
+++ b/libavfilter/buffersrc.h
@@ -145,6 +145,8 @@ int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame);
  *
  * @param buffer_src  pointer to a buffer source context
  * @param frame       a frame, or NULL to mark EOF
+ *                    (Using NULL to mark EOF is deprecated, use
+ *                    av_buffersrc_close() instead.)
  * @param flags       a combination of AV_BUFFERSRC_FLAG_*
  * @return            >= 0 in case of success, a negative AVERROR code
  *                    in case of failure
@@ -154,6 +156,19 @@ int av_buffersrc_add_frame_flags(AVFilterContext *buffer_src,
 
 
 /**
+ * Close a buffer source.
+ *
+ * This cause EOF to be propagated along the filter graph.
+ *
+ * @param buffer_src  pointer to a buffer source context
+ * @param pts         the timestamp of the end of stream
+ * @param flags       a combination of AV_BUFFERSRC_FLAG_*
+ * @return            >= 0 in case of success, a negative AVERROR code
+ *                    in case of failure
+ */
+int av_buffersrc_close(AVFilterContext *buffer_src, int64_t pts, int flags);
+
+/**
  * @}
  */
 
-- 
2.0.1



More information about the ffmpeg-devel mailing list