mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2026-06-16 04:32:47 +02:00
swscale/ops: split SwsConst up into op-specific structs
It was a bit clunky, lacked semantic contextual information, and made it harder to reason about the effects of extending this struct. There should be zero runtime overhead as a result of the fact that this is already a big union. I made the changes in this commit by hand, but due to the length and noise level of the commit, I used Opus 4.6 to verify that I did not accidentally introduce any bugs or typos. Signed-off-by: Niklas Haas <git@haasn.dev>
This commit is contained in:
@@ -851,7 +851,7 @@ static void asmgen_op_pack(SwsAArch64Context *s, const SwsAArch64OpImplParams *p
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
/* logical left shift of raw pixel values by (u8) */
|
||||
/* logical left shift of raw pixel values */
|
||||
/* AARCH64_SWS_OP_LSHIFT */
|
||||
|
||||
static void asmgen_op_lshift(SwsAArch64Context *s, const SwsAArch64OpImplParams *p)
|
||||
@@ -865,7 +865,7 @@ static void asmgen_op_lshift(SwsAArch64Context *s, const SwsAArch64OpImplParams
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
/* right shift of raw pixel values by (u8) */
|
||||
/* right shift of raw pixel values */
|
||||
/* AARCH64_SWS_OP_RSHIFT */
|
||||
|
||||
static void asmgen_op_rshift(SwsAArch64Context *s, const SwsAArch64OpImplParams *p)
|
||||
@@ -1012,7 +1012,7 @@ static void asmgen_op_expand(SwsAArch64Context *s, const SwsAArch64OpImplParams
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
/* numeric minimum (q4) */
|
||||
/* numeric minimum */
|
||||
/* AARCH64_SWS_OP_MIN */
|
||||
|
||||
static void asmgen_op_min(SwsAArch64Context *s, const SwsAArch64OpImplParams *p)
|
||||
@@ -1036,7 +1036,7 @@ static void asmgen_op_min(SwsAArch64Context *s, const SwsAArch64OpImplParams *p)
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
/* numeric maximum (q4) */
|
||||
/* numeric maximum */
|
||||
/* AARCH64_SWS_OP_MAX */
|
||||
|
||||
static void asmgen_op_max(SwsAArch64Context *s, const SwsAArch64OpImplParams *p)
|
||||
@@ -1060,7 +1060,7 @@ static void asmgen_op_max(SwsAArch64Context *s, const SwsAArch64OpImplParams *p)
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
/* multiplication by scalar (q) */
|
||||
/* multiplication by scalar */
|
||||
/* AARCH64_SWS_OP_SCALE */
|
||||
|
||||
static void asmgen_op_scale(SwsAArch64Context *s, const SwsAArch64OpImplParams *p)
|
||||
|
||||
@@ -181,14 +181,14 @@ static int convert_to_aarch64_impl(SwsContext *ctx, const SwsOpList *ops, int n,
|
||||
break;
|
||||
case AARCH64_SWS_OP_LSHIFT:
|
||||
case AARCH64_SWS_OP_RSHIFT:
|
||||
out->shift = op->c.u;
|
||||
out->shift = op->shift.amount;
|
||||
break;
|
||||
case AARCH64_SWS_OP_CLEAR:
|
||||
out->mask = 0;
|
||||
MASK_SET(out->mask, 0, !!op->c.q4[0].den);
|
||||
MASK_SET(out->mask, 1, !!op->c.q4[1].den);
|
||||
MASK_SET(out->mask, 2, !!op->c.q4[2].den);
|
||||
MASK_SET(out->mask, 3, !!op->c.q4[3].den);
|
||||
MASK_SET(out->mask, 0, !!op->clear.value[0].den);
|
||||
MASK_SET(out->mask, 1, !!op->clear.value[1].den);
|
||||
MASK_SET(out->mask, 2, !!op->clear.value[2].den);
|
||||
MASK_SET(out->mask, 3, !!op->clear.value[3].den);
|
||||
break;
|
||||
case AARCH64_SWS_OP_EXPAND:
|
||||
case AARCH64_SWS_OP_CONVERT:
|
||||
|
||||
+33
-32
@@ -827,7 +827,7 @@ static int cmp_comp(const void *a, const void *b) {
|
||||
}
|
||||
|
||||
static int fmt_analyze_regular(const AVPixFmtDescriptor *desc, SwsReadWriteOp *rw_op,
|
||||
SwsSwizzleOp *swizzle, int *shift)
|
||||
SwsSwizzleOp *swizzle, SwsShiftOp *shift)
|
||||
{
|
||||
if (desc->nb_components == 2) {
|
||||
/* YA formats */
|
||||
@@ -848,7 +848,7 @@ static int fmt_analyze_regular(const AVPixFmtDescriptor *desc, SwsReadWriteOp *r
|
||||
*swizzle = swiz;
|
||||
}
|
||||
|
||||
*shift = desc->comp[0].shift;
|
||||
*shift = (SwsShiftOp) { desc->comp[0].shift };
|
||||
*rw_op = (SwsReadWriteOp) {
|
||||
.elems = desc->nb_components,
|
||||
.packed = desc->nb_components > 1 && !(desc->flags & AV_PIX_FMT_FLAG_PLANAR),
|
||||
@@ -857,8 +857,9 @@ static int fmt_analyze_regular(const AVPixFmtDescriptor *desc, SwsReadWriteOp *r
|
||||
}
|
||||
|
||||
static int fmt_analyze(enum AVPixelFormat fmt, SwsReadWriteOp *rw_op,
|
||||
SwsPackOp *pack_op, SwsSwizzleOp *swizzle, int *shift,
|
||||
SwsPixelType *pixel_type, SwsPixelType *raw_type)
|
||||
SwsPackOp *pack_op, SwsSwizzleOp *swizzle,
|
||||
SwsShiftOp *shift, SwsPixelType *pixel_type,
|
||||
SwsPixelType *raw_type)
|
||||
{
|
||||
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
|
||||
if (!desc)
|
||||
@@ -889,7 +890,7 @@ static int fmt_analyze(enum AVPixelFormat fmt, SwsReadWriteOp *rw_op,
|
||||
*rw_op = info.rw;
|
||||
*pack_op = info.pack;
|
||||
*swizzle = info.swizzle;
|
||||
*shift = info.shift;
|
||||
*shift = (SwsShiftOp) { info.shift };
|
||||
|
||||
if (info.pack.pattern[0]) {
|
||||
const int sum = info.pack.pattern[0] + info.pack.pattern[1] +
|
||||
@@ -923,17 +924,17 @@ static SwsSwizzleOp swizzle_inv(SwsSwizzleOp swiz) {
|
||||
* it will end up getting pushed towards the output or optimized away entirely
|
||||
* by the optimization pass.
|
||||
*/
|
||||
static SwsConst fmt_clear(enum AVPixelFormat fmt)
|
||||
static SwsClearOp fmt_clear(enum AVPixelFormat fmt)
|
||||
{
|
||||
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
|
||||
const bool has_chroma = desc->nb_components >= 3;
|
||||
const bool has_alpha = desc->flags & AV_PIX_FMT_FLAG_ALPHA;
|
||||
|
||||
SwsConst c = {0};
|
||||
SwsClearOp c = {0};
|
||||
if (!has_chroma)
|
||||
c.q4[1] = c.q4[2] = Q0;
|
||||
c.value[1] = c.value[2] = Q0;
|
||||
if (!has_alpha)
|
||||
c.q4[3] = Q0;
|
||||
c.value[3] = Q0;
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -952,7 +953,7 @@ int ff_sws_decode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
|
||||
SwsSwizzleOp swizzle;
|
||||
SwsPackOp unpack;
|
||||
SwsComps *comps = &ops->comps_src;
|
||||
int shift;
|
||||
SwsShiftOp shift;
|
||||
|
||||
RET(fmt_analyze(fmt, &rw_op, &unpack, &swizzle, &shift,
|
||||
&pixel_type, &raw_type));
|
||||
@@ -974,7 +975,7 @@ int ff_sws_decode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
|
||||
* canonical order {Y, U, V, A} */
|
||||
const int is_ya = desc->nb_components == 2;
|
||||
for (int c = 0; c < desc->nb_components; c++) {
|
||||
const int bits = desc->comp[c].depth + shift;
|
||||
const int bits = desc->comp[c].depth + shift.amount;
|
||||
const int idx = swizzle.in[is_ya ? 3 * c : c];
|
||||
comps->min[idx] = Q0;
|
||||
if (bits < 32) /* FIXME: AVRational is limited to INT_MAX */
|
||||
@@ -1016,18 +1017,18 @@ int ff_sws_decode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
|
||||
.swizzle = swizzle,
|
||||
}));
|
||||
|
||||
if (shift) {
|
||||
if (shift.amount) {
|
||||
RET(ff_sws_op_list_append(ops, &(SwsOp) {
|
||||
.op = SWS_OP_RSHIFT,
|
||||
.type = pixel_type,
|
||||
.c.u = shift,
|
||||
.op = SWS_OP_RSHIFT,
|
||||
.type = pixel_type,
|
||||
.shift = shift,
|
||||
}));
|
||||
}
|
||||
|
||||
RET(ff_sws_op_list_append(ops, &(SwsOp) {
|
||||
.op = SWS_OP_CLEAR,
|
||||
.type = pixel_type,
|
||||
.c = fmt_clear(fmt),
|
||||
.op = SWS_OP_CLEAR,
|
||||
.type = pixel_type,
|
||||
.clear = fmt_clear(fmt),
|
||||
}));
|
||||
|
||||
return 0;
|
||||
@@ -1040,16 +1041,16 @@ int ff_sws_encode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
|
||||
SwsReadWriteOp rw_op;
|
||||
SwsSwizzleOp swizzle;
|
||||
SwsPackOp pack;
|
||||
int shift;
|
||||
SwsShiftOp shift;
|
||||
|
||||
RET(fmt_analyze(fmt, &rw_op, &pack, &swizzle, &shift,
|
||||
&pixel_type, &raw_type));
|
||||
|
||||
if (shift) {
|
||||
if (shift.amount) {
|
||||
RET(ff_sws_op_list_append(ops, &(SwsOp) {
|
||||
.op = SWS_OP_LSHIFT,
|
||||
.type = pixel_type,
|
||||
.c.u = shift,
|
||||
.op = SWS_OP_LSHIFT,
|
||||
.type = pixel_type,
|
||||
.shift = shift,
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -1059,7 +1060,7 @@ int ff_sws_encode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
|
||||
RET(ff_sws_op_list_append(ops, &(SwsOp) {
|
||||
.op = SWS_OP_CLEAR,
|
||||
.type = pixel_type,
|
||||
.c.q4[3] = Q0,
|
||||
.clear.value[3] = Q0,
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -1513,26 +1514,26 @@ int ff_sws_encode_colors(SwsContext *ctx, SwsPixelType type,
|
||||
}));
|
||||
|
||||
if (!(dst->desc->flags & AV_PIX_FMT_FLAG_FLOAT)) {
|
||||
SwsConst range = {0};
|
||||
SwsClampOp range = {0};
|
||||
|
||||
const bool is_ya = dst->desc->nb_components == 2;
|
||||
for (int i = 0; i < dst->desc->nb_components; i++) {
|
||||
/* Clamp to legal pixel range */
|
||||
const int idx = i * (is_ya ? 3 : 1);
|
||||
range.q4[idx] = Q((1 << dst->desc->comp[i].depth) - 1);
|
||||
range.limit[idx] = Q((1 << dst->desc->comp[i].depth) - 1);
|
||||
}
|
||||
|
||||
RET(fmt_dither(ctx, ops, type, src, dst));
|
||||
RET(ff_sws_op_list_append(ops, &(SwsOp) {
|
||||
.op = SWS_OP_MAX,
|
||||
.type = type,
|
||||
.c.q4 = { Q0, Q0, Q0, Q0 },
|
||||
.op = SWS_OP_MAX,
|
||||
.type = type,
|
||||
.clamp = {{ Q0, Q0, Q0, Q0 }},
|
||||
}));
|
||||
|
||||
RET(ff_sws_op_list_append(ops, &(SwsOp) {
|
||||
.op = SWS_OP_MIN,
|
||||
.type = type,
|
||||
.c = range,
|
||||
.op = SWS_OP_MIN,
|
||||
.type = type,
|
||||
.clamp = range,
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
+23
-23
@@ -177,13 +177,13 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4])
|
||||
return;
|
||||
case SWS_OP_CLEAR:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (op->c.q4[i].den)
|
||||
x[i] = op->c.q4[i];
|
||||
if (op->clear.value[i].den)
|
||||
x[i] = op->clear.value[i];
|
||||
}
|
||||
return;
|
||||
case SWS_OP_LSHIFT: {
|
||||
av_assert1(ff_sws_pixel_type_is_int(op->type));
|
||||
AVRational mult = Q(1 << op->c.u);
|
||||
AVRational mult = Q(1 << op->shift.amount);
|
||||
for (int i = 0; i < 4; i++)
|
||||
x[i] = x[i].den ? av_mul_q(x[i], mult) : x[i];
|
||||
return;
|
||||
@@ -191,7 +191,7 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4])
|
||||
case SWS_OP_RSHIFT: {
|
||||
av_assert1(ff_sws_pixel_type_is_int(op->type));
|
||||
for (int i = 0; i < 4; i++)
|
||||
x[i] = x[i].den ? Q((x[i].num / x[i].den) >> op->c.u) : x[i];
|
||||
x[i] = x[i].den ? Q((x[i].num / x[i].den) >> op->shift.amount) : x[i];
|
||||
return;
|
||||
}
|
||||
case SWS_OP_SWIZZLE: {
|
||||
@@ -219,11 +219,11 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4])
|
||||
return;
|
||||
case SWS_OP_MIN:
|
||||
for (int i = 0; i < 4; i++)
|
||||
x[i] = av_min_q(x[i], op->c.q4[i]);
|
||||
x[i] = av_min_q(x[i], op->clamp.limit[i]);
|
||||
return;
|
||||
case SWS_OP_MAX:
|
||||
for (int i = 0; i < 4; i++)
|
||||
x[i] = av_max_q(x[i], op->c.q4[i]);
|
||||
x[i] = av_max_q(x[i], op->clamp.limit[i]);
|
||||
return;
|
||||
case SWS_OP_LINEAR: {
|
||||
av_assert1(!ff_sws_pixel_type_is_int(op->type));
|
||||
@@ -238,7 +238,7 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4])
|
||||
}
|
||||
case SWS_OP_SCALE:
|
||||
for (int i = 0; i < 4; i++)
|
||||
x[i] = x[i].den ? av_mul_q(x[i], op->c.q) : x[i];
|
||||
x[i] = x[i].den ? av_mul_q(x[i], op->scale.factor) : x[i];
|
||||
return;
|
||||
case SWS_OP_FILTER_H:
|
||||
case SWS_OP_FILTER_V:
|
||||
@@ -362,11 +362,11 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
|
||||
break;
|
||||
case SWS_OP_MIN:
|
||||
propagate_flags(op, &prev);
|
||||
clear_undefined_values(op->comps.max, op->c.q4);
|
||||
clear_undefined_values(op->comps.max, op->clamp.limit);
|
||||
break;
|
||||
case SWS_OP_MAX:
|
||||
propagate_flags(op, &prev);
|
||||
clear_undefined_values(op->comps.min, op->c.q4);
|
||||
clear_undefined_values(op->comps.min, op->clamp.limit);
|
||||
break;
|
||||
case SWS_OP_DITHER:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
@@ -405,11 +405,11 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
|
||||
}
|
||||
case SWS_OP_CLEAR:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (op->c.q4[i].den) {
|
||||
if (op->clear.value[i].den) {
|
||||
op->comps.flags[i] = 0;
|
||||
if (op->c.q4[i].num == 0)
|
||||
if (op->clear.value[i].num == 0)
|
||||
op->comps.flags[i] |= SWS_COMP_ZERO;
|
||||
if (op->c.q4[i].den == 1)
|
||||
if (op->clear.value[i].den == 1)
|
||||
op->comps.flags[i] |= SWS_COMP_EXACT;
|
||||
} else {
|
||||
op->comps.flags[i] = prev.flags[i];
|
||||
@@ -460,9 +460,9 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
|
||||
case SWS_OP_SCALE:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
op->comps.flags[i] = prev.flags[i];
|
||||
if (op->c.q.den != 1) /* fractional scale */
|
||||
if (op->scale.factor.den != 1) /* fractional scale */
|
||||
op->comps.flags[i] &= ~SWS_COMP_EXACT;
|
||||
if (op->c.q.num < 0)
|
||||
if (op->scale.factor.num < 0)
|
||||
FFSWAP(AVRational, op->comps.min[i], op->comps.max[i]);
|
||||
}
|
||||
break;
|
||||
@@ -524,7 +524,7 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
|
||||
break;
|
||||
case SWS_OP_CLEAR:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!op->c.q4[i].den)
|
||||
if (!op->clear.value[i].den)
|
||||
need_in[i] = need_out[i];
|
||||
}
|
||||
break;
|
||||
@@ -839,10 +839,10 @@ void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op)
|
||||
op->rw.filter == SWS_OP_FILTER_H ? 'H' : 'V');
|
||||
break;
|
||||
case SWS_OP_LSHIFT:
|
||||
av_bprintf(bp, "%-20s: << %u", name, op->c.u);
|
||||
av_bprintf(bp, "%-20s: << %u", name, op->shift.amount);
|
||||
break;
|
||||
case SWS_OP_RSHIFT:
|
||||
av_bprintf(bp, "%-20s: >> %u", name, op->c.u);
|
||||
av_bprintf(bp, "%-20s: >> %u", name, op->shift.amount);
|
||||
break;
|
||||
case SWS_OP_PACK:
|
||||
case SWS_OP_UNPACK:
|
||||
@@ -852,7 +852,7 @@ void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op)
|
||||
break;
|
||||
case SWS_OP_CLEAR:
|
||||
av_bprintf(bp, "%-20s: ", name);
|
||||
print_q4(bp, op->c.q4, true, op->comps.flags);
|
||||
print_q4(bp, op->clear.value, true, op->comps.flags);
|
||||
break;
|
||||
case SWS_OP_SWIZZLE:
|
||||
av_bprintf(bp, "%-20s: %d%d%d%d", name,
|
||||
@@ -872,11 +872,11 @@ void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op)
|
||||
break;
|
||||
case SWS_OP_MIN:
|
||||
av_bprintf(bp, "%-20s: x <= ", name);
|
||||
print_q4(bp, op->c.q4, true, op->comps.flags);
|
||||
print_q4(bp, op->clamp.limit, true, op->comps.flags);
|
||||
break;
|
||||
case SWS_OP_MAX:
|
||||
av_bprintf(bp, "%-20s: ", name);
|
||||
print_q4(bp, op->c.q4, true, op->comps.flags);
|
||||
print_q4(bp, op->clamp.limit, true, op->comps.flags);
|
||||
av_bprintf(bp, " <= x");
|
||||
break;
|
||||
case SWS_OP_LINEAR:
|
||||
@@ -892,9 +892,9 @@ void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op)
|
||||
av_bprintf(bp, "]");
|
||||
break;
|
||||
case SWS_OP_SCALE:
|
||||
av_bprintf(bp, "%-20s: * %d", name, op->c.q.num);
|
||||
if (op->c.q.den != 1)
|
||||
av_bprintf(bp, "/%d", op->c.q.den);
|
||||
av_bprintf(bp, "%-20s: * %d", name, op->scale.factor.num);
|
||||
if (op->scale.factor.den != 1)
|
||||
av_bprintf(bp, "/%d", op->scale.factor.den);
|
||||
break;
|
||||
case SWS_OP_FILTER_H:
|
||||
case SWS_OP_FILTER_V: {
|
||||
|
||||
+25
-16
@@ -55,15 +55,15 @@ typedef enum SwsOpType {
|
||||
/* Bit manipulation operations. Defined for integers only. */
|
||||
SWS_OP_UNPACK, /* split tightly packed data into components */
|
||||
SWS_OP_PACK, /* compress components into tightly packed data */
|
||||
SWS_OP_LSHIFT, /* logical left shift of raw pixel values by (u8) */
|
||||
SWS_OP_RSHIFT, /* right shift of raw pixel values by (u8) */
|
||||
SWS_OP_LSHIFT, /* logical left shift of raw pixel values */
|
||||
SWS_OP_RSHIFT, /* right shift of raw pixel values */
|
||||
|
||||
/* Generic arithmetic. Defined and implemented for all types */
|
||||
SWS_OP_CLEAR, /* clear pixel values */
|
||||
SWS_OP_CONVERT, /* convert (cast) between formats */
|
||||
SWS_OP_MIN, /* numeric minimum (q4) */
|
||||
SWS_OP_MAX, /* numeric maximum (q4) */
|
||||
SWS_OP_SCALE, /* multiplication by scalar (q) */
|
||||
SWS_OP_MIN, /* numeric minimum */
|
||||
SWS_OP_MAX, /* numeric maximum */
|
||||
SWS_OP_SCALE, /* multiplication by scalar */
|
||||
|
||||
/* Floating-point only arithmetic operations. */
|
||||
SWS_OP_LINEAR, /* generalized linear affine transform */
|
||||
@@ -87,16 +87,6 @@ typedef enum SwsCompFlags {
|
||||
|
||||
#define SWS_OP_NEEDED(op, idx) (!((op)->comps.flags[idx] & SWS_COMP_GARBAGE))
|
||||
|
||||
typedef union SwsConst {
|
||||
/* Generic constant value */
|
||||
AVRational q4[4];
|
||||
AVRational q;
|
||||
unsigned u;
|
||||
} SwsConst;
|
||||
|
||||
static_assert(sizeof(SwsConst) == sizeof(AVRational) * 4,
|
||||
"First field of SwsConst should span the entire union");
|
||||
|
||||
typedef struct SwsComps {
|
||||
SwsCompFlags flags[4]; /* knowledge about (output) component contents */
|
||||
bool unused[4]; /* which input components are definitely unused */
|
||||
@@ -152,11 +142,27 @@ typedef struct SwsSwizzleOp {
|
||||
|
||||
#define SWS_SWIZZLE(X,Y,Z,W) ((SwsSwizzleOp) { .in = {X, Y, Z, W} })
|
||||
|
||||
typedef struct SwsShiftOp {
|
||||
uint8_t amount; /* number of bits to shift */
|
||||
} SwsShiftOp;
|
||||
|
||||
typedef struct SwsClearOp {
|
||||
AVRational value[4]; /* value to set, or {0, 0} for no-op */
|
||||
} SwsClearOp;
|
||||
|
||||
typedef struct SwsConvertOp {
|
||||
SwsPixelType to; /* type of pixel to convert to */
|
||||
bool expand; /* if true, integers are expanded to the full range */
|
||||
} SwsConvertOp;
|
||||
|
||||
typedef struct SwsClampOp {
|
||||
AVRational limit[4]; /* per-component min/max value */
|
||||
} SwsClampOp;
|
||||
|
||||
typedef struct SwsScaleOp {
|
||||
AVRational factor; /* scalar multiplication factor */
|
||||
} SwsScaleOp;
|
||||
|
||||
typedef struct SwsDitherOp {
|
||||
AVRational *matrix; /* tightly packed dither matrix (refstruct) */
|
||||
AVRational min, max; /* minimum/maximum value in `matrix` */
|
||||
@@ -217,10 +223,13 @@ typedef struct SwsOp {
|
||||
SwsReadWriteOp rw;
|
||||
SwsPackOp pack;
|
||||
SwsSwizzleOp swizzle;
|
||||
SwsShiftOp shift;
|
||||
SwsClearOp clear;
|
||||
SwsConvertOp convert;
|
||||
SwsClampOp clamp;
|
||||
SwsScaleOp scale;
|
||||
SwsDitherOp dither;
|
||||
SwsFilterOp filter;
|
||||
SwsConst c;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+10
-8
@@ -115,7 +115,9 @@ static int op_match(const SwsOp *op, const SwsOpEntry *entry)
|
||||
if (op->op == SWS_OP_CLEAR) {
|
||||
/* Clear pattern must match exactly, regardless of `entry->flexible` */
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (SWS_OP_NEEDED(op, i) && entry->unused[i] != !!op->c.q4[i].den)
|
||||
if (!SWS_OP_NEEDED(op, i))
|
||||
continue;
|
||||
if (entry->unused[i] != !!op->clear.value[i].den)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -147,9 +149,9 @@ static int op_match(const SwsOp *op, const SwsOpEntry *entry)
|
||||
return score;
|
||||
case SWS_OP_CLEAR:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!op->c.q4[i].den || !SWS_OP_NEEDED(op, i))
|
||||
if (!op->clear.value[i].den || !SWS_OP_NEEDED(op, i))
|
||||
continue;
|
||||
if (av_cmp_q(op->c.q4[i], Q(entry->clear_value)))
|
||||
if (av_cmp_q(op->clear.value[i], Q(entry->clear_value)))
|
||||
return 0;
|
||||
}
|
||||
return score;
|
||||
@@ -188,7 +190,7 @@ static int op_match(const SwsOp *op, const SwsOpEntry *entry)
|
||||
score += av_popcount(SWS_MASK_ALL ^ entry->linear_mask);
|
||||
return score;
|
||||
case SWS_OP_SCALE:
|
||||
return av_cmp_q(op->c.q, entry->scale) ? 0 : score;
|
||||
return av_cmp_q(op->scale.factor, entry->scale) ? 0 : score;
|
||||
case SWS_OP_FILTER_H:
|
||||
case SWS_OP_FILTER_V:
|
||||
return score;
|
||||
@@ -265,14 +267,14 @@ int ff_sws_op_compile_tables(SwsContext *ctx, const SwsOpTable *const tables[],
|
||||
|
||||
int ff_sws_setup_shift(const SwsImplParams *params, SwsImplResult *out)
|
||||
{
|
||||
out->priv.u8[0] = params->op->c.u;
|
||||
out->priv.u8[0] = params->op->shift.amount;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_sws_setup_scale(const SwsImplParams *params, SwsImplResult *out)
|
||||
{
|
||||
const SwsOp *op = params->op;
|
||||
const AVRational factor = op->c.q;
|
||||
const AVRational factor = op->scale.factor;
|
||||
switch (op->type) {
|
||||
case SWS_PIXEL_U8: out->priv.u8[0] = q2pixel(uint8_t, factor); break;
|
||||
case SWS_PIXEL_U16: out->priv.u16[0] = q2pixel(uint16_t, factor); break;
|
||||
@@ -288,7 +290,7 @@ int ff_sws_setup_clamp(const SwsImplParams *params, SwsImplResult *out)
|
||||
{
|
||||
const SwsOp *op = params->op;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
const AVRational limit = op->c.q4[i];
|
||||
const AVRational limit = op->clamp.limit[i];
|
||||
switch (op->type) {
|
||||
case SWS_PIXEL_U8: out->priv.u8[i] = q2pixel(uint8_t, limit); break;
|
||||
case SWS_PIXEL_U16: out->priv.u16[i] = q2pixel(uint16_t, limit); break;
|
||||
@@ -305,7 +307,7 @@ int ff_sws_setup_clear(const SwsImplParams *params, SwsImplResult *out)
|
||||
{
|
||||
const SwsOp *op = params->op;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
const AVRational value = op->c.q4[i];
|
||||
const AVRational value = op->clear.value[i];
|
||||
if (!value.den)
|
||||
continue;
|
||||
switch (op->type) {
|
||||
|
||||
@@ -86,20 +86,20 @@ static int compile(SwsContext *ctx, SwsOpList *ops, SwsCompiledOp *out)
|
||||
|
||||
case SWS_OP_CLEAR:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!op->c.q4[i].den)
|
||||
if (!op->clear.value[i].den)
|
||||
continue;
|
||||
if (op->c.q4[i].den != 1)
|
||||
if (op->clear.value[i].den != 1)
|
||||
return AVERROR(ENOTSUP);
|
||||
|
||||
/* Ensure all bytes to be cleared are the same, because we
|
||||
* can't memset on multi-byte sequences */
|
||||
uint8_t val = op->c.q4[i].num & 0xFF;
|
||||
uint8_t val = op->clear.value[i].num & 0xFF;
|
||||
uint32_t ref = val;
|
||||
switch (ff_sws_pixel_type_size(op->type)) {
|
||||
case 2: ref *= 0x101; break;
|
||||
case 4: ref *= 0x1010101; break;
|
||||
}
|
||||
if (ref != op->c.q4[i].num)
|
||||
if (ref != op->clear.value[i].num)
|
||||
return AVERROR(ENOTSUP);
|
||||
p.clear_value[i] = val;
|
||||
p.index[i] = -1;
|
||||
|
||||
+49
-47
@@ -39,7 +39,7 @@
|
||||
*/
|
||||
static bool op_commute_clear(SwsOp *op, SwsOp *next)
|
||||
{
|
||||
SwsOp tmp;
|
||||
SwsClearOp tmp;
|
||||
|
||||
av_assert1(op->op == SWS_OP_CLEAR);
|
||||
switch (next->op) {
|
||||
@@ -56,21 +56,21 @@ static bool op_commute_clear(SwsOp *op, SwsOp *next)
|
||||
case SWS_OP_SWIZZLE:
|
||||
case SWS_OP_FILTER_H:
|
||||
case SWS_OP_FILTER_V:
|
||||
ff_sws_apply_op_q(next, op->c.q4);
|
||||
ff_sws_apply_op_q(next, op->clear.value);
|
||||
return true;
|
||||
case SWS_OP_SWAP_BYTES:
|
||||
switch (next->type) {
|
||||
case SWS_PIXEL_U16:
|
||||
ff_sws_apply_op_q(next, op->c.q4); /* always works */
|
||||
ff_sws_apply_op_q(next, op->clear.value); /* always works */
|
||||
return true;
|
||||
case SWS_PIXEL_U32:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
uint32_t v = av_bswap32(op->c.q4[i].num);
|
||||
uint32_t v = av_bswap32(op->clear.value[i].num);
|
||||
if (v > INT_MAX)
|
||||
return false; /* can't represent as AVRational anymore */
|
||||
tmp.c.q4[i] = Q(v);
|
||||
tmp.value[i] = Q(v);
|
||||
}
|
||||
op->c = tmp.c;
|
||||
op->clear = tmp;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -124,14 +124,14 @@ static bool op_commute_swizzle(SwsOp *op, SwsOp *next)
|
||||
*/
|
||||
case SWS_OP_MIN:
|
||||
case SWS_OP_MAX: {
|
||||
const SwsConst c = next->c;
|
||||
const SwsClampOp c = next->clamp;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!SWS_OP_NEEDED(op, i))
|
||||
continue;
|
||||
const int j = op->swizzle.in[i];
|
||||
if (seen[j] && av_cmp_q(next->c.q4[j], c.q4[i]))
|
||||
if (seen[j] && av_cmp_q(next->clamp.limit[j], c.limit[i]))
|
||||
return false;
|
||||
next->c.q4[j] = c.q4[i];
|
||||
next->clamp.limit[j] = c.limit[i];
|
||||
seen[j] = true;
|
||||
}
|
||||
return true;
|
||||
@@ -238,9 +238,9 @@ static int exact_log2_q(const AVRational x)
|
||||
* the corresponding scaling factor, or 0 otherwise.
|
||||
*/
|
||||
static bool extract_scalar(const SwsLinearOp *c, SwsComps comps, SwsComps prev,
|
||||
SwsConst *out_scale)
|
||||
SwsScaleOp *out_scale)
|
||||
{
|
||||
SwsConst scale = {0};
|
||||
SwsScaleOp scale = {0};
|
||||
|
||||
/* There are components not on the main diagonal */
|
||||
if (c->mask & ~SWS_MASK_DIAG4)
|
||||
@@ -251,21 +251,21 @@ static bool extract_scalar(const SwsLinearOp *c, SwsComps comps, SwsComps prev,
|
||||
if ((prev.flags[i] & SWS_COMP_ZERO) ||
|
||||
(comps.flags[i] & SWS_COMP_GARBAGE))
|
||||
continue;
|
||||
if (scale.q.den && av_cmp_q(s, scale.q))
|
||||
if (scale.factor.den && av_cmp_q(s, scale.factor))
|
||||
return false;
|
||||
scale.q = s;
|
||||
scale.factor = s;
|
||||
}
|
||||
|
||||
if (scale.q.den)
|
||||
if (scale.factor.den)
|
||||
*out_scale = scale;
|
||||
return scale.q.den;
|
||||
return scale.factor.den;
|
||||
}
|
||||
|
||||
/* Extracts an integer clear operation (subset) from the given linear op. */
|
||||
static bool extract_constant_rows(SwsLinearOp *c, SwsComps prev,
|
||||
SwsConst *out_clear)
|
||||
SwsClearOp *out_clear)
|
||||
{
|
||||
SwsConst clear = {0};
|
||||
SwsClearOp clear = {0};
|
||||
bool ret = false;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
@@ -275,7 +275,7 @@ static bool extract_constant_rows(SwsLinearOp *c, SwsComps prev,
|
||||
(prev.flags[j] & SWS_COMP_ZERO); /* input is zero */
|
||||
}
|
||||
if (const_row && (c->mask & SWS_MASK_ROW(i))) {
|
||||
clear.q4[i] = c->m[i][4];
|
||||
clear.value[i] = c->m[i][4];
|
||||
for (int j = 0; j < 5; j++)
|
||||
c->m[i][j] = Q(i == j);
|
||||
c->mask &= ~SWS_MASK_ROW(i);
|
||||
@@ -428,13 +428,13 @@ retry:
|
||||
case SWS_OP_RSHIFT:
|
||||
/* Two shifts in the same direction */
|
||||
if (next->op == op->op) {
|
||||
op->c.u += next->c.u;
|
||||
op->shift.amount += next->shift.amount;
|
||||
ff_sws_op_list_remove_at(ops, n + 1, 1);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* No-op shift */
|
||||
if (!op->c.u) {
|
||||
if (!op->shift.amount) {
|
||||
ff_sws_op_list_remove_at(ops, n, 1);
|
||||
goto retry;
|
||||
}
|
||||
@@ -442,19 +442,19 @@ retry:
|
||||
|
||||
case SWS_OP_CLEAR:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!op->c.q4[i].den)
|
||||
if (!op->clear.value[i].den)
|
||||
continue;
|
||||
|
||||
if ((prev->comps.flags[i] & SWS_COMP_ZERO) &&
|
||||
!(prev->comps.flags[i] & SWS_COMP_GARBAGE) &&
|
||||
op->c.q4[i].num == 0)
|
||||
op->clear.value[i].num == 0)
|
||||
{
|
||||
/* Redundant clear-to-zero of zero component */
|
||||
op->c.q4[i].den = 0;
|
||||
op->clear.value[i].den = 0;
|
||||
} else if (!SWS_OP_NEEDED(op, i)) {
|
||||
/* Unnecessary clear of unused component */
|
||||
op->c.q4[i] = (AVRational) {0, 0};
|
||||
} else if (op->c.q4[i].den) {
|
||||
op->clear.value[i] = (AVRational) {0, 0};
|
||||
} else if (op->clear.value[i].den) {
|
||||
noop = false;
|
||||
}
|
||||
}
|
||||
@@ -467,8 +467,8 @@ retry:
|
||||
/* Transitive clear */
|
||||
if (next->op == SWS_OP_CLEAR) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (next->c.q4[i].den)
|
||||
op->c.q4[i] = next->c.q4[i];
|
||||
if (next->clear.value[i].den)
|
||||
op->clear.value[i] = next->clear.value[i];
|
||||
}
|
||||
ff_sws_op_list_remove_at(ops, n + 1, 1);
|
||||
goto retry;
|
||||
@@ -548,7 +548,8 @@ retry:
|
||||
if (next->op == SWS_OP_SCALE && !op->convert.expand &&
|
||||
ff_sws_pixel_type_is_int(op->type) &&
|
||||
ff_sws_pixel_type_is_int(op->convert.to) &&
|
||||
!av_cmp_q(next->c.q, ff_sws_pixel_expand(op->type, op->convert.to)))
|
||||
!av_cmp_q(next->scale.factor,
|
||||
ff_sws_pixel_expand(op->type, op->convert.to)))
|
||||
{
|
||||
op->convert.expand = true;
|
||||
ff_sws_op_list_remove_at(ops, n + 1, 1);
|
||||
@@ -558,9 +559,9 @@ retry:
|
||||
|
||||
case SWS_OP_MIN:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!SWS_OP_NEEDED(op, i) || !op->c.q4[i].den)
|
||||
if (!SWS_OP_NEEDED(op, i) || !op->clamp.limit[i].den)
|
||||
continue;
|
||||
if (av_cmp_q(op->c.q4[i], prev->comps.max[i]) < 0)
|
||||
if (av_cmp_q(op->clamp.limit[i], prev->comps.max[i]) < 0)
|
||||
noop = false;
|
||||
}
|
||||
|
||||
@@ -572,9 +573,9 @@ retry:
|
||||
|
||||
case SWS_OP_MAX:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!SWS_OP_NEEDED(op, i) || !op->c.q4[i].den)
|
||||
if (!SWS_OP_NEEDED(op, i) || !op->clamp.limit[i].den)
|
||||
continue;
|
||||
if (av_cmp_q(prev->comps.min[i], op->c.q4[i]) < 0)
|
||||
if (av_cmp_q(prev->comps.min[i], op->clamp.limit[i]) < 0)
|
||||
noop = false;
|
||||
}
|
||||
|
||||
@@ -604,7 +605,8 @@ retry:
|
||||
|
||||
case SWS_OP_LINEAR: {
|
||||
SwsSwizzleOp swizzle;
|
||||
SwsConst c;
|
||||
SwsClearOp clear;
|
||||
SwsScaleOp scale;
|
||||
|
||||
/* No-op (identity) linear operation */
|
||||
if (!op->lin.mask) {
|
||||
@@ -654,20 +656,20 @@ retry:
|
||||
}
|
||||
|
||||
/* Convert constant rows to explicit clear instruction */
|
||||
if (extract_constant_rows(&op->lin, prev->comps, &c)) {
|
||||
if (extract_constant_rows(&op->lin, prev->comps, &clear)) {
|
||||
RET(ff_sws_op_list_insert_at(ops, n + 1, &(SwsOp) {
|
||||
.op = SWS_OP_CLEAR,
|
||||
.type = op->type,
|
||||
.comps = op->comps,
|
||||
.c = c,
|
||||
.clear = clear,
|
||||
}));
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* Multiplication by scalar constant */
|
||||
if (extract_scalar(&op->lin, op->comps, prev->comps, &c)) {
|
||||
op->op = SWS_OP_SCALE;
|
||||
op->c = c;
|
||||
if (extract_scalar(&op->lin, op->comps, prev->comps, &scale)) {
|
||||
op->op = SWS_OP_SCALE;
|
||||
op->scale = scale;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
@@ -684,20 +686,20 @@ retry:
|
||||
}
|
||||
|
||||
case SWS_OP_SCALE: {
|
||||
const int factor2 = exact_log2_q(op->c.q);
|
||||
const int factor2 = exact_log2_q(op->scale.factor);
|
||||
|
||||
/* No-op scaling */
|
||||
if (op->c.q.num == 1 && op->c.q.den == 1) {
|
||||
if (op->scale.factor.num == 1 && op->scale.factor.den == 1) {
|
||||
ff_sws_op_list_remove_at(ops, n, 1);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* Merge consecutive scaling operations (that don't overflow) */
|
||||
if (next->op == SWS_OP_SCALE) {
|
||||
int64_t p = op->c.q.num * (int64_t) next->c.q.num;
|
||||
int64_t q = op->c.q.den * (int64_t) next->c.q.den;
|
||||
int64_t p = op->scale.factor.num * (int64_t) next->scale.factor.num;
|
||||
int64_t q = op->scale.factor.den * (int64_t) next->scale.factor.den;
|
||||
if (FFABS(p) <= INT_MAX && FFABS(q) <= INT_MAX) {
|
||||
av_reduce(&op->c.q.num, &op->c.q.den, p, q, INT_MAX);
|
||||
av_reduce(&op->scale.factor.num, &op->scale.factor.den, p, q, INT_MAX);
|
||||
ff_sws_op_list_remove_at(ops, n + 1, 1);
|
||||
goto retry;
|
||||
}
|
||||
@@ -706,7 +708,7 @@ retry:
|
||||
/* Scaling by exact power of two */
|
||||
if (factor2 && ff_sws_pixel_type_is_int(op->type)) {
|
||||
op->op = factor2 > 0 ? SWS_OP_LSHIFT : SWS_OP_RSHIFT;
|
||||
op->c.u = FFABS(factor2);
|
||||
op->shift.amount = FFABS(factor2);
|
||||
goto retry;
|
||||
}
|
||||
break;
|
||||
@@ -760,7 +762,7 @@ retry:
|
||||
|
||||
case SWS_OP_SCALE:
|
||||
/* Scaling by integer before conversion to int */
|
||||
if (op->c.q.den == 1 && next->op == SWS_OP_CONVERT &&
|
||||
if (op->scale.factor.den == 1 && next->op == SWS_OP_CONVERT &&
|
||||
ff_sws_pixel_type_is_int(next->convert.to))
|
||||
{
|
||||
op->type = next->convert.to;
|
||||
@@ -812,9 +814,9 @@ int ff_sws_solve_shuffle(const SwsOpList *const ops, uint8_t shuffle[],
|
||||
|
||||
case SWS_OP_CLEAR:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!op->c.q4[i].den)
|
||||
if (!op->clear.value[i].den)
|
||||
continue;
|
||||
if (op->c.q4[i].num != 0 || !clear_val)
|
||||
if (op->clear.value[i].num != 0 || !clear_val)
|
||||
return AVERROR(ENOTSUP);
|
||||
mask[i] = 0x1010101ul * clear_val;
|
||||
}
|
||||
|
||||
@@ -65,11 +65,16 @@ static int register_op(SwsContext *ctx, void *opaque, SwsOp *op)
|
||||
}
|
||||
break;
|
||||
case SWS_OP_SCALE:
|
||||
op->scale.factor = (AVRational) { 0, 1 };
|
||||
break;
|
||||
case SWS_OP_MIN:
|
||||
case SWS_OP_MAX:
|
||||
for (int i = 0; i < 4; i++)
|
||||
op->clamp.limit[i] = (AVRational) { 0, 1 };
|
||||
break;
|
||||
case SWS_OP_CLEAR:
|
||||
for (int i = 0; i < 4; i++)
|
||||
op->c.q4[i] = (AVRational) { 0, !!op->c.q4[i].den };
|
||||
op->clear.value[i] = (AVRational) { 0, !!op->clear.value[i].den };
|
||||
break;
|
||||
case SWS_OP_DITHER:
|
||||
/* Strip arbitrary offset */
|
||||
|
||||
@@ -274,32 +274,32 @@ static int add_ops_glsl(VulkanPriv *p, FFVulkanOpsCtx *s,
|
||||
}
|
||||
case SWS_OP_CLEAR: {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!op->c.q4[i].den)
|
||||
if (!op->clear.value[i].den)
|
||||
continue;
|
||||
av_bprintf(&shd->src, " %s.%c = %s"QSTR";\n", type_name,
|
||||
"xyzw"[i], type_s, QTYPE(op->c.q4[i]));
|
||||
"xyzw"[i], type_s, QTYPE(op->clear.value[i]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SWS_OP_SCALE:
|
||||
av_bprintf(&shd->src, " %s = %s * "QSTR";\n",
|
||||
type_name, type_name, QTYPE(op->c.q));
|
||||
type_name, type_name, QTYPE(op->scale.factor));
|
||||
break;
|
||||
case SWS_OP_MIN:
|
||||
case SWS_OP_MAX:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!op->c.q4[i].den)
|
||||
if (!op->clamp.limit[i].den)
|
||||
continue;
|
||||
av_bprintf(&shd->src, " %s.%c = %s(%s.%c, "QSTR");\n",
|
||||
type_name, "xyzw"[i],
|
||||
op->op == SWS_OP_MIN ? "min" : "max",
|
||||
type_name, "xyzw"[i], QTYPE(op->c.q4[i]));
|
||||
type_name, "xyzw"[i], QTYPE(op->clamp.limit[i]));
|
||||
}
|
||||
break;
|
||||
case SWS_OP_LSHIFT:
|
||||
case SWS_OP_RSHIFT:
|
||||
av_bprintf(&shd->src, " %s %s= %i;\n", type_name,
|
||||
op->op == SWS_OP_LSHIFT ? "<<" : ">>", op->c.u);
|
||||
op->op == SWS_OP_LSHIFT ? "<<" : ">>", op->shift.amount);
|
||||
break;
|
||||
case SWS_OP_CONVERT:
|
||||
if (ff_sws_pixel_type_is_int(cur_type) && op->convert.expand) {
|
||||
|
||||
@@ -133,7 +133,7 @@ static int setup_clear(const SwsImplParams *params, SwsImplResult *out)
|
||||
{
|
||||
const SwsOp *op = params->op;
|
||||
for (int i = 0; i < 4; i++)
|
||||
out->priv.u32[i] = (uint32_t) op->c.q4[i].num;
|
||||
out->priv.u32[i] = (uint32_t) op->clear.value[i].num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ static int setup_clear(const SwsImplParams *params, SwsImplResult *out)
|
||||
|
||||
static int setup_shift(const SwsImplParams *params, SwsImplResult *out)
|
||||
{
|
||||
out->priv.u16[0] = params->op->c.u;
|
||||
out->priv.u16[0] = params->op->shift.amount;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -944,7 +944,7 @@ static void normalize_clear(SwsOp *op)
|
||||
ff_sws_setup_clear(&(const SwsImplParams) { .op = op }, &res);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!op->c.q4[i].den)
|
||||
if (!op->clear.value[i].den)
|
||||
continue;
|
||||
switch (ff_sws_pixel_type_size(op->type)) {
|
||||
case 1: c.u32 = 0x1010101U * res.priv.u8[i]; break;
|
||||
@@ -952,8 +952,8 @@ static void normalize_clear(SwsOp *op)
|
||||
case 4: c.u32 = res.priv.u32[i]; break;
|
||||
}
|
||||
|
||||
op->c.q4[i].num = c.i;
|
||||
op->c.q4[i].den = 1;
|
||||
op->clear.value[i].num = c.i;
|
||||
op->clear.value[i].den = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+39
-39
@@ -498,45 +498,45 @@ static void check_clear(void)
|
||||
const AVRational zero = (AVRational) { 0, 1};
|
||||
const AVRational none = {0};
|
||||
|
||||
const SwsConst patterns[] = {
|
||||
const SwsClearOp patterns[] = {
|
||||
/* Zero only */
|
||||
{.q4 = { none, none, none, zero }},
|
||||
{.q4 = { zero, none, none, none }},
|
||||
{{ none, none, none, zero }},
|
||||
{{ zero, none, none, none }},
|
||||
/* Alpha only */
|
||||
{.q4 = { none, none, none, alpha }},
|
||||
{.q4 = { alpha, none, none, none }},
|
||||
{{ none, none, none, alpha }},
|
||||
{{ alpha, none, none, none }},
|
||||
/* Chroma only */
|
||||
{.q4 = { chroma, chroma, none, none }},
|
||||
{.q4 = { none, chroma, chroma, none }},
|
||||
{.q4 = { none, none, chroma, chroma }},
|
||||
{.q4 = { chroma, none, chroma, none }},
|
||||
{.q4 = { none, chroma, none, chroma }},
|
||||
{{ chroma, chroma, none, none }},
|
||||
{{ none, chroma, chroma, none }},
|
||||
{{ none, none, chroma, chroma }},
|
||||
{{ chroma, none, chroma, none }},
|
||||
{{ none, chroma, none, chroma }},
|
||||
/* Alpha+chroma */
|
||||
{.q4 = { chroma, chroma, none, alpha }},
|
||||
{.q4 = { none, chroma, chroma, alpha }},
|
||||
{.q4 = { alpha, none, chroma, chroma }},
|
||||
{.q4 = { chroma, none, chroma, alpha }},
|
||||
{.q4 = { alpha, chroma, none, chroma }},
|
||||
{{ chroma, chroma, none, alpha }},
|
||||
{{ none, chroma, chroma, alpha }},
|
||||
{{ alpha, none, chroma, chroma }},
|
||||
{{ chroma, none, chroma, alpha }},
|
||||
{{ alpha, chroma, none, chroma }},
|
||||
/* Random values */
|
||||
{.q4 = { none, rndq(t), rndq(t), rndq(t) }},
|
||||
{.q4 = { none, rndq(t), rndq(t), rndq(t) }},
|
||||
{.q4 = { none, rndq(t), rndq(t), rndq(t) }},
|
||||
{.q4 = { none, rndq(t), rndq(t), rndq(t) }},
|
||||
{{ none, rndq(t), rndq(t), rndq(t) }},
|
||||
{{ none, rndq(t), rndq(t), rndq(t) }},
|
||||
{{ none, rndq(t), rndq(t), rndq(t) }},
|
||||
{{ none, rndq(t), rndq(t), rndq(t) }},
|
||||
};
|
||||
|
||||
for (int i = 0; i < FF_ARRAY_ELEMS(patterns); i++) {
|
||||
CHECK(FMT("clear_pattern_%s[%d]", type, i), 4, 4, t, t, {
|
||||
.op = SWS_OP_CLEAR,
|
||||
.type = t,
|
||||
.c = patterns[i],
|
||||
.op = SWS_OP_CLEAR,
|
||||
.type = t,
|
||||
.clear = patterns[i],
|
||||
});
|
||||
}
|
||||
} else if (!ff_sws_pixel_type_is_int(t)) {
|
||||
/* Floating point YUV doesn't exist, only alpha needs to be cleared */
|
||||
CHECK(FMT("clear_alpha_%s", type), 4, 4, t, t, {
|
||||
.op = SWS_OP_CLEAR,
|
||||
.type = t,
|
||||
.c.q4[3] = { 0, 1 },
|
||||
.op = SWS_OP_CLEAR,
|
||||
.type = t,
|
||||
.clear.value[3] = { 0, 1 },
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -551,15 +551,15 @@ static void check_shift(void)
|
||||
|
||||
for (int shift = 1; shift <= 8; shift++) {
|
||||
CHECK_COMMON(FMT("lshift%d_%s", shift, type), t, t, {
|
||||
.op = SWS_OP_LSHIFT,
|
||||
.type = t,
|
||||
.c.u = shift,
|
||||
.op = SWS_OP_LSHIFT,
|
||||
.type = t,
|
||||
.shift = { shift },
|
||||
});
|
||||
|
||||
CHECK_COMMON(FMT("rshift%d_%s", shift, type), t, t, {
|
||||
.op = SWS_OP_RSHIFT,
|
||||
.type = t,
|
||||
.c.u = shift,
|
||||
.op = SWS_OP_RSHIFT,
|
||||
.type = t,
|
||||
.shift = { shift },
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -697,13 +697,13 @@ static void check_min_max(void)
|
||||
CHECK_COMMON(FMT("min_%s", type), t, t, {
|
||||
.op = SWS_OP_MIN,
|
||||
.type = t,
|
||||
.c.q4 = { rndq(t), rndq(t), rndq(t), rndq(t) },
|
||||
.clamp = {{ rndq(t), rndq(t), rndq(t), rndq(t) }},
|
||||
});
|
||||
|
||||
CHECK_COMMON(FMT("max_%s", type), t, t, {
|
||||
.op = SWS_OP_MAX,
|
||||
.type = t,
|
||||
.c.q4 = { rndq(t), rndq(t), rndq(t), rndq(t) },
|
||||
.clamp = {{ rndq(t), rndq(t), rndq(t), rndq(t) }},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -776,15 +776,15 @@ static void check_scale(void)
|
||||
const unsigned scale = rnd() & max;
|
||||
const unsigned range = max / (scale ? scale : 1);
|
||||
CHECK_COMMON_RANGE(FMT("scale_%s", type), range, t, t, {
|
||||
.op = SWS_OP_SCALE,
|
||||
.type = t,
|
||||
.c.q = { scale, 1 },
|
||||
.op = SWS_OP_SCALE,
|
||||
.type = t,
|
||||
.scale = {{ scale, 1 }},
|
||||
});
|
||||
} else {
|
||||
CHECK_COMMON(FMT("scale_%s", type), t, t, {
|
||||
.op = SWS_OP_SCALE,
|
||||
.type = t,
|
||||
.c.q = rndq(t),
|
||||
.op = SWS_OP_SCALE,
|
||||
.type = t,
|
||||
.scale = { rndq(t) },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user