This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 6b38a4035ab9250d9e04cf211675f87fe279c6c0 Author: Niklas Haas <[email protected]> AuthorDate: Tue Aug 4 12:17:58 2026 +0200 Commit: Niklas Haas <[email protected]> CommitDate: Sun Aug 9 21:03:33 2026 +0200 swscale/graph: add plane copy metadata This can be set opportunistically by passes which are effectively memcopies. Information about end-to-end plane copies will also propagate upwards to the SwsGraph, and can be used there by the caller. The reason we need to solve it this way is deeply tied to the way SwsGraph is designed; specifically the fact that it can be used with arbitrary frames and also lives per-field (rather than per-frame), meaning that we can't just directly mutate the output frame somehow from the run() call to ref the output planes. Signed-off-by: Niklas Haas <[email protected]> --- libswscale/graph.c | 49 ++++++++++++++++++++++++++++++++++++++++++------- libswscale/graph.h | 19 +++++++++++++++++++ 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/libswscale/graph.c b/libswscale/graph.c index 978be35203..012bb53388 100644 --- a/libswscale/graph.c +++ b/libswscale/graph.c @@ -207,6 +207,7 @@ int ff_sws_graph_add_pass(SwsGraph *graph, enum AVPixelFormat fmt, pass->output->height = height; pass->output->width = width; pass->output->width_align = 1; + memset(pass->output->plane_copy, -1, sizeof(pass->output->plane_copy)); if (!align) { pass->slice_h = pass->lines; @@ -242,6 +243,13 @@ void ff_sws_pass_link_output(SwsPass *dst, const SwsPass *src) keep->width_align = FFMAX(keep->width_align, drop->width_align); keep->width_pad = FFMAX(keep->width_pad, drop->width_pad); + for (int i = 0; i < FF_ARRAY_ELEMS(keep->plane_copy); i++) { + if (keep->plane_copy[i] < 0) + keep->plane_copy[i] = drop->plane_copy[i]; + else if (drop->plane_copy[i] >= 0) + av_assert1(keep->plane_copy[i] == drop->plane_copy[i]); + } + av_refstruct_replace(&dst->output, src->output); } @@ -790,15 +798,41 @@ static int init_passes(SwsGraph *graph) return ret; } - if (pass) - return 0; + if (!pass) { + /* No passes were added, so no operations were necessary */ + graph->noop = 1; + + const int nb_planes = av_pix_fmt_count_planes(dst.format); + for (int i = 0; i < nb_planes; i++) + graph->plane_copy[i] = i; - /* No passes were added, so no operations were necessary */ - graph->noop = 1; + /* Add threaded memcpy pass */ + return ff_sws_graph_add_pass(graph, dst.format, dst.width, dst.height, + pass, 0, 1, run_copy, NULL, NULL, NULL, &pass); + } - /* Add threaded memcpy pass */ - return ff_sws_graph_add_pass(graph, dst.format, dst.width, dst.height, - pass, 0, 1, run_copy, NULL, NULL, NULL, &pass); + /* Compute end-to-end plane copy map */ + for (int n = 0; n < graph->num_passes; n++) { + const SwsPass *pass = graph->passes[n]; + /* This pass writes to an output buffer other than the image + * output, or copies from the output of a different pass */ + if (pass->output->avframe || pass->input) + continue; + for (int i = 0; i < FF_ARRAY_ELEMS(graph->plane_copy); i++) { + const int idx = pass->output->plane_copy[i]; + if (idx < 0) + continue; + if (graph->plane_copy[i] < 0) { + graph->plane_copy[i] = idx; + av_log(graph->ctx, AV_LOG_DEBUG, "Plane %d passthrough from " + "plane %d\n", i, idx); + } else { + av_assert0(graph->plane_copy[i] == idx); + } + } + } + + return 0; } static void sws_graph_worker(void *priv, int jobnr, int threadnr, int nb_jobs, @@ -845,6 +879,7 @@ int ff_sws_graph_init(SwsGraph *graph, SwsContext *ctx, const SwsFormat *dst, graph->opts_copy = *ctx; av_assert0(src->interlaced == dst->interlaced); av_assert0(src->field == dst->field); + memset(graph->plane_copy, -1, sizeof(graph->plane_copy)); if (ctx->threads == 1) { graph->num_threads = 1; diff --git a/libswscale/graph.h b/libswscale/graph.h index 4399346d46..7380a991ce 100644 --- a/libswscale/graph.h +++ b/libswscale/graph.h @@ -66,6 +66,15 @@ typedef struct SwsPassBuffer { /* Optional allocation hints for optimal performance */ int width_align; /* Align width to multiple of this */ int width_pad; /* Extra padding pixels */ + + /** + * Map of planes which are directly copied from the pass input. These + * may be promoted from a memcpy to a refcopy. + * + * Each entry maps the output index to the corresponding input plane + * index, or -1 for no copythrough. + */ + int plane_copy[4]; } SwsPassBuffer; /** @@ -130,6 +139,16 @@ typedef struct SwsGraph { AVBufferRef *hw_frames_ref; + /** + * Map of planes which directly copied from the input. These may be + * promoted from a memcpy to a refcopy. This requires special handling + * by the caller. + * + * Each entry maps the output index to the corresponding input plane + * index, or -1 for no copythrough. + */ + int plane_copy[4]; + /** Sorted sequence of filter passes to apply */ SwsPass **passes; int num_passes; _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
