swscale/ops: lift read op metadata to SwsOpList

Instead of awkwardly preserving these from the `SwsOp` itself. This
interpretation lessens the risk of bugs as a result of changing the plane
swizzle mask without updating the corresponding components.

After this commit, the plane swizzle mask is automatically taken into
account; i.e. the src_comps mask is always interpreted as if the read op
was in-order (unswizzled).

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
This commit is contained in:
Niklas Haas
2026-02-19 17:20:25 +01:00
committed by Niklas Haas
parent 1940662ac6
commit da47951bd7
3 changed files with 25 additions and 16 deletions

View File

@@ -896,7 +896,7 @@ int ff_sws_decode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
SwsReadWriteOp rw_op;
SwsSwizzleOp swizzle;
SwsPackOp unpack;
SwsComps comps = {0};
SwsComps *comps = &ops->comps_src;
int shift;
RET(fmt_analyze(fmt, &rw_op, &unpack, &swizzle, &shift,
@@ -908,8 +908,8 @@ int ff_sws_decode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
const int integer = ff_sws_pixel_type_is_int(raw_type);
const int swapped = (desc->flags & AV_PIX_FMT_FLAG_BE) != NATIVE_ENDIAN_FLAG;
for (int i = 0; i < rw_op.elems; i++) {
comps.flags[i] = (integer ? SWS_COMP_EXACT : 0) |
(swapped ? SWS_COMP_SWAPPED : 0);
comps->flags[i] = (integer ? SWS_COMP_EXACT : 0) |
(swapped ? SWS_COMP_SWAPPED : 0);
}
/* Generate value range information for simple unpacked formats */
@@ -920,9 +920,9 @@ int ff_sws_decode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
for (int c = 0; c < desc->nb_components; c++) {
const int bits = desc->comp[c].depth + shift;
const int idx = swizzle.in[is_ya ? 3 * c : c];
comps.min[idx] = Q0;
comps->min[idx] = Q0;
if (bits < 32) /* FIXME: AVRational is limited to INT_MAX */
comps.max[idx] = Q((1ULL << bits) - 1);
comps->max[idx] = Q((1ULL << bits) - 1);
}
}
@@ -931,7 +931,6 @@ int ff_sws_decode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
.op = SWS_OP_READ,
.type = raw_type,
.rw = rw_op,
.comps = comps,
}));
if (swapped) {

View File

@@ -249,8 +249,14 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
switch (op->op) {
case SWS_OP_READ:
/* Active components are preserved from the user-provided value,
/* Active components are taken from the user-provided values,
* other components are explicitly stripped */
for (int i = 0; i < op->rw.elems; i++) {
const int idx = op->rw.packed ? i : ops->order_src.in[i];
op->comps.flags[i] = ops->comps_src.flags[idx];
op->comps.min[i] = ops->comps_src.min[idx];
op->comps.max[i] = ops->comps_src.max[idx];
}
for (int i = op->rw.elems; i < 4; i++) {
op->comps.flags[i] = prev.flags[i];
op->comps.min[i] = prev.min[i];

View File

@@ -197,15 +197,8 @@ typedef struct SwsOp {
};
/**
* Metadata about the operation's input/output components.
*
* For SWS_OP_READ, this is informative; and lets the optimizer know
* additional information about the value range and/or pixel data to expect.
* The default value of {0} is safe to pass in the case that no additional
* information is known.
*
* For every other operation, this metadata is discarded and regenerated
* automatically by `ff_sws_op_list_update_comps()`.
* Metadata about the operation's input/output components. Discarded
* and regenerated automatically by `ff_sws_op_list_update_comps()`.
*
* Note that backends may rely on the presence and accuracy of this
* metadata for all operations, during ff_sws_ops_compile().
@@ -233,6 +226,17 @@ typedef struct SwsOpList {
/* Input/output plane pointer swizzle mask */
SwsSwizzleOp order_src, order_dst;
/**
* Source component metadata associated with pixel values from each
* corresponding component (in plane/memory order, i.e. not affected by
* `order_src`). Lets the optimizer know additional information about
* the value range and/or pixel data to expect.
*
* The default value of {0} is safe to pass in the case that no additional
* information is known.
*/
SwsComps comps_src;
/* Purely informative metadata associated with this operation list */
SwsFormat src, dst;
} SwsOpList;