This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit b4bcb00cd3853316fb8f1d869b82919fa00babb3 Author: Niklas Haas <[email protected]> AuthorDate: Thu Mar 5 18:08:25 2026 +0100 Commit: Niklas Haas <[email protected]> CommitDate: Thu Mar 5 23:34:56 2026 +0000 swscale/ops: add and use ff_sws_op_list_input/output() Makes various pieces of code that expect to get a SWS_OP_READ more robust, and also allows us to generalize to introduce more input op types in the future (in particular, I am looking ahead towards filter ops). Signed-off-by: Niklas Haas <[email protected]> --- libswscale/ops.c | 26 +++++++++++++++++++++----- libswscale/ops.h | 15 +++++++++++++++ libswscale/ops_dispatch.c | 15 +++++---------- libswscale/ops_optimizer.c | 14 ++++++-------- libswscale/x86/ops.c | 6 +++--- 5 files changed, 50 insertions(+), 26 deletions(-) diff --git a/libswscale/ops.c b/libswscale/ops.c index d2837d97c7..9961f4f791 100644 --- a/libswscale/ops.c +++ b/libswscale/ops.c @@ -541,6 +541,24 @@ SwsOpList *ff_sws_op_list_duplicate(const SwsOpList *ops) return copy; } +const SwsOp *ff_sws_op_list_input(const SwsOpList *ops) +{ + if (!ops->num_ops) + return NULL; + + const SwsOp *read = &ops->ops[0]; + return read->op == SWS_OP_READ ? read : NULL; +} + +const SwsOp *ff_sws_op_list_output(const SwsOpList *ops) +{ + if (!ops->num_ops) + return NULL; + + const SwsOp *write = &ops->ops[ops->num_ops - 1]; + return write->op == SWS_OP_WRITE ? write : NULL; +} + void ff_sws_op_list_remove_at(SwsOpList *ops, int index, int count) { const int end = ops->num_ops - count; @@ -575,11 +593,9 @@ bool ff_sws_op_list_is_noop(const SwsOpList *ops) if (!ops->num_ops) return true; - const SwsOp *read = &ops->ops[0]; - const SwsOp *write = &ops->ops[1]; - if (ops->num_ops != 2 || - read->op != SWS_OP_READ || - write->op != SWS_OP_WRITE || + const SwsOp *read = ff_sws_op_list_input(ops); + const SwsOp *write = ff_sws_op_list_output(ops); + if (!read || !write || ops->num_ops > 2 || read->type != write->type || read->rw.packed != write->rw.packed || read->rw.elems != write->rw.elems || diff --git a/libswscale/ops.h b/libswscale/ops.h index 1684107f00..64a4a6dd61 100644 --- a/libswscale/ops.h +++ b/libswscale/ops.h @@ -249,6 +249,21 @@ void ff_sws_op_list_free(SwsOpList **ops); */ SwsOpList *ff_sws_op_list_duplicate(const SwsOpList *ops); +/** + * Returns the input operation for a given op list, or NULL if there is none + * (e.g. for a pure CLEAR-only operation list). + * + * This will always be an op of type SWS_OP_READ. + */ +const SwsOp *ff_sws_op_list_input(const SwsOpList *ops); + +/** + * Returns the output operation for a given op list, or NULL if there is none. + * + * This will always be an op of type SWS_OP_WRITE. + */ +const SwsOp *ff_sws_op_list_output(const SwsOpList *ops); + /** * Returns whether an op list represents a true no-op operation, i.e. may be * eliminated entirely from an execution graph. diff --git a/libswscale/ops_dispatch.c b/libswscale/ops_dispatch.c index 3faa677858..5d3bb73123 100644 --- a/libswscale/ops_dispatch.c +++ b/libswscale/ops_dispatch.c @@ -335,8 +335,8 @@ static int compile(SwsGraph *graph, const SwsOpList *ops, if (ret < 0) goto fail; - const SwsOp *read = &ops->ops[0]; - const SwsOp *write = &ops->ops[ops->num_ops - 1]; + const SwsOp *read = ff_sws_op_list_input(ops); + const SwsOp *write = ff_sws_op_list_output(ops); p->planes_in = rw_planes(read); p->planes_out = rw_planes(write); p->pixel_bits_in = rw_pixel_bits(read); @@ -375,8 +375,6 @@ int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, int flags, const SwsFormat *dst, SwsPass *input, SwsPass **output) { SwsContext *ctx = graph->ctx; - const SwsOp *read = &ops->ops[0]; - const SwsOp *write = &ops->ops[ops->num_ops - 1]; int ret; /* Check if the whole operation graph is an end-to-end no-op */ @@ -385,12 +383,9 @@ int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, int flags, return 0; } - if (ops->num_ops < 2) { - av_log(ctx, AV_LOG_ERROR, "Need at least two operations.\n"); - return AVERROR(EINVAL); - } - - if (read->op != SWS_OP_READ || write->op != SWS_OP_WRITE) { + const SwsOp *read = ff_sws_op_list_input(ops); + const SwsOp *write = ff_sws_op_list_output(ops); + if (!read || !write) { av_log(ctx, AV_LOG_ERROR, "First and last operations must be a read " "and write, respectively.\n"); return AVERROR(EINVAL); diff --git a/libswscale/ops_optimizer.c b/libswscale/ops_optimizer.c index 9cddb3d7f5..abba9df2ff 100644 --- a/libswscale/ops_optimizer.c +++ b/libswscale/ops_optimizer.c @@ -690,15 +690,13 @@ int ff_sws_solve_shuffle(const SwsOpList *const ops, uint8_t shuffle[], if (!ops->num_ops) return AVERROR(EINVAL); - const SwsOp read = ops->ops[0]; - const int read_size = ff_sws_pixel_type_size(read.type); - uint32_t mask[4] = {0}; - - if (read.op != SWS_OP_READ || read.rw.frac || - (!read.rw.packed && read.rw.elems > 1)) + const SwsOp *read = ff_sws_op_list_input(ops); + if (!read || read->rw.frac || (!read->rw.packed && read->rw.elems > 1)) return AVERROR(ENOTSUP); - for (int i = 0; i < read.rw.elems; i++) + const int read_size = ff_sws_pixel_type_size(read->type); + uint32_t mask[4] = {0}; + for (int i = 0; i < read->rw.elems; i++) mask[i] = 0x01010101 * i * read_size + 0x03020100; for (int opidx = 1; opidx < ops->num_ops; opidx++) { @@ -750,7 +748,7 @@ int ff_sws_solve_shuffle(const SwsOpList *const ops, uint8_t shuffle[], memset(shuffle, clear_val, size); const int write_size = ff_sws_pixel_type_size(op->type); - const int read_chunk = read.rw.elems * read_size; + const int read_chunk = read->rw.elems * read_size; const int write_chunk = op->rw.elems * write_size; const int num_groups = size / FFMAX(read_chunk, write_chunk); for (int n = 0; n < num_groups; n++) { diff --git a/libswscale/x86/ops.c b/libswscale/x86/ops.c index 45e2b10bff..61288cc229 100644 --- a/libswscale/x86/ops.c +++ b/libswscale/x86/ops.c @@ -679,9 +679,9 @@ static int compile(SwsContext *ctx, SwsOpList *ops, SwsCompiledOp *out) if (mmsize < 0) return mmsize; - av_assert1(ops->num_ops > 0); - const SwsOp *read = ops->ops[0].op == SWS_OP_READ ? &ops->ops[0] : NULL; - const SwsOp *write = &ops->ops[ops->num_ops - 1]; + const SwsOp *read = ff_sws_op_list_input(ops); + const SwsOp *write = ff_sws_op_list_output(ops); + av_assert1(write); int ret; /* Special fast path for in-place packed shuffle */ _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
