[FFmpeg-devel] [PATCH] avfilter/vf_fps: extend support for expressions
Gyan Doshi
ffmpeg at gyani.pro
Sat Jun 19 22:56:38 EEST 2021
On 2021-06-05 21:22, James Almer wrote:
> AV_OPT_TYPE_VIDEO_RATE AVOption types are parsed as expressions, but in a
> limited way. For example, name constants can only be parsed alone and not as
> part of a longer expression.
>
> This change allows usage like
>
> ffmpeg -i IN -vf fps="if(eq(source_fps\,film)\,ntsc_film\,source_fps)" OUT
>
> Suggested-by: ffmpeg at fb.com
> Signed-off-by: James Almer <jamrial at gmail.com>
> ---
> libavfilter/vf_fps.c | 65 ++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 60 insertions(+), 5 deletions(-)
>
> diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c
> index b7b2d6f2db..29588a5f6e 100644
> --- a/libavfilter/vf_fps.c
> +++ b/libavfilter/vf_fps.c
> @@ -30,6 +30,7 @@
> #include <stdint.h>
>
> #include "libavutil/avassert.h"
> +#include "libavutil/eval.h"
> #include "libavutil/mathematics.h"
> #include "libavutil/opt.h"
> #include "avfilter.h"
> @@ -42,12 +43,47 @@ enum EOFAction {
> EOF_ACTION_NB
> };
>
> +static const char *const var_names[] = {
> + "source_fps",
> + "ntsc",
> + "pal",
> + "qntsc",
> + "qpal",
> + "sntsc",
> + "spal",
> + "film",
> + "ntsc_film",
> + NULL
> +};
> +
> +enum var_name {
> + VAR_SOURCE_FPS,
> + VAR_FPS_NTSC,
> + VAR_FPS_PAL,
> + VAR_FPS_QNTSC,
> + VAR_FPS_QPAL,
> + VAR_FPS_SNTSC,
> + VAR_FPS_SPAL,
> + VAR_FPS_FILM,
> + VAR_FPS_NTSC_FILM,
> + VARS_NB
> +};
> +
> +static const double ntsc_fps = 30000.0 / 1001.0;
> +static const double pal_fps = 25.0;
> +static const double qntsc_fps = 30000.0 / 1001.0;
> +static const double qpal_fps = 25.0;
> +static const double sntsc_fps = 30000.0 / 1001.0;
> +static const double spal_fps = 25.0;
> +static const double film_fps = 24.0;
> +static const double ntsc_film_fps = 24000.0 / 1001.0;
Sorry, I missed this before you applied it but what's the q- and s-
prefixed standards with identical rates?
I can't find any specs or docs online.
> +
> typedef struct FPSContext {
> const AVClass *class;
>
> double start_time; ///< pts, in seconds, of the expected first frame
>
> - AVRational framerate; ///< target framerate
> + char *framerate; ///< expression that defines the target framerate
> int rounding; ///< AVRounding method for timestamps
> int eof_action; ///< action performed for last frame in FIFO
>
> @@ -76,7 +112,7 @@ typedef struct FPSContext {
> #define V AV_OPT_FLAG_VIDEO_PARAM
> #define F AV_OPT_FLAG_FILTERING_PARAM
> static const AVOption fps_options[] = {
> - { "fps", "A string describing desired output framerate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, { .str = "25" }, 0, INT_MAX, V|F },
> + { "fps", "A string describing desired output framerate", OFFSET(framerate), AV_OPT_TYPE_STRING, { .str = "25" }, 0, 0, V|F },
> { "start_time", "Assume the first PTS should be this value.", OFFSET(start_time), AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX}, -DBL_MAX, DBL_MAX, V|F },
> { "round", "set rounding method for timestamps", OFFSET(rounding), AV_OPT_TYPE_INT, { .i64 = AV_ROUND_NEAR_INF }, 0, 5, V|F, "round" },
> { "zero", "round towards 0", 0, AV_OPT_TYPE_CONST, { .i64 = AV_ROUND_ZERO }, 0, 0, V|F, "round" },
> @@ -99,7 +135,6 @@ 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);
> return 0;
> }
>
> @@ -153,8 +188,26 @@ static int config_props(AVFilterLink* outlink)
> AVFilterLink *inlink = ctx->inputs[0];
> FPSContext *s = ctx->priv;
>
> - outlink->time_base = av_inv_q(s->framerate);
> - outlink->frame_rate = s->framerate;
> + double var_values[VARS_NB], res;
> + int ret;
> +
> + var_values[VAR_SOURCE_FPS] = av_q2d(inlink->frame_rate);
> + var_values[VAR_FPS_NTSC] = ntsc_fps;
> + var_values[VAR_FPS_PAL] = pal_fps;
> + var_values[VAR_FPS_QNTSC] = qntsc_fps;
> + var_values[VAR_FPS_QPAL] = qpal_fps;
> + var_values[VAR_FPS_SNTSC] = sntsc_fps;
> + var_values[VAR_FPS_SPAL] = spal_fps;
> + var_values[VAR_FPS_FILM] = film_fps;
> + var_values[VAR_FPS_NTSC_FILM] = ntsc_film_fps;
> + ret = av_expr_parse_and_eval(&res, s->framerate,
> + var_names, var_values,
> + NULL, NULL, NULL, NULL, NULL, 0, ctx);
> + if (ret < 0)
> + return ret;
> +
> + outlink->frame_rate = av_d2q(res, INT_MAX);
> + outlink->time_base = av_inv_q(outlink->frame_rate);
>
> /* Calculate the input and output pts offsets for start_time */
> if (s->start_time != DBL_MAX && s->start_time != AV_NOPTS_VALUE) {
> @@ -173,6 +226,8 @@ static int config_props(AVFilterLink* outlink)
> s->in_pts_off, s->out_pts_off, s->start_time);
> }
>
> + av_log(ctx, AV_LOG_VERBOSE, "fps=%d/%d\n", outlink->frame_rate.num, outlink->frame_rate.den);
> +
> return 0;
> }
>
More information about the ffmpeg-devel
mailing list