This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 5640bd3a4fda77a913980f97be48b873a5890179
Author:     Ramiro Polla <[email protected]>
AuthorDate: Sat Mar 7 20:11:02 2026 +0100
Commit:     Ramiro Polla <[email protected]>
CommitDate: Sat Mar 14 06:13:19 2026 +0000

    swscale/tests/swscale: require reference file to perform comparisons
    
    The legacy scaler is no longer implicitly used to generate a reference
    to perform comparisons for every conversion. It is now up to the user
    to generate a reference file and use it as input for a separate run to
    perform comparisons.
    
    It is now possible to compare against previous runs of the graph-based
    scaler, for example to test for newer optimizations.
    
    This reduces the overall time necessary to obtain speedup numbers from
    the legacy scaler to the graph-based scaler (or any other comparison,
    for that matter) since the reference must only be run once.
    
    For example, to check the speedup between the legacy scaler and the
    graph-based scaler:
      ./libswscale/tests/swscale [...] -bench 50 -legacy 1 > legacy_ref.txt
      ./libswscale/tests/swscale [...] -bench 50 -ref legacy_ref.txt
    
    If no -ref file is specified, we are assuming that we are generating a
    reference file, and therefore all information is printed (including
    ssim/loss, and benchmarks if -bench is used).
    
    If a -ref file is specified, the output printed depends on whether we
    are testing for correctness (ssim/loss only) or benchmarking (time/
    speedup only, along with overall speedup).
    
    Sponsored-by: Sovereign Tech Fund
    Signed-off-by: Ramiro Polla <[email protected]>
---
 libswscale/tests/swscale.c | 102 +++++++++++++++++++++------------------------
 1 file changed, 47 insertions(+), 55 deletions(-)

diff --git a/libswscale/tests/swscale.c b/libswscale/tests/swscale.c
index 7388cdfb3b..03e07918c8 100644
--- a/libswscale/tests/swscale.c
+++ b/libswscale/tests/swscale.c
@@ -65,6 +65,7 @@ struct test_results {
     float ssim[4];
     float loss;
     int64_t time;
+    int iters;
 };
 
 const SwsFlags flags[] = {
@@ -313,26 +314,32 @@ static void print_results(const AVFrame *ref, const 
AVFrame *src, const AVFrame
                opts->pretty ?  8 : 0, mode->flags,
                mode->dither);
 
-        printf(", SSIM={Y=%f U=%f V=%f A=%f} loss=%e",
-               r->ssim[0], r->ssim[1], r->ssim[2], r->ssim[3],
-               r->loss);
-
-        if (opts->bench && ref_r->time) {
-            double ratio = (double) ref_r->time / r->time;
-            if (FFMIN(r->time, ref_r->time) > 100 /* don't pollute stats with 
low precision */) {
-                speedup_min = FFMIN(speedup_min, ratio);
-                speedup_max = FFMAX(speedup_max, ratio);
-                speedup_logavg += log(ratio);
-                speedup_count++;
-            }
+        if (!opts->bench || !ref_r) {
+            printf(", SSIM={Y=%f U=%f V=%f A=%f} loss=%e",
+                   r->ssim[0], r->ssim[1], r->ssim[2], r->ssim[3],
+                   r->loss);
+            if (ref_r)
+                printf(" (ref=%e)", ref_r->loss);
+        }
 
-            printf(", time=%*"PRId64"/%u us (ref=%*"PRId64"/%u us), 
speedup=%*.3fx %s%s\033[0m",
-                   opts->pretty ? 7 : 0, r->time, opts->iters,
-                   opts->pretty ? 7 : 0, ref_r->time, opts->iters,
-                   opts->pretty ? 6 : 0, ratio,
-                   speedup_color(ratio), ratio >= 1.0 ? "faster" : "slower");
-        } else if (opts->bench) {
-            printf(", time=%"PRId64"/%u us", r->time, opts->iters);
+        if (opts->bench) {
+            printf(", time=%*"PRId64"/%u us",
+                   opts->pretty ? 7 : 0, r->time, opts->iters);
+            if (ref_r) {
+                double ratio = ((double) ref_r->time / ref_r->iters)
+                             / ((double) r->time / opts->iters);
+                if (FFMIN(r->time, ref_r->time) > 100 /* don't pollute stats 
with low precision */) {
+                    speedup_min = FFMIN(speedup_min, ratio);
+                    speedup_max = FFMAX(speedup_max, ratio);
+                    speedup_logavg += log(ratio);
+                    speedup_count++;
+                }
+
+                printf(" (ref=%*"PRId64"/%u us), speedup=%*.3fx %s%s\033[0m",
+                       opts->pretty ? 7 : 0, ref_r->time, ref_r->iters,
+                       opts->pretty ? 6 : 0, ratio,
+                       speedup_color(ratio), ratio >= 1.0 ? "faster" : 
"slower");
+            }
         }
         printf("\n");
 
@@ -348,7 +355,7 @@ static void print_results(const AVFrame *ref, const AVFrame 
*src, const AVFrame
                r->loss, worse_str, r->loss - expected_loss, expected_loss);
     }
 
-    if (!isnan(ref_r->loss) && r->loss - ref_r->loss > 1e-4) {
+    if (ref_r && r->loss - ref_r->loss > 1e-4) {
         const int bad = r->loss - ref_r->loss > 1e-2;
         const int level = bad ? AV_LOG_ERROR : AV_LOG_WARNING;
         const char *worse_str = bad ? "WORSE" : "worse";
@@ -377,7 +384,8 @@ static int init_frame(AVFrame **pframe, const AVFrame *ref,
 static int run_test(enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt,
                     int dst_w, int dst_h,
                     const struct mode *mode, const struct options *opts,
-                    const AVFrame *ref, AVFrame *src, const float ssim_ref[4])
+                    const AVFrame *ref, AVFrame *src,
+                    const struct test_results *ref_r)
 {
     AVFrame *dst = NULL, *out = NULL;
     const int comps = fmt_comps(src_fmt) & fmt_comps(dst_fmt);
@@ -395,7 +403,6 @@ static int run_test(enum AVPixelFormat src_fmt, enum 
AVPixelFormat dst_fmt,
     const float expected_loss = get_loss(ssim_expected);
 
     struct test_results r = { 0 };
-    struct test_results ref_r = { .loss = NAN };
 
     if (src->format != src_fmt) {
         av_frame_unref(src);
@@ -446,34 +453,7 @@ static int run_test(enum AVPixelFormat src_fmt, enum 
AVPixelFormat dst_fmt,
         goto bad_loss;
     }
 
-    if (!ssim_ref || opts->bench) {
-        /* Compare against the legacy swscale API as a reference */
-        ret = scale_legacy(dst, src, mode, opts, &ref_r.time);
-        if (ret < 0)
-            goto error;
-
-        ret = checked_sws_scale_frame(sws_dst_out, out, dst);
-        if (ret < 0)
-            goto error;
-
-        get_ssim(ref_r.ssim, out, ref, comps);
-
-        /* Legacy swscale does not perform bit accurate upconversions of low
-         * bit depth RGB. This artificially improves the SSIM score because the
-         * resulting error deletes some of the input dither noise. This gives
-         * it an unfair advantage when compared against a bit exact reference.
-         * Work around this by ensuring that the reference SSIM score is not
-         * higher than it theoretically "should" be. */
-        if (src_var > dst_var) {
-            const float src_loss = (2 * ref_var + c1) / (2 * ref_var + src_var 
+ c1);
-            ref_r.ssim[0] = FFMIN(ref_r.ssim[0], src_loss);
-        }
-    } else {
-        memcpy(ref_r.ssim, ssim_ref, sizeof(ref_r.ssim));
-    }
-
-    ref_r.loss = get_loss(ref_r.ssim);
-    if (r.loss - ref_r.loss > 1e-2) {
+    if (ref_r && r.loss - ref_r->loss > 1e-2) {
         ret = -1;
         goto bad_loss;
     }
@@ -484,7 +464,7 @@ bad_loss:
     print_results(ref, src, dst,
                   dst_w, dst_h,
                   mode, opts,
-                  &r, &ref_r,
+                  &r, ref_r,
                   expected_loss);
 
  error:
@@ -580,21 +560,33 @@ static int run_file_tests(const AVFrame *ref, FILE *fp, 
const struct options *op
         enum AVPixelFormat src_fmt;
         enum AVPixelFormat dst_fmt;
         int sw, sh, dw, dh;
-        struct test_results r;
+        struct test_results r = { 0 };
         struct mode mode;
+        int n = 0;
 
         ret = sscanf(buf,
                      "%20s %dx%d -> %20s %dx%d, flags=0x%x dither=%u, "
-                     "SSIM={Y=%f U=%f V=%f A=%f} loss=%e\n",
+                     "SSIM={Y=%f U=%f V=%f A=%f} loss=%e%n",
                      src_fmt_str, &sw, &sh, dst_fmt_str, &dw, &dh,
                      &mode.flags, &mode.dither,
                      &r.ssim[0], &r.ssim[1], &r.ssim[2], &r.ssim[3],
-                     &r.loss);
+                     &r.loss, &n);
         if (ret != 13) {
             av_log(NULL, AV_LOG_FATAL,
                    "Malformed reference file in line %d\n", line);
             goto error;
         }
+        if (opts->bench) {
+            ret = sscanf(buf + n,
+                         ", time=%"PRId64"/%u us",
+                         &r.time, &r.iters);
+            if (ret != 2) {
+                av_log(NULL, AV_LOG_FATAL,
+                       "Missing benchmarks from reference file in line %d\n",
+                       line);
+                goto error;
+            }
+        }
 
         src_fmt = av_get_pix_fmt(src_fmt_str);
         dst_fmt = av_get_pix_fmt(dst_fmt_str);
@@ -616,7 +608,7 @@ static int run_file_tests(const AVFrame *ref, FILE *fp, 
const struct options *op
             opts->dst_fmt != AV_PIX_FMT_NONE && dst_fmt != opts->dst_fmt)
             continue;
 
-        ret = run_test(src_fmt, dst_fmt, dw, dh, &mode, opts, ref, src, 
r.ssim);
+        ret = run_test(src_fmt, dst_fmt, dw, dh, &mode, opts, ref, src, &r);
         if (ret < 0)
             goto error;
     }

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to