Commit 3367cee3ba for ffmpeg
commit 3367cee3ba5116bc00ad93c890f5ee2fc7974c46
Author: Niklas Haas <git@haasn.dev>
Date: Mon Oct 19 22:43:02 2026 +0200
swscale/ops: keep track of pixel type on the output pad
The optimizer can use this metadata going forward, instead of relying on
the ambiguous SwsOp.type (to be removed).
If a type collision would happen, instead mark the output pad as invalid.
Signed-off-by: Niklas Haas <git@haasn.dev>
diff --git a/libswscale/ops.c b/libswscale/ops.c
index 895fefc7ef..a66832f3e9 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -345,7 +345,9 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
}
}
+ SwsCompMask invalid = 0;
for (int i = 0; i < 4; i++) {
+ op->outputs[i].type = SWS_PIXEL_NONE;
op->outputs[i].flags = SWS_COMP_IDENTITY;
op->outputs[i].dep_in = SWS_COMP_NONE;
}
@@ -354,12 +356,16 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
SwsOpPad *dst = &op->outputs[I]; \
const SwsOpPad *src = &prev[J]; \
SwsCompFlags flags = src->flags; \
+ if (!src->type || dst->type && dst->type != src->type) \
+ invalid |= SWS_COMP(I); \
dst->flags = merge_comp_flags(dst->flags, (EXPR)); \
dst->dep_in |= src->dep_in; \
+ dst->type = src->type; \
} while (0)
#define RESET(I) do { \
SwsOpPad *dst = &op->outputs[I]; \
+ dst->type = SWS_PIXEL_NONE; \
dst->flags = SWS_COMP_GARBAGE; \
dst->min = dst->max = (AVRational64) {0}; \
dst->dep_in = SWS_COMP_NONE; \
@@ -380,6 +386,7 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
const SwsOpPad *src = &ops->inputs[idx];
SwsOpPad *dst = &op->outputs[i];
av_assert0(!(src->flags & SWS_COMP_GARBAGE));
+ dst->type = op->rw.type;
dst->flags = src->flags & SWS_COMP_DIRTY;
dst->min = src->min;
dst->max = src->max;
@@ -399,6 +406,8 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
if (op->rw.filter.op) {
memcpy(prev, op->outputs, sizeof(prev));
apply_filter_weights(op->outputs, prev, op->rw.filter.kernel);
+ for (int i = 0; i < op->rw.elems; i++)
+ op->outputs[i].type = op->rw.filter.type;
}
break;
case SWS_OP_SWAP_BYTES:
@@ -470,6 +479,7 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
case SWS_OP_CLEAR:
for (int i = 0; i < 4; i++) {
if (SWS_COMP_TEST(op->clear.mask, i)) {
+ op->outputs[i].type = op->clear.type[i];
op->outputs[i].flags = SWS_COMP_CONST;
if (op->clear.value[i].num == 0)
op->outputs[i].flags |= SWS_COMP_ZERO;
@@ -487,6 +497,7 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
case SWS_OP_CONVERT:
for (int i = 0; i < 4; i++) {
FORWARD(i, i, flags);
+ op->outputs[i].type = op->convert.to;
if (!(prev[i].flags & SWS_COMP_EXACT))
op->outputs[i].flags &= SWS_COMP_DIRTY;
if (ff_sws_pixel_type_is_int(op->convert.to))
@@ -497,6 +508,7 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
for (int i = 0; i < 4; i++) {
SwsOpPad *dst = &op->outputs[i];
bool first = true;
+ dst->type = op->lin.type[i];
dst->min = dst->max = Q(0);
for (int j = 0; j < 4; j++) {
const SwsOpPad *src = &prev[j];
@@ -537,6 +549,8 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
case SWS_OP_FILTER_H:
case SWS_OP_FILTER_V: {
apply_filter_weights(op->outputs, prev, op->filter.kernel);
+ for (int i = 0; i < 4; i++)
+ op->outputs[i].type = op->filter.type;
break;
}
case SWS_OP_LUT_3D:
@@ -559,6 +573,12 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
av_unreachable("Invalid operation type!");
}
+ /* Explicitly reset any pads that did not receive valid data */
+ for (int i = 0; i < 4; i++) {
+ if (!op->outputs[i].type || SWS_COMP_TEST(invalid, i))
+ RESET(i);
+ }
+
memcpy(prev, op->outputs, sizeof(prev));
}
@@ -999,21 +1019,6 @@ static void desc_plane_order(AVBPrint *bp, int nb_planes, const uint8_t *order)
av_bprintf(bp, "}");
}
-static SwsPixelType op_result_type(const SwsOp *op)
-{
- switch (op->op) {
- case SWS_OP_CONVERT:
- return op->convert.to;
- case SWS_OP_READ:
- return op->rw.filter.op ? op->rw.filter.type : op->type;
- case SWS_OP_FILTER_H:
- case SWS_OP_FILTER_V:
- return op->filter.type;
- default:
- return op->type;
- }
-}
-
void ff_sws_op_list_print(void *log, int lev, int lev_extra,
const SwsOpList *ops)
{
@@ -1045,7 +1050,7 @@ void ff_sws_op_list_print(void *log, int lev, int lev_extra,
if (!SWS_COMP_TEST(mask, i))
continue;
av_bprint_clear(bp);
- av_bprintf(bp, " %c: %3s,", "XYZW"[i], ff_sws_pixel_type_name(op_result_type(op)));
+ av_bprintf(bp, " %c: %3s,", "XYZW"[i], ff_sws_pixel_type_name(pad->type));
print_deps(bp, pad->dep_in);
av_bprintf(bp, " ->");
print_deps(bp, pad->dep_out);
diff --git a/libswscale/ops.h b/libswscale/ops.h
index 8f5b8bbf9d..aad48660b3 100644
--- a/libswscale/ops.h
+++ b/libswscale/ops.h
@@ -236,6 +236,7 @@ typedef enum SwsCompFlags {
} SwsCompFlags;
typedef struct SwsOpPad {
+ SwsPixelType type; /* pixel type of this output component */
SwsCompFlags flags; /* knowledge about (output) component contents */
/* Keeps track of the known possible value range, or {0, 0} for undefined