diff --git a/doc/filters.texi b/doc/filters.texi index 51fb6cdcee..d4fbb5ac9b 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -12459,7 +12459,31 @@ Supersampling Scale (resize) the input video, based on a reference video. See the scale filter for available options, scale2ref supports the same but -uses the reference video instead of the main input as basis. +uses the reference video instead of the main input as basis. scale2ref also +supports the following additional constants for the @option{w} and +@option{h} options: + +@table @var +@item main_w +@item main_h +The main input video's width and height + +@item main_a +The same as @var{main_w} / @var{main_h} + +@item main_sar +The main input video's sample aspect ratio + +@item main_dar, mdar +The main input video's display aspect ratio. Calculated from +@code{(main_w / main_h) * main_sar}. + +@item main_hsub +@item main_vsub +The main input video's horizontal and vertical chroma subsample values. +For example for the pixel format "yuv422p" @var{hsub} is 2 and @var{vsub} +is 1. +@end table @subsection Examples diff --git a/libavfilter/scale.c b/libavfilter/scale.c index 50cd442849..e3a2fb5923 100644 --- a/libavfilter/scale.c +++ b/libavfilter/scale.c @@ -60,6 +60,49 @@ enum var_name { 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[] = { + "PI", + "PHI", + "E", + "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, + VAR_S2R_MAIN_SAR, + VAR_S2R_MAIN_DAR, VAR_S2R_MDAR, + VAR_S2R_MAIN_HSUB, + VAR_S2R_MAIN_VSUB, + VARS_S2R_NB +}; + int ff_scale_eval_dimensions(void *log_ctx, const char *w_expr, const char *h_expr, AVFilterLink *inlink, AVFilterLink *outlink, @@ -72,7 +115,16 @@ int ff_scale_eval_dimensions(void *log_ctx, int factor_w, factor_h; int eval_w, eval_h; int ret; - double var_values[VARS_NB], res; + const char scale2ref = outlink->src->inputs[1] == inlink; + double var_values[VARS_NB + VARS_S2R_NB], res; + const AVPixFmtDescriptor *main_desc; + const AVFilterLink *main_link; + const char *const *names = scale2ref ? var_names_scale2ref : var_names; + + if (scale2ref) { + main_link = outlink->src->inputs[0]; + main_desc = av_pix_fmt_desc_get(main_link->format); + } var_values[VAR_PI] = M_PI; var_values[VAR_PHI] = M_PHI; @@ -90,20 +142,32 @@ int ff_scale_eval_dimensions(void *log_ctx, var_values[VAR_OHSUB] = 1 << out_desc->log2_chroma_w; var_values[VAR_OVSUB] = 1 << out_desc->log2_chroma_h; + if (scale2ref) { + var_values[VARS_NB + VAR_S2R_MAIN_W] = main_link->w; + var_values[VARS_NB + VAR_S2R_MAIN_H] = main_link->h; + var_values[VARS_NB + VAR_S2R_MAIN_A] = (double) main_link->w / main_link->h; + var_values[VARS_NB + VAR_S2R_MAIN_SAR] = main_link->sample_aspect_ratio.num ? + (double) main_link->sample_aspect_ratio.num / main_link->sample_aspect_ratio.den : 1; + var_values[VARS_NB + VAR_S2R_MAIN_DAR] = var_values[VARS_NB + VAR_S2R_MDAR] = + var_values[VARS_NB + VAR_S2R_MAIN_A] * var_values[VARS_NB + VAR_S2R_MAIN_SAR]; + var_values[VARS_NB + VAR_S2R_MAIN_HSUB] = 1 << main_desc->log2_chroma_w; + var_values[VARS_NB + VAR_S2R_MAIN_VSUB] = 1 << main_desc->log2_chroma_h; + } + /* evaluate width and height */ av_expr_parse_and_eval(&res, (expr = w_expr), - var_names, var_values, + names, var_values, NULL, NULL, NULL, NULL, NULL, 0, log_ctx); eval_w = var_values[VAR_OUT_W] = var_values[VAR_OW] = res; if ((ret = av_expr_parse_and_eval(&res, (expr = h_expr), - var_names, var_values, + names, var_values, NULL, NULL, NULL, NULL, NULL, 0, log_ctx)) < 0) goto fail; eval_h = var_values[VAR_OUT_H] = var_values[VAR_OH] = res; /* evaluate again the width, as it may depend on the output height */ if ((ret = av_expr_parse_and_eval(&res, (expr = w_expr), - var_names, var_values, + names, var_values, NULL, NULL, NULL, NULL, NULL, 0, log_ctx)) < 0) goto fail; eval_w = res;