Sometimes, the reference SSIM is significantly higher than the SSIM level expected for the test. This is the case when the source format has a much lower bit depth than the destination format. In this case, the fact that legacy swscale does not accurately preserve the source dither pattern gives it an unfair advantage in a direct comparison, leading to false positives. For example, conversion like rgb4 -> rgb565 should be lossless, but swscale low passes / downscales the input chroma, throwing away massive amounts of detail. This gives it a higher SSIM score since the lowpassed result removes some of the dither noise that was present in the source.
Unified · Split
| @@ -321,6 +321,18 @@ static int run_test(enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt, · 320 unmodified lines | ||
| 321 | 321 | goto error; |
| 322 | 322 | |
| 323 | 323 | get_ssim(ssim_sws, out, ref, comps); |
| 324 | + | |
| 325 | + /* Legacy swscale does not perform bit accurate upconversions of low | |
| 326 | + * bit depth RGB. This artificially improves the SSIM score because the | |
| 327 | + * resulting error deletes some of the input dither noise. This gives | |
| 328 | + * it an unfair advantage when compared against a bit exact reference. | |
| 329 | + * Work around this by ensuring that the reference SSIM score is not | |
| 330 | + * higher than it theoretically "should" be. */ | |
| 331 | + if (src_var > dst_var) { | |
| 332 | + const float src_loss = (2 * ref_var + c1) / (2 * ref_var + src_var + c1); | |
| 333 | + ssim_sws[0] = FFMIN(ssim_sws[0], src_loss); | |
| 334 | + } | |
| 335 | + | |
| 324 | 336 | ssim_ref = ssim_sws; |
| 325 | 337 | } |
| 326 | 338 | |