This is much faster than doing 1 bit and updating a state Signed-off-by: Michael Niedermayer <mich...@niedermayer.cc> --- libavcodec/rangecoder.h | 53 +++++++++++++++++++++++++++++++++++ libavcodec/tests/rangecoder.c | 13 +++++++++ 2 files changed, 66 insertions(+)
diff --git a/libavcodec/rangecoder.h b/libavcodec/rangecoder.h index da13c453edd..4cfdd2fdbe9 100644 --- a/libavcodec/rangecoder.h +++ b/libavcodec/rangecoder.h @@ -82,6 +82,28 @@ static inline void renorm_encoder(RangeCoder *c) c->range <<= 8; } +static inline void renorm_encoder_raw(RangeCoder *c, int extra) +{ + if (c->outstanding_byte < 0) { + c->outstanding_byte = c->low >> 8 + extra; + } else if (c->low <= 0xFF00 << extra) { + *c->bytestream++ = c->outstanding_byte; + for (; c->outstanding_count; c->outstanding_count--) + *c->bytestream++ = 0xFF; + c->outstanding_byte = c->low >> 8 + extra; + } else if (c->low >= 0x10000 << extra) { + *c->bytestream++ = c->outstanding_byte + 1; + for (; c->outstanding_count; c->outstanding_count--) + *c->bytestream++ = 0x00; + c->outstanding_byte = (c->low >> 8 + extra) & 0xFF; + } else { + c->outstanding_count++; + } + + c->low = (c->low & ((1 << 8 + extra) - 1)) << 8 - extra; + c->range <<= 8 - extra; +} + static inline int get_rac_count(RangeCoder *c) { int x = c->bytestream - c->bytestream_start + c->outstanding_count; @@ -110,6 +132,21 @@ 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; + av_assert2(len <= 8); + av_assert2(bits >> len == 0); + + if (r < 0x100) { + c->low = (c->low << len) + c->range * bits; + renorm_encoder_raw(c, len); + } else { + c->low += r * bits; + c->range = r; + } +} + static inline void refill(RangeCoder *c) { c->range <<= 8; @@ -141,4 +178,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".