mirror of
https://mirror.skon.top/https://github.com/FFmpeg/FFmpeg
synced 2026-04-20 21:00:41 +08:00
swscale/ops_chain: split generic setup helpers into op-specific helpers
This has the side benefit of not relying on the q2pixel macro to avoid division by zero, since we can now explicitly avoid operating on undefined clear values. Signed-off-by: Niklas Haas <git@haasn.dev>
This commit is contained in:
@@ -143,12 +143,14 @@ static int aarch64_setup(SwsOpList *ops, int block_size, int n,
|
||||
}
|
||||
break;
|
||||
case SWS_OP_CLEAR:
|
||||
ff_sws_setup_clear(&(const SwsImplParams) { .op = op }, out);
|
||||
break;
|
||||
case SWS_OP_MIN:
|
||||
case SWS_OP_MAX:
|
||||
ff_sws_setup_q4(&(const SwsImplParams) { .op = op }, out);
|
||||
ff_sws_setup_clamp(&(const SwsImplParams) { .op = op }, out);
|
||||
break;
|
||||
case SWS_OP_SCALE:
|
||||
ff_sws_setup_q(&(const SwsImplParams) { .op = op }, out);
|
||||
ff_sws_setup_scale(&(const SwsImplParams) { .op = op }, out);
|
||||
break;
|
||||
case SWS_OP_LINEAR:
|
||||
return aarch64_setup_linear(p, op, out);
|
||||
|
||||
@@ -263,33 +263,56 @@ int ff_sws_op_compile_tables(SwsContext *ctx, const SwsOpTable *const tables[],
|
||||
|
||||
#define q2pixel(type, q) ((q).den ? (type) (q).num / (q).den : 0)
|
||||
|
||||
int ff_sws_setup_u8(const SwsImplParams *params, SwsImplResult *out)
|
||||
int ff_sws_setup_shift(const SwsImplParams *params, SwsImplResult *out)
|
||||
{
|
||||
out->priv.u8[0] = params->op->c.u;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_sws_setup_q(const SwsImplParams *params, SwsImplResult *out)
|
||||
int ff_sws_setup_scale(const SwsImplParams *params, SwsImplResult *out)
|
||||
{
|
||||
const SwsOp *op = params->op;
|
||||
const AVRational factor = op->c.q;
|
||||
switch (op->type) {
|
||||
case SWS_PIXEL_U8: out->priv.u8[0] = q2pixel(uint8_t, op->c.q); return 0;
|
||||
case SWS_PIXEL_U16: out->priv.u16[0] = q2pixel(uint16_t, op->c.q); return 0;
|
||||
case SWS_PIXEL_U32: out->priv.u32[0] = q2pixel(uint32_t, op->c.q); return 0;
|
||||
case SWS_PIXEL_F32: out->priv.f32[0] = q2pixel(float, op->c.q); return 0;
|
||||
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;
|
||||
case SWS_PIXEL_U32: out->priv.u32[0] = q2pixel(uint32_t, factor); break;
|
||||
case SWS_PIXEL_F32: out->priv.f32[0] = q2pixel(float, factor); break;
|
||||
default: return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_sws_setup_q4(const SwsImplParams *params, SwsImplResult *out)
|
||||
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];
|
||||
switch (op->type) {
|
||||
case SWS_PIXEL_U8: out->priv.u8[i] = q2pixel(uint8_t, op->c.q4[i]); break;
|
||||
case SWS_PIXEL_U16: out->priv.u16[i] = q2pixel(uint16_t, op->c.q4[i]); break;
|
||||
case SWS_PIXEL_U32: out->priv.u32[i] = q2pixel(uint32_t, op->c.q4[i]); break;
|
||||
case SWS_PIXEL_F32: out->priv.f32[i] = q2pixel(float, op->c.q4[i]); break;
|
||||
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;
|
||||
case SWS_PIXEL_U32: out->priv.u32[i] = q2pixel(uint32_t, limit); break;
|
||||
case SWS_PIXEL_F32: out->priv.f32[i] = q2pixel(float, limit); break;
|
||||
default: return AVERROR(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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];
|
||||
if (!value.den)
|
||||
continue;
|
||||
switch (op->type) {
|
||||
case SWS_PIXEL_U8: out->priv.u8[i] = q2pixel(uint8_t, value); break;
|
||||
case SWS_PIXEL_U16: out->priv.u16[i] = q2pixel(uint16_t, value); break;
|
||||
case SWS_PIXEL_U32: out->priv.u32[i] = q2pixel(uint32_t, value); break;
|
||||
case SWS_PIXEL_F32: out->priv.f32[i] = q2pixel(float, value); break;
|
||||
default: return AVERROR(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,10 +140,11 @@ typedef struct SwsOpEntry {
|
||||
bool (*check)(const SwsImplParams *params); /* optional, return true if supported */
|
||||
} SwsOpEntry;
|
||||
|
||||
/* Setup helpers */
|
||||
int ff_sws_setup_u8(const SwsImplParams *params, SwsImplResult *out);
|
||||
int ff_sws_setup_q(const SwsImplParams *params, SwsImplResult *out);
|
||||
int ff_sws_setup_q4(const SwsImplParams *params, SwsImplResult *out);
|
||||
/* Setup helpers for common/trivial operation types */
|
||||
int ff_sws_setup_shift(const SwsImplParams *params, SwsImplResult *out);
|
||||
int ff_sws_setup_scale(const SwsImplParams *params, SwsImplResult *out);
|
||||
int ff_sws_setup_clamp(const SwsImplParams *params, SwsImplResult *out);
|
||||
int ff_sws_setup_clear(const SwsImplParams *params, SwsImplResult *out);
|
||||
|
||||
static inline void ff_op_priv_free(SwsOpPriv *priv)
|
||||
{
|
||||
|
||||
@@ -85,7 +85,7 @@ DECL_IMPL(clear##_##X##Y##Z##W)
|
||||
} \
|
||||
\
|
||||
DECL_ENTRY(clear##_##X##Y##Z##W, \
|
||||
.setup = ff_sws_setup_q4, \
|
||||
.setup = ff_sws_setup_clear, \
|
||||
.op = SWS_OP_CLEAR, \
|
||||
.flexible = true, \
|
||||
.unused = { !X, !Y, !Z, !W }, \
|
||||
@@ -141,13 +141,13 @@ DECL_PATTERN(max)
|
||||
|
||||
WRAP_COMMON_PATTERNS(min,
|
||||
.op = SWS_OP_MIN,
|
||||
.setup = ff_sws_setup_q4,
|
||||
.setup = ff_sws_setup_clamp,
|
||||
.flexible = true,
|
||||
);
|
||||
|
||||
WRAP_COMMON_PATTERNS(max,
|
||||
.op = SWS_OP_MAX,
|
||||
.setup = ff_sws_setup_q4,
|
||||
.setup = ff_sws_setup_clamp,
|
||||
.flexible = true,
|
||||
);
|
||||
|
||||
@@ -172,7 +172,7 @@ DECL_PATTERN(scale)
|
||||
|
||||
WRAP_COMMON_PATTERNS(scale,
|
||||
.op = SWS_OP_SCALE,
|
||||
.setup = ff_sws_setup_q,
|
||||
.setup = ff_sws_setup_scale,
|
||||
.flexible = true,
|
||||
);
|
||||
|
||||
|
||||
@@ -383,13 +383,13 @@ DECL_PATTERN(rshift)
|
||||
|
||||
WRAP_COMMON_PATTERNS(lshift,
|
||||
.op = SWS_OP_LSHIFT,
|
||||
.setup = ff_sws_setup_u8,
|
||||
.setup = ff_sws_setup_shift,
|
||||
.flexible = true,
|
||||
);
|
||||
|
||||
WRAP_COMMON_PATTERNS(rshift,
|
||||
.op = SWS_OP_RSHIFT,
|
||||
.setup = ff_sws_setup_u8,
|
||||
.setup = ff_sws_setup_shift,
|
||||
.flexible = true,
|
||||
);
|
||||
#endif /* BIT_DEPTH != 8 */
|
||||
|
||||
@@ -185,20 +185,20 @@ static int setup_shift(const SwsImplParams *params, SwsImplResult *out)
|
||||
#define DECL_MIN_MAX(EXT) \
|
||||
DECL_COMMON_PATTERNS(F32, min##EXT, \
|
||||
.op = SWS_OP_MIN, \
|
||||
.setup = ff_sws_setup_q4, \
|
||||
.setup = ff_sws_setup_clamp, \
|
||||
.flexible = true, \
|
||||
); \
|
||||
\
|
||||
DECL_COMMON_PATTERNS(F32, max##EXT, \
|
||||
.op = SWS_OP_MAX, \
|
||||
.setup = ff_sws_setup_q4, \
|
||||
.setup = ff_sws_setup_clamp, \
|
||||
.flexible = true, \
|
||||
);
|
||||
|
||||
#define DECL_SCALE(EXT) \
|
||||
DECL_COMMON_PATTERNS(F32, scale##EXT, \
|
||||
.op = SWS_OP_SCALE, \
|
||||
.setup = ff_sws_setup_q, \
|
||||
.setup = ff_sws_setup_scale, \
|
||||
.flexible = true, \
|
||||
);
|
||||
|
||||
@@ -941,7 +941,7 @@ static void normalize_clear(SwsOp *op)
|
||||
int i;
|
||||
} c;
|
||||
|
||||
ff_sws_setup_q4(&(const SwsImplParams) { .op = op }, &res);
|
||||
ff_sws_setup_clear(&(const SwsImplParams) { .op = op }, &res);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!op->c.q4[i].den)
|
||||
|
||||
Reference in New Issue
Block a user