[FFmpeg-devel] [PATCH 4/4] lavfi/vf_fps: accept EOF timestamp.

Nicolas George george at nsup.org
Thu Jul 24 15:39:45 CEST 2014


This makes the FPS filter duplicate the last frame to take
its duration into account, exactly like the other ones.

TODO find corresponding trac ticket(s).

Signed-off-by: Nicolas George <george at nsup.org>
---
 libavfilter/vf_fps.c | 59 +++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 40 insertions(+), 19 deletions(-)


Note: this will not work if there are filters before vf_fps, unless they
are converted to accept messages and forward the end timestamp.
When more filters are adapted, a warning could be added.


diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c
index a38633d..7028f28 100644
--- a/libavfilter/vf_fps.c
+++ b/libavfilter/vf_fps.c
@@ -28,6 +28,7 @@
 #include <float.h>
 #include <stdint.h>
 
+#include "libavutil/avassert.h"
 #include "libavutil/common.h"
 #include "libavutil/fifo.h"
 #include "libavutil/mathematics.h"
@@ -88,11 +89,13 @@ static av_cold int init(AVFilterContext *ctx)
     return 0;
 }
 
+/* FIXME: misnommer, the frames are discarded, not flushed */
 static void flush_fifo(AVFifoBuffer *fifo)
 {
     while (av_fifo_size(fifo)) {
         AVFrame *tmp;
         av_fifo_generic_read(fifo, &tmp, sizeof(tmp), NULL);
+        av_log(0, 16, "discard frame %d %ld\n", tmp->format, tmp->pts);
         av_frame_free(&tmp);
     }
 }
@@ -131,25 +134,10 @@ static int request_frame(AVFilterLink *outlink)
 
     while (ret >= 0 && s->frames_out == frames_out)
         ret = ff_request_frame(ctx->inputs[0]);
-
-    /* flush the fifo */
-    if (ret == AVERROR_EOF && av_fifo_size(s->fifo)) {
-        int i;
-        for (i = 0; av_fifo_size(s->fifo); i++) {
-            AVFrame *buf;
-
-            av_fifo_generic_read(s->fifo, &buf, sizeof(buf), NULL);
-            buf->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base,
-                                    outlink->time_base) + s->frames_out;
-
-            if ((ret = ff_filter_frame(outlink, buf)) < 0)
-                return ret;
-
-            s->frames_out++;
-        }
-        return 0;
+    if (ret == AVERROR_EOF) {
+        flush_fifo(s->fifo);
+        av_assert1(!av_fifo_size(s->fifo));
     }
-
     return ret;
 }
 
@@ -157,6 +145,7 @@ static int write_to_fifo(AVFifoBuffer *fifo, AVFrame *buf)
 {
     int ret;
 
+    av_assert1(buf->format >= 0);
     if (!av_fifo_space(fifo) &&
         (ret = av_fifo_realloc2(fifo, 2*av_fifo_size(fifo)))) {
         av_frame_free(&buf);
@@ -167,6 +156,25 @@ static int write_to_fifo(AVFifoBuffer *fifo, AVFrame *buf)
     return 0;
 }
 
+static int flush_fifo_to_out(AVFilterContext *ctx)
+{
+    FPSContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+    AVFrame *frame;
+    int ret;
+
+    while (av_fifo_size(s->fifo)) {
+
+        av_fifo_generic_read(s->fifo, &frame, sizeof(frame), NULL);
+        frame->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base,
+                                outlink->time_base) + s->frames_out;
+        if ((ret = ff_filter_frame(outlink, frame)) < 0)
+            return ret;
+        s->frames_out++;
+    }
+    return 0;
+}
+
 static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
 {
     AVFilterContext    *ctx = inlink->dst;
@@ -194,6 +202,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
             } else {
                 s->first_pts = buf->pts;
             }
+        } else if (buf->format < 0) {
+            return 0;
         } else {
             av_log(ctx, AV_LOG_WARNING, "Discarding initial frame(s) with no "
                    "timestamp.\n");
@@ -203,8 +213,18 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
         return 0;
     }
 
+    if (buf->format < 0) {
+        if (buf->format != FF_FRAME_MSG_EOF)
+            return 0;
+        if (buf->pts == AV_NOPTS_VALUE)
+            return flush_fifo_to_out(ctx);
+        if (!av_fifo_size(s->fifo))
+            return 0;
+    }
+
     /* now wait for the next timestamp */
     if (buf->pts == AV_NOPTS_VALUE || av_fifo_size(s->fifo) <= 0) {
+        av_assert1(buf->format >= 0);
         return write_to_fifo(s->fifo, buf);
     }
 
@@ -264,7 +284,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
     }
     flush_fifo(s->fifo);
 
-    ret = write_to_fifo(s->fifo, buf);
+    ret = buf->format < 0 ? 0 : write_to_fifo(s->fifo, buf);
 
     return ret;
 }
@@ -295,6 +315,7 @@ AVFilter ff_vf_fps = {
     .uninit      = uninit,
     .priv_size   = sizeof(FPSContext),
     .priv_class  = &fps_class,
+    .flags       = FF_FILTER_FLAG_SUPPORT_MESSAGES,
     .inputs      = avfilter_vf_fps_inputs,
     .outputs     = avfilter_vf_fps_outputs,
 };
-- 
2.0.1



More information about the ffmpeg-devel mailing list