diff mbox

[FFmpeg-devel,1/2] avfilter/vf_fps: add way to get CFR output without knowing input frame rate

Message ID 20191029134744.470-1-onemda@gmail.com
State Superseded
Headers show

Commit Message

Paul B Mahol Oct. 29, 2019, 1:47 p.m. UTC
Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
 doc/filters.texi     |  3 +++
 libavfilter/vf_fps.c | 10 +++++++++-
 2 files changed, 12 insertions(+), 1 deletion(-)

Comments

Gyan Doshi Oct. 29, 2019, 1:53 p.m. UTC | #1
On 29-10-2019 07:17 PM, Paul B Mahol wrote:
> Signed-off-by: Paul B Mahol <onemda@gmail.com>
> ---
>   doc/filters.texi     |  3 +++
>   libavfilter/vf_fps.c | 10 +++++++++-
>   2 files changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/doc/filters.texi b/doc/filters.texi
> index 11f715319a..1e815bf940 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -10737,6 +10737,9 @@ Pass through last frame if input duration has not been reached yet.
>   @end table
>   The default is @code{round}.
>   
> +@item input
> +Pick output frame rate from input if it is available. The default is disabled.
> +Useful to change input to constant frame rate without needing to know input frame rate.
>   @end table
>   
>   Alternatively, the options can be specified as a flat string:
> diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c
> index cf1e36726a..3561332f0e 100644
> --- a/libavfilter/vf_fps.c
> +++ b/libavfilter/vf_fps.c
> @@ -70,6 +70,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 input;                 ///< should filter use input framerate if one is set
>   } FPSContext;
>   
>   #define OFFSET(x) offsetof(FPSContext, x)
> @@ -87,6 +88,7 @@ static const AVOption fps_options[] = {
>       { "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" },
> +    { "input", "use input framerate is available", OFFSET(input), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, V|F },
>       { NULL }
>   };
>   
> @@ -99,7 +101,8 @@ static av_cold int init(AVFilterContext *ctx)
>       s->status_pts   = AV_NOPTS_VALUE;
>       s->next_pts     = AV_NOPTS_VALUE;
>   
> -    av_log(ctx, AV_LOG_VERBOSE, "fps=%d/%d\n", s->framerate.num, s->framerate.den);
> +    if (!s->input)
> +        av_log(ctx, AV_LOG_VERBOSE, "fps=%d/%d\n", s->framerate.num, s->framerate.den);
>       return 0;
>   }
>   
> @@ -153,8 +156,13 @@ static int config_props(AVFilterLink* outlink)
>       AVFilterLink    *inlink = ctx->inputs[0];
>       FPSContext      *s      = ctx->priv;
>   
> +    if (s->input && inlink->frame_rate.num > 0 && inlink->frame_rate.den > 0) {
> +        outlink->time_base  = av_inv_q(inlink->frame_rate);
> +        outlink->frame_rate = inlink->frame_rate;

Maybe add some sanity checks for very high frame rates e.g. some WebMs 
whose video fps is detected as 1000.

> +    } else {
>       outlink->time_base  = av_inv_q(s->framerate);
>       outlink->frame_rate = s->framerate;
> +    }
>   
>       /* Calculate the input and output pts offsets for start_time */
>       if (s->start_time != DBL_MAX && s->start_time != AV_NOPTS_VALUE) {

Gyan
Paul B Mahol Oct. 29, 2019, 2 p.m. UTC | #2
On 10/29/19, Gyan <ffmpeg@gyani.pro> wrote:
>
>
> On 29-10-2019 07:17 PM, Paul B Mahol wrote:
>> Signed-off-by: Paul B Mahol <onemda@gmail.com>
>> ---
>>   doc/filters.texi     |  3 +++
>>   libavfilter/vf_fps.c | 10 +++++++++-
>>   2 files changed, 12 insertions(+), 1 deletion(-)
>>
>> diff --git a/doc/filters.texi b/doc/filters.texi
>> index 11f715319a..1e815bf940 100644
>> --- a/doc/filters.texi
>> +++ b/doc/filters.texi
>> @@ -10737,6 +10737,9 @@ Pass through last frame if input duration has not
>> been reached yet.
>>   @end table
>>   The default is @code{round}.
>>
>> +@item input
>> +Pick output frame rate from input if it is available. The default is
>> disabled.
>> +Useful to change input to constant frame rate without needing to know
>> input frame rate.
>>   @end table
>>
>>   Alternatively, the options can be specified as a flat string:
>> diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c
>> index cf1e36726a..3561332f0e 100644
>> --- a/libavfilter/vf_fps.c
>> +++ b/libavfilter/vf_fps.c
>> @@ -70,6 +70,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 input;                 ///< should filter use input framerate if
>> one is set
>>   } FPSContext;
>>
>>   #define OFFSET(x) offsetof(FPSContext, x)
>> @@ -87,6 +88,7 @@ static const AVOption fps_options[] = {
>>       { "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" },
>> +    { "input", "use input framerate is available", OFFSET(input),
>> AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, V|F },
>>       { NULL }
>>   };
>>
>> @@ -99,7 +101,8 @@ static av_cold int init(AVFilterContext *ctx)
>>       s->status_pts   = AV_NOPTS_VALUE;
>>       s->next_pts     = AV_NOPTS_VALUE;
>>
>> -    av_log(ctx, AV_LOG_VERBOSE, "fps=%d/%d\n", s->framerate.num,
>> s->framerate.den);
>> +    if (!s->input)
>> +        av_log(ctx, AV_LOG_VERBOSE, "fps=%d/%d\n", s->framerate.num,
>> s->framerate.den);
>>       return 0;
>>   }
>>
>> @@ -153,8 +156,13 @@ static int config_props(AVFilterLink* outlink)
>>       AVFilterLink    *inlink = ctx->inputs[0];
>>       FPSContext      *s      = ctx->priv;
>>
>> +    if (s->input && inlink->frame_rate.num > 0 && inlink->frame_rate.den
>> > 0) {
>> +        outlink->time_base  = av_inv_q(inlink->frame_rate);
>> +        outlink->frame_rate = inlink->frame_rate;
>
> Maybe add some sanity checks for very high frame rates e.g. some WebMs
> whose video fps is detected as 1000.

Not needed.

>
>> +    } else {
>>       outlink->time_base  = av_inv_q(s->framerate);
>>       outlink->frame_rate = s->framerate;
>> +    }
>>
>>       /* Calculate the input and output pts offsets for start_time */
>>       if (s->start_time != DBL_MAX && s->start_time != AV_NOPTS_VALUE) {
>
> Gyan
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Moritz Barsnick Oct. 29, 2019, 2:32 p.m. UTC | #3
On Tue, Oct 29, 2019 at 14:47:43 +0100, Paul B Mahol wrote:
> +    { "input", "use input framerate is available", OFFSET(input), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, V|F },

I assume you meant:
is -> if

> -    av_log(ctx, AV_LOG_VERBOSE, "fps=%d/%d\n", s->framerate.num, s->framerate.den);
> +    if (!s->input)
> +        av_log(ctx, AV_LOG_VERBOSE, "fps=%d/%d\n", s->framerate.num, s->framerate.den);

Could it still be reported elsewhere? Like down there:

> +    if (s->input && inlink->frame_rate.num > 0 && inlink->frame_rate.den > 0) {
> +        outlink->time_base  = av_inv_q(inlink->frame_rate);
> +        outlink->frame_rate = inlink->frame_rate;
> +    } else {
>      outlink->time_base  = av_inv_q(s->framerate);
>      outlink->frame_rate = s->framerate;
> +    }

Now the used framerate is known, could be reported here?

Moritz
diff mbox

Patch

diff --git a/doc/filters.texi b/doc/filters.texi
index 11f715319a..1e815bf940 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -10737,6 +10737,9 @@  Pass through last frame if input duration has not been reached yet.
 @end table
 The default is @code{round}.
 
+@item input
+Pick output frame rate from input if it is available. The default is disabled.
+Useful to change input to constant frame rate without needing to know input frame rate.
 @end table
 
 Alternatively, the options can be specified as a flat string:
diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c
index cf1e36726a..3561332f0e 100644
--- a/libavfilter/vf_fps.c
+++ b/libavfilter/vf_fps.c
@@ -70,6 +70,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 input;                 ///< should filter use input framerate if one is set
 } FPSContext;
 
 #define OFFSET(x) offsetof(FPSContext, x)
@@ -87,6 +88,7 @@  static const AVOption fps_options[] = {
     { "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" },
+    { "input", "use input framerate is available", OFFSET(input), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, V|F },
     { NULL }
 };
 
@@ -99,7 +101,8 @@  static av_cold int init(AVFilterContext *ctx)
     s->status_pts   = AV_NOPTS_VALUE;
     s->next_pts     = AV_NOPTS_VALUE;
 
-    av_log(ctx, AV_LOG_VERBOSE, "fps=%d/%d\n", s->framerate.num, s->framerate.den);
+    if (!s->input)
+        av_log(ctx, AV_LOG_VERBOSE, "fps=%d/%d\n", s->framerate.num, s->framerate.den);
     return 0;
 }
 
@@ -153,8 +156,13 @@  static int config_props(AVFilterLink* outlink)
     AVFilterLink    *inlink = ctx->inputs[0];
     FPSContext      *s      = ctx->priv;
 
+    if (s->input && inlink->frame_rate.num > 0 && inlink->frame_rate.den > 0) {
+        outlink->time_base  = av_inv_q(inlink->frame_rate);
+        outlink->frame_rate = inlink->frame_rate;
+    } else {
     outlink->time_base  = av_inv_q(s->framerate);
     outlink->frame_rate = s->framerate;
+    }
 
     /* Calculate the input and output pts offsets for start_time */
     if (s->start_time != DBL_MAX && s->start_time != AV_NOPTS_VALUE) {