[FFmpeg-devel] [PATCH 3/5] NOT-FOR-GIT: avcodec/tests/rangecoder: ffv1 symbol read/write test

Michael Niedermayer michael at niedermayer.cc
Fri Jan 10 06:06:12 EET 2025


this is not for git, just for testing, unless someone wants to turn it
into a pretty test

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>
---
 libavcodec/tests/rangecoder.c | 152 +++++++++++++++++++++++++++++++++-
 1 file changed, 151 insertions(+), 1 deletion(-)

diff --git a/libavcodec/tests/rangecoder.c b/libavcodec/tests/rangecoder.c
index fd858535a5b..3555138db85 100644
--- a/libavcodec/tests/rangecoder.c
+++ b/libavcodec/tests/rangecoder.c
@@ -22,6 +22,7 @@
 #include "libavutil/error.h"
 #include "libavutil/lfg.h"
 #include "libavutil/log.h"
+#include "libavutil/common.h"
 
 #include "libavcodec/rangecoder.h"
 
@@ -53,13 +54,129 @@ static int rac_check_termination(RangeCoder *c, int version)
     return 0;
 }
 
+static av_always_inline av_flatten void put_symbol_inline(RangeCoder *c,
+                                                          uint8_t *state, int v,
+                                                          int is_signed,
+                                                          uint64_t rc_stat[256][2],
+                                                          uint64_t rc_stat2[32][2])
+{
+    int i;
+
+#define put_rac(C, S, B)                        \
+    do {                                        \
+        if (rc_stat) {                          \
+            rc_stat[*(S)][B]++;                 \
+            rc_stat2[(S) - state][B]++;         \
+        }                                       \
+        put_rac(C, S, B);                       \
+    } while (0)
+
+    if (v) {
+        const unsigned a = is_signed ? FFABS(v) : v;
+        const int e = av_log2(a);
+        put_rac(c, state + 0, 0);
+        if (e <= 9) {
+            for (i = 0; i < e; i++)
+                put_rac(c, state + 1 + i, 1);  // 1..10
+            put_rac(c, state + 1 + i, 0);
+
+            for (i = e - 1; i >= 0; i--)
+                put_rac(c, state + 22 + i, (a >> i) & 1);  // 22..31
+
+            if (is_signed)
+                put_rac(c, state + 11 + e, v < 0);  // 11..21
+        } else {
+            for (i = 0; i < e; i++)
+                put_rac(c, state + 1 + FFMIN(i, 9), 1);  // 1..10
+            put_rac(c, state + 1 + 9, 0);
+
+            for (i = e - 1; i >= 0; i--)
+                put_rac(c, state + 22 + FFMIN(i, 9), (a >> i) & 1);  // 22..31
+
+            if (is_signed)
+                put_rac(c, state + 11 + 10, v < 0);  // 11..21
+        }
+    } else {
+        put_rac(c, state + 0, 1);
+    }
+#undef put_rac
+}
+
+static inline av_flatten int get_symbol_inline(RangeCoder *c, uint8_t *state,
+                                               int is_signed)
+{
+    if (get_rac(c, state + 0))
+        return 0;
+    else {
+        int e;
+        unsigned a;
+        e = 0;
+        while (get_rac(c, state + 1 + FFMIN(e, 9))) { // 1..10
+            e++;
+            if (e > 31)
+                return AVERROR_INVALIDDATA;
+        }
+
+        a = 1;
+        for (int i = e - 1; i >= 0; i--)
+            a += a + get_rac(c, state + 22 + FFMIN(i, 9));  // 22..31
+
+        e = -(is_signed && get_rac(c, state + 11 + FFMIN(e, 10))); // 11..21
+        return (a ^ e) - e;
+    }
+}
+
 int main(void)
 {
     RangeCoder c;
     uint8_t b[9 * SIZE] = {0};
     uint8_t r[9 * SIZE];
+    int32_t sym[] = {
+        0,
+        1,
+        2,
+        3,
+        4,
+        5,
+        0x00000007, 0x00000008, 0x00000009,
+        0x0000000F, 0x00000010, 0x00000011,
+        0x0000001F, 0x00000020, 0x00000021,
+        0x0000003F, 0x00000040, 0x00000041,
+        0x0000007F, 0x00000080, 0x00000081,
+        0x000000FF, 0x00000100, 0x00000101,
+
+        0x000001FF, 0x00000200, 0x00000201,
+        0x000003FF, 0x00000400, 0x00000401,
+        0x000007FF, 0x00000800, 0x00000801,
+        0x00000FFF, 0x00001000, 0x00001001,
+        0x00001FFF, 0x00002000, 0x00002001,
+        0x00003FFF, 0x00004000, 0x00004001,
+        0x00007FFF, 0x00008000, 0x00008001,
+        0x0000FFFF, 0x00010000, 0x00010001,
+
+        0x0001FFFF, 0x00020000, 0x00020001,
+        0x0003FFFF, 0x00040000, 0x00040001,
+        0x0007FFFF, 0x00080000, 0x00080001,
+        0x000FFFFF, 0x00100000, 0x00100001,
+        0x001FFFFF, 0x00200000, 0x00200001,
+        0x003FFFFF, 0x00400000, 0x00400001,
+        0x007FFFFF, 0x00800000, 0x00800001,
+        0x00FFFFFF, 0x01000000, 0x01000001,
+
+        0x00FFFFFF, 0x01000000, 0x01000001,
+        0x01FFFFFF, 0x02000000, 0x02000001,
+        0x03FFFFFF, 0x04000000, 0x04000001,
+        0x07FFFFFF, 0x08000000, 0x08000001,
+        0x0FFFFFFF, 0x10000000, 0x10000001,
+
+        0x0FFFFFFF, 0x10000000, 0x10000001,
+        0x1FFFFFFF, 0x20000000, 0x20000001,
+        0x3FFFFFFF, 0x40000000, 0x40000001,
+        0x7FFFFFFF, 0x80000000, 0x80000001,
+        0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFD,
+    };
     int i, p, actual_length, version;
-    uint8_t state[10];
+    uint8_t state[100];
     AVLFG prng;
 
     av_lfg_init(&prng, 1);
@@ -76,6 +193,15 @@ int main(void)
             for (i = 0; i < SIZE; i++)
                 put_rac(&c, state, r[i] & 1);
 
+            for (i = 0; i<FF_ARRAY_ELEMS(sym); i++)
+                put_symbol_inline(&c,state,  sym[i], 1, NULL, NULL);
+
+            for (i = 0; i<FF_ARRAY_ELEMS(sym); i++)
+                put_symbol_inline(&c,state, -sym[i], 1, NULL, NULL);
+
+            for (i = 0; i<FF_ARRAY_ELEMS(sym); i++)
+                put_symbol_inline(&c,state, sym[i], 0, NULL, NULL);
+
             actual_length = ff_rac_terminate(&c, version);
 
             ff_init_range_decoder(&c, b, version ? SIZE : actual_length);
@@ -88,6 +214,30 @@ int main(void)
                     return 1;
                 }
 
+            for (i = 0; i<FF_ARRAY_ELEMS(sym); i++) {
+                int v = get_symbol_inline(&c, state, 1);
+                if (v != sym[i]) {
+                    av_log(NULL, AV_LOG_ERROR, "symbol S failure %X %X\n", v, sym[i]);
+                    return 1;
+                }
+            }
+
+            for (i = 0; i<FF_ARRAY_ELEMS(sym); i++) {
+                int v = -get_symbol_inline(&c, state, 1);
+                if (v != sym[i]) {
+                    av_log(NULL, AV_LOG_ERROR, "symbol -S failure %X %X\n", v, sym[i]);
+                    return 1;
+                }
+            }
+
+            for (i = 0; i<FF_ARRAY_ELEMS(sym); i++) {
+                int v = get_symbol_inline(&c, state, 0);
+                if (v != sym[i]) {
+                    av_log(NULL, AV_LOG_ERROR, "symbol U failure %X %X\n", v, sym[i]);
+                    return 1;
+                }
+            }
+
             if (rac_check_termination(&c, version) < 0) {
                 av_log(NULL, AV_LOG_ERROR, "rac failure at termination pass %d version %d\n", p, version);
                 return 1;
-- 
2.47.0



More information about the ffmpeg-devel mailing list