Commit 92a5c7e4f5 for ffmpeg

commit 92a5c7e4f524b277d758940689c4a8d20fe4b9db
Author: Marcos Ashton Iglesias <marcosashiglesias@gmail.com>
Date:   Wed Sep 30 19:37:41 2026 +0100

    avfilter/vf_avgblur_vulkan: use the documented radius and edge handling

    sizeX/sizeY were used as radius - 1, the normalisation ignored the
    vertical radius and pixels outside the frame were read as black. Match
    avgblur: use the radii, limited to half the chroma plane, and repeat the
    edge pixels. Existing uses now blur one pixel more, as documented.

diff --git a/libavfilter/vf_avgblur_vulkan.c b/libavfilter/vf_avgblur_vulkan.c
index be11a76070..c198720cb6 100644
--- a/libavfilter/vf_avgblur_vulkan.c
+++ b/libavfilter/vf_avgblur_vulkan.c
@@ -20,6 +20,7 @@

 #include "libavutil/random_seed.h"
 #include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
 #include "vulkan_filter.h"

 #include "filters.h"
@@ -53,6 +54,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
     AvgBlurVulkanContext *s = ctx->priv;
     FFVulkanContext *vkctx = &s->vkctx;
     const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->vkctx.output_format);

     s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
     if (!s->qf) {
@@ -90,11 +92,13 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
     RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));

     s->initialized = 1;
-    s->opts.filter_len[0] = s->size_x - 1;
-    s->opts.filter_len[1] = s->size_y - 1;
+    /* like avgblur, at most half the chroma plane */
+    s->opts.filter_len[0] = FFMIN(s->size_x,
+                                  AV_CEIL_RSHIFT(vkctx->output_width,  desc->log2_chroma_w) / 2);
+    s->opts.filter_len[1] = FFMIN(s->size_y,
+                                  AV_CEIL_RSHIFT(vkctx->output_height, desc->log2_chroma_h) / 2);

-    s->opts.filter_norm[0] = s->opts.filter_len[0]*2 + 1;
-    s->opts.filter_norm[0] = 1.0/(s->opts.filter_norm[0]*s->opts.filter_norm[0]);
+    s->opts.filter_norm[0] = 1.0/((s->opts.filter_len[0]*2 + 1)*(s->opts.filter_len[1]*2 + 1));
     s->opts.filter_norm[1] = s->opts.filter_norm[0];
     s->opts.filter_norm[2] = s->opts.filter_norm[0];
     s->opts.filter_norm[3] = s->opts.filter_norm[0];
diff --git a/libavfilter/vulkan/avgblur.comp.glsl b/libavfilter/vulkan/avgblur.comp.glsl
index 4cfd4f433d..1a6f26ad07 100644
--- a/libavfilter/vulkan/avgblur.comp.glsl
+++ b/libavfilter/vulkan/avgblur.comp.glsl
@@ -54,7 +54,7 @@ void main()
     for (int y = -filter_len.y; y <= filter_len.y; y++)
         for (int x = -filter_len.x; x <= filter_len.x; x++)
             sum += imageLoad(input_img[nonuniformEXT(gl_LocalInvocationID.z)],
-                             pos + ivec2(x, y));
+                             clamp(pos + ivec2(x, y), ivec2(0), size - 1));

     imageStore(output_img[nonuniformEXT(gl_LocalInvocationID.z)],
                pos, sum * filter_norm);