[FFmpeg-devel] [PATCH 6/7] get_bits: change refill to RAD pattern
Christophe Gisquet
christophe.gisquet at gmail.com
Tue Apr 14 13:25:02 EEST 2020
Described as variant 4 in the linked article.
Results in faster and smaller code. Also, cases for the "refill_all" cases
(usually when we want to empty/fill it) have been inlined.
---
libavcodec/get_bits.h | 103 +++++++++++++++++-------------------------
1 file changed, 41 insertions(+), 62 deletions(-)
diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h
index da054ebfcb..baff86ecf6 100644
--- a/libavcodec/get_bits.h
+++ b/libavcodec/get_bits.h
@@ -153,11 +153,7 @@ static inline unsigned int show_bits(GetBitContext *s, int n);
*/
#if CACHED_BITSTREAM_READER
-# if BITSTREAM_BITS == 32
-# define MIN_CACHE_BITS (32-7)
-# else
-# define MIN_CACHE_BITS 32
-# endif
+# define MIN_CACHE_BITS (BITSTREAM_BITS-7)
#elif defined LONG_BITSTREAM_READER
# define MIN_CACHE_BITS 32
#else
@@ -262,46 +258,21 @@ static inline int get_bits_count(const GetBitContext *s)
}
#if CACHED_BITSTREAM_READER
-static inline void refill_half(GetBitContext *s, int is_le)
+// See variant 4 in the following article:
+// https://fgiesen.wordpress.com/2018/02/20/reading-bits-in-far-too-many-ways-part-2/
+static inline void refill_gb(GetBitContext *s, int is_le)
{
#if !UNCHECKED_BITSTREAM_READER
if (s->ptr >= s->buffer_end)
return;
#endif
-#if BITSTREAM_BITS == 32
- if (s->bits_left > 16) {
- if (is_le)
- s->cache |= (uint32_t)s->ptr[0] << s->bits_left;
- else
- s->cache |= (uint32_t)s->ptr[0] << (32 - s->bits_left);
- s->ptr++;
- s->bits_left += 8;
- return;
- }
-#endif
-
if (is_le)
- s->cache |= (cache_type)AV_RL_HALF(s->ptr) << s->bits_left;
+ s->cache |= (cache_type)AV_RL_ALL(s->ptr) << s->bits_left;
else
- s->cache |= (cache_type)AV_RB_HALF(s->ptr) << (BITSTREAM_HBITS - s->bits_left);
- s->ptr += sizeof(s->cache)/2;
- s->bits_left += BITSTREAM_HBITS;
-}
-
-static inline void refill_all(GetBitContext *s, int is_le)
-{
-#if !UNCHECKED_BITSTREAM_READER
- if (s->ptr >= s->buffer_end)
- return;
-#endif
-
- if (is_le)
- s->cache = AV_RL_ALL(s->ptr);
- else
- s->cache = AV_RB_ALL(s->ptr);
- s->ptr += sizeof(s->cache);
- s->bits_left = BITSTREAM_BITS;
+ s->cache |= (cache_type)AV_RB_ALL(s->ptr) >> s->bits_left;
+ s->ptr += (BITSTREAM_BITS-1 - s->bits_left) >> 3;
+ s->bits_left |= BITSTREAM_BITS-8;
}
static inline cache_type get_val(GetBitContext *s, unsigned n, int is_le)
@@ -374,9 +345,9 @@ static inline int get_xbits(GetBitContext *s, int n)
if (n > s->bits_left)
#ifdef BITSTREAM_READER_LE
- refill_half(s, 1);
+ refill_gb(s, 1);
#else
- refill_half(s, 0);
+ refill_gb(s, 0);
#endif
#if BITSTREAM_BITS == 32
@@ -448,9 +419,9 @@ static inline unsigned int get_bits(GetBitContext *s, int n)
av_assert2(n>0 && n<=32);
if (n > s->bits_left) {
#ifdef BITSTREAM_READER_LE
- refill_half(s, 1);
+ refill_gb(s, 1);
#else
- refill_half(s, 0);
+ refill_gb(s, 0);
#endif
if (s->bits_left < BITSTREAM_HBITS)
s->bits_left = n;
@@ -486,7 +457,7 @@ static inline unsigned int get_bits_le(GetBitContext *s, int n)
#if CACHED_BITSTREAM_READER
av_assert2(n>0 && n<=32);
if (n > s->bits_left) {
- refill_half(s, 1);
+ refill_gb(s, 1);
if (s->bits_left < BITSTREAM_HBITS)
s->bits_left = n;
}
@@ -513,9 +484,9 @@ static inline unsigned int show_bits(GetBitContext *s, int n)
#if CACHED_BITSTREAM_READER
if (n > s->bits_left)
#ifdef BITSTREAM_READER_LE
- refill_half(s, 1);
+ refill_gb(s, 1);
#else
- refill_half(s, 0);
+ refill_gb(s, 0);
#endif
tmp = show_val(s, n);
@@ -535,7 +506,6 @@ static inline void skip_bits(GetBitContext *s, int n)
skip_remaining(s, n);
else {
n -= s->bits_left;
- s->cache = 0;
if (n >= BITSTREAM_BITS) {
unsigned skip = n / 8;
@@ -543,11 +513,14 @@ static inline void skip_bits(GetBitContext *s, int n)
n -= 8*skip;
s->ptr += skip;
}
+
#ifdef BITSTREAM_READER_LE
- refill_all(s, 1);
+ s->cache = AV_RL_ALL(s->ptr);
#else
- refill_all(s, 0);
+ s->cache = AV_RB_ALL(s->ptr);
#endif
+ s->ptr += sizeof(cache_type);
+ s->bits_left = BITSTREAM_BITS;
if (n)
skip_remaining(s, n);
}
@@ -561,12 +534,15 @@ static inline void skip_bits(GetBitContext *s, int n)
static inline unsigned int get_bits1(GetBitContext *s)
{
#if CACHED_BITSTREAM_READER
- if (!s->bits_left)
+ if (!s->bits_left) {
#ifdef BITSTREAM_READER_LE
- refill_all(s, 1);
+ s->cache = AV_RL_ALL(s->ptr);
#else
- refill_all(s, 0);
+ s->cache = AV_RB_ALL(s->ptr);
#endif
+ s->ptr += sizeof(cache_type);
+ s->bits_left = BITSTREAM_BITS;
+ }
#ifdef BITSTREAM_READER_LE
return get_val(s, 1, 1);
@@ -621,20 +597,21 @@ static inline unsigned int get_bits_long(GetBitContext *s, int n)
if (n > s->bits_left) {
n -= s->bits_left;
# ifdef BITSTREAM_READER_LE
- left = s->bits_left;
- ret = get_val(s, s->bits_left, 1);
- refill_all(s, 1);
+ ret = s->cache & ((CACHE_TYPE(1) << s->bits_left) - 1);
+ s->cache = AV_RL_ALL(s->ptr);
# else
- ret = get_val(s, s->bits_left, 0);
- refill_all(s, 0);
+ ret = s->cache >> (BITSTREAM_BITS - s->bits_left);
+ s->cache = AV_RB_ALL(s->ptr);
# endif
+ s->ptr += sizeof(cache_type);
+ s->bits_left = BITSTREAM_BITS; // OK because consumed right after
}
-#ifdef BITSTREAM_READER_LE
+# ifdef BITSTREAM_READER_LE
ret = get_val(s, n, 1) << left | ret;
-#else
+# else
ret = get_val(s, n, 0) | ret << n;
-#endif
+# endif
return ret;
#else
@@ -725,10 +702,12 @@ static inline int init_get_bits_xe(GetBitContext *s, const uint8_t *buffer,
s->buffer_end = buffer + buffer_size;
#if CACHED_BITSTREAM_READER
- s->ptr = buffer;
- s->cache = 0;
- s->bits_left = 0;
- refill_all(s, is_le);
+ if (is_le)
+ s->cache = AV_RL_ALL(buffer);
+ else
+ s->cache = AV_RB_ALL(buffer);
+ s->ptr = buffer+sizeof(cache_type);
+ s->bits_left = BITSTREAM_BITS;
#else
s->index = 0;
#endif
--
2.26.0
More information about the ffmpeg-devel
mailing list