This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 3743d2851d23d6b98d4348f19582781bd4a93bb9 Author: Niklas Haas <[email protected]> AuthorDate: Thu Jun 25 01:20:44 2026 +0200 Commit: Niklas Haas <[email protected]> CommitDate: Thu Jun 25 01:20:44 2026 +0200 swscale/ops: switch from AVRational to AVRational64 This has two immediate consequences: 1. Fixes overflow in the range tracker for some 32-bit packed formats: rgb24 -> v30xbe: [ u8 +++X] SWS_OP_READ : 3 elem(s) packed >> 0 min: {0 0 0 _}, max: {255 255 255 _} [ u8 +++X] SWS_OP_CONVERT : u8 -> f32 min: {0 0 0 _}, max: {255 255 255 _} [f32 ...X] SWS_OP_LINEAR : matrix3+off3 [...] min: {64 64 64 _}, max: {940 960 960 _} [f32 ...X] SWS_OP_DITHER : 16x16 matrix + {0 3 2 -1} min: {64.001953 64.001953 64.001953 _}, max: {940.998047 960.998047 960.998047 _} [f32 +++X] SWS_OP_CONVERT : f32 -> u32 min: {64 64 64 _}, max: {940 960 960 _} [u32 +++X] SWS_OP_SWIZZLE : 2013 min: {64 64 64 _}, max: {960 940 960 _} [u32 ++++] SWS_OP_CLEAR : {_ _ _ 1} min: {64 64 64 1}, max: {960 940 960 1} [u32 +XXX] SWS_OP_PACK : {10 10 10 2} - min: {268697857 _ _ _}, max: {-264581375 _ _ _} + min: {268697857 _ _ _}, max: {4030385921 _ _ _} [u32 zXXX] SWS_OP_SWAP_BYTES - min: {268697857 _ _ _}, max: {-264581375 _ _ _} + min: {268697857 _ _ _}, max: {4030385921 _ _ _} 2. Slightly increases the accuracy of intermediate values for some linear ops: yuv444p10be -> rgb48be: [u16 zzzX] SWS_OP_READ : 3 elem(s) planar >> 0 min: {0 0 0 _}, max: {1023 1023 1023 _} [u16 +++X] SWS_OP_SWAP_BYTES min: {0 0 0 _}, max: {1023 1023 1023 _} [u16 +++X] SWS_OP_CONVERT : u16 -> f32 min: {0 0 0 _}, max: {1023 1023 1023 _} [f32 ...X] SWS_OP_LINEAR : matrix3+off3 [...] 46.813777] [0 0 0 1 0]] - min: {-57290.842348 -44341.337325 -71146.813777 _}, max: {124144.718860 111375.162457 137973.627845 _} + min: {-57290.842348 -44341.337326 -71146.813777 _}, max: {124144.718860 111375.162457 137973.627845 _} [f32 ...X] SWS_OP_MAX : {0 0 0 _} <= x min: {0 0 0 _}, max: {124144.718860 111375.162457 137973.627845 _} [f32 ...X] SWS_OP_MIN : x <= {65535 65535 65535 _} min: {0 0 0 _}, max: {65535 65535 65535 _} [f32 +++X] SWS_OP_CONVERT : f32 -> u16 min: {0 0 0 _}, max: {65535 65535 65535 _} [u16 zzzX] SWS_OP_SWAP_BYTES min: {0 0 0 _}, max: {65535 65535 65535 _} [u16 XXXX] SWS_OP_WRITE : 3 elem(s) packed >> 0 (X = unused, z = byteswapped, + = exact, 0 = zero) Importantly, none of the changes affect the actual operation list, just the range tracking metadata. Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas <[email protected]> --- libswscale/aarch64/ops_impl_conv.c | 2 +- libswscale/format.c | 80 ++++++++++++++++---------------- libswscale/ops.c | 94 +++++++++++++++++++------------------- libswscale/ops.h | 21 +++++---- libswscale/ops_chain.c | 6 +-- libswscale/ops_internal.h | 4 +- libswscale/ops_optimizer.c | 26 +++++------ libswscale/uops.c | 18 ++++---- libswscale/vulkan/ops.c | 14 +++--- tests/checkasm/sw_ops.c | 38 +++++++-------- tests/ref/fate/sws-ops-list | 2 +- 11 files changed, 153 insertions(+), 152 deletions(-) diff --git a/libswscale/aarch64/ops_impl_conv.c b/libswscale/aarch64/ops_impl_conv.c index 075569b3b9..431af91d98 100644 --- a/libswscale/aarch64/ops_impl_conv.c +++ b/libswscale/aarch64/ops_impl_conv.c @@ -209,7 +209,7 @@ static int convert_to_aarch64_impl(SwsContext *ctx, const SwsOpList *ops, int n, continue; MASK_SET(out->mask, i, 1); for (int j = 0; j < 5; j++) { - const AVRational k = op->lin.m[i][j]; + const AVRational64 k = op->lin.m[i][j]; int jj = linear_index_from_sws_op(j); if (j < 4 && k.num == k.den) LINEAR_MASK_SET(out->linear.mask, i, jj, LINEAR_MASK_1); diff --git a/libswscale/format.c b/libswscale/format.c index e14db551fc..f1e0e3242e 100644 --- a/libswscale/format.c +++ b/libswscale/format.c @@ -1011,10 +1011,10 @@ static SwsClearOp fmt_clear(const SwsFormat *fmt) # define NATIVE_ENDIAN_FLAG 0 #endif -static inline AVRational intmax_q(int bits) +static inline AVRational64 intmax_q64(int bits) { - av_assert1(bits >= 0 && bits < 32); - return Q(UINT32_MAX >> (32 - bits)); + av_assert1(bits >= 0 && bits < 64); + return Q(UINT64_MAX >> (64 - bits)); } int ff_sws_decode_pixfmt(SwsOpList *ops, const SwsFormat *fmt) @@ -1051,7 +1051,7 @@ int ff_sws_decode_pixfmt(SwsOpList *ops, const SwsFormat *fmt) const int idx = swizzle.in[is_ya ? 3 * c : c]; comps->min[idx] = Q(0); if (bits < 32) /* FIXME: AVRational is limited to INT_MAX */ - comps->max[idx] = intmax_q(bits); + comps->max[idx] = intmax_q64(bits); } } @@ -1177,15 +1177,15 @@ int ff_sws_encode_pixfmt(SwsOpList *ops, const SwsFormat *fmt) return 0; } -static inline AVRational av_neg_q(AVRational x) +static inline AVRational64 av_neg_q64(AVRational64 x) { - return (AVRational) { -x.num, x.den }; + return (AVRational64) { -x.num, x.den }; } static SwsLinearOp fmt_encode_range(const SwsFormat *fmt, bool *incomplete) { - const AVRational q0 = Q(0); - const AVRational q1 = Q(1); + const AVRational64 q0 = Q(0); + const AVRational64 q1 = Q(1); SwsLinearOp c = { .m = { { q1, q0, q0, q0, q0 }, @@ -1204,17 +1204,17 @@ static SwsLinearOp fmt_encode_range(const SwsFormat *fmt, bool *incomplete) return c; /* floats are directly output as-is */ if (fmt->csp == AVCOL_SPC_RGB || (desc->flags & AV_PIX_FMT_FLAG_XYZ)) { - c.m[0][0] = intmax_q(depth0); - c.m[1][1] = intmax_q(depth1); - c.m[2][2] = intmax_q(depth2); + c.m[0][0] = intmax_q64(depth0); + c.m[1][1] = intmax_q64(depth1); + c.m[2][2] = intmax_q64(depth2); } else if (fmt->range == AVCOL_RANGE_JPEG) { /* Full range YUV */ - c.m[0][0] = intmax_q(depth0); + c.m[0][0] = intmax_q64(depth0); if (desc->nb_components >= 3) { /* This follows the ITU-R convention, which is slightly different * from the JFIF convention. */ - c.m[1][1] = intmax_q(depth1); - c.m[2][2] = intmax_q(depth2); + c.m[1][1] = intmax_q64(depth1); + c.m[2][2] = intmax_q64(depth2); c.m[1][4] = Q(1 << (depth1 - 1)); c.m[2][4] = Q(1 << (depth2 - 1)); } @@ -1234,13 +1234,13 @@ static SwsLinearOp fmt_encode_range(const SwsFormat *fmt, bool *incomplete) if (desc->flags & AV_PIX_FMT_FLAG_ALPHA) { const bool is_ya = desc->nb_components == 2; - c.m[3][3] = intmax_q(is_ya ? depth1 : depth3); + c.m[3][3] = intmax_q64(is_ya ? depth1 : depth3); } if (fmt->format == AV_PIX_FMT_MONOWHITE) { /* This format is inverted, 0 = white, 1 = black */ - c.m[0][4] = av_add_q(c.m[0][4], c.m[0][0]); - c.m[0][0] = av_neg_q(c.m[0][0]); + c.m[0][4] = av_add_q64(c.m[0][4], c.m[0][0]); + c.m[0][0] = av_neg_q64(c.m[0][0]); } c.mask = ff_sws_linear_mask(&c); @@ -1254,8 +1254,8 @@ static SwsLinearOp fmt_decode_range(const SwsFormat *fmt, bool *incomplete) /* Invert main diagonal + offset: x = s * y + k ==> y = (x - k) / s */ for (int i = 0; i < 4; i++) { av_assert1(c.m[i][i].num); - c.m[i][i] = av_inv_q(c.m[i][i]); - c.m[i][4] = av_mul_q(c.m[i][4], av_neg_q(c.m[i][i])); + c.m[i][i] = av_inv_q64(c.m[i][i]); + c.m[i][4] = av_mul_q64(c.m[i][4], av_neg_q64(c.m[i][i])); } /* Explicitly initialize alpha for sanity */ @@ -1266,11 +1266,11 @@ static SwsLinearOp fmt_decode_range(const SwsFormat *fmt, bool *incomplete) return c; } -static AVRational *generate_bayer_matrix(const int size_log2) +static AVRational64 *generate_bayer_matrix(const int size_log2) { const int size = 1 << size_log2; const int num_entries = size * size; - AVRational *m = av_refstruct_allocz(sizeof(*m) * num_entries); + AVRational64 *m = av_refstruct_allocz(sizeof(*m) * num_entries); av_assert1(size_log2 < 16); if (!m) return NULL; @@ -1283,10 +1283,10 @@ static AVRational *generate_bayer_matrix(const int size_log2) const int den = 4 * sz * sz; for (int y = 0; y < sz; y++) { for (int x = 0; x < sz; x++) { - const AVRational cur = m[y * size + x]; - m[(y + sz) * size + x + sz] = av_add_q(cur, av_make_q(1, den)); - m[(y ) * size + x + sz] = av_add_q(cur, av_make_q(2, den)); - m[(y + sz) * size + x ] = av_add_q(cur, av_make_q(3, den)); + const AVRational64 cur = m[y * size + x]; + m[(y + sz) * size + x + sz] = av_add_q64(cur, av_make_q64(1, den)); + m[(y ) * size + x + sz] = av_add_q64(cur, av_make_q64(2, den)); + m[(y + sz) * size + x ] = av_add_q64(cur, av_make_q64(3, den)); } } } @@ -1302,7 +1302,7 @@ static AVRational *generate_bayer_matrix(const int size_log2) * To make the average value equal to 1/2 = N/(2N), add a bias of 1/(2N). */ for (int i = 0; i < num_entries; i++) - m[i] = av_add_q(m[i], av_make_q(1, 2 * num_entries)); + m[i] = av_add_q64(m[i], av_make_q64(1, 2 * num_entries)); return m; } @@ -1341,10 +1341,10 @@ static int fmt_dither(SwsContext *ctx, SwsOpList *ops, case SWS_DITHER_NONE: if (ctx->flags & SWS_ACCURATE_RND) { /* Add constant 0.5 for correct rounding */ - AVRational *bias = av_refstruct_allocz(sizeof(*bias)); + AVRational64 *bias = av_refstruct_allocz(sizeof(*bias)); if (!bias) return AVERROR(ENOMEM); - *bias = (AVRational) {1, 2}; + *bias = (AVRational64) {1, 2}; return ff_sws_op_list_append(ops, &(SwsOp) { .op = SWS_OP_DITHER, .type = type, @@ -1369,9 +1369,9 @@ static int fmt_dither(SwsContext *ctx, SwsOpList *ops, const int size = 1 << dither.size_log2; dither.min = dither.max = dither.matrix[0]; for (int i = 1; i < size * size; i++) { - if (av_cmp_q(dither.min, dither.matrix[i]) > 0) + if (av_cmp_q64(dither.min, dither.matrix[i]) > 0) dither.min = dither.matrix[i]; - if (av_cmp_q(dither.matrix[i], dither.max) > 0) + if (av_cmp_q64(dither.matrix[i], dither.max) > 0) dither.max = dither.matrix[i]; } @@ -1417,18 +1417,18 @@ static int fmt_dither(SwsContext *ctx, SwsOpList *ops, return AVERROR(EINVAL); } +#define Q64(x) av_make_q64((x).num, (x).den) + static inline SwsLinearOp linear_mat3(const AVRational m00, const AVRational m01, const AVRational m02, const AVRational m10, const AVRational m11, const AVRational m12, const AVRational m20, const AVRational m21, const AVRational m22) { - const AVRational q0 = Q(0); - const AVRational q1 = Q(1); SwsLinearOp c = {{ - { m00, m01, m02, q0, q0 }, - { m10, m11, m12, q0, q0 }, - { m20, m21, m22, q0, q0 }, - { q0, q0, q0, q1, q0 }, + { Q64(m00), Q64(m01), Q64(m02), Q(0), Q(0) }, + { Q64(m10), Q64(m11), Q64(m12), Q(0), Q(0) }, + { Q64(m20), Q64(m21), Q64(m22), Q(0), Q(0) }, + { Q(0), Q(0), Q(0), Q(1), Q(0) }, }}; c.mask = ff_sws_linear_mask(&c); @@ -1484,9 +1484,9 @@ int ff_sws_decode_colors(SwsContext *ctx, SwsPixelType type, if (!pixel_type) return AVERROR(ENOTSUP); - const AVRational q0 = Q(0); - const AVRational q1 = Q(1); - const AVRational q2 = Q(2); + const AVRational q0 = av_make_q(0, 1); + const AVRational q1 = av_make_q(1, 1); + const AVRational q2 = av_make_q(2, 1); RET(ff_sws_op_list_append(ops, &(SwsOp) { .op = SWS_OP_CONVERT, @@ -1647,7 +1647,7 @@ int ff_sws_encode_colors(SwsContext *ctx, SwsPixelType type, for (int i = 0; i < dst->desc->nb_components; i++) { /* Clamp to legal pixel range */ const int idx = i * (is_ya ? 3 : 1); - range.limit[idx] = intmax_q(dst->desc->comp[i].depth); + range.limit[idx] = intmax_q64(dst->desc->comp[i].depth); } RET(fmt_dither(ctx, ops, type, src, dst)); diff --git a/libswscale/ops.c b/libswscale/ops.c index 26e6a6171c..666a570216 100644 --- a/libswscale/ops.c +++ b/libswscale/ops.c @@ -134,7 +134,7 @@ const char *ff_sws_op_type_name(SwsOpType op) return "ERR"; } -SwsCompMask ff_sws_comp_mask_q4(const AVRational q[4]) +SwsCompMask ff_sws_comp_mask_q4(const AVRational64 q[4]) { SwsCompMask mask = 0; for (int i = 0; i < 4; i++) { @@ -181,17 +181,17 @@ int ff_sws_rw_op_planes(const SwsOp *op) } /* biased towards `a` */ -static AVRational av_min_q(AVRational a, AVRational b) +static AVRational64 av_min_q64(AVRational64 a, AVRational64 b) { - return av_cmp_q(a, b) == 1 ? b : a; + return av_cmp_q64(a, b) == 1 ? b : a; } -static AVRational av_max_q(AVRational a, AVRational b) +static AVRational64 av_max_q64(AVRational64 a, AVRational64 b) { - return av_cmp_q(a, b) == -1 ? b : a; + return av_cmp_q64(a, b) == -1 ? b : a; } -void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4]) +void ff_sws_apply_op_q(const SwsOp *op, AVRational64 x[4]) { uint64_t mask[4]; int shift[4]; @@ -238,9 +238,9 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4]) return; case SWS_OP_LSHIFT: { av_assert1(ff_sws_pixel_type_is_int(op->type)); - AVRational mult = Q(1 << op->shift.amount); + AVRational64 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]; + x[i] = x[i].den ? av_mul_q64(x[i], mult) : x[i]; return; } case SWS_OP_RSHIFT: { @@ -250,18 +250,18 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4]) return; } case SWS_OP_SWIZZLE: { - const AVRational orig[4] = { x[0], x[1], x[2], x[3] }; + const AVRational64 orig[4] = { x[0], x[1], x[2], x[3] }; for (int i = 0; i < 4; i++) x[i] = orig[op->swizzle.in[i]]; return; } case SWS_OP_CONVERT: if (ff_sws_pixel_type_is_int(op->convert.to)) { - const AVRational scale = ff_sws_pixel_expand(op->type, op->convert.to); + const AVRational64 scale = ff_sws_pixel_expand(op->type, op->convert.to); for (int i = 0; i < 4; i++) { x[i] = x[i].den ? Q(x[i].num / x[i].den) : x[i]; if (op->convert.expand) - x[i] = av_mul_q(x[i], scale); + x[i] = av_mul_q64(x[i], scale); } } return; @@ -269,31 +269,31 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4]) av_assert1(!ff_sws_pixel_type_is_int(op->type)); for (int i = 0; i < 4; i++) { if (op->dither.y_offset[i] >= 0 && x[i].den) - x[i] = av_add_q(x[i], av_make_q(1, 2)); + x[i] = av_add_q64(x[i], av_make_q64(1, 2)); } return; case SWS_OP_MIN: for (int i = 0; i < 4; i++) - x[i] = av_min_q(x[i], op->clamp.limit[i]); + x[i] = av_min_q64(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->clamp.limit[i]); + x[i] = av_max_q64(x[i], op->clamp.limit[i]); return; case SWS_OP_LINEAR: { av_assert1(!ff_sws_pixel_type_is_int(op->type)); - const AVRational orig[4] = { x[0], x[1], x[2], x[3] }; + const AVRational64 orig[4] = { x[0], x[1], x[2], x[3] }; for (int i = 0; i < 4; i++) { - AVRational sum = op->lin.m[i][4]; + AVRational64 sum = op->lin.m[i][4]; for (int j = 0; j < 4; j++) - sum = av_add_q(sum, av_mul_q(orig[j], op->lin.m[i][j])); + sum = av_add_q64(sum, av_mul_q64(orig[j], op->lin.m[i][j])); x[i] = sum; } return; } case SWS_OP_SCALE: for (int i = 0; i < 4; i++) - x[i] = x[i].den ? av_mul_q(x[i], op->scale.factor) : x[i]; + x[i] = x[i].den ? av_mul_q64(x[i], op->scale.factor) : x[i]; return; case SWS_OP_FILTER_H: case SWS_OP_FILTER_V: @@ -323,18 +323,18 @@ static SwsCompFlags merge_comp_flags(SwsCompFlags a, SwsCompFlags b) static void apply_filter_weights(SwsComps *comps, const SwsComps *prev, const SwsFilterWeights *weights) { - const AVRational posw = { weights->sum_positive, SWS_FILTER_SCALE }; - const AVRational negw = { weights->sum_negative, SWS_FILTER_SCALE }; + 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; /* Only point sampling preserves exactness */ if (weights->filter_size != 1) comps->flags[i] &= ~SWS_COMP_EXACT; /* Update min/max assuming extremes */ - comps->min[i] = av_add_q(av_mul_q(prev->min[i], posw), - av_mul_q(prev->max[i], negw)); - comps->max[i] = av_add_q(av_mul_q(prev->min[i], negw), - av_mul_q(prev->max[i], posw)); + comps->min[i] = av_add_q64(av_mul_q64(prev->min[i], posw), + av_mul_q64(prev->max[i], negw)); + comps->max[i] = av_add_q64(av_mul_q64(prev->min[i], negw), + av_mul_q64(prev->max[i], posw)); } } @@ -418,7 +418,7 @@ void ff_sws_op_list_update_comps(SwsOpList *ops) break; case SWS_OP_MIN: case SWS_OP_MAX: { - AVRational *bound = op->op == SWS_OP_MIN ? op->comps.max : op->comps.min; + AVRational64 *bound = op->op == SWS_OP_MIN ? op->comps.max : op->comps.min; for (int i = 0; i < 4; i++) { op->comps.flags[i] = prev.flags[i]; if (op->clamp.limit[i].den) @@ -437,8 +437,8 @@ void ff_sws_op_list_update_comps(SwsOpList *ops) continue; /* Strip zero flag because of the nonzero dithering offset */ op->comps.flags[i] &= ~SWS_COMP_ZERO & SWS_COMP_DIRTY; - op->comps.min[i] = av_add_q(op->comps.min[i], op->dither.min); - op->comps.max[i] = av_add_q(op->comps.max[i], op->dither.max); + op->comps.min[i] = av_add_q64(op->comps.min[i], op->dither.min); + op->comps.max[i] = av_add_q64(op->comps.max[i], op->dither.max); } break; case SWS_OP_UNPACK: @@ -493,21 +493,21 @@ void ff_sws_op_list_update_comps(SwsOpList *ops) case SWS_OP_LINEAR: for (int i = 0; i < 4; i++) { SwsCompFlags flags = SWS_COMP_IDENTITY; - AVRational min = Q(0), max = Q(0); + AVRational64 min = Q(0), max = Q(0); bool first = true; for (int j = 0; j < 4; j++) { - const AVRational k = op->lin.m[i][j]; - AVRational mink = av_mul_q(prev.min[j], k); - AVRational maxk = av_mul_q(prev.max[j], k); + const AVRational64 k = op->lin.m[i][j]; + AVRational64 mink = av_mul_q64(prev.min[j], k); + AVRational64 maxk = av_mul_q64(prev.max[j], k); if (k.num) { flags = merge_comp_flags(flags, prev.flags[j]); if (k.den != 1) /* fractional coefficient */ flags &= ~SWS_COMP_EXACT; if (k.num < 0) - FFSWAP(AVRational, mink, maxk); - min = av_add_q(min, mink); - max = av_add_q(max, maxk); - if (!first || av_cmp_q(k, Q(1))) + FFSWAP(AVRational64, mink, maxk); + min = av_add_q64(min, mink); + max = av_add_q64(max, maxk); + if (!first || av_cmp_q64(k, Q(1))) flags &= SWS_COMP_DIRTY; first = false; } @@ -516,8 +516,8 @@ void ff_sws_op_list_update_comps(SwsOpList *ops) flags &= ~SWS_COMP_ZERO & SWS_COMP_DIRTY; if (op->lin.m[i][4].den != 1) /* fractional offset */ flags &= ~SWS_COMP_EXACT; - min = av_add_q(min, op->lin.m[i][4]); - max = av_add_q(max, op->lin.m[i][4]); + min = av_add_q64(min, op->lin.m[i][4]); + max = av_add_q64(max, op->lin.m[i][4]); } op->comps.flags[i] = flags; op->comps.min[i] = min; @@ -530,7 +530,7 @@ void ff_sws_op_list_update_comps(SwsOpList *ops) if (op->scale.factor.den != 1) /* fractional scale */ op->comps.flags[i] &= ~SWS_COMP_EXACT; if (op->scale.factor.num < 0) - FFSWAP(AVRational, op->comps.min[i], op->comps.max[i]); + FFSWAP(AVRational64, op->comps.min[i], op->comps.max[i]); } break; case SWS_OP_FILTER_H: @@ -787,7 +787,7 @@ uint32_t ff_sws_linear_mask(const SwsLinearOp *c) uint32_t mask = 0; for (int i = 0; i < 4; i++) { for (int j = 0; j < 5; j++) { - if (av_cmp_q(c->m[i][j], Q(i == j))) + if (av_cmp_q64(c->m[i][j], Q(i == j))) mask |= SWS_MASK(i, j); } } @@ -812,20 +812,20 @@ static char describe_comp_flags(SwsCompFlags flags) return '.'; } -static void print_q(AVBPrint *bp, const AVRational q) +static void print_q(AVBPrint *bp, const AVRational64 q) { if (!q.den) { av_bprintf(bp, "%s", q.num > 0 ? "inf" : q.num < 0 ? "-inf" : "nan"); } else if (q.den == 1) { - av_bprintf(bp, "%d", q.num); - } else if (abs(q.num) > 1000 || abs(q.den) > 1000) { - av_bprintf(bp, "%f", av_q2d(q)); + av_bprintf(bp, "%"PRId64, q.num); + } else if (q.num > 1000 || q.num < -1000 || q.den > 1000 || q.den < -1000) { + av_bprintf(bp, "%f", av_q2d_64(q)); } else { - av_bprintf(bp, "%d/%d", q.num, q.den); + av_bprintf(bp, "%"PRId64"/%"PRId64, q.num, q.den); } } -static void print_q4(AVBPrint *bp, const AVRational q4[4], SwsCompMask mask) +static void print_q4(AVBPrint *bp, const AVRational64 q4[4], SwsCompMask mask) { av_bprintf(bp, "{"); for (int i = 0; i < 4; i++) { @@ -922,9 +922,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->scale.factor.num); + av_bprintf(bp, "%-20s: * %"PRId64, name, op->scale.factor.num); if (op->scale.factor.den != 1) - av_bprintf(bp, "/%d", op->scale.factor.den); + av_bprintf(bp, "/%"PRId64, op->scale.factor.den); break; case SWS_OP_FILTER_H: case SWS_OP_FILTER_V: { diff --git a/libswscale/ops.h b/libswscale/ops.h index f2a57612b4..22ace4fef9 100644 --- a/libswscale/ops.h +++ b/libswscale/ops.h @@ -29,6 +29,7 @@ #include "graph.h" #include "filters.h" +#include "rational64.h" #include "uops.h" typedef enum SwsOpType { @@ -67,7 +68,7 @@ typedef enum SwsOpType { const char *ff_sws_op_type_name(SwsOpType op); /* Compute SwsCompMask from values with denominator != 0 */ -SwsCompMask ff_sws_comp_mask_q4(const AVRational q[4]); +SwsCompMask ff_sws_comp_mask_q4(const AVRational64 q[4]); typedef enum SwsCompFlags { SWS_COMP_GARBAGE = 1 << 0, /* contents are undefined / garbage data */ @@ -83,7 +84,7 @@ typedef struct SwsComps { /* Keeps track of the known possible value range, or {0, 0} for undefined * or (unknown range) floating point inputs */ - AVRational min[4], max[4]; + AVRational64 min[4], max[4]; } SwsComps; typedef enum SwsReadWriteMode { @@ -158,7 +159,7 @@ typedef struct SwsShiftOp { typedef struct SwsClearOp { SwsCompMask mask; /* mask of components to clear */ - AVRational value[4]; /* value to set */ + AVRational64 value[4]; /* value to set */ } SwsClearOp; typedef struct SwsConvertOp { @@ -167,16 +168,16 @@ typedef struct SwsConvertOp { } SwsConvertOp; typedef struct SwsClampOp { - AVRational limit[4]; /* per-component min/max value */ + AVRational64 limit[4]; /* per-component min/max value */ } SwsClampOp; typedef struct SwsScaleOp { - AVRational factor; /* scalar multiplication factor */ + AVRational64 factor; /* scalar multiplication factor */ } SwsScaleOp; typedef struct SwsDitherOp { - AVRational *matrix; /* tightly packed dither matrix (refstruct) */ - AVRational min, max; /* minimum/maximum value in `matrix` */ + AVRational64 *matrix; /* tightly packed dither matrix (refstruct) */ + AVRational64 min, max; /* minimum/maximum value in `matrix` */ int size_log2; /* size (in bits) of the dither matrix */ int8_t y_offset[4]; /* row offset for each component, or -1 for ignored */ } SwsDitherOp; @@ -194,7 +195,7 @@ typedef struct SwsLinearOp { * example the common subset of {A, E, G, J, M, O} can be implemented with * just three fused multiply-add operations. */ - AVRational m[4][5]; + AVRational64 m[4][5]; uint32_t mask; /* m[i][j] <-> 1 << (5 * i + j) */ } SwsLinearOp; @@ -254,9 +255,9 @@ void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op); void ff_sws_op_uninit(SwsOp *op); /** - * Apply an operation to an AVRational. No-op for read/write operations. + * Apply an operation to an AVRational64. No-op for read/write operations. */ -void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4]); +void ff_sws_apply_op_q(const SwsOp *op, AVRational64 x[4]); /** * Helper struct for representing a list of operations. diff --git a/libswscale/ops_chain.c b/libswscale/ops_chain.c index 02350bd6a2..40719e753f 100644 --- a/libswscale/ops_chain.c +++ b/libswscale/ops_chain.c @@ -63,7 +63,7 @@ int ff_sws_op_chain_append(SwsOpChain *chain, SwsFuncPtr func, int ff_sws_setup_scale(const SwsImplParams *params, SwsImplResult *out) { const SwsOp *op = params->op; - const AVRational factor = op->scale.factor; + const AVRational64 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; @@ -79,7 +79,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->clamp.limit[i]; + const AVRational64 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; @@ -96,7 +96,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->clear.value[i]; + const AVRational64 value = op->clear.value[i]; if (!value.den) continue; switch (op->type) { diff --git a/libswscale/ops_internal.h b/libswscale/ops_internal.h index 54c79ba67a..b85a72c928 100644 --- a/libswscale/ops_internal.h +++ b/libswscale/ops_internal.h @@ -26,9 +26,9 @@ #include "ops.h" #include "ops_dispatch.h" -#define Q(N) ((AVRational) { N, 1 }) +#define Q(N) ((AVRational64) { N, 1 }) -static inline AVRational ff_sws_pixel_expand(SwsPixelType from, SwsPixelType to) +static inline AVRational64 ff_sws_pixel_expand(SwsPixelType from, SwsPixelType to) { const int src = ff_sws_pixel_type_size(from); const int dst = ff_sws_pixel_type_size(to); diff --git a/libswscale/ops_optimizer.c b/libswscale/ops_optimizer.c index 8bf7f89e33..c38d4b278f 100644 --- a/libswscale/ops_optimizer.c +++ b/libswscale/ops_optimizer.c @@ -139,7 +139,7 @@ static bool op_commute_swizzle(SwsOp *op, SwsOp *next) if (!SWS_OP_NEEDED(op, i)) continue; const int j = op->swizzle.in[i]; - if (seen[j] && av_cmp_q(next->clamp.limit[j], c.limit[i])) + if (seen[j] && av_cmp_q64(next->clamp.limit[j], c.limit[i])) return false; next->clamp.limit[j] = c.limit[i]; seen[j] = true; @@ -229,7 +229,7 @@ static int exact_log2(const int x) return (1 << p) == x ? p : 0; } -static int exact_log2_q(const AVRational x) +static int exact_log2_q64(const AVRational64 x) { if (x.den == 1) return exact_log2(x.num); @@ -254,11 +254,11 @@ static bool extract_scalar(const SwsLinearOp *c, return false; for (int i = 0; i < 4; i++) { - const AVRational s = c->m[i][i]; + const AVRational64 s = c->m[i][i]; if ((prev->flags[i] & SWS_COMP_ZERO) || (comps->flags[i] & SWS_COMP_GARBAGE)) continue; - if (scale.factor.den && av_cmp_q(s, scale.factor)) + if (scale.factor.den && av_cmp_q64(s, scale.factor)) return false; scale.factor = s; } @@ -578,8 +578,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->scale.factor, - ff_sws_pixel_expand(op->type, op->convert.to))) + !av_cmp_q64(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); @@ -591,7 +591,7 @@ retry: for (int i = 0; i < 4; i++) { if (!SWS_OP_NEEDED(op, i) || !op->clamp.limit[i].den) continue; - if (av_cmp_q(op->clamp.limit[i], prev->comps.max[i]) < 0) + if (av_cmp_q64(op->clamp.limit[i], prev->comps.max[i]) < 0) noop = false; } @@ -605,7 +605,7 @@ retry: for (int i = 0; i < 4; i++) { if (!SWS_OP_NEEDED(op, i) || !op->clamp.limit[i].den) continue; - if (av_cmp_q(prev->comps.min[i], op->clamp.limit[i]) < 0) + if (av_cmp_q64(prev->comps.min[i], op->clamp.limit[i]) < 0) noop = false; } @@ -650,11 +650,11 @@ retry: const SwsLinearOp m2 = next->lin; for (int i = 0; i < 4; i++) { for (int j = 0; j < 5; j++) { - AVRational sum = Q(0); + AVRational64 sum = Q(0); for (int k = 0; k < 4; k++) - sum = av_add_q(sum, av_mul_q(m2.m[i][k], m1.m[k][j])); + sum = av_add_q64(sum, av_mul_q64(m2.m[i][k], m1.m[k][j])); if (j == 4) /* m1.m[4][j] == 1 */ - sum = av_add_q(sum, m2.m[i][4]); + sum = av_add_q64(sum, m2.m[i][4]); op->lin.m[i][j] = sum; } } @@ -716,7 +716,7 @@ retry: } case SWS_OP_SCALE: { - const int factor2 = exact_log2_q(op->scale.factor); + const int factor2 = exact_log2_q64(op->scale.factor); /* No-op scaling */ if (op->scale.factor.num == 1 && op->scale.factor.den == 1) { @@ -726,7 +726,7 @@ retry: /* Merge consecutive scaling operations */ if (next->op == SWS_OP_SCALE) { - op->scale.factor = av_mul_q(op->scale.factor, next->scale.factor); + op->scale.factor = av_mul_q64(op->scale.factor, next->scale.factor); ff_sws_op_list_remove_at(ops, n + 1, 1); goto retry; } diff --git a/libswscale/uops.c b/libswscale/uops.c index 98f1c8c2cf..4c37a65829 100644 --- a/libswscale/uops.c +++ b/libswscale/uops.c @@ -95,7 +95,7 @@ static const struct { [SWS_PIXEL_F32] = { "SWS_PIXEL_F32", "F32_" }, }; -static SwsPixel pixel_from_q(SwsPixelType type, AVRational val) +static SwsPixel pixel_from_q64(SwsPixelType type, AVRational64 val) { av_assert1(val.den != 0); switch (type) { @@ -111,7 +111,7 @@ static SwsPixel pixel_from_q(SwsPixelType type, AVRational val) return (SwsPixel) {0}; } -#define Q2PIXEL(val) pixel_from_q(op->type, val) +#define Q2PIXEL(val) pixel_from_q64(op->type, val) static bool pixel_is_1s(SwsPixelType type, SwsPixel val) { @@ -427,15 +427,15 @@ static bool exact_product_f32(float a, float b) static bool exact_prod(SwsPixelType type, SwsPixel coef, const SwsComps *comps, int idx) { - const AVRational minq = comps->min[idx]; - const AVRational maxq = comps->max[idx]; + 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) return false; /* unknown bounds */ - const SwsPixel min = pixel_from_q(type, minq); - const SwsPixel max = pixel_from_q(type, maxq); + const SwsPixel min = pixel_from_q64(type, minq); + const SwsPixel max = pixel_from_q64(type, maxq); switch (type) { case SWS_PIXEL_F32: return exact_product_f32(coef.f32, min.f32) && @@ -715,7 +715,7 @@ static int translate_linear_op(SwsContext *ctx, SwsUOpList *ops, uop.mask |= SWS_COMP(i); bool nonzero = (op->lin.m[i][4].num != 0); for (int j = 0; j < 5; j++) { - const AVRational k = op->lin.m[i][j]; + const AVRational64 k = op->lin.m[i][j]; const SwsPixel px = Q2PIXEL(k); uop.data.mat4[i][j] = px; if (k.num == 0) @@ -738,7 +738,7 @@ static int translate_linear_op(SwsContext *ctx, SwsUOpList *ops, return ff_sws_uop_list_append(ops, &uop); } -static bool is_expand_bit(SwsPixelType type, AVRational factor) +static bool is_expand_bit(SwsPixelType type, AVRational64 factor) { if (factor.den != 1) return false; @@ -821,7 +821,7 @@ static int translate_op(SwsContext *ctx, SwsUOpList *uops, SwsUOpFlags flags, for (int i = 0; i < 4; i++) { if (!SWS_COMP_TEST(op->clear.mask, i)) continue; - const AVRational v = op->clear.value[i]; + const AVRational64 v = op->clear.value[i]; const SwsPixel px = Q2PIXEL(op->clear.value[i]); uop.data.vec4[i] = px; if (v.num == 0) diff --git a/libswscale/vulkan/ops.c b/libswscale/vulkan/ops.c index 024f162d15..045f220745 100644 --- a/libswscale/vulkan/ops.c +++ b/libswscale/vulkan/ops.c @@ -237,7 +237,7 @@ static int create_dither_buf(FFVulkanOpsCtx *s, VulkanPriv *p, for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { - const AVRational r = dd->matrix[i*size + j]; + const AVRational64 r = dd->matrix[i*size + j]; dither_data[i*size + j] = r.num/(float)r.den; } } @@ -533,7 +533,7 @@ static void define_shader_consts(SwsContext *sws, const SwsOpList *ops, switch (op->op) { case SWS_OP_CONVERT: if (ff_sws_pixel_type_is_int(op->convert.to) && op->convert.expand) { - AVRational m = ff_sws_pixel_expand(op->type, op->convert.to); + AVRational64 m = ff_sws_pixel_expand(op->type, op->convert.to); int tmp = spi_OpConstantUInt(spi, id->u32_type, m.num); tmp = spi_OpConstantComposite(spi, id->u32vec4_type, tmp, tmp, tmp, tmp); @@ -544,7 +544,7 @@ static void define_shader_consts(SwsContext *sws, const SwsOpList *ops, for (int i = 0; i < 4; i++) { if (!SWS_COMP_TEST(op->clear.mask, i)) continue; - AVRational cv = op->clear.value[i]; + AVRational64 cv = op->clear.value[i]; if (op->type == SWS_PIXEL_F32) { float q = (float)cv.num/cv.den; id->const_ids[id->nb_const_ids++] = @@ -584,7 +584,7 @@ static void define_shader_consts(SwsContext *sws, const SwsOpList *ops, case SWS_OP_MAX: for (int i = 0; i < 4; i++) { int tmp; - AVRational cl = op->clamp.limit[i]; + AVRational64 cl = op->clamp.limit[i]; if (!op->clamp.limit[i].den) { continue; } else if (op->type == SWS_PIXEL_F32) { @@ -1312,7 +1312,7 @@ static void add_desc_read_write(FFVulkanDescriptorSetBinding *out_desc, *out_rep = op->type == SWS_PIXEL_F32 ? FF_VK_REP_FLOAT : FF_VK_REP_UINT; } -#define QSTR "(%i/%i%s)" +#define QSTR "(%"PRId64"/%"PRId64"%s)" #define QTYPE(Q) (Q).num, (Q).den, cur_type == SWS_PIXEL_F32 ? ".0f" : "" static void read_glsl(const SwsOpList *ops, const SwsOp *op, FFVulkanShader *shd, @@ -1546,8 +1546,8 @@ static int add_ops_glsl(SwsContext *sws, VulkanPriv *p, FFVulkanOpsCtx *s, break; case SWS_OP_CONVERT: if (ff_sws_pixel_type_is_int(cur_type) && op->convert.expand) { - const AVRational sc = ff_sws_pixel_expand(op->type, op->convert.to); - av_bprintf(&shd->src, " %s = %s((%s*%i)/%i);\n", + const AVRational64 sc = ff_sws_pixel_expand(op->type, op->convert.to); + av_bprintf(&shd->src, " %s = %s((%s*%"PRId64")/%"PRId64");\n", type_name, type_v, ff_sws_pixel_type_name(op->type), sc.num, sc.den); } else { diff --git a/tests/checkasm/sw_ops.c b/tests/checkasm/sw_ops.c index 40093009ac..d8b027b9d7 100644 --- a/tests/checkasm/sw_ops.c +++ b/tests/checkasm/sw_ops.c @@ -113,12 +113,12 @@ static void fill8(uint8_t *line, int num, unsigned range) } } -static void set_range(AVRational *rangeq, unsigned range, unsigned range_def) +static void set_range(AVRational64 *rangeq, unsigned range, unsigned range_def) { if (!range) range = range_def; - if (range && range <= INT_MAX) - *rangeq = (AVRational) { range, 1 }; + if (range) + *rangeq = (AVRational64) { range, 1 }; } static void check_compiled(const char *name, @@ -280,20 +280,20 @@ static void check_ops(const char *name, const unsigned ranges[NB_PLANES], switch (read_op->type) { case U8: set_range(&oplist.comps_src.max[p], ranges[p], UINT8_MAX); - oplist.comps_src.min[p] = (AVRational) { 0, 1 }; + oplist.comps_src.min[p] = (AVRational64) { 0, 1 }; break; case U16: set_range(&oplist.comps_src.max[p], ranges[p], UINT16_MAX); - oplist.comps_src.min[p] = (AVRational) { 0, 1 }; + oplist.comps_src.min[p] = (AVRational64) { 0, 1 }; break; case U32: set_range(&oplist.comps_src.max[p], ranges[p], UINT32_MAX); - oplist.comps_src.min[p] = (AVRational) { 0, 1 }; + oplist.comps_src.min[p] = (AVRational64) { 0, 1 }; break; case F32: if (ranges[p] && ranges[p] <= INT_MAX) { - oplist.comps_src.max[p] = (AVRational) { ranges[p], 1 }; - oplist.comps_src.min[p] = (AVRational) { 0, 1 }; + oplist.comps_src.max[p] = (AVRational64) { ranges[p], 1 }; + oplist.comps_src.min[p] = (AVRational64) { 0, 1 }; } break; } @@ -392,16 +392,16 @@ do { CHECK_RANGES(NAME, RANGES, 4, num, IN, OUT, __VA_ARGS__); \ } while (0) -static AVRational rndq(SwsPixelType t) +static AVRational64 rndq(SwsPixelType t) { const unsigned num = rnd(); if (ff_sws_pixel_type_is_int(t)) { const int bits = ff_sws_pixel_type_size(t) * 8; const unsigned mask = UINT_MAX >> (32 - bits); - return (AVRational) { num & mask, 1 }; + return (AVRational64) { num & mask, 1 }; } else { const unsigned den = rnd(); - return (AVRational) { num, den ? den : 1 }; + return (AVRational64) { num, den ? den : 1 }; } } @@ -541,7 +541,7 @@ static void check_cast(const char *name, const SwsUOp *uop) static void check_expand_bit(const char *name, const SwsUOp *uop) { - AVRational factor = { .den = 1 }; + AVRational64 factor = { .den = 1 }; switch (uop->type) { case SWS_PIXEL_U8: factor.num = UINT8_MAX; break; case SWS_PIXEL_U16: factor.num = UINT16_MAX; break; @@ -588,13 +588,13 @@ static void check_swizzle(const char *name, const SwsUOp *uop) static void check_scale(const char *name, const SwsUOp *uop) { unsigned range = 0; - AVRational scale; + AVRational64 scale; if (ff_sws_pixel_type_is_int(uop->type)) { /* Ensure the result won't exceed the value range */ const int bits = ff_sws_pixel_type_size(uop->type) * 8; const unsigned max = UINT32_MAX >> (32 - bits); - scale = (AVRational) { rnd() & (max >> 1), 1 }; + scale = (AVRational64) { rnd() & (max >> 1), 1 }; range = max / (scale.num ? scale.num : 1); } else { scale = rndq(uop->type); @@ -668,9 +668,9 @@ static void check_clear(const char *name, const SwsUOp *uop) const SwsPixelType type = uop->type; const int bits = ff_sws_pixel_type_size(type) * 8; const unsigned range = UINT32_MAX >> (32 - bits); - const AVRational one = (AVRational) { (int) range, 1}; - const AVRational zero = (AVRational) { 0, 1}; - const AVRational val = { (rand() & 0x7F) | 1, 1 }; + const AVRational64 one = (AVRational64) { (int) range, 1}; + const AVRational64 zero = (AVRational64) { 0, 1}; + const AVRational64 val = { (rand() & 0x7F) | 1, 1 }; SwsClearOp clear = { .mask = uop->mask }; for (int i = 0; i < 4; i++) { @@ -698,9 +698,9 @@ static void check_linear(const char *name, const SwsUOp *uop) for (int i = 0; i < 4; i++) { for (int j = 0; j < 5; j++) { if (uop->par.lin.one & SWS_MASK(i, j)) - lin.m[i][j] = (AVRational) { 1, 1 }; + lin.m[i][j] = (AVRational64) { 1, 1 }; else if (uop->par.lin.zero & SWS_MASK(i, j)) - lin.m[i][j] = (AVRational) { 0, 1 }; + lin.m[i][j] = (AVRational64) { 0, 1 }; else lin.m[i][j] = rndq(type); } diff --git a/tests/ref/fate/sws-ops-list b/tests/ref/fate/sws-ops-list index f0b27a6d16..6d60f02ec1 100644 --- a/tests/ref/fate/sws-ops-list +++ b/tests/ref/fate/sws-ops-list @@ -1 +1 @@ -cb589b85a77bc2b82a73de8a9bde9158 +53c637960d4d49e638a9ed8766266875 _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
