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 | goto error; | 321 | goto error; |
| 322 | 322 | ||
| 323 | get_ssim(ssim_sws, out, ref, comps); | 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 | ssim_ref = ssim_sws; | 336 | ssim_ref = ssim_sws; |
| 325 | } | 337 | } |
| 326 | 338 | ||