diff --git a/doc/filters.texi b/doc/filters.texi
index 107fe61447..2cea6b74e6 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -12429,7 +12429,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;
