From patchwork Sat Jun 5 15:52:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Almer X-Patchwork-Id: 28097 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a6b:b214:0:0:0:0:0 with SMTP id b20csp2063076iof; Sat, 5 Jun 2021 08:54:03 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw5IeRiqbybcumhv2nQjIBwOvNt6fqQ86L/ij5Gvpd6i78PaYNQAyS3U9OFecRj1R6MVzsB X-Received: by 2002:a05:6402:1559:: with SMTP id p25mr11083770edx.343.1622908443002; Sat, 05 Jun 2021 08:54:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1622908442; cv=none; d=google.com; s=arc-20160816; b=irtkO/nfdtJ5sKykdr7LMwvO0nU6JvtNmtBXVZIaRQCfSkFx/d/x2g6DpWSIx5aHAp oizWLhTg+bT1nTPRaKYC7fPbttb9RiK5viv8mo8HNBFiB8cH616oEnKqSIZOK6e9a73h q9TfDcoclRht5GrfW6I9HEoUjW+lQ3eAis9r4IjrLtHXWIVXtX9djHMOZZ3dqJ5Obn1L QCBhH0N7sMMSV/c7XzF7vDBGkvhdHLFWSpqD+B7QeFCQyDvrpT5K6pcFhgOmH/fHUNr9 Qkq/wrQYh83zP9P8sQwa/+1QsjCHXfE5c+duyrjubxCI/POitd7le+Ri2rBdUecTinyN 2ICQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:message-id:date:to:from :dkim-signature:delivered-to; bh=muqf7jh5drKy6NqYoBWUfWLpNfxlzUSHh88rzjfE5EI=; b=Awn9CkeE6+CZB3cWQoJU1UZMfD57HdR2T72zWRF3aYLdS6lajkMtQ0+WEDfrqiRjyg VO+tLHpdLc9p7jSOs/bM0bjuPzQdJB+MdtcOL/zo/FrW7W+BveoqKonF+221rfERXmjl PiqFjBW6fSWtEXx3KF59DBMZx/u8E+DA8/3YO3vRDYU5ENgxMfa+m823BLyiJuFXmlCg +7QDVGMveCwV92xNeczdycFX+UodeUJRTZcVQ/ldfp9IsJTl4F5EFugNWo1ZWYIlY8Ir 79SgA4uiY2d+d09MBsTE4gmdeoCPS37/uDh4s2D0CLYACAd6CuxWYYOi7A1XXEk5YrbG 9wYg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=pb7MGlCo; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id bo19si7695371edb.416.2021.06.05.08.54.02; Sat, 05 Jun 2021 08:54:02 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=pb7MGlCo; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id D504E689C28; Sat, 5 Jun 2021 18:53:58 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qv1-f54.google.com (mail-qv1-f54.google.com [209.85.219.54]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id CC4CE689C28 for ; Sat, 5 Jun 2021 18:53:51 +0300 (EEST) Received: by mail-qv1-f54.google.com with SMTP id hf3so680271qvb.1 for ; Sat, 05 Jun 2021 08:53:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=ip6vUXkItwnaU07bUV63UfL7/Ha0yV0uuv6hQ/cLMyw=; b=pb7MGlComfFmFBZT3lEtS9nSaxUeFB7HSB1gmgiE4zrDRZ1l3hM4AP+lhV9573wSsx WrLSzSLNcCAv24VMjK/U6sMb/9A+eePX1HYkaxjzwF4kCaMHOO8zcA9x9ucN5vFJ3p7c nXiXVD8rB+05mitKsA+Ty+tNptzvhsFADfwXzOIllA4Cxs7HwpNqnit5ir8pVC35I9Ic w9rGpXjFmMBFYeBRVZOmfgkh6Tl5vn6TgFDYgAhbb83QSI40lruwf4g0QK8eQl+YbI7F 4eA9VysZLqUQk8G6v1OCxSHPGLBejxcmoS3CLeUBwZ/lAPvgY6BHsS0zqWoE2KIWSvq4 eAng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=ip6vUXkItwnaU07bUV63UfL7/Ha0yV0uuv6hQ/cLMyw=; b=HCuEU7owd4M/ZItkf0n0olReBcmMTthB+wkSod/+M5aS2/NnUDKdGEF4RJ5m6eVb+t HaFiZ8mNL/yuxYO9Nzv/Xf/Lg3USQ46l3+ggvS+vrhRLfAxTky+E4C5z82IXs0lRrWuq 8kjcRYdwFwqq/bEHtzBHTnYBWiQZXIkZc4al6ceNL9MRXL+Mqplpvzc/naNo6BQVWY6X /aHoi6aLaRtUAB9xMoQYfscs8u/luUVxQ4NWkbvugTlbFzU1haJsi92FkumkJb2Zvas4 dl2jKNhY2wJVK0kHGZ1sMY6DLCux7ab6bKoIU9ILXbpqMzLkOnG8ngdS+HjkifB3JZT3 sAXQ== X-Gm-Message-State: AOAM532It4+OLlEOZgLZ0uRqDpS4ozK9vxuNskE13nnb2BDM9fuoli3Q ePNqZ91d0cvkRWjY+y9Rw4YYEJdQc7s= X-Received: by 2002:ad4:5f0e:: with SMTP id fo14mr9940861qvb.42.1622908430385; Sat, 05 Jun 2021 08:53:50 -0700 (PDT) Received: from localhost.localdomain ([191.83.217.13]) by smtp.gmail.com with ESMTPSA id h3sm6075394qkk.82.2021.06.05.08.53.49 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 05 Jun 2021 08:53:50 -0700 (PDT) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Jun 2021 12:52:13 -0300 Message-Id: <20210605155213.3334-1-jamrial@gmail.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] avfilter/vf_fps: extend support for expressions X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: lPCX/dADQylX 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 --- 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 #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; }