From 648efac60cc0ff006897d13af4f327b9a69788c3 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Sat, 2 Sep 2023 21:49:13 +0200
Subject: [PATCH] shaders/colorspace: bias PQ deltas for mostly black frames

To avoid triggering huge scene change detections when only a tiny part
of the image contains nonzero data, even though the average values may
jump around wildly in such a case.

Fixes: https://code.videolan.org/videolan/libplacebo/-/issues/298
---
 src/shaders/colorspace.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/shaders/colorspace.c b/src/shaders/colorspace.c
index 31bf6e2ba..c623187d2 100644
--- a/src/shaders/colorspace.c
+++ b/src/shaders/colorspace.c
@@ -1133,9 +1133,10 @@ static void update_peak_buf(pl_gpu gpu, struct sh_color_map_obj *obj, bool force
         return;
     }
 
-    uint64_t frame_sum_pq = 0u, frame_wg_active = 0u;
+    uint64_t frame_sum_pq = 0u, frame_wg_count = 0u, frame_wg_active = 0u;
     for (int k = 0; k < SLICES; k++) {
         frame_sum_pq    += data.frame_sum_pq[k];
+        frame_wg_count  += data.frame_wg_count[k];
         frame_wg_active += data.frame_wg_active[k];
     }
     float avg_pq, max_pq;
@@ -1170,7 +1171,8 @@ static void update_peak_buf(pl_gpu gpu, struct sh_color_map_obj *obj, bool force
         const float log10_pq = 1e-2f; // experimentally determined approximate
         const float thresh_low = params->scene_threshold_low * log10_pq;
         const float thresh_high = params->scene_threshold_high * log10_pq;
-        const float delta = fabsf(avg_pq - obj->peak.avg_pq);
+        const float bias = (float) frame_wg_active / frame_wg_count;
+        const float delta = bias * fabsf(avg_pq - obj->peak.avg_pq);
         const float mix_coeff = pl_smoothstep(thresh_low, thresh_high, delta);
         obj->peak.avg_pq = PL_MIX(obj->peak.avg_pq, avg_pq, mix_coeff);
         obj->peak.max_pq = PL_MIX(obj->peak.max_pq, max_pq, mix_coeff);
-- 
GitLab