From eb1aa837acc495c6e86cdb8577a8c361252c7d54 Mon Sep 17 00:00:00 2001
From: Thomas Mundt <tmundt75@gmail.com>
Date: Tue, 13 Jun 2017 18:55:20 +0200
Subject: [PATCH] avfilter/vf_fps: fix duration

Fix ticket #2674
This makes the fps filter take account of the duration of constant frame rate input files.

Signed-off-by: Thomas Mundt <tmundt75@gmail.com>
---
 libavfilter/vf_fps.c        | 35 +++++++++++++++++++++++++++++------
 tests/ref/fate/filter-fps   | 19 +++++++++++++++++++
 tests/ref/fate/filter-fps-r | 15 +++++++++++++++
 3 files changed, 63 insertions(+), 6 deletions(-)

diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c
index 20ccd79..123f26d 100644
--- a/libavfilter/vf_fps.c
+++ b/libavfilter/vf_fps.c
@@ -56,6 +56,7 @@ typedef struct FPSContext {
     int frames_out;            ///< number of frames on output
     int dup;                   ///< number of frames duplicated
     int drop;                  ///< number of framed dropped
+    int frames_in_proc;        ///< number of input frames processed
 } FPSContext;
 
 #define OFFSET(x) offsetof(FPSContext, x)
@@ -126,24 +127,45 @@ static int request_frame(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
     FPSContext        *s = ctx->priv;
+    AVFilterLink *inlink = ctx->inputs[0];
     int ret;
 
-    ret = ff_request_frame(ctx->inputs[0]);
+    ret = ff_request_frame(inlink);
 
     /* flush the fifo */
     if (ret == AVERROR_EOF && av_fifo_size(s->fifo)) {
         int i;
         for (i = 0; av_fifo_size(s->fifo); i++) {
+            int j, delta;
             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;
+            // FIXME this calculation is wrong for variable frame rates
+            if (s->frames_in_proc) {
+                delta = av_rescale_q_rnd((s->frames_in_proc + 1) *
+                                         (buf->pts - s->first_pts) /
+                                         s->frames_in_proc, inlink->time_base,
+                                         outlink->time_base, s->rounding) -
+                                         s->frames_out;
+            } else
+                delta = 1;
+
+            if (delta < 1) {
+                s->drop++;
+                continue;
+            }
+            for (j = 0; j < delta; j++) {
+                AVFrame *out = av_frame_clone(buf);
+                out->pts = av_rescale_q(s->first_pts, inlink->time_base,
+                                        outlink->time_base) + s->frames_out;
 
-            if ((ret = ff_filter_frame(outlink, buf)) < 0)
-                return ret;
+                if ((ret = ff_filter_frame(outlink, out)) < 0)
+                    return ret;
 
-            s->frames_out++;
+                s->frames_out++;
+                if (j)
+                    s->dup++;
+            }
         }
         return 0;
     }
@@ -206,6 +228,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
         return write_to_fifo(s->fifo, buf);
     }
 
+    s->frames_in_proc++;
     /* number of output frames */
     delta = av_rescale_q_rnd(buf->pts - s->first_pts, inlink->time_base,
                              outlink->time_base, s->rounding) - s->frames_out ;
diff --git a/tests/ref/fate/filter-fps b/tests/ref/fate/filter-fps
index 55712cf..8d7cff4 100644
--- a/tests/ref/fate/filter-fps
+++ b/tests/ref/fate/filter-fps
@@ -85,3 +85,22 @@
 0,         79,         79,        1,    30576, 0xa2fcd06f
 0,         80,         80,        1,    30576, 0xa2fcd06f
 0,         81,         81,        1,    30576, 0xd4150aad
+0,         82,         82,        1,    30576, 0xd4150aad
+0,         83,         83,        1,    30576, 0xd4150aad
+0,         84,         84,        1,    30576, 0xd4150aad
+0,         85,         85,        1,    30576, 0xd4150aad
+0,         86,         86,        1,    30576, 0xd4150aad
+0,         87,         87,        1,    30576, 0xd4150aad
+0,         88,         88,        1,    30576, 0xd4150aad
+0,         89,         89,        1,    30576, 0xd4150aad
+0,         90,         90,        1,    30576, 0xd4150aad
+0,         91,         91,        1,    30576, 0xd4150aad
+0,         92,         92,        1,    30576, 0xd4150aad
+0,         93,         93,        1,    30576, 0xd4150aad
+0,         94,         94,        1,    30576, 0xd4150aad
+0,         95,         95,        1,    30576, 0xd4150aad
+0,         96,         96,        1,    30576, 0xd4150aad
+0,         97,         97,        1,    30576, 0xd4150aad
+0,         98,         98,        1,    30576, 0xd4150aad
+0,         99,         99,        1,    30576, 0xd4150aad
+0,        100,        100,        1,    30576, 0xd4150aad
diff --git a/tests/ref/fate/filter-fps-r b/tests/ref/fate/filter-fps-r
index 826b1ed..6e9da45 100644
--- a/tests/ref/fate/filter-fps-r
+++ b/tests/ref/fate/filter-fps-r
@@ -72,3 +72,18 @@
 0,         79,         79,        1,    30576, 0xa2fcd06f
 0,         80,         80,        1,    30576, 0xa2fcd06f
 0,         82,         82,        1,    30576, 0xd4150aad
+0,         83,         83,        1,    30576, 0xd4150aad
+0,         84,         84,        1,    30576, 0xd4150aad
+0,         85,         85,        1,    30576, 0xd4150aad
+0,         86,         86,        1,    30576, 0xd4150aad
+0,         88,         88,        1,    30576, 0xd4150aad
+0,         89,         89,        1,    30576, 0xd4150aad
+0,         90,         90,        1,    30576, 0xd4150aad
+0,         91,         91,        1,    30576, 0xd4150aad
+0,         92,         92,        1,    30576, 0xd4150aad
+0,         94,         94,        1,    30576, 0xd4150aad
+0,         95,         95,        1,    30576, 0xd4150aad
+0,         96,         96,        1,    30576, 0xd4150aad
+0,         97,         97,        1,    30576, 0xd4150aad
+0,         98,         98,        1,    30576, 0xd4150aad
+0,        100,        100,        1,    30576, 0xd4150aad
-- 
2.7.4.windows.1

