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

Git pushed a commit to branch master
in repository ffmpeg.

commit cf2f8fc5a2a8dc4a1b490bab99ef0f6019222f2d
Author:     Lynne <[email protected]>
AuthorDate: Sat Nov 7 17:38:00 2026 +0800
Commit:     Lynne <[email protected]>
CommitDate: Sat Nov 7 22:20:30 2026 +0800

    avfilter/vf_bwdif_vulkan: make bwdif's decisions on whole sample values
    
    bwdif treats a sample as still when its halved temporal differences,
    rounded down, are all 0, so a change of one step counts as none. And it
    interpolates from the current field alone unless abs(c - e) is above
    temporal_diff0. The shader works on floats, which aren't exact and whose
    halves aren't rounded down, so both decisions could go the other way:
    after the previous commit, still 1-row stripes with a step of noise were
    off by up to 1022, and moving pictures by up to 338.
    
    Pass the size of a step to the shader, and put both thresholds halfway
    between the integer outcomes. Float formats have no steps and keep the
    plain comparisons.
    
    On moving, edge and still striped pictures in yuv420p, yuv422p10,
    yuv444p12, gbrp10, NV12 and P010, with both field orders and both modes,
    the output now matches bwdif within a code everywhere, on an RX 6900 XT
    and on lavapipe.
    
    Fixes: #25106
    Reported-by: oittaa
---
 libavfilter/vf_bwdif_vulkan.c      |  3 ++-
 libavfilter/vulkan/bwdif.comp.glsl | 14 +++++++++++---
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/libavfilter/vf_bwdif_vulkan.c b/libavfilter/vf_bwdif_vulkan.c
index 9afd9ae409..0fd0255c4d 100644
--- a/libavfilter/vf_bwdif_vulkan.c
+++ b/libavfilter/vf_bwdif_vulkan.c
@@ -80,10 +80,11 @@ static av_cold int init_filter(AVFilterContext *ctx)
         clip_max = ((1 << desc->comp[0].depth) - 1) * unit;
     }
 
-    SPEC_LIST_CREATE(sl, 3, 2*sizeof(int) + sizeof(float))
+    SPEC_LIST_CREATE(sl, 4, 2*sizeof(int) + 2*sizeof(float))
     SPEC_LIST_ADD(sl, 0, 32, vkctx->output_height);
     SPEC_LIST_ADD(sl, 1, 32, AV_CEIL_RSHIFT(vkctx->output_height, 
desc->log2_chroma_h));
     SPEC_LIST_ADD(sl, 2, 32, av_float2int(clip_max));
+    SPEC_LIST_ADD(sl, 3, 32, av_float2int(unit));
 
     ff_vk_shader_load(&s->shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
                       (uint32_t [3]) { 1, 64, planes }, 0);
diff --git a/libavfilter/vulkan/bwdif.comp.glsl 
b/libavfilter/vulkan/bwdif.comp.glsl
index 76d330cf9f..b477be63c4 100644
--- a/libavfilter/vulkan/bwdif.comp.glsl
+++ b/libavfilter/vulkan/bwdif.comp.glsl
@@ -34,6 +34,11 @@ layout (constant_id = 1) const int chroma_height = 0;
 /* The largest sample value, which bwdif clips to */
 layout (constant_id = 2) const float clip_max = 1.0;
 
+/* bwdif decides on whole sample values. These are floats, which aren't
+ * exact, so the decisions are made on steps of this size, 0 for float
+ * formats. */
+layout (constant_id = 3) const float unit = 0.0;
+
 layout (set = 0, binding = 0) uniform writeonly image2D  dst[];
 layout (set = 0, binding = 1) uniform readonly  image2D prev[];
 layout (set = 0, binding = 2) uniform readonly  image2D  cur[];
@@ -80,7 +85,9 @@ vec4 process_line(vec4 prev2[5], vec4 prev1[2], vec4 cur[4], 
vec4 next1[2], vec4
    temp_diff[1] = (abs(prev1[0] - fc) + abs(prev1[1] - fe)) / 2;
    temp_diff[2] = (abs(next1[0] - fc) + abs(next1[1] - fe)) / 2;
    vec4 diff = max(temp_diff[0] / 2, max(temp_diff[1], temp_diff[2]));
-   bvec4 diff_mask = equal(diff, vec4(0));
+   /* bwdif halves with shifts, so a change of one step is no motion: diff
+    * is then at most half a step, and otherwise at least one */
+   bvec4 diff_mask = lessThanEqual(diff, vec4(unit * 0.75));
 
    vec4 fbs = prev2[1] + next2[1];
    vec4 ffs = prev2[3] + next2[3];
@@ -97,7 +104,8 @@ vec4 process_line(vec4 prev2[5], vec4 prev1[2], vec4 cur[4], 
vec4 next1[2], vec4
                            coef_lf[0]*(fc + fe) - coef_lf[1]*(cur[0] + 
cur[3])) / (1 << 13);
    vec4 interpolate_cur = (coef_sp[0]*(fc + fe) - coef_sp[1]*(cur[0] + 
cur[3])) / (1 << 13);
 
-   bvec4 interpolate_cnd1 = greaterThan(abs(fc - fe), temp_diff[0]);
+   /* bwdif takes interpolate_cur when the differences are equal */
+   bvec4 interpolate_cnd1 = greaterThan(abs(fc - fe), temp_diff[0] + unit * 
0.5);
    vec4 interpol = mix(interpolate_cur, interpolate_all, interpolate_cnd1);
    interpol = clamp(interpol, fd - diff, fd + diff);
    return mix(interpol, fd, diff_mask);
@@ -117,7 +125,7 @@ vec4 process_edge(vec4 prev2[3], vec4 prev1[2], vec4 
cur[2], vec4 next1[2], vec4
    temp_diff[1] = (abs(prev1[0] - fc) + abs(prev1[1] - fe)) / 2;
    temp_diff[2] = (abs(next1[0] - fc) + abs(next1[1] - fe)) / 2;
    vec4 diff = max(temp_diff[0] / 2, max(temp_diff[1], temp_diff[2]));
-   bvec4 diff_mask = equal(diff, vec4(0));
+   bvec4 diff_mask = lessThanEqual(diff, vec4(unit * 0.75));
 
    if (spat) {
        vec4 fb = (prev2[0] + next2[0]) / 2 - fc;

-- 
To stop receiving notification emails like this one, please contact
[email protected].
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to