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

Git pushed a commit to branch master
in repository ffmpeg.

commit ba1c1d9eee75a2bd5f2677907af1753112c5c69f
Author:     Niklas Haas <[email protected]>
AuthorDate: Sat Jun 20 02:55:31 2026 +0200
Commit:     Niklas Haas <[email protected]>
CommitDate: Sat Jun 20 03:04:27 2026 +0200

    swscale/graph: separate pass dispatch size from buffer size
    
    This allows adding passes which will be dispatched over a reduced number of
    lines, without affecting the allocated buffer dimensions - e.g. for passes
    which purely write to subsampled chroma planes.
    
    A few hard-coded references to pass->width/height need to be replaced by
    the corresponding output frame references, but it's not a huge deal.
    
    Sponsored-by: Sovereign Tech Fund
    Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/graph.c        | 43 +++++++++++++++++++++++--------------------
 libswscale/graph.h        |  6 ++++--
 libswscale/ops_dispatch.c | 15 ++++++++-------
 3 files changed, 35 insertions(+), 29 deletions(-)

diff --git a/libswscale/graph.c b/libswscale/graph.c
index 06e5ebefc8..a765b4cd5c 100644
--- a/libswscale/graph.c
+++ b/libswscale/graph.c
@@ -174,7 +174,8 @@ static void pass_free(SwsPass *pass)
 
 int ff_sws_graph_add_pass(SwsGraph *graph, enum AVPixelFormat fmt,
                           int width, int height, SwsPass *input,
-                          int align, SwsPassFunc run, SwsPassSetup setup,
+                          int lines, int align,
+                          SwsPassFunc run, SwsPassSetup setup,
                           void *priv, void (*free_cb)(void *priv),
                           SwsPass **out_pass)
 {
@@ -186,14 +187,16 @@ int ff_sws_graph_add_pass(SwsGraph *graph, enum 
AVPixelFormat fmt,
         return AVERROR(ENOMEM);
     }
 
+    if (!lines)
+        lines = height;
+
     pass->graph  = graph;
     pass->run    = run;
     pass->setup  = setup;
     pass->priv   = priv;
     pass->free   = free_cb;
     pass->format = fmt;
-    pass->width  = width;
-    pass->height = height;
+    pass->lines  = lines;
     pass->input  = input;
     pass->output = av_refstruct_alloc_ext(sizeof(*pass->output), 0, NULL, 
free_buffer);
     if (!pass->output) {
@@ -201,17 +204,17 @@ int ff_sws_graph_add_pass(SwsGraph *graph, enum 
AVPixelFormat fmt,
         goto fail;
     }
 
-    pass->output->height = pass->height;
-    pass->output->width  = pass->width;
+    pass->output->height = height;
+    pass->output->width  = width;
     pass->output->width_align = 1;
 
     if (!align) {
-        pass->slice_h = pass->height;
+        pass->slice_h = pass->lines;
         pass->num_slices = 1;
     } else {
-        pass->slice_h = (pass->height + graph->num_threads - 1) / 
graph->num_threads;
+        pass->slice_h = (pass->lines + graph->num_threads - 1) / 
graph->num_threads;
         pass->slice_h = FFALIGN(pass->slice_h, align);
-        pass->num_slices = (pass->height + pass->slice_h - 1) / pass->slice_h;
+        pass->num_slices = (pass->lines + pass->slice_h - 1) / pass->slice_h;
     }
 
     ret = av_dynarray_add_nofree(&graph->passes, &graph->num_passes, pass);
@@ -267,7 +270,7 @@ static void run_rgb0(const SwsFrame *out, const SwsFrame 
*in, int y, int h,
 {
     SwsInternal *c = pass->priv;
     const int x0 = c->src0Alpha - 1;
-    const int w4 = 4 * pass->width;
+    const int w4 = 4 * out->width;
     const int src_stride = in->linesize[0];
     const int dst_stride = out->linesize[0];
     const uint8_t *src = in->data[0] + y * src_stride;
@@ -289,7 +292,7 @@ static void run_xyz2rgb(const SwsFrame *out, const SwsFrame 
*in, int y, int h,
     const SwsInternal *c = pass->priv;
     c->xyz12Torgb48(c, out->data[0] + y * out->linesize[0], out->linesize[0],
                     in->data[0] + y * in->linesize[0], in->linesize[0],
-                    pass->width, h);
+                    out->width, h);
 }
 
 static void run_rgb2xyz(const SwsFrame *out, const SwsFrame *in, int y, int h,
@@ -298,7 +301,7 @@ static void run_rgb2xyz(const SwsFrame *out, const SwsFrame 
*in, int y, int h,
     const SwsInternal *c = pass->priv;
     c->rgb48Toxyz12(c, out->data[0] + y * out->linesize[0], out->linesize[0],
                     in->data[0] + y * in->linesize[0], in->linesize[0],
-                    pass->width, h);
+                    out->width, h);
 }
 
 /***********************************************************************
@@ -465,7 +468,7 @@ static int init_legacy_subpass(SwsGraph *graph, SwsContext 
*sws,
 
     if (c->src0Alpha && !c->dst0Alpha && isALPHA(sws->dst_format)) {
         ret = ff_sws_graph_add_pass(graph, AV_PIX_FMT_RGBA, src_w, src_h, 
input,
-                                    1, run_rgb0, NULL, c, NULL, &input);
+                                    0, 1, run_rgb0, NULL, c, NULL, &input);
         if (ret < 0) {
             sws_free_context(&sws);
             return ret;
@@ -474,14 +477,14 @@ static int init_legacy_subpass(SwsGraph *graph, 
SwsContext *sws,
 
     if (c->srcXYZ && !(c->dstXYZ && unscaled)) {
         ret = ff_sws_graph_add_pass(graph, AV_PIX_FMT_RGB48, src_w, src_h, 
input,
-                                    1, run_xyz2rgb, NULL, c, NULL, &input);
+                                    0, 1, run_xyz2rgb, NULL, c, NULL, &input);
         if (ret < 0) {
             sws_free_context(&sws);
             return ret;
         }
     }
 
-    ret = ff_sws_graph_add_pass(graph, sws->dst_format, dst_w, dst_h, input, 
align,
+    ret = ff_sws_graph_add_pass(graph, sws->dst_format, dst_w, dst_h, input, 
0, align,
                                 c->convert_unscaled ? run_legacy_unscaled : 
run_legacy_swscale,
                                 setup_legacy_swscale, sws, 
free_legacy_swscale, &pass);
     if (ret < 0)
@@ -533,7 +536,7 @@ static int init_legacy_subpass(SwsGraph *graph, SwsContext 
*sws,
 
     if (c->dstXYZ && !(c->srcXYZ && unscaled)) {
         ret = ff_sws_graph_add_pass(graph, AV_PIX_FMT_RGB48, dst_w, dst_h, 
pass,
-                                    1, run_rgb2xyz, NULL, c, NULL, &pass);
+                                    0, 1, run_rgb2xyz, NULL, c, NULL, &pass);
         if (ret < 0)
             return ret;
     }
@@ -715,7 +718,7 @@ static void run_lut3d(const SwsFrame *out, const SwsFrame 
*in, int y, int h,
     frame_shift(out, y, out_data);
 
     ff_sws_lut3d_apply(lut, in_data[0], in->linesize[0], out_data[0],
-                       out->linesize[0], pass->width, h);
+                       out->linesize[0], out->width, h);
 }
 
 static int adapt_colors(SwsGraph *graph, const SwsFormat *src_fmt,
@@ -777,7 +780,7 @@ static int adapt_colors(SwsGraph *graph, const SwsFormat 
*src_fmt,
     }
 
     return ff_sws_graph_add_pass(graph, fmt_out, src.width, src.height,
-                                 input, 1, run_lut3d, setup_lut3d, lut,
+                                 input, 0, 1, run_lut3d, setup_lut3d, lut,
                                  free_lut3d, output);
 }
 
@@ -812,7 +815,7 @@ static int init_passes(SwsGraph *graph)
 
     /* Add threaded memcpy pass */
     return ff_sws_graph_add_pass(graph, dst.format, dst.width, dst.height,
-                                 pass, 1, run_copy, NULL, NULL, NULL, &pass);
+                                 pass, 0, 1, run_copy, NULL, NULL, NULL, 
&pass);
 }
 
 static void sws_graph_worker(void *priv, int jobnr, int threadnr, int nb_jobs,
@@ -821,7 +824,7 @@ static void sws_graph_worker(void *priv, int jobnr, int 
threadnr, int nb_jobs,
     SwsGraph *graph = priv;
     const SwsPass *pass = graph->exec.pass;
     const int slice_y = jobnr * pass->slice_h;
-    const int slice_h = FFMIN(pass->slice_h, pass->height - slice_y);
+    const int slice_h = FFMIN(pass->slice_h, pass->lines - slice_y);
 
     pass->run(graph->exec.output, graph->exec.input, slice_y, slice_h, pass);
 }
@@ -1016,7 +1019,7 @@ int ff_sws_graph_run(SwsGraph *graph, const AVFrame *dst, 
const AVFrame *src)
         }
 
         if (pass->num_slices == 1) {
-            pass->run(graph->exec.output, graph->exec.input, 0, pass->height, 
pass);
+            pass->run(graph->exec.output, graph->exec.input, 0, pass->lines, 
pass);
         } else {
             avpriv_slicethread_execute(graph->slicethread, pass->num_slices, 
0);
         }
diff --git a/libswscale/graph.h b/libswscale/graph.h
index adf4b19675..eff2dcc47f 100644
--- a/libswscale/graph.h
+++ b/libswscale/graph.h
@@ -83,7 +83,7 @@ struct SwsPass {
     SwsPassFunc run;
     SwsBackend backend; /* backend this pass is using, or 0 */
     enum AVPixelFormat format; /* new pixel format */
-    int width, height; /* new output size */
+    int lines;         /* pass dispatch size */
     int slice_h;       /* filter granularity */
     int num_slices;
 
@@ -184,6 +184,7 @@ int ff_sws_graph_create(SwsContext *ctx, const SwsFormat 
*dst, const SwsFormat *
  * @param w      Width of the output image.
  * @param h      Height of the output image.
  * @param input  Previous pass to read from, or NULL for the input image.
+ * @param lines  Override the number of lines processed for this pass. 
(Optional)
  * @param align  Minimum slice alignment for this pass, or 0 for no threading.
  * @param run    Filter function to run.
  * @param setup  Optional setup function to run from the main thread.
@@ -194,7 +195,8 @@ int ff_sws_graph_create(SwsContext *ctx, const SwsFormat 
*dst, const SwsFormat *
  */
 int ff_sws_graph_add_pass(SwsGraph *graph, enum AVPixelFormat fmt,
                           int width, int height, SwsPass *input,
-                          int align, SwsPassFunc run, SwsPassSetup setup,
+                          int lines, int align,
+                          SwsPassFunc run, SwsPassSetup setup,
                           void *priv, void (*free)(void *priv),
                           SwsPass **out_pass);
 
diff --git a/libswscale/ops_dispatch.c b/libswscale/ops_dispatch.c
index 44248195d7..abf67b0d55 100644
--- a/libswscale/ops_dispatch.c
+++ b/libswscale/ops_dispatch.c
@@ -202,6 +202,7 @@ static int op_pass_setup(const SwsFrame *out, const 
SwsFrame *in,
 {
     const AVPixFmtDescriptor *indesc  = av_pix_fmt_desc_get(in->format);
     const bool float_in = indesc->flags & AV_PIX_FMT_FLAG_FLOAT;
+    const int width = out->width;
 
     SwsOpPass *p = pass->priv;
     SwsOpExec *exec = &p->exec_base;
@@ -209,9 +210,9 @@ static int op_pass_setup(const SwsFrame *out, const 
SwsFrame *in,
 
     /* Set up main loop parameters */
     const unsigned block_size = comp->block_size;
-    const size_t num_blocks   = (pass->width + block_size - 1) / block_size;
+    const size_t num_blocks   = (width + block_size - 1) / block_size;
     const size_t aligned_w    = num_blocks * block_size;
-    if (aligned_w < pass->width) /* overflow */
+    if (aligned_w < width) /* overflow */
         return AVERROR(EINVAL);
     p->num_blocks   = num_blocks;
     p->memcpy_first = false;
@@ -280,14 +281,14 @@ static int op_pass_setup(const SwsFrame *out, const 
SwsFrame *in,
     *tail = *exec;
 
     const size_t safe_width = safe_blocks * block_size;
-    const size_t tail_size  = pass->width - safe_width;
+    const size_t tail_size  = width - safe_width;
     p->tail_off_out  = pixel_bytes(safe_width, p->pixel_bits_out, 
AV_ROUND_DOWN);
     p->tail_size_out = pixel_bytes(tail_size,  p->pixel_bits_out, AV_ROUND_UP);
     p->tail_blocks   = num_blocks - safe_blocks;
 
     if (exec->in_offset_x) {
         p->tail_off_in  = exec->in_offset_x[safe_width];
-        p->tail_size_in = exec->in_offset_x[pass->width - 1] - p->tail_off_in;
+        p->tail_size_in = exec->in_offset_x[width - 1] - p->tail_off_in;
         p->tail_size_in += pixel_bytes(p->filter_size_h, p->pixel_bits_in, 
AV_ROUND_UP);
     } else {
         p->tail_off_in  = pixel_bytes(safe_width, p->pixel_bits_in, 
AV_ROUND_DOWN);
@@ -387,7 +388,7 @@ static void op_pass_run(const SwsFrame *out, const SwsFrame 
*in, const int y,
      *    memcpy the last column on the output side if unpadded.
      */
 
-    const bool memcpy_in  = p->memcpy_last && y + h == pass->height ||
+    const bool memcpy_in  = p->memcpy_last && y + h == pass->lines ||
                             p->memcpy_first && y == 0;
     const bool memcpy_out = p->memcpy_out;
     const size_t num_blocks  = p->num_blocks;
@@ -515,7 +516,7 @@ static int compile(SwsGraph *graph, const SwsOpBackend 
*backend,
         SwsCompiledOp c = *comp;
         av_free(p);
         ret = ff_sws_graph_add_pass(graph, dst->format, dst->width, 
dst->height,
-                                    input, c.slice_align, c.func_opaque,
+                                    input, 0, c.slice_align, c.func_opaque,
                                     NULL, c.priv, c.free, output);
         if (ret >= 0)
             (*output)->backend = comp->backend->flags;
@@ -616,7 +617,7 @@ static int compile(SwsGraph *graph, const SwsOpBackend 
*backend,
     }
 
     ret = ff_sws_graph_add_pass(graph, dst->format, dst->width, dst->height,
-                                input, comp->slice_align, op_pass_run,
+                                input, 0, comp->slice_align, op_pass_run,
                                 op_pass_setup, p, op_pass_free, output);
     if (ret < 0)
         return ret;

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to