summaryrefslogtreecommitdiff
path: root/libavfilter/vf_fps.c
diff options
context:
space:
mode:
authorJames Almer <jamrial@gmail.com>2021-02-24 14:40:04 -0300
committerJames Almer <jamrial@gmail.com>2021-06-13 17:32:45 -0300
commitdd770883e976c91feeb8de58eacd97dfb4e8308e (patch)
tree429bc82a8971c2a790fde36fad3d37944883a5d6 /libavfilter/vf_fps.c
parent91ba771a3fee9757273416789ba01e1a7c62890b (diff)
downloadffmpeg-dd770883e976c91feeb8de58eacd97dfb4e8308e.tar.gz
avfilter/vf_fps: extend support for expressions
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@fb.com Signed-off-by: James Almer <jamrial@gmail.com>
Diffstat (limited to 'libavfilter/vf_fps.c')
-rw-r--r--libavfilter/vf_fps.c65
1 files 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;
+
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;
}