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

Git pushed a commit to branch master
in repository ffmpeg.

commit a2b7a8210e3fbffbbb959752f832484b57864325
Author:     Diego de Souza <[email protected]>
AuthorDate: Wed Aug 12 17:15:17 2026 +0200
Commit:     Niklas Haas <[email protected]>
CommitDate: Wed Aug 26 09:52:59 2026 +0000

    avfilter/vf_scale_cuda: regenerate filters for cropped frames
    
    Generic filter coefficients depend on visible input dimensions, which
    can change through per-frame crop metadata. Rebuild the filter set when
    that geometry changes and synchronize before freeing active CUDA
    resources.
    
    Match av_frame_apply_cropping() for subsampled planes by flooring crop
    origins while rounding visible extents up. This prevents odd left or top
    crops from shifting chroma by one sample.
    
    Clear applied cropping and size-dependent side data from the output.
    Use visible dimensions when updating the sample aspect ratio.
    
    Signed-off-by: Diego de Souza <[email protected]>
---
 libavfilter/vf_scale_cuda.c | 146 +++++++++++++++++++++++++++++++++++++-------
 1 file changed, 124 insertions(+), 22 deletions(-)

diff --git a/libavfilter/vf_scale_cuda.c b/libavfilter/vf_scale_cuda.c
index 1e46d14e98..d527783f56 100644
--- a/libavfilter/vf_scale_cuda.c
+++ b/libavfilter/vf_scale_cuda.c
@@ -139,6 +139,8 @@ typedef struct CUDAScaleFilterSet {
     CUDATex inter_tex;
     CUDAScalePassPlan pass_plan;
     unsigned int tmp_planes;
+    int in_width, in_height;
+    int normalize_crop;
 } CUDAScaleFilterSet;
 
 typedef struct CUDAScaleContext {
@@ -296,8 +298,7 @@ static void cuda_tex_uninit(CudaFunctions *cu, CUDATex *t)
     memset(t, 0, sizeof(*t));
 }
 
-static av_cold void filter_set_uninit(CudaFunctions *cu,
-                                      CUDAScaleFilterSet *set)
+static void filter_set_uninit(CudaFunctions *cu, CUDAScaleFilterSet *set)
 {
     cuda_tex_uninit(cu, &set->inter_tex);
     for (int i = 0; i < FF_ARRAY_ELEMS(set->filters); i++) {
@@ -369,9 +370,9 @@ fail:
     return ret;
 }
 
-static av_cold int inter_buf_init(AVFilterContext *ctx, CUDATex *tex,
-                                  int out_width, int in_height,
-                                  unsigned int planes)
+static int inter_buf_init(AVFilterContext *ctx, CUDATex *tex,
+                          int out_width, int in_height,
+                          unsigned int planes)
 {
     CUDAScaleContext *s = ctx->priv;
     CudaFunctions *cu = s->hwctx->internal->cuda_dl;
@@ -684,10 +685,10 @@ fail:
     return ret;
 }
 
-static av_cold int cudascale_filter_init(AVFilterContext *ctx,
-                                         CUDAScaleFilter *f,
-                                         int src_size, int dst_size,
-                                         double virtual_size, int needs_scale)
+static int cudascale_filter_init(AVFilterContext *ctx,
+                                 CUDAScaleFilter *f,
+                                 int src_size, int dst_size,
+                                 double virtual_size, int needs_scale)
 {
     CUDAScaleContext *s = ctx->priv;
     CudaFunctions *cu = s->hwctx->internal->cuda_dl;
@@ -766,9 +767,10 @@ fail:
     return ret;
 }
 
-static av_cold int cudascale_filter_set_init(AVFilterContext *ctx,
-                                             CUDAScaleFilterSet *set,
-                                             int in_width, int in_height)
+static int cudascale_filter_set_init(AVFilterContext *ctx,
+                                     CUDAScaleFilterSet *set,
+                                     int in_width, int in_height,
+                                     int normalize_crop)
 {
     CUDAScaleContext *s = ctx->priv;
     AVFilterLink *outlink = ctx->outputs[0];
@@ -784,6 +786,10 @@ static av_cold int 
cudascale_filter_set_init(AVFilterContext *ctx,
                                     (has_chroma ? CUDA_SCALE_PLANE_CHROMA : 0);
     int pass_x, pass_y;
 
+    set->in_width       = in_width;
+    set->in_height      = in_height;
+    set->normalize_crop = normalize_crop;
+
     cudascale_plan_passes(&set->pass_plan,
                           in_width, in_height, outlink->w, outlink->h,
                           in_sub_x, in_sub_y, out_sub_x, out_sub_y,
@@ -803,7 +809,8 @@ static av_cold int 
cudascale_filter_set_init(AVFilterContext *ctx,
 
     if (pass_x >= 0) {
         const unsigned int planes = pass_x == FILTER_TMP ?
-                                    set->pass_plan.x_planes :
+                                    (normalize_crop ? all_planes :
+                                                      set->pass_plan.x_planes) 
:
                                     all_planes;
 
         if (pass_x == FILTER_TMP)
@@ -866,6 +873,48 @@ fail:
     return ret;
 }
 
+static int cudascale_prepare_filter_set(AVFilterContext *ctx,
+                                        int in_width, int in_height,
+                                        int normalize_crop)
+{
+    CUDAScaleContext *s = ctx->priv;
+    CudaFunctions *cu = s->hwctx->internal->cuda_dl;
+    CUDAScaleFilterSet next = { 0 };
+    CUDAScaleFilterSet old;
+    int ret;
+
+    if (s->filter_set.in_width == in_width &&
+        s->filter_set.in_height == in_height &&
+        s->filter_set.normalize_crop == normalize_crop)
+        return 0;
+
+    ret = cudascale_filter_set_init(ctx, &next, in_width, in_height,
+                                    normalize_crop);
+    if (ret < 0)
+        goto fail;
+
+    if (s->filter_set.in_width) {
+        /* Queued kernels may still reference the active LUTs and texture. */
+        ret = CHECK_CU(cu->cuStreamSynchronize(s->cu_stream));
+        if (ret < 0)
+            goto fail;
+    }
+
+    old = s->filter_set;
+    s->filter_set = next;
+    memset(&next, 0, sizeof(next));
+    filter_set_uninit(cu, &old);
+
+    av_log(ctx, AV_LOG_VERBOSE,
+           "Prepared generic filters for visible input %dx%d%s\n",
+           in_width, in_height, normalize_crop ? " (cropped)" : "");
+    return 0;
+
+fail:
+    filter_set_uninit(cu, &next);
+    return ret;
+}
+
 static av_cold int cudascale_setup_filters(AVFilterContext *ctx,
                                            int in_width, int in_height)
 {
@@ -878,8 +927,7 @@ static av_cold int cudascale_setup_filters(AVFilterContext 
*ctx,
     if (ret < 0)
         return ret;
 
-    ret = cudascale_filter_set_init(ctx, &s->filter_set,
-                                    in_width, in_height);
+    ret = cudascale_prepare_filter_set(ctx, in_width, in_height, 0);
 
     CHECK_CU(cu->cuCtxPopCurrent(&dummy));
     return ret;
@@ -961,6 +1009,36 @@ fail:
     return ret;
 }
 
+static int cudascale_frame_geometry(AVFilterContext *ctx, const AVFrame *frame,
+                                    int *width, int *height,
+                                    int *normalize_crop)
+{
+    AVFilterLink *inlink = ctx->inputs[0];
+    size_t frame_width, frame_height;
+
+    if (frame->width <= 0 || frame->height <= 0) {
+        av_log(ctx, AV_LOG_ERROR, "Invalid crop rectangle\n");
+        return AVERROR(EINVAL);
+    }
+
+    frame_width  = frame->width;
+    frame_height = frame->height;
+    if (frame->crop_left >= frame_width ||
+        frame->crop_right >= frame_width - frame->crop_left ||
+        frame->crop_top >= frame_height ||
+        frame->crop_bottom >= frame_height - frame->crop_top) {
+        av_log(ctx, AV_LOG_ERROR, "Invalid crop rectangle\n");
+        return AVERROR(EINVAL);
+    }
+
+    *width  = (int)(frame_width  - frame->crop_left - frame->crop_right);
+    *height = (int)(frame_height - frame->crop_top  - frame->crop_bottom);
+    *normalize_crop = frame->crop_left || frame->crop_top ||
+                      *width != inlink->w || *height != inlink->h;
+
+    return 0;
+}
+
 /* if depths/channels are NULL, only maps pointers without creating textures */
 static int cuda_tex_map_frame(AVFilterContext *ctx, const AVFrame *frame,
                               const int depths[4], const int channels[4],
@@ -1114,9 +1192,11 @@ static int scalecuda_resize(AVFilterContext *ctx,
         (pass != FILTER_TMP ||
          (set->tmp_planes & CUDA_SCALE_PLANE_CHROMA))) {
         // scale UV plane. Scale function sets both U and V plane, or singular 
interleaved plane.
+        /* Match av_frame_apply_cropping(): subsampled plane origins round
+         * down, while visible plane extents round up. */
         ret = call_resize_kernel(ctx, func_uv, in->tex,
-                                 AV_CEIL_RSHIFT(in->crop_left, 
in->log2_chroma_w),
-                                 AV_CEIL_RSHIFT(in->crop_top, 
in->log2_chroma_h),
+                                 in->crop_left >> in->log2_chroma_w,
+                                 in->crop_top  >> in->log2_chroma_h,
                                  AV_CEIL_RSHIFT(in->crop_width, 
in->log2_chroma_w),
                                  AV_CEIL_RSHIFT(in->crop_height, 
in->log2_chroma_h),
                                  out->data,
@@ -1130,13 +1210,21 @@ static int scalecuda_resize(AVFilterContext *ctx,
     return 0;
 }
 
-static int cudascale_scale(AVFilterContext *ctx, AVFrame *out, AVFrame *in)
+static int cudascale_scale(AVFilterContext *ctx, AVFrame *out, AVFrame *in,
+                           int in_width, int in_height, int normalize_crop)
 {
     CUDAScaleContext *s = ctx->priv;
     CudaFunctions *cu = s->hwctx->internal->cuda_dl;
     AVFilterLink *outlink = ctx->outputs[0];
     int ret = 0;
 
+    if (s->use_filters) {
+        ret = cudascale_prepare_filter_set(ctx, in_width, in_height,
+                                           normalize_crop);
+        if (ret < 0)
+            return ret;
+    }
+
     CUDATex in_tex = {0}, out_tex = {0};
     ret = cuda_tex_map_frame(ctx, in, s->in_plane_depths,
                              s->in_plane_channels, &in_tex,
@@ -1185,7 +1273,14 @@ static int cudascale_scale(AVFilterContext *ctx, AVFrame 
*out, AVFrame *in)
     if (ret < 0)
         goto fail;
 
-    if (out->width != in->width || out->height != in->height) {
+    out->crop_top    = 0;
+    out->crop_bottom = 0;
+    out->crop_left   = 0;
+    out->crop_right  = 0;
+
+    if (in->crop_left || in->crop_right ||
+        in->crop_top  || in->crop_bottom ||
+        out->width != in_width || out->height != in_height) {
         av_frame_side_data_remove_by_props(&out->side_data, &out->nb_side_data,
                                            AV_SIDE_DATA_PROP_SIZE_DEPENDENT);
     }
@@ -1205,11 +1300,17 @@ static int cudascale_filter_frame(AVFilterLink *link, 
AVFrame *in)
 
     AVFrame *out = NULL;
     CUcontext dummy;
+    int in_width, in_height, normalize_crop;
     int ret = 0;
 
     if (s->passthrough)
         return ff_filter_frame(outlink, in);
 
+    ret = cudascale_frame_geometry(ctx, in, &in_width, &in_height,
+                                   &normalize_crop);
+    if (ret < 0)
+        goto fail;
+
     out = av_frame_alloc();
     if (!out) {
         ret = AVERROR(ENOMEM);
@@ -1220,7 +1321,8 @@ static int cudascale_filter_frame(AVFilterLink *link, 
AVFrame *in)
     if (ret < 0)
         goto fail;
 
-    ret = cudascale_scale(ctx, out, in);
+    ret = cudascale_scale(ctx, out, in, in_width, in_height,
+                          normalize_crop);
 
     CHECK_CU(cu->cuCtxPopCurrent(&dummy));
     if (ret < 0)
@@ -1230,8 +1332,8 @@ static int cudascale_filter_frame(AVFilterLink *link, 
AVFrame *in)
         out->sample_aspect_ratio = (AVRational){1, 1};
     } else {
         av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den,
-                  (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w,
-                  (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h,
+                  (int64_t)in->sample_aspect_ratio.num * outlink->h * in_width,
+                  (int64_t)in->sample_aspect_ratio.den * outlink->w * 
in_height,
                   INT_MAX);
     }
 

-- 
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