This is much faster than doing 1 bit and updating a state Signed-off-by: Michael Niedermayer <mich...@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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".