diff mbox

[FFmpeg-devel,v2,2/2] avfilter/vf_fps: add eof_action filter option

Message ID 1506339079-14869-2-git-send-email-t.rapp@noa-archive.com
State Accepted
Commit 62bdec806ecd3539856dffc86542bdc46a1932c1
Headers show

Commit Message

Tobias Rapp Sept. 25, 2017, 11:31 a.m. UTC
Allows to specify the action to be performed when reading the last frame
from the internal FIFO buffer. By default the last frame is written to
filter output depending on the timestamp rounding method. When using
"pass" action the last frame is passed through if input duration
has not been reached yet.

Examples using an input file with 25Hz, 1.4sec duration:
 - "fps=fps=1:round=near" generates an output file of 1sec
 - "fps=fps=1:round=near:eof_action=pass" generates an output file of
   2sec

Signed-off-by: Tobias Rapp <t.rapp@noa-archive.com>
---
 doc/filters.texi      | 12 ++++++++++++
 libavfilter/version.h |  2 +-
 libavfilter/vf_fps.c  | 14 +++++++++++++-
 3 files changed, 26 insertions(+), 2 deletions(-)

Comments

Tobias Rapp Oct. 4, 2017, 8:45 a.m. UTC | #1
On 25.09.2017 13:31, Tobias Rapp wrote:
> Allows to specify the action to be performed when reading the last frame
> from the internal FIFO buffer. By default the last frame is written to
> filter output depending on the timestamp rounding method. When using
> "pass" action the last frame is passed through if input duration
> has not been reached yet.
> 
> Examples using an input file with 25Hz, 1.4sec duration:
>   - "fps=fps=1:round=near" generates an output file of 1sec
>   - "fps=fps=1:round=near:eof_action=pass" generates an output file of
>     2sec
> 
> Signed-off-by: Tobias Rapp <t.rapp@noa-archive.com>
> ---
>   doc/filters.texi      | 12 ++++++++++++
>   libavfilter/version.h |  2 +-
>   libavfilter/vf_fps.c  | 14 +++++++++++++-
>   3 files changed, 26 insertions(+), 2 deletions(-)
> 
> [...]

Ping.
Michael Niedermayer Oct. 4, 2017, 9:34 p.m. UTC | #2
On Mon, Sep 25, 2017 at 01:31:19PM +0200, Tobias Rapp wrote:
> Allows to specify the action to be performed when reading the last frame
> from the internal FIFO buffer. By default the last frame is written to
> filter output depending on the timestamp rounding method. When using
> "pass" action the last frame is passed through if input duration
> has not been reached yet.
> 
> Examples using an input file with 25Hz, 1.4sec duration:
>  - "fps=fps=1:round=near" generates an output file of 1sec
>  - "fps=fps=1:round=near:eof_action=pass" generates an output file of
>    2sec
> 
> Signed-off-by: Tobias Rapp <t.rapp@noa-archive.com>
> ---
>  doc/filters.texi      | 12 ++++++++++++
>  libavfilter/version.h |  2 +-
>  libavfilter/vf_fps.c  | 14 +++++++++++++-
>  3 files changed, 26 insertions(+), 2 deletions(-)

ok with me assuming noone (maybe nicolas ?) has comments

[...]
Tobias Rapp Oct. 6, 2017, 3:17 p.m. UTC | #3
On 04.10.2017 23:34, Michael Niedermayer wrote:
> On Mon, Sep 25, 2017 at 01:31:19PM +0200, Tobias Rapp wrote:
>> Allows to specify the action to be performed when reading the last frame
>> from the internal FIFO buffer. By default the last frame is written to
>> filter output depending on the timestamp rounding method. When using
>> "pass" action the last frame is passed through if input duration
>> has not been reached yet.
>>
>> Examples using an input file with 25Hz, 1.4sec duration:
>>   - "fps=fps=1:round=near" generates an output file of 1sec
>>   - "fps=fps=1:round=near:eof_action=pass" generates an output file of
>>     2sec
>>
>> Signed-off-by: Tobias Rapp <t.rapp@noa-archive.com>
>> ---
>>   doc/filters.texi      | 12 ++++++++++++
>>   libavfilter/version.h |  2 +-
>>   libavfilter/vf_fps.c  | 14 +++++++++++++-
>>   3 files changed, 26 insertions(+), 2 deletions(-)
> 
> ok with me assuming noone (maybe nicolas ?) has comments

Pushed, thanks for the review.

Regards,
Tobias
diff mbox

Patch

diff --git a/doc/filters.texi b/doc/filters.texi
index a46865f..1b48793 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -8695,6 +8695,18 @@  round to nearest
 @end table
 The default is @code{near}.
 
+@item eof_action
+Action performed when reading the last frame.
+
+Possible values are:
+@table @option
+@item round
+Use same timestamp rounding method as used for other frames.
+@item pass
+Pass through last frame if input duration has not been reached yet.
+@end table
+The default is @code{round}.
+
 @end table
 
 Alternatively, the options can be specified as a flat string:
diff --git a/libavfilter/version.h b/libavfilter/version.h
index fb382d4..8191c59 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -31,7 +31,7 @@ 
 
 #define LIBAVFILTER_VERSION_MAJOR   6
 #define LIBAVFILTER_VERSION_MINOR 106
-#define LIBAVFILTER_VERSION_MICRO 100
+#define LIBAVFILTER_VERSION_MICRO 101
 
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
                                                LIBAVFILTER_VERSION_MINOR, \
diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c
index a5e51c3..dbafd2c 100644
--- a/libavfilter/vf_fps.c
+++ b/libavfilter/vf_fps.c
@@ -40,6 +40,12 @@ 
 #include "internal.h"
 #include "video.h"
 
+enum EOFAction {
+    EOF_ACTION_ROUND,
+    EOF_ACTION_PASS,
+    EOF_ACTION_NB
+};
+
 typedef struct FPSContext {
     const AVClass *class;
 
@@ -52,6 +58,7 @@  typedef struct FPSContext {
 
     AVRational framerate;   ///< target framerate
     int rounding;           ///< AVRounding method for timestamps
+    int eof_action;         ///< action performed for last frame in FIFO
 
     /* statistics */
     int frames_in;             ///< number of frames on input
@@ -72,6 +79,9 @@  static const AVOption fps_options[] = {
         { "down", "round towards -infty",            0, AV_OPT_TYPE_CONST, { .i64 = AV_ROUND_DOWN     }, 0, 0, V|F, "round" },
         { "up",   "round towards +infty",            0, AV_OPT_TYPE_CONST, { .i64 = AV_ROUND_UP       }, 0, 0, V|F, "round" },
         { "near", "round to nearest",                0, AV_OPT_TYPE_CONST, { .i64 = AV_ROUND_NEAR_INF }, 0, 0, V|F, "round" },
+    { "eof_action", "action performed for last frame", OFFSET(eof_action), AV_OPT_TYPE_INT, { .i64 = EOF_ACTION_ROUND }, 0, EOF_ACTION_NB-1, V|F, "eof_action" },
+        { "round", "round similar to other frames",  0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_ROUND }, 0, 0, V|F, "eof_action" },
+        { "pass",  "pass through last frame",        0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_PASS  }, 0, 0, V|F, "eof_action" },
     { NULL }
 };
 
@@ -151,9 +161,11 @@  static int request_frame(AVFilterLink *outlink)
                 /* This is the last frame, we may have to duplicate it to match
                  * the last frame duration */
                 int j;
+                int eof_rounding = (s->eof_action == EOF_ACTION_PASS) ? AV_ROUND_UP : s->rounding;
                 int delta = av_rescale_q_rnd(ctx->inputs[0]->current_pts - s->first_pts,
                                              ctx->inputs[0]->time_base,
-                                             outlink->time_base, s->rounding) - s->frames_out ;
+                                             outlink->time_base, eof_rounding) - s->frames_out;
+                av_log(ctx, AV_LOG_DEBUG, "EOF frames_out:%d delta:%d\n", s->frames_out, delta);
                 /* if the delta is equal to 1, it means we just need to output
                  * the last frame. Greater than 1 means we will need duplicate
                  * delta-1 frames */