PR #24799 opened by Kacper Michajłow (kasper93) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24799 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24799.patch
From b6e295467dbcd7927278850610e30de7f65d7b6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]> Date: Wed, 30 Sep 2026 00:10:42 +0200 Subject: [PATCH 1/4] avutil/rational: fix the sign handling in av_q2intfloat() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sign was shifted into bit 31 of an int and INT_MIN was negated as an int, both undefined. Negate in int64_t and keep the sign as the bit itself. A negative value over zero now gives a negative infinity, the sign of an infinity was read from the numerator after it had been made positive. Signed-off-by: Kacper Michajłow <[email protected]> --- libavutil/rational.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/libavutil/rational.c b/libavutil/rational.c index fdb1da7f48..d2a92fdda8 100644 --- a/libavutil/rational.c +++ b/libavutil/rational.c @@ -152,37 +152,37 @@ int av_find_nearest_q_idx(AVRational q, const AVRational* q_list) } uint32_t av_q2intfloat(AVRational q) { - int64_t n; + int64_t n, num = q.num, den = q.den; int shift; - int sign = 0; + uint32_t sign = 0; - if (q.den < 0) { - q.den *= -1; - q.num *= -1; + if (den < 0) { + den = -den; + num = -num; } - if (q.num < 0) { - q.num *= -1; - sign = 1; + if (num < 0) { + num = -num; + sign = 1U << 31; } - if (!q.num && !q.den) return 0xFFC00000; - if (!q.num) return 0; - if (!q.den) return 0x7F800000 | (q.num & 0x80000000); + if (!num && !den) return 0xFFC00000; + if (!num) return 0; + if (!den) return sign | 0x7F800000; - shift = 23 + av_log2(q.den) - av_log2(q.num); - if (shift >= 0) n = av_rescale(q.num, 1LL<<shift, q.den); - else n = av_rescale(q.num, 1, ((int64_t)q.den) << -shift); + shift = 23 + av_log2(den) - av_log2(num); + if (shift >= 0) n = av_rescale(num, 1LL<<shift, den); + else n = av_rescale(num, 1, den << -shift); shift -= n >= (1<<24); shift += n < (1<<23); - if (shift >= 0) n = av_rescale(q.num, 1LL<<shift, q.den); - else n = av_rescale(q.num, 1, ((int64_t)q.den) << -shift); + if (shift >= 0) n = av_rescale(num, 1LL<<shift, den); + else n = av_rescale(num, 1, den << -shift); av_assert1(n < (1<<24)); av_assert1(n >= (1<<23)); - return sign<<31 | (150-shift)<<23 | (n - (1<<23)); + return sign | (150-shift)<<23 | (n - (1<<23)); } AVRational av_gcd_q(AVRational a, AVRational b, int max_den, AVRational def) -- 2.52.0 From c795e02b59ad7658e3231725f993bdd920cb4491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]> Date: Wed, 30 Sep 2026 00:10:42 +0200 Subject: [PATCH 2/4] avutil/tests/rational: fix the av_q2intfloat() checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The denominator loop multiplied an int past INT_MAX after 3^19, step it in int64_t over the same values. Compare infinities and NaNs exactly, the relative tolerance accepted an infinity of either sign, and check INT_MIN and zero denominators. Signed-off-by: Kacper Michajłow <[email protected]> --- libavutil/tests/rational.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/libavutil/tests/rational.c b/libavutil/tests/rational.c index 13090c11d5..dabedd8a0b 100644 --- a/libavutil/tests/rational.c +++ b/libavutil/tests/rational.c @@ -23,6 +23,23 @@ #include "libavutil/integer.h" #include "libavutil/intfloat.h" +static int check_q2intfloat(AVRational q) +{ + float f = av_int2float(av_q2intfloat(q)); + float f2 = av_q2d(q); + int fail; + + if (isnan(f) || isnan(f2)) + fail = !isnan(f) || !isnan(f2); + else if (isinf(f) || isinf(f2)) + fail = f != f2; + else + fail = fabs(f - f2) > fabs(f)/5000000; + if (fail) + av_log(NULL, AV_LOG_ERROR, "%d/%d %f %f\n", q.num, q.den, f, f2); + return fail; +} + int main(void) { AVRational a,b,r; @@ -179,18 +196,22 @@ int main(void) } } - for (a.den = 1; a.den < 0x100000000U/3; a.den*=3) { + for (int64_t den = 1; den <= INT_MAX; den *= 3) { + a.den = den; for (a.num = -1; a.num < (1<<27); a.num += 1 + a.num/100) { - float f = av_int2float(av_q2intfloat(a)); - float f2 = av_q2d(a); - if (fabs(f - f2) > fabs(f)/5000000) { - av_log(NULL, AV_LOG_ERROR, "%d/%d %f %f\n", a.num, - a.den, f, f2); + if (check_q2intfloat(a)) return 1; - } - } } + static const AVRational q2intfloat_list[] = { + {INT_MIN, 1}, {1, INT_MIN}, {INT_MIN, INT_MIN}, {INT_MIN, -1}, {-1, INT_MIN}, + {INT_MAX, INT_MIN}, {INT_MIN, INT_MAX}, {-3, -7}, {3, -7}, + {1, 0}, {-1, 0}, {INT_MIN, 0}, {0, 0}, {0, 1}, {0, INT_MIN}, + }; + + for (i = 0; i < FF_ARRAY_ELEMS(q2intfloat_list); i++) + ret |= check_q2intfloat(q2intfloat_list[i]); + return ret; } -- 2.52.0 From bf03855e0bf22920dffc84adfac338c84010eac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]> Date: Wed, 30 Sep 2026 00:10:42 +0200 Subject: [PATCH 3/4] swresample: skip the rematrix stage when there are no samples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When resampling first, a call that produced no output passed midbuf to swri_rematrix() before it was ever allocated, and copied channels did a memcpy() of zero bytes from NULL. Skip rematrixing zero samples, as the output conversion already does. Signed-off-by: Kacper Michajłow <[email protected]> --- libswresample/swresample.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libswresample/swresample.c b/libswresample/swresample.c index cd84c731d9..52ad73836e 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -680,10 +680,10 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co if(postin != midbuf) if ((out_count = resample(s, midbuf, out_count, postin, in_count)) < 0) return out_count; - if(midbuf != preout) + if(midbuf != preout && out_count) swri_rematrix(s, preout, midbuf, out_count, preout==out); }else{ - if(postin != midbuf) + if(postin != midbuf && in_count) swri_rematrix(s, midbuf, postin, in_count, midbuf==out); if(midbuf != preout) if ((out_count = resample(s, preout, out_count, midbuf, in_count)) < 0) -- 2.52.0 From 7903784007b8eef99330f6200ca07f8e63e6a108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]> Date: Wed, 30 Sep 2026 00:10:42 +0200 Subject: [PATCH 4/4] avutil/tests/softfloat: only run the timers with -t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit START_TIMER reads the PMU cycle counter on aarch64 and ARMv7 Linux, which user space usually cannot access, and the test died with SIGILL there. Time the add and mul loops only when -t is given, like the other lavu tests do, and otherwise compute only the last iteration, the one that is printed. Signed-off-by: Kacper Michajłow <[email protected]> --- libavutil/tests/softfloat.c | 53 +++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/libavutil/tests/softfloat.c b/libavutil/tests/softfloat.c index a2e628fe81..2ec313f1cf 100644 --- a/libavutil/tests/softfloat.c +++ b/libavutil/tests/softfloat.c @@ -27,17 +27,38 @@ #include "libavutil/log.h" #include <stdio.h> +#include <string.h> static const SoftFloat FLOAT_0_017776489257 = {0x1234, 12}; static const SoftFloat FLOAT_1374_40625 = {0xabcd, 25}; static const SoftFloat FLOAT_0_1249694824218 = {0xFFF, 15}; +static double add_mul(int i) +{ + double d1 = i, d2 = i/100.0; -int main(void){ + for (int j = 0; j < 1000; j++) + d1 = (d1+1)*d2; + return d1; +} + +static SoftFloat add_mul_sf(int i) +{ + SoftFloat one = av_int2sf(1, 0); + SoftFloat sf1 = av_int2sf(i, 0); + SoftFloat sf2 = av_div_sf(av_int2sf(i, 2), av_int2sf(200, 3)); + + for (int j = 0; j < 1000; j++) + sf1 = av_mul_sf(av_add_sf(sf1, one), sf2); + return sf1; +} + +int main(int argc, char **argv){ SoftFloat one= av_int2sf(1, 0); SoftFloat sf1, sf2, sf3; double d1, d2, d3; int i, j; + int bench = argc > 1 && !strcmp(argv[1], "-t"); av_log_set_level(AV_LOG_DEBUG); d1= 1; @@ -53,26 +74,24 @@ int main(void){ printf("test1 sf =%d\n", av_sf2int(sf1, 24)); - for(i= 0; i<100; i++){ - START_TIMER - d1= i; - d2= i/100.0; - for(j= 0; j<1000; j++){ - d1= (d1+1)*d2; + if (bench) { + for(i= 0; i<100; i++){ + START_TIMER + d1= add_mul(i); + STOP_TIMER("float add mul") } - STOP_TIMER("float add mul") - } + } else + d1= add_mul(99); printf("test2 double=%d\n", (int)(d1 * (1<<24))); - for(i= 0; i<100; i++){ - START_TIMER - sf1= av_int2sf(i, 0); - sf2= av_div_sf(av_int2sf(i, 2), av_int2sf(200, 3)); - for(j= 0; j<1000; j++){ - sf1= av_mul_sf(av_add_sf(sf1, one),sf2); + if (bench) { + for(i= 0; i<100; i++){ + START_TIMER + sf1= add_mul_sf(i); + STOP_TIMER("softfloat add mul") } - STOP_TIMER("softfloat add mul") - } + } else + sf1= add_mul_sf(99); printf("test2 sf =%d (%d %d)\n", av_sf2int(sf1, 24), sf1.exp, sf1.mant); d1 = 0.0177764893; -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
