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

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


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

Fix trac ticket #2674.

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


Aded a ref to the trac ticket and fixed a corner case raised by it.
Note that the whole logic of vf_fps is overly complex, but this is for
another patch.


diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c
index a3ad1bb..5bf5bda 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"
@@ -150,10 +151,8 @@ 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))
-        return flush_fifo_to_out(ctx);
+    if (ret == AVERROR_EOF)
+        av_assert1(!av_fifo_size(s->fifo));
     return ret;
 }
 
@@ -161,6 +160,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);
@@ -198,6 +198,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");
@@ -207,8 +209,18 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
         return 0;
     }
 
+    if (buf->format < 0) {
+        if (buf->format != FF_METAFRAME_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);
     }
 
@@ -226,10 +238,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
 
         av_fifo_generic_read(s->fifo, &tmp, sizeof(tmp), NULL);
         flush_fifo(s->fifo);
-        ret = write_to_fifo(s->fifo, tmp);
 
-        av_frame_free(&buf);
-        return ret;
+        if (buf->format >= 0) {
+            /* requeue last frame if not EOF */
+            ret = write_to_fifo(s->fifo, tmp);
+            av_frame_free(&buf);
+            return ret;
+        }
+        return 0;
     }
 
     /* can output >= 1 frames */
@@ -268,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;
 }
@@ -299,6 +315,7 @@ AVFilter ff_vf_fps = {
     .uninit      = uninit,
     .priv_size   = sizeof(FPSContext),
     .priv_class  = &fps_class,
+    .flags       = FF_FILTER_FLAG_SUPPORT_METAFRAMES,
     .inputs      = avfilter_vf_fps_inputs,
     .outputs     = avfilter_vf_fps_outputs,
 };
-- 
2.0.1



More information about the ffmpeg-devel mailing list