From patchwork Sun Dec 15 17:07:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gyan Doshi X-Patchwork-Id: 16804 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 3470B44819F for ; Sun, 15 Dec 2019 19:07:39 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1BCF968A3ED; Sun, 15 Dec 2019 19:07:39 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mout-p-202.mailbox.org (mout-p-202.mailbox.org [80.241.56.172]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 83350689CFF for ; Sun, 15 Dec 2019 19:07:32 +0200 (EET) Received: from smtp2.mailbox.org (smtp2.mailbox.org [80.241.60.241]) (using TLSv1.2 with cipher ECDHE-RSA-CHACHA20-POLY1305 (256/256 bits)) (No client certificate requested) by mout-p-202.mailbox.org (Postfix) with ESMTPS id 47bW6r1GTGzQlCg for ; Sun, 15 Dec 2019 18:07:32 +0100 (CET) X-Virus-Scanned: amavisd-new at heinlein-support.de Received: from smtp2.mailbox.org ([80.241.60.241]) by spamfilter05.heinlein-hosting.de (spamfilter05.heinlein-hosting.de [80.241.56.123]) (amavisd-new, port 10030) with ESMTP id AMzeJ5viGiY0 for ; Sun, 15 Dec 2019 18:07:25 +0100 (CET) To: FFmpeg development discussions and patches From: Gyan Message-ID: <066cf0ff-d208-c57b-b5cf-687d37e9cf06@gyani.pro> Date: Sun, 15 Dec 2019 22:37:13 +0530 MIME-Version: 1.0 Content-Language: en-US Subject: [FFmpeg-devel] [PATCH 4/5] avfilter/scale: add function to check expressions X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 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" 4th of 5 factorized patches; supersedes https://patchwork.ffmpeg.org/patch/16272/ From 4428afaba039756f47c177f2533fe23c0bfb4bc1 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Fri, 13 Dec 2019 00:12:53 +0530 Subject: [PATCH 4/5] avfilter/scale: add function to check expressions Allows finer identification and logging of invalid expressions and use of a single list for symbols and their index for both scale and scale2ref. --- libavfilter/vf_scale.c | 122 +++++++++++++++++++++++------------------ 1 file changed, 70 insertions(+), 52 deletions(-) diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index 8eb74bf7dc..225fb2ff83 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -54,6 +54,13 @@ static const char *const var_names[] = { "vsub", "ohsub", "ovsub", + "main_w", + "main_h", + "main_a", + "main_sar", + "main_dar", "mdar", + "main_hsub", + "main_vsub", NULL }; @@ -69,39 +76,6 @@ enum var_name { VAR_VSUB, VAR_OHSUB, VAR_OVSUB, - VARS_NB -}; - -/** - * This must be kept in sync with var_names so that it is always a - * complete list of var_names with the scale2ref specific names - * appended. scale2ref values must appear in the order they appear - * in the var_name_scale2ref enum but also be below all of the - * non-scale2ref specific values. - */ -static const char *const var_names_scale2ref[] = { - "in_w", "iw", - "in_h", "ih", - "out_w", "ow", - "out_h", "oh", - "a", - "sar", - "dar", - "hsub", - "vsub", - "ohsub", - "ovsub", - "main_w", - "main_h", - "main_a", - "main_sar", - "main_dar", "mdar", - "main_hsub", - "main_vsub", - NULL -}; - -enum var_name_scale2ref { VAR_S2R_MAIN_W, VAR_S2R_MAIN_H, VAR_S2R_MAIN_A, @@ -109,7 +83,7 @@ enum var_name_scale2ref { VAR_S2R_MAIN_DAR, VAR_S2R_MDAR, VAR_S2R_MAIN_HSUB, VAR_S2R_MAIN_VSUB, - VARS_S2R_NB + VARS_NB }; enum EvalMode { @@ -145,7 +119,7 @@ typedef struct ScaleContext { char *h_expr; ///< height expression string AVExpr *w_pexpr; AVExpr *h_pexpr; - double var_values[VARS_NB + VARS_S2R_NB]; + double var_values[VARS_NB]; char *flags_str; @@ -171,12 +145,53 @@ typedef struct ScaleContext { AVFilter ff_vf_scale2ref; +static int check_exprs(AVFilterContext *ctx) +{ + ScaleContext *scale = ctx->priv; + unsigned vars_w[VARS_NB] = { 0 }, vars_h[VARS_NB] = { 0 }; + + if (!scale->w_pexpr || !scale->h_pexpr) + return AVERROR(EINVAL); + + av_expr_count_vars(scale->w_pexpr, vars_w, VARS_NB); + av_expr_count_vars(scale->h_pexpr, vars_h, VARS_NB); + + if (vars_w[VAR_OUT_W] || vars_w[VAR_OW]) { + av_log(ctx, AV_LOG_ERROR, "Width expression cannot be self-referencing: '%s'.\n", scale->w_expr); + return AVERROR(EINVAL); + } + + if (vars_h[VAR_OUT_H] || vars_h[VAR_OH]) { + av_log(ctx, AV_LOG_ERROR, "Height expression cannot be self-referencing: '%s'.\n", scale->h_expr); + return AVERROR(EINVAL); + } + + if ((vars_w[VAR_OUT_H] || vars_w[VAR_OH]) && + (vars_h[VAR_OUT_W] || vars_h[VAR_OW])) { + av_log(ctx, AV_LOG_ERROR, "Circular expressions invalid for width '%s' and height '%s'.\n", scale->w_expr, scale->h_expr); + return AVERROR(EINVAL); + } + + if (ctx->filter != &ff_vf_scale2ref && + (vars_w[VAR_S2R_MAIN_W] || vars_h[VAR_S2R_MAIN_W] || + vars_w[VAR_S2R_MAIN_H] || vars_h[VAR_S2R_MAIN_H] || + vars_w[VAR_S2R_MAIN_A] || vars_h[VAR_S2R_MAIN_A] || + vars_w[VAR_S2R_MAIN_SAR] || vars_h[VAR_S2R_MAIN_SAR] || + vars_w[VAR_S2R_MAIN_DAR] || vars_h[VAR_S2R_MAIN_DAR] || + vars_w[VAR_S2R_MDAR] || vars_h[VAR_S2R_MDAR] || + vars_w[VAR_S2R_MAIN_HSUB] || vars_h[VAR_S2R_MAIN_HSUB] || + vars_w[VAR_S2R_MAIN_VSUB] || vars_h[VAR_S2R_MAIN_VSUB]) ) { + av_log(ctx, AV_LOG_ERROR, "Expressions with scale2ref variables are not valid in scale filter.\n"); + return AVERROR(EINVAL); + } + + return 0; +} + static av_cold int init_dict(AVFilterContext *ctx, AVDictionary **opts) { ScaleContext *scale = ctx->priv; int ret; - const char scale2ref = ctx->filter == &ff_vf_scale2ref; - const char *const *names = scale2ref ? var_names_scale2ref : var_names; if (scale->size_str && (scale->w_expr || scale->h_expr)) { av_log(ctx, AV_LOG_ERROR, @@ -205,7 +220,7 @@ static av_cold int init_dict(AVFilterContext *ctx, AVDictionary **opts) av_opt_set(scale, "h", "ih", 0); ret = av_expr_parse(&scale->w_pexpr, scale->w_expr, - names, + var_names, NULL, NULL, NULL, NULL, 0, ctx); if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Cannot parse width expression: '%s'\n", scale->w_expr); @@ -213,13 +228,17 @@ static av_cold int init_dict(AVFilterContext *ctx, AVDictionary **opts) } ret = av_expr_parse(&scale->h_pexpr, scale->h_expr, - names, + var_names, NULL, NULL, NULL, NULL, 0, ctx); if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Cannot parse height expression: '%s'\n", scale->h_expr); return ret; } + ret = check_exprs(ctx); + if (ret < 0) + return ret; + av_log(ctx, AV_LOG_VERBOSE, "w:%s h:%s flags:'%s' interl:%d\n", scale->w_expr, scale->h_expr, (char *)av_x_if_null(scale->flags_str, ""), scale->interlaced); @@ -348,15 +367,15 @@ static int scale_eval_dimensions(AVFilterContext *ctx) scale->var_values[VAR_OVSUB] = 1 << out_desc->log2_chroma_h; if (scale2ref) { - scale->var_values[VARS_NB + VAR_S2R_MAIN_W] = main_link->w; - scale->var_values[VARS_NB + VAR_S2R_MAIN_H] = main_link->h; - scale->var_values[VARS_NB + VAR_S2R_MAIN_A] = (double) main_link->w / main_link->h; - scale->var_values[VARS_NB + VAR_S2R_MAIN_SAR] = main_link->sample_aspect_ratio.num ? + scale->var_values[VAR_S2R_MAIN_W] = main_link->w; + scale->var_values[VAR_S2R_MAIN_H] = main_link->h; + scale->var_values[VAR_S2R_MAIN_A] = (double) main_link->w / main_link->h; + scale->var_values[VAR_S2R_MAIN_SAR] = main_link->sample_aspect_ratio.num ? (double) main_link->sample_aspect_ratio.num / main_link->sample_aspect_ratio.den : 1; - scale->var_values[VARS_NB + VAR_S2R_MAIN_DAR] = scale->var_values[VARS_NB + VAR_S2R_MDAR] = - scale->var_values[VARS_NB + VAR_S2R_MAIN_A] * scale->var_values[VARS_NB + VAR_S2R_MAIN_SAR]; - scale->var_values[VARS_NB + VAR_S2R_MAIN_HSUB] = 1 << main_desc->log2_chroma_w; - scale->var_values[VARS_NB + VAR_S2R_MAIN_VSUB] = 1 << main_desc->log2_chroma_h; + scale->var_values[VAR_S2R_MAIN_DAR] = scale->var_values[VAR_S2R_MDAR] = + scale->var_values[VAR_S2R_MAIN_A] * scale->var_values[VAR_S2R_MAIN_SAR]; + scale->var_values[VAR_S2R_MAIN_HSUB] = 1 << main_desc->log2_chroma_w; + scale->var_values[VAR_S2R_MAIN_VSUB] = 1 << main_desc->log2_chroma_h; } res = av_expr_eval(scale->w_pexpr, scale->var_values, NULL); @@ -750,8 +769,6 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar char *old_w_str, *old_h_str; AVExpr *old_w_pexpr, *old_h_pexpr; int ret, w = 0, h = 0; - const char scale2ref = ctx->filter == &ff_vf_scale2ref; - const char *const *names = scale2ref ? var_names_scale2ref : var_names; w = !strcmp(cmd, "width") || !strcmp(cmd, "w"); h = !strcmp(cmd, "height") || !strcmp(cmd, "h"); @@ -778,7 +795,7 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar if (w) { ret = av_expr_parse(&scale->w_pexpr, scale->w_expr, - names, + var_names, NULL, NULL, NULL, NULL, 0, ctx); if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Cannot parse width expression: '%s'\n", scale->w_expr); @@ -791,7 +808,7 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar if (h) { ret = av_expr_parse(&scale->h_pexpr, scale->h_expr, - names, + var_names, NULL, NULL, NULL, NULL, 0, ctx); if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Cannot parse height expression: '%s'\n", scale->h_expr); @@ -802,7 +819,8 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar } } - if ((ret = config_props(outlink)) < 0) { + if ((ret = check_exprs(ctx)) < 0 || + (ret = config_props(outlink)) < 0) { if (w) { av_opt_set(scale, "w", old_w_str, 0);