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]

Reply via email to