[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