Commit a3d9acfaed for ffmpeg
commit a3d9acfaed39bded9261339304b1cf4f149fdcaa
Author: Niklas Haas <git@haasn.dev>
Date: Tue Oct 20 20:55:04 2026 +0200
swscale/ops: switch SwsComps from SoA to AoS
And name them SwsOpPad instead. This is a purely cosmetic refactor that
makes some parts of the code easier, since it allows taking pointers to
specific output pads without having to thread through the index as well.
Signed-off-by: Niklas Haas <git@haasn.dev>
diff --git a/libswscale/format.c b/libswscale/format.c
index 4f75adcc0f..1167c0446c 100644
--- a/libswscale/format.c
+++ b/libswscale/format.c
@@ -1093,7 +1093,7 @@ static int decode_pixfmt(SwsOpList *ops, const SwsFormat *fmt)
SwsReadWriteOp rw_op;
SwsSwizzleOp swizzle;
SwsPackOp unpack;
- SwsComps *comps = &ops->comps_src;
+ SwsOpPad *inputs = ops->inputs;
SwsShiftOp shift;
RET(fmt_analyze(fmt->format, &rw_op, &unpack, &swizzle, &shift,
@@ -1106,7 +1106,7 @@ static int decode_pixfmt(SwsOpList *ops, const SwsFormat *fmt)
const int swapped = ff_sws_pixel_type_size(raw_type) > 1 &&
(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) |
+ inputs[i].flags = (integer ? SWS_COMP_EXACT : 0) |
(swapped ? SWS_COMP_SWAPPED : 0);
}
@@ -1118,8 +1118,8 @@ static int decode_pixfmt(SwsOpList *ops, const SwsFormat *fmt)
for (int c = 0; c < desc->nb_components; c++) {
const int bits = desc->comp[c].depth + shift.amount;
const int idx = swizzle.in[is_ya ? 3 * c : c];
- comps->min[idx] = Q(0);
- comps->max[idx] = intmax_q64(bits);
+ inputs[idx].min = Q(0);
+ inputs[idx].max = intmax_q64(bits);
}
}
diff --git a/libswscale/ops.c b/libswscale/ops.c
index 800a41befa..07159b57d8 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -287,31 +287,34 @@ static SwsCompFlags merge_comp_flags(SwsCompFlags a, SwsCompFlags b)
return ((a & b) & flags_and) | ((a | b) & flags_or);
}
-static void apply_filter_weights(SwsComps *comps, const SwsComps *prev,
+static void apply_filter_weights(SwsOpPad outputs[4], const SwsOpPad inputs[4],
const SwsFilterWeights *weights)
{
const AVRational64 posw = { weights->sum_positive, SWS_FILTER_SCALE };
const AVRational64 negw = { weights->sum_negative, SWS_FILTER_SCALE };
for (int i = 0; i < 4; i++) {
- comps->flags[i] = prev->flags[i] & SWS_COMP_DIRTY;
- comps->dep_in[i] = prev->dep_in[i];
+ outputs[i].flags = inputs[i].flags & SWS_COMP_DIRTY;
+ outputs[i].dep_in = inputs[i].dep_in;
/* Only point sampling preserves exactness */
if (weights->filter_size != 1)
- comps->flags[i] &= ~SWS_COMP_EXACT;
+ outputs[i].flags &= ~SWS_COMP_EXACT;
/* Update min/max assuming extremes */
- comps->min[i] = ff_add_q64(ff_mul_q64(prev->min[i], posw),
- ff_mul_q64(prev->max[i], negw));
- comps->max[i] = ff_add_q64(ff_mul_q64(prev->min[i], negw),
- ff_mul_q64(prev->max[i], posw));
+ outputs[i].min = ff_add_q64(ff_mul_q64(inputs[i].min, posw),
+ ff_mul_q64(inputs[i].max, negw));
+ outputs[i].max = ff_add_q64(ff_mul_q64(inputs[i].min, negw),
+ ff_mul_q64(inputs[i].max, posw));
}
}
/* Infer + propagate known information about components */
void ff_sws_op_list_update_comps(SwsOpList *ops)
{
- SwsComps prev = { .flags = {
- SWS_COMP_GARBAGE, SWS_COMP_GARBAGE, SWS_COMP_GARBAGE, SWS_COMP_GARBAGE,
- }};
+ SwsOpPad prev[4] = {
+ { .flags = SWS_COMP_GARBAGE },
+ { .flags = SWS_COMP_GARBAGE },
+ { .flags = SWS_COMP_GARBAGE },
+ { .flags = SWS_COMP_GARBAGE },
+ };
/* Forwards pass, propagates knowledge about the incoming pixel values */
for (int n = 0; n < ops->num_ops; n++) {
@@ -326,29 +329,40 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
case SWS_OP_FILTER_V:
case SWS_OP_LUT_3D:
break; /* special cases, handled below */
- default:
- memcpy(op->comps.min, prev.min, sizeof(prev.min));
- memcpy(op->comps.max, prev.max, sizeof(prev.max));
- ff_sws_apply_op_q(op, op->comps.min);
- ff_sws_apply_op_q(op, op->comps.max);
+ default: {
+ AVRational64 min[4], max[4];
+ for (int i = 0; i < 4; i++) {
+ min[i] = prev[i].min;
+ max[i] = prev[i].max;
+ }
+ ff_sws_apply_op_q(op, min);
+ ff_sws_apply_op_q(op, max);
+ for (int i = 0; i < 4; i++) {
+ op->outputs[i].min = min[i];
+ op->outputs[i].max = max[i];
+ }
break;
}
+ }
for (int i = 0; i < 4; i++) {
- op->comps.flags[i] = SWS_COMP_IDENTITY;
- op->comps.dep_in[i] = SWS_COMP_NONE;
+ op->outputs[i].flags = SWS_COMP_IDENTITY;
+ op->outputs[i].dep_in = SWS_COMP_NONE;
}
#define FORWARD(I, J, EXPR) do { \
- SwsCompFlags flags = prev.flags[J]; \
- op->comps.flags[I] = merge_comp_flags(op->comps.flags[I], (EXPR)); \
- op->comps.dep_in[I] |= prev.dep_in[J]; \
+ SwsOpPad *dst = &op->outputs[I]; \
+ const SwsOpPad *src = &prev[J]; \
+ SwsCompFlags flags = src->flags; \
+ dst->flags = merge_comp_flags(dst->flags, (EXPR)); \
+ dst->dep_in |= src->dep_in; \
} while (0)
#define RESET(I) do { \
- op->comps.flags[I] = SWS_COMP_GARBAGE; \
- op->comps.min[I] = op->comps.max[I] = (AVRational64) {0}; \
- op->comps.dep_in[I] = SWS_COMP_NONE; \
+ SwsOpPad *dst = &op->outputs[I]; \
+ dst->flags = SWS_COMP_GARBAGE; \
+ dst->min = dst->max = (AVRational64) {0}; \
+ dst->dep_in = SWS_COMP_NONE; \
} while (0)
switch (op->op) {
@@ -363,11 +377,13 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
case SWS_RW_PLANAR: idx = ops->plane_src[i]; break;
}
- av_assert0(!(ops->comps_src.flags[idx] & SWS_COMP_GARBAGE));
- op->comps.flags[i] = ops->comps_src.flags[idx] & SWS_COMP_DIRTY;
- op->comps.min[i] = ops->comps_src.min[idx];
- op->comps.max[i] = ops->comps_src.max[idx];
- op->comps.dep_in[i] = SWS_COMP(i);
+ const SwsOpPad *src = &ops->inputs[idx];
+ SwsOpPad *dst = &op->outputs[i];
+ av_assert0(!(src->flags & SWS_COMP_GARBAGE));
+ dst->flags = src->flags & SWS_COMP_DIRTY;
+ dst->min = src->min;
+ dst->max = src->max;
+ dst->dep_in = SWS_COMP(i);
/**
* Don't mark packed or fractional reads as a copy, because the
@@ -377,24 +393,24 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
* is already covered by the no-op check.
*/
if (op->rw.mode == SWS_RW_PLANAR && !op->rw.frac)
- op->comps.flags[i] |= SWS_COMP_COPY;
+ dst->flags |= SWS_COMP_COPY;
}
if (op->rw.filter.op) {
- const SwsComps prev = op->comps;
- apply_filter_weights(&op->comps, &prev, op->rw.filter.kernel);
+ memcpy(prev, op->outputs, sizeof(prev));
+ apply_filter_weights(op->outputs, prev, op->rw.filter.kernel);
}
break;
case SWS_OP_SWAP_BYTES:
for (int i = 0; i < 4; i++) {
FORWARD(i, i, (flags ^ SWS_COMP_SWAPPED) & SWS_COMP_DIRTY);
- op->comps.min[i] = prev.min[i];
- op->comps.max[i] = prev.max[i];
+ op->outputs[i].min = prev[i].min;
+ op->outputs[i].max = prev[i].max;
}
break;
case SWS_OP_WRITE:
for (int i = 0; i < op->rw.elems; i++)
- av_assert1(!(prev.flags[i] & SWS_COMP_GARBAGE));
+ av_assert1(!(prev[i].flags & SWS_COMP_GARBAGE));
for (int i = 0; i < 4; i++)
FORWARD(i, i, flags);
break;
@@ -405,27 +421,30 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
break;
case SWS_OP_MIN:
case SWS_OP_MAX: {
- AVRational64 *bound = op->op == SWS_OP_MIN ? op->comps.max : op->comps.min;
for (int i = 0; i < 4; i++) {
+ SwsOpPad *dst = &op->outputs[i];
FORWARD(i, i, flags);
if (op->clamp.limit[i].den)
- op->comps.flags[i] &= SWS_COMP_DIRTY;
- if (!bound[i].den) /* reset undefined bounds to known range */
- bound[i] = op->clamp.limit[i];
+ dst->flags &= SWS_COMP_DIRTY;
+
+ /* Reset undefined bounds to known range */
+ AVRational64 *bound = op->op == SWS_OP_MIN ? &dst->max : &dst->min;
+ if (!bound->den)
+ *bound = op->clamp.limit[i];
}
break;
}
case SWS_OP_DITHER:
for (int i = 0; i < 4; i++) {
FORWARD(i, i, flags);
- op->comps.min[i] = prev.min[i];
- op->comps.max[i] = prev.max[i];
+ op->outputs[i].min = prev[i].min;
+ op->outputs[i].max = prev[i].max;
if (op->dither.y_offset[i] < 0)
continue;
/* Strip zero flag because of the nonzero dithering offset */
- op->comps.flags[i] &= ~SWS_COMP_ZERO & SWS_COMP_DIRTY;
- op->comps.min[i] = ff_add_q64(op->comps.min[i], op->dither.min);
- op->comps.max[i] = ff_add_q64(op->comps.max[i], op->dither.max);
+ op->outputs[i].flags &= ~SWS_COMP_ZERO & SWS_COMP_DIRTY;
+ op->outputs[i].min = ff_add_q64(op->outputs[i].min, op->dither.min);
+ op->outputs[i].max = ff_add_q64(op->outputs[i].max, op->dither.max);
}
break;
case SWS_OP_UNPACK:
@@ -434,8 +453,8 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
if (pattern) {
av_assert1(pattern < 32);
FORWARD(i, 0, flags & SWS_COMP_DIRTY);
- op->comps.min[i] = Q(0);
- op->comps.max[i] = Q((1ULL << pattern) - 1);
+ op->outputs[i].min = Q(0);
+ op->outputs[i].max = Q((1ULL << pattern) - 1);
} else
RESET(i);
}
@@ -451,11 +470,11 @@ 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->comps.flags[i] = SWS_COMP_CONST;
+ op->outputs[i].flags = SWS_COMP_CONST;
if (op->clear.value[i].num == 0)
- op->comps.flags[i] |= SWS_COMP_ZERO;
+ op->outputs[i].flags |= SWS_COMP_ZERO;
if (op->clear.value[i].den == 1)
- op->comps.flags[i] |= SWS_COMP_EXACT;
+ op->outputs[i].flags |= SWS_COMP_EXACT;
} else {
FORWARD(i, i, flags);
}
@@ -468,56 +487,56 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
case SWS_OP_CONVERT:
for (int i = 0; i < 4; i++) {
FORWARD(i, i, flags);
- if (!(prev.flags[i] & SWS_COMP_EXACT))
- op->comps.flags[i] &= SWS_COMP_DIRTY;
+ if (!(prev[i].flags & SWS_COMP_EXACT))
+ op->outputs[i].flags &= SWS_COMP_DIRTY;
if (ff_sws_pixel_type_is_int(op->convert.to))
- op->comps.flags[i] |= SWS_COMP_EXACT;
+ op->outputs[i].flags |= SWS_COMP_EXACT;
}
break;
case SWS_OP_LINEAR:
for (int i = 0; i < 4; i++) {
- AVRational64 min = Q(0), max = Q(0);
+ SwsOpPad *dst = &op->outputs[i];
bool first = true;
+ dst->min = dst->max = Q(0);
for (int j = 0; j < 4; j++) {
+ const SwsOpPad *src = &prev[j];
const AVRational64 k = op->lin.m[i][j];
- AVRational64 mink = ff_mul_q64(prev.min[j], k);
- AVRational64 maxk = ff_mul_q64(prev.max[j], k);
+ AVRational64 mink = ff_mul_q64(src->min, k);
+ AVRational64 maxk = ff_mul_q64(src->max, k);
if (k.num) {
FORWARD(i, j, flags);
if (k.den != 1) /* fractional coefficient */
- op->comps.flags[i] &= ~SWS_COMP_EXACT;
+ dst->flags &= ~SWS_COMP_EXACT;
if (k.num < 0)
FFSWAP(AVRational64, mink, maxk);
- min = ff_add_q64(min, mink);
- max = ff_add_q64(max, maxk);
+ dst->min = ff_add_q64(dst->min, mink);
+ dst->max = ff_add_q64(dst->max, maxk);
if (!first || ff_cmp_q64(k, Q(1)))
- op->comps.flags[i] &= SWS_COMP_DIRTY;
+ dst->flags &= SWS_COMP_DIRTY;
first = false;
}
}
if (op->lin.m[i][4].num) { /* nonzero offset */
- op->comps.flags[i] &= ~SWS_COMP_ZERO & SWS_COMP_DIRTY;
+ dst->flags &= ~SWS_COMP_ZERO & SWS_COMP_DIRTY;
if (op->lin.m[i][4].den != 1) /* fractional offset */
- op->comps.flags[i] &= ~SWS_COMP_EXACT;
- min = ff_add_q64(min, op->lin.m[i][4]);
- max = ff_add_q64(max, op->lin.m[i][4]);
+ dst->flags &= ~SWS_COMP_EXACT;
+ dst->min = ff_add_q64(dst->min, op->lin.m[i][4]);
+ dst->max = ff_add_q64(dst->max, op->lin.m[i][4]);
}
- op->comps.min[i] = min;
- op->comps.max[i] = max;
}
break;
case SWS_OP_SCALE:
for (int i = 0; i < 4; i++) {
FORWARD(i, i, flags & SWS_COMP_DIRTY);
if (op->scale.factor.den != 1) /* fractional scale */
- op->comps.flags[i] &= ~SWS_COMP_EXACT;
+ op->outputs[i].flags &= ~SWS_COMP_EXACT;
if (op->scale.factor.num < 0)
- FFSWAP(AVRational64, op->comps.min[i], op->comps.max[i]);
+ FFSWAP(AVRational64, op->outputs[i].min, op->outputs[i].max);
}
break;
case SWS_OP_FILTER_H:
case SWS_OP_FILTER_V: {
- apply_filter_weights(&op->comps, &prev, op->filter.kernel);
+ apply_filter_weights(op->outputs, prev, op->filter.kernel);
break;
}
case SWS_OP_LUT_3D:
@@ -527,20 +546,20 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
for (int j = 0; j < 3; j++)
FORWARD(i, j, flags & SWS_COMP_GARBAGE);
/* LUT output domain is always scaled to full 16-bit range */
- op->comps.min[i] = Q(0);
- op->comps.max[i] = Q(UINT16_MAX);
+ op->outputs[i].min = Q(0);
+ op->outputs[i].max = Q(UINT16_MAX);
}
/* Pass through alpha channel untouched */
FORWARD(3, 3, flags);
- op->comps.min[3] = prev.min[3];
- op->comps.max[3] = prev.max[3];
+ op->outputs[3].min = prev[3].min;
+ op->outputs[3].max = prev[3].max;
break;
case SWS_OP_INVALID:
case SWS_OP_TYPE_NB:
av_unreachable("Invalid operation type!");
}
- prev = op->comps;
+ memcpy(prev, op->outputs, sizeof(prev));
}
/* Backwards pass, solves for output component dependencies */
@@ -551,7 +570,7 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
SwsCompMask need_in[4] = {0};
for (int i = 0; i < 4; i++) {
- op->comps.dep_out[i] = need_out[i];
+ op->outputs[i].dep_out = need_out[i];
if (!need_out[i])
RESET(i);
}
@@ -1018,29 +1037,28 @@ void ff_sws_op_list_print(void *log, int lev, int lev_extra,
av_log(log, lev, "%s\n", bp->str);
for (int i = 0; i < 4; i++) {
+ const SwsOpPad *pad = &op->outputs[i];
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)));
- print_deps(bp, op->comps.dep_in[i]);
+ print_deps(bp, pad->dep_in);
av_bprintf(bp, " ->");
- print_deps(bp, op->comps.dep_out[i]);
- av_bprintf(bp, " %7s", describe_comp_flags(op->comps.flags[i]));
+ print_deps(bp, pad->dep_out);
+ av_bprintf(bp, " %7s", describe_comp_flags(pad->flags));
- const AVRational64 min = op->comps.min[i];
- const AVRational64 max = op->comps.max[i];
- if (min.den || max.den) {
- if (op->comps.flags[i] & SWS_COMP_ZERO) {
+ if (pad->min.den || pad->max.den) {
+ if (pad->flags & SWS_COMP_ZERO) {
/* don't print any value */
- } else if (op->comps.flags[i] & SWS_COMP_CONST) {
+ } else if (pad->flags & SWS_COMP_CONST) {
av_bprintf(bp, " = ");
- av_assert1(ff_cmp_q64(min, max) == 0);
- print_q(bp, min);
+ av_assert1(ff_cmp_q64(pad->min, pad->max) == 0);
+ print_q(bp, pad->min);
} else {
av_bprintf(bp, " in [");
- print_q(bp, min);
+ print_q(bp, pad->min);
av_bprintf(bp, ", ");
- print_q(bp, max);
+ print_q(bp, pad->max);
av_bprintf(bp, "]");
}
}
diff --git a/libswscale/ops.h b/libswscale/ops.h
index a6dc28621a..35263b9d74 100644
--- a/libswscale/ops.h
+++ b/libswscale/ops.h
@@ -83,16 +83,16 @@ typedef enum SwsCompFlags {
SWS_COMP_CONST = 1 << 5, /* value is a fixed constant */
} SwsCompFlags;
-typedef struct SwsComps {
- SwsCompFlags flags[4]; /* knowledge about (output) component contents */
+typedef struct SwsOpPad {
+ SwsCompFlags flags; /* knowledge about (output) component contents */
/* Keeps track of the known possible value range, or {0, 0} for undefined
* or (unknown range) floating point inputs */
- AVRational64 min[4], max[4];
+ AVRational64 min, max;
/* Keeps track of input (forward) and output (reverse) dependencies */
- SwsCompMask dep_in[4], dep_out[4];
-} SwsComps;
+ SwsCompMask dep_in, dep_out;
+} SwsOpPad;
typedef enum SwsReadWriteMode {
/**
@@ -263,10 +263,10 @@ typedef struct SwsOp {
* Note that backends may rely on the presence and accuracy of this
* metadata for all operations, during ff_sws_ops_compile().
*/
- SwsComps comps;
+ SwsOpPad outputs[4];
} SwsOp;
-#define SWS_OP_NEEDED(op, idx) (!((op)->comps.flags[idx] & SWS_COMP_GARBAGE))
+#define SWS_OP_NEEDED(op, idx) (!((op)->outputs[idx].flags & SWS_COMP_GARBAGE))
/* Compute SwsCompMask from a mask of needed components */
SwsCompMask ff_sws_comp_mask_needed(const SwsOp *op);
@@ -313,7 +313,7 @@ typedef struct SwsOpList {
* The default value of {0} is safe to pass in the case that no additional
* information is known.
*/
- SwsComps comps_src;
+ SwsOpPad inputs[4];
} SwsOpList;
SwsOpList *ff_sws_op_list_alloc(void);
diff --git a/libswscale/ops_dispatch.c b/libswscale/ops_dispatch.c
index a0d049f616..3177f4b667 100644
--- a/libswscale/ops_dispatch.c
+++ b/libswscale/ops_dispatch.c
@@ -482,12 +482,12 @@ static void op_list_get_plane_copy(const SwsOpList *ops, SwsPass *pass)
const SwsOp *prev = &ops->ops[ops->num_ops - 2];
int *plane_copy = pass->output->plane_copy;
for (int i = 0; i < write->rw.elems; i++) {
- SwsCompFlags flags = prev->comps.flags[i];
+ SwsCompFlags flags = prev->outputs[i].flags;
if (!(flags & SWS_COMP_COPY))
continue;
const int out_idx = ops->plane_dst[i];
- switch (prev->comps.dep_in[i]) {
+ switch (prev->outputs[i].dep_in) {
case SWS_COMP(0): plane_copy[out_idx] = ops->plane_src[0]; break;
case SWS_COMP(1): plane_copy[out_idx] = ops->plane_src[1]; break;
case SWS_COMP(2): plane_copy[out_idx] = ops->plane_src[2]; break;
@@ -707,7 +707,7 @@ static SwsCompMask plane_mask_flags(const SwsOp *op, SwsCompFlags flags)
{
SwsCompMask planes = 0;
for (int c = 0; c < 4; c++) {
- if (op->comps.flags[c] & flags)
+ if (op->outputs[c].flags & flags)
planes |= SWS_COMP(c);
}
diff --git a/libswscale/ops_optimizer.c b/libswscale/ops_optimizer.c
index 77e6d01682..bd1723f053 100644
--- a/libswscale/ops_optimizer.c
+++ b/libswscale/ops_optimizer.c
@@ -235,7 +235,7 @@ static int exact_log2_q64(const AVRational64 x)
* the corresponding scaling factor, or 0 otherwise.
*/
static bool extract_scalar(const SwsLinearOp *c,
- const SwsComps *comps, const SwsComps *prev,
+ const SwsOpPad outputs[4], const SwsOpPad inputs[4],
SwsScaleOp *out_scale)
{
SwsScaleOp scale = {0};
@@ -246,8 +246,8 @@ static bool extract_scalar(const SwsLinearOp *c,
for (int i = 0; i < 4; i++) {
const AVRational64 s = c->m[i][i];
- if ((prev->flags[i] & SWS_COMP_ZERO) ||
- (comps->flags[i] & SWS_COMP_GARBAGE))
+ if ((inputs[i].flags & SWS_COMP_ZERO) ||
+ (outputs[i].flags & SWS_COMP_GARBAGE))
continue;
if (scale.factor.den && ff_cmp_q64(s, scale.factor))
return false;
@@ -260,7 +260,7 @@ static bool extract_scalar(const SwsLinearOp *c,
}
/* Extracts an integer clear operation (subset) from the given linear op. */
-static bool extract_constant_rows(SwsLinearOp *c, const SwsComps *prev,
+static bool extract_constant_rows(SwsLinearOp *c, const SwsOpPad inputs[4],
SwsClearOp *out_clear)
{
const uint32_t mask = ff_sws_linear_mask(c);
@@ -271,7 +271,7 @@ static bool extract_constant_rows(SwsLinearOp *c, const SwsComps *prev,
bool const_row = c->m[i][4].den == 1; /* offset is integer */
for (int j = 0; j < 4; j++) {
const_row &= c->m[i][j].num == 0 || /* scalar is zero */
- (prev->flags[j] & SWS_COMP_ZERO); /* input is zero */
+ (inputs[j].flags & SWS_COMP_ZERO); /* input is zero */
}
if (const_row && (mask & SWS_MASK_ROW(i))) {
clear.mask |= SWS_COMP(i);
@@ -289,7 +289,7 @@ static bool extract_constant_rows(SwsLinearOp *c, const SwsComps *prev,
/* Unswizzle a linear operation by aligning single-input rows with
* their corresponding diagonal */
-static bool extract_swizzle(SwsLinearOp *op, const SwsComps *prev,
+static bool extract_swizzle(SwsLinearOp *op, const SwsOpPad inputs[4],
SwsSwizzleOp *out_swiz)
{
SwsSwizzleOp swiz = SWS_SWIZZLE(0, 1, 2, 3);
@@ -299,7 +299,7 @@ static bool extract_swizzle(SwsLinearOp *op, const SwsComps *prev,
uint32_t nonzero = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
- if (!c.m[i][j].num || (prev->flags[j] & SWS_COMP_ZERO))
+ if (!c.m[i][j].num || (inputs[j].flags & SWS_COMP_ZERO))
continue;
nonzero |= SWS_MASK(i, j);
}
@@ -332,7 +332,7 @@ static bool extract_swizzle(SwsLinearOp *op, const SwsComps *prev,
static int op_result_is_exact(const SwsOp *op)
{
for (int i = 0; i < 4; i++) {
- if (SWS_OP_NEEDED(op, i) && !(op->comps.flags[i] & SWS_COMP_EXACT))
+ if (SWS_OP_NEEDED(op, i) && !(op->outputs[i].flags & SWS_COMP_EXACT))
return false;
}
@@ -464,8 +464,8 @@ retry:
if (!SWS_COMP_TEST(op->clear.mask, i))
continue;
- if ((prev->comps.flags[i] & SWS_COMP_ZERO) &&
- !(prev->comps.flags[i] & SWS_COMP_GARBAGE) &&
+ if ((prev->outputs[i].flags & SWS_COMP_ZERO) &&
+ !(prev->outputs[i].flags & SWS_COMP_GARBAGE) &&
op->clear.value[i].num == 0)
{
/* Redundant clear-to-zero of zero component */
@@ -585,7 +585,7 @@ retry:
for (int i = 0; i < 4; i++) {
if (!SWS_OP_NEEDED(op, i) || !op->clamp.limit[i].den)
continue;
- if (ff_cmp_q64(op->clamp.limit[i], prev->comps.max[i]) >= 0)
+ if (ff_cmp_q64(op->clamp.limit[i], prev->outputs[i].max) >= 0)
op->clamp.limit[i] = (AVRational64) {0}; /* no-op */
else
noop = false;
@@ -601,7 +601,7 @@ retry:
for (int i = 0; i < 4; i++) {
if (!SWS_OP_NEEDED(op, i) || !op->clamp.limit[i].den)
continue;
- if (ff_cmp_q64(prev->comps.min[i], op->clamp.limit[i]) >= 0)
+ if (ff_cmp_q64(prev->outputs[i].min, op->clamp.limit[i]) >= 0)
op->clamp.limit[i] = (AVRational64) {0};
else
noop = false;
@@ -617,7 +617,7 @@ retry:
for (int i = 0; i < 4; i++) {
if (op->dither.y_offset[i] < 0)
continue;
- if (!SWS_OP_NEEDED(op, i) || (prev->comps.flags[i] & SWS_COMP_EXACT)) {
+ if (!SWS_OP_NEEDED(op, i) || (prev->outputs[i].flags & SWS_COMP_EXACT)) {
op->dither.y_offset[i] = -1; /* unnecessary dither */
goto retry;
} else {
@@ -664,7 +664,7 @@ retry:
/* Optimize away zero columns */
for (int j = 0; j < 4; j++) {
const uint32_t col = SWS_MASK_COL(j);
- if (!(prev->comps.flags[j] & SWS_COMP_ZERO) || !(mask & col))
+ if (!(prev->outputs[j].flags & SWS_COMP_ZERO) || !(mask & col))
continue;
for (int i = 0; i < 4; i++)
op->lin.m[i][j] = Q(i == j);
@@ -682,7 +682,7 @@ retry:
}
/* Convert constant rows to explicit clear instruction */
- if (extract_constant_rows(&op->lin, &prev->comps, &clear)) {
+ if (extract_constant_rows(&op->lin, prev->outputs, &clear)) {
RET(ff_sws_op_list_insert_at(ops, n + 1, &(SwsOp) {
.op = SWS_OP_CLEAR,
.type = op->type,
@@ -692,14 +692,14 @@ retry:
}
/* Multiplication by scalar constant */
- if (extract_scalar(&op->lin, &op->comps, &prev->comps, &scale)) {
+ if (extract_scalar(&op->lin, op->outputs, prev->outputs, &scale)) {
op->op = SWS_OP_SCALE;
op->scale = scale;
goto retry;
}
/* Swizzle by fixed pattern */
- if (extract_swizzle(&op->lin, &prev->comps, &swizzle)) {
+ if (extract_swizzle(&op->lin, prev->outputs, &swizzle)) {
RET(ff_sws_op_list_insert_at(ops, n, &(SwsOp) {
.op = SWS_OP_SWIZZLE,
.type = op->type,
@@ -1203,9 +1203,9 @@ int ff_sws_op_list_split_at(SwsOpList *ops1, SwsOpList **out_ops2, int index)
for (int i = 0; i < nb_planes; i++) {
const int idx = swiz_wr.in[i];
ops1->plane_dst[i] = ops2->plane_src[i] = i;
- ops2->comps_src.flags[i] = prev->comps.flags[idx];
- ops2->comps_src.min[i] = prev->comps.min[idx];
- ops2->comps_src.max[i] = prev->comps.max[idx];
+ ops2->inputs[i].flags = prev->outputs[idx].flags;
+ ops2->inputs[i].min = prev->outputs[idx].min;
+ ops2->inputs[i].max = prev->outputs[idx].max;
}
ff_sws_op_list_remove_at(ops1, index, ops1->num_ops - index);
diff --git a/libswscale/uops.c b/libswscale/uops.c
index 21396daf70..8d6ad36692 100644
--- a/libswscale/uops.c
+++ b/libswscale/uops.c
@@ -228,18 +228,15 @@ static bool exact_product_f32(float a, float b)
return !b || result == a;
}
-static bool exact_prod(SwsPixelType type, SwsPixel coef,
- const SwsComps *comps, int idx)
+static bool exact_prod(SwsPixelType type, SwsPixel coef, const SwsOpPad *input)
{
- const AVRational64 minq = comps->min[idx];
- const AVRational64 maxq = comps->max[idx];
if (ff_sws_pixel_type_is_int(type))
return true;
- else if (!minq.den || !maxq.den)
+ else if (!input->min.den || !input->max.den)
return false; /* unknown bounds */
- const SwsPixel min = ff_sws_pixel_from_q64(type, minq);
- const SwsPixel max = ff_sws_pixel_from_q64(type, maxq);
+ const SwsPixel min = ff_sws_pixel_from_q64(type, input->min);
+ const SwsPixel max = ff_sws_pixel_from_q64(type, input->max);
switch (type) {
case SWS_PIXEL_F32:
return exact_product_f32(coef.f32, min.f32) &&
@@ -476,7 +473,7 @@ static int translate_dither_op(SwsUOpList *ops, SwsUOpFlags flags, const SwsOp *
static int translate_linear_op(SwsContext *ctx, SwsUOpList *ops,
SwsUOpFlags flags, const SwsOp *op,
- const SwsComps *input)
+ const SwsOpPad inputs[4])
{
SwsUOp uop = {
.type = op->type,
@@ -502,7 +499,7 @@ static int translate_linear_op(SwsContext *ctx, SwsUOpList *ops,
uop.par.lin.zero |= SWS_MASK(i, j);
else if (j < 4 && k.num == k.den)
uop.par.lin.one |= SWS_MASK(i, j);
- else if (j < 4 && nonzero && (!bitexact || exact_prod(uop.type, px, input, j)))
+ else if (j < 4 && nonzero && (!bitexact || exact_prod(uop.type, px, &inputs[j])))
exact |= SWS_MASK(i, j);
if (k.num != 0)
nonzero = true;
@@ -519,7 +516,7 @@ static int translate_linear_op(SwsContext *ctx, SwsUOpList *ops,
}
static int translate_op(SwsContext *ctx, SwsUOpList *uops, SwsUOpFlags flags,
- const SwsOp *op, const SwsComps *input)
+ const SwsOp *op, const SwsOpPad inputs[4])
{
switch (op->op) {
case SWS_OP_FILTER_H:
@@ -533,7 +530,7 @@ static int translate_op(SwsContext *ctx, SwsUOpList *uops, SwsUOpFlags flags,
case SWS_OP_DITHER:
return translate_dither_op(uops, flags, op);
case SWS_OP_LINEAR:
- return translate_linear_op(ctx, uops, flags, op, input);
+ return translate_linear_op(ctx, uops, flags, op, inputs);
default:
break;
}
@@ -618,17 +615,17 @@ static int translate_op(SwsContext *ctx, SwsUOpList *uops, SwsUOpFlags flags,
int ff_sws_ops_translate(SwsContext *ctx, const SwsOpList *ops,
SwsUOpFlags flags, SwsUOpList *uops)
{
- SwsComps input = ops->comps_src;
+ const SwsOpPad *inputs = ops->inputs;
for (int i = 0; i < ops->num_ops; i++) {
const SwsOp *op = &ops->ops[i];
const int pixel_size = ff_sws_pixel_type_size(op->type);
if (pixel_size > uops->pixel_size_max)
uops->pixel_size_max = pixel_size;
- int ret = translate_op(ctx, uops, flags, op, &input);
+ int ret = translate_op(ctx, uops, flags, op, inputs);
if (ret < 0)
return ret;
- input = ops->ops[i].comps;
+ inputs = op->outputs;
}
return ff_sws_uop_list_optimize(ctx, flags, uops);