PR #25291 opened by rajeshgk URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25291 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25291.patch
## Summary Fix two independently reproduced correctness issues in the XPSNR video filter. ### 1. High-bit-depth reference stride For high-bit-depth video, the reference planes may contain row padding. The XPSNR calculation previously used the visible plane width as the reference stride, which could result in incorrect pixel addressing. Use the actual reference frame linesizes, converted to sample strides, for high-bit-depth reference planes. ### 2. Scalar highds activity calculation Preserve the return value from `highds()` in the scalar activity-calculation path. Previously, the calculated activity was discarded, potentially producing incorrect perceptual weighting for narrow blocks. ## Validation - Successfully built against upstream FFmpeg master `3b3dc211fe`. - Confirmed exact reference-metadata matches for 10-bit stride, 12-bit stride, and highds-edge regression cases. - Independently isolated both fixes against the earlier regression-test revision. - All five XPSNR FATE tests passed with the combined fixes on that revision. - All five XPSNR tests also passed under AddressSanitizer and UndefinedBehaviorSanitizer on that revision, without reported sanitizer findings. ## Regression coverage Regression tests are provided separately in PR #25251: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25251 The implementation fix should be merged before the test-only PR, because those regression tests reproduce failures in the unpatched implementation. ## Scope Only `libavfilter/vf_xpsnr.c` is modified. One commit, five insertions and five deletions. >From 6eebbfb3a996ed94bec6be91631197aeb0214209 Mon Sep 17 00:00:00 2001 From: Rajesh Gopinath Kumar <[email protected]> Date: Wed, 21 Oct 2026 01:41:01 -0500 Subject: [PATCH] avfilter/xpsnr: fix reference stride and scalar highds activity Use actual reference frame linesizes for high-bit-depth XPSNR. Padded reference rows must not be treated as tightly packed. Preserve the return value of scalar highds() for narrow blocks. Previously the calculated activity was discarded. Regression coverage: FFmpeg PR #25251. --- libavfilter/vf_xpsnr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavfilter/vf_xpsnr.c b/libavfilter/vf_xpsnr.c index 89f4f279ba4..a604e172d84 100644 --- a/libavfilter/vf_xpsnr.c +++ b/libavfilter/vf_xpsnr.c @@ -194,7 +194,7 @@ static inline double calc_squared_error_and_weight (XPSNRContext const *s, if (w_act > 12) sa_act = s->dsp.highds_func(x_act, y_act, w_act, h_act, o_m0, o); else - highds(x_act, y_act, w_act, h_act, o_m0, o); + sa_act = highds(x_act, y_act, w_act, h_act, o_m0, o); } else { /* <=HD highpass without downsampling */ for (int y = y_act; y < h_act; y++) { for (int x = x_act; x < w_act; x++) { @@ -267,7 +267,7 @@ static inline double get_avg_xpsnr (const double sqrt_wsse_val, const double su } static int get_wsse(AVFilterContext *ctx, int16_t **org, int16_t *org_m1, - int16_t *org_m2, int16_t **rec, uint64_t *const wsse64) + int16_t *org_m2, int16_t **rec, const int *stride_rec, uint64_t *const wsse64) { XPSNRContext *const s = ctx->priv; const uint32_t w = s->plane_width [0]; /* luma image width in pixels */ @@ -298,7 +298,7 @@ static int get_wsse(AVFilterContext *ctx, int16_t **org, int16_t *org_m1, const int16_t *p_org = org[0]; const uint32_t s_org = stride_org[0] / s->bpp; const int16_t *p_rec = rec[0]; - const uint32_t s_rec = s->plane_width[0]; + const uint32_t s_rec = s->bpp == 1 ? s->plane_width[0] : stride_rec[0] / s->bpp; double wsse_luma = 0.0; for (y = 0; y < h; y += b) { /* calculate block SSE and perceptual weights */ @@ -349,7 +349,7 @@ static int get_wsse(AVFilterContext *ctx, int16_t **org, int16_t *org_m1, const int16_t *p_org = org[c]; const uint32_t s_org = stride_org[c] / s->bpp; const int16_t *p_rec = rec[c]; - const uint32_t s_rec = s->plane_width[c]; + const uint32_t s_rec = s->bpp == 1 ? s->plane_width[c] : stride_rec[c] / s->bpp; const uint32_t w_pln = s->plane_width[c]; const uint32_t h_pln = s->plane_height[c]; @@ -461,7 +461,7 @@ static int do_xpsnr(FFFrameSync *fs) } /* extended perceptually weighted peak signal-to-noise ratio (XPSNR) value */ - ret_value = get_wsse(ctx, porg, s->buf_org_m1, s->buf_org_m2, prec, wsse64); + ret_value = get_wsse(ctx, porg, s->buf_org_m1, s->buf_org_m2, prec, ref->linesize, wsse64); if ( ret_value < 0 ) return ret_value; /* an error here means something went wrong earlier! */ -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
