[FFmpeg-devel] [PATCH 7/8] avcodec/rangecoder: Implement reading and writing upto 8 bits raw
Michael Niedermayer
michael at niedermayer.cc
Wed Oct 16 22:49:54 EEST 2024
This is much faster than doing 1 bit and updating a state
Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>
---
libavcodec/rangecoder.h | 46 +++++++++++++++++++++++++++++++++++
libavcodec/tests/rangecoder.c | 13 ++++++++++
2 files changed, 59 insertions(+)
diff --git a/libavcodec/rangecoder.h b/libavcodec/rangecoder.h
index 15217a99a3c..39eb5987ca8 100644
--- a/libavcodec/rangecoder.h
+++ b/libavcodec/rangecoder.h
@@ -76,6 +76,22 @@ static inline void renorm_encoder(RangeCoder *c)
c->range <<= 8;
}
+static inline void renorm_encoder_raw(RangeCoder *c)
+{
+ if (c->low - 0xFF0001 >= 0x1000000 - 0xFF0001U) {
+ int mask = c->low - 0xFF0001 >> 31;
+ *c->bytestream = c->outstanding_byte + 1 + mask;
+ c->bytestream += c->outstanding_byte >= 0;
+ for (; c->outstanding_count; c->outstanding_count--)
+ *c->bytestream++ = mask;
+ c->outstanding_byte = c->low >> 16;
+ } else {
+ c->outstanding_count++;
+ }
+
+ c->low &= 0xFFFF;
+}
+
static inline int get_rac_count(RangeCoder *c)
{
int x = c->bytestream - c->bytestream_start + c->outstanding_count;
@@ -104,6 +120,20 @@ static inline void put_rac(RangeCoder *c, uint8_t *const state, int bit)
renorm_encoder(c);
}
+static inline void put_rac_raw(RangeCoder *c, int bits, int len)
+{
+ int r = c->range >> len;
+
+ if (r < 0x100) {
+ c->range <<= 8 - len;
+ c->low = (c->low << 8) + c->range * bits;
+ renorm_encoder_raw(c);
+ } else {
+ c->low += r * bits;
+ c->range = r;
+ }
+}
+
static inline void refill(RangeCoder *c)
{
c->range <<= 8;
@@ -135,4 +165,20 @@ static inline int get_rac(RangeCoder *c, uint8_t *const state)
}
}
+static inline int get_rac_raw(RangeCoder *c, int len)
+{
+ int bits;
+ int r = c->range >> len;
+ av_assert2(len <= 8);
+
+ if (r < 0x100) {
+ refill(c);
+ r = c->range >> len;
+ }
+ bits = c->low / r;
+ c->low -= r * bits;
+ c->range = r;
+ return bits;
+}
+
#endif /* AVCODEC_RANGECODER_H */
diff --git a/libavcodec/tests/rangecoder.c b/libavcodec/tests/rangecoder.c
index fd858535a5b..7634953585d 100644
--- a/libavcodec/tests/rangecoder.c
+++ b/libavcodec/tests/rangecoder.c
@@ -76,6 +76,11 @@ int main(void)
for (i = 0; i < SIZE; i++)
put_rac(&c, state, r[i] & 1);
+ for (i = 0; i < SIZE; i++) {
+ int len = r[i++] % 7 + 1;
+ put_rac_raw(&c, r[i]&((1<<len) - 1), len);
+ }
+
actual_length = ff_rac_terminate(&c, version);
ff_init_range_decoder(&c, b, version ? SIZE : actual_length);
@@ -87,6 +92,14 @@ int main(void)
av_log(NULL, AV_LOG_ERROR, "rac failure at %d pass %d version %d\n", i, p, version);
return 1;
}
+ for (i = 0; i < SIZE; i++) {
+ int len = r[i++] % 7 + 1;
+ int mask = (1<<len) - 1;
+ if ((r[i] & mask) != get_rac_raw(&c, len)) {
+ av_log(NULL, AV_LOG_ERROR, "rac raw failure at %d pass %d version %d\n", i, p, version);
+ 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);
--
2.47.0
More information about the ffmpeg-devel
mailing list