[FFmpeg-devel] [PATCH 2/7] get_bits: support 32bits cache

Christophe Gisquet christophe.gisquet at gmail.com
Tue Apr 14 13:24:58 EEST 2020


Therefore, also activate it under ARCH_X86 (testing for more archs welcome)
for the only codecs supporting said cache reader.
For UTVideo, on 8 bits samples and ARCH_X86_32 (X86_64 being unaffected),
timings for one line do ~19.4k -> 15.1k and 16.5k (roughly 17% speedup).
---
 libavcodec/get_bits.h   | 110 ++++++++++++++++++++++++++++------------
 libavcodec/mvha.c       |   2 +-
 libavcodec/utvideodec.c |   2 +-
 3 files changed, 80 insertions(+), 34 deletions(-)

diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h
index 66fb877599..cb4df98e54 100644
--- a/libavcodec/get_bits.h
+++ b/libavcodec/get_bits.h
@@ -58,10 +58,40 @@
 #define CACHED_BITSTREAM_READER 0
 #endif
 
+#if CACHED_BITSTREAM_READER
+
+# ifndef BITSTREAM_BITS
+#   if HAVE_FAST_64BIT || defined(LONG_BITSTREAM_READER)
+#     define BITSTREAM_BITS   64
+#   else
+#     define BITSTREAM_BITS   32
+#   endif
+# endif
+
+# if BITSTREAM_BITS == 64
+#   define BITSTREAM_HBITS  32
+typedef uint64_t cache_type;
+#   define AV_RB_ALL  AV_RB64
+#   define AV_RL_ALL  AV_RL64
+#   define AV_RB_HALF AV_RB32
+#   define AV_RL_HALF AV_RL32
+#   define CACHE_TYPE(a) UINT64_C(a)
+# else
+#   define BITSTREAM_HBITS  16
+typedef uint32_t cache_type;
+#   define AV_RB_ALL  AV_RB32
+#   define AV_RL_ALL  AV_RL32
+#   define AV_RB_HALF AV_RB16
+#   define AV_RL_HALF AV_RL16
+#   define CACHE_TYPE(a) UINT32_C(a)
+#endif
+
+#endif
+
 typedef struct GetBitContext {
     const uint8_t *buffer, *buffer_end;
 #if CACHED_BITSTREAM_READER
-    uint64_t cache;
+    cache_type cache;
     unsigned bits_left;
 #endif
     int index;
@@ -121,7 +151,11 @@ static inline unsigned int show_bits(GetBitContext *s, int n);
  */
 
 #if CACHED_BITSTREAM_READER
-#   define MIN_CACHE_BITS 64
+# if BITSTREAM_BITS == 32
+#   define MIN_CACHE_BITS (32-7)
+# else
+#   define MIN_CACHE_BITS  32
+# endif
 #elif defined LONG_BITSTREAM_READER
 #   define MIN_CACHE_BITS 32
 #else
@@ -226,22 +260,34 @@ static inline int get_bits_count(const GetBitContext *s)
 }
 
 #if CACHED_BITSTREAM_READER
-static inline void refill_32(GetBitContext *s, int is_le)
+static inline void refill_half(GetBitContext *s, int is_le)
 {
 #if !UNCHECKED_BITSTREAM_READER
     if (s->index >> 3 >= s->buffer_end - s->buffer)
         return;
 #endif
 
+#if BITSTREAM_BITS == 32
+    if (s->bits_left > 16) {
+        if (is_le)
+        s->cache |= (uint32_t)s->buffer[s->index >> 3] << s->bits_left;
+        else
+        s->cache |= (uint32_t)s->buffer[s->index >> 3] << (32 - s->bits_left);
+        s->index += 8;
+        s->bits_left += 8;
+        return;
+    }
+#endif
+
     if (is_le)
-        s->cache = (uint64_t)AV_RL32(s->buffer + (s->index >> 3)) << s->bits_left | s->cache;
+        s->cache |= (cache_type)AV_RL_HALF(s->buffer + (s->index >> 3)) << s->bits_left;
     else
-        s->cache = s->cache | (uint64_t)AV_RB32(s->buffer + (s->index >> 3)) << (32 - s->bits_left);
-    s->index     += 32;
-    s->bits_left += 32;
+        s->cache |= (cache_type)AV_RB_HALF(s->buffer + (s->index >> 3)) << (BITSTREAM_HBITS - s->bits_left);
+    s->index     += BITSTREAM_HBITS;
+    s->bits_left += BITSTREAM_HBITS;
 }
 
-static inline void refill_64(GetBitContext *s, int is_le)
+static inline void refill_all(GetBitContext *s, int is_le)
 {
 #if !UNCHECKED_BITSTREAM_READER
     if (s->index >> 3 >= s->buffer_end - s->buffer)
@@ -249,22 +295,22 @@ static inline void refill_64(GetBitContext *s, int is_le)
 #endif
 
     if (is_le)
-        s->cache = AV_RL64(s->buffer + (s->index >> 3));
+        s->cache = AV_RL_ALL(s->buffer + (s->index >> 3));
     else
-        s->cache = AV_RB64(s->buffer + (s->index >> 3));
-    s->index += 64;
-    s->bits_left = 64;
+        s->cache = AV_RB_ALL(s->buffer + (s->index >> 3));
+    s->index += BITSTREAM_BITS;
+    s->bits_left = BITSTREAM_BITS;
 }
 
-static inline uint64_t get_val(GetBitContext *s, unsigned n, int is_le)
+static inline cache_type get_val(GetBitContext *s, unsigned n, int is_le)
 {
-    uint64_t ret;
+    cache_type ret;
     av_assert2(n>0 && n<=63);
     if (is_le) {
-        ret = s->cache & ((UINT64_C(1) << n) - 1);
+        ret = s->cache & ((CACHE_TYPE(1) << n) - 1);
         s->cache >>= n;
     } else {
-        ret = s->cache >> (64 - n);
+        ret = s->cache >> (BITSTREAM_BITS - n);
         s->cache <<= n;
     }
     s->bits_left -= n;
@@ -274,12 +320,12 @@ static inline uint64_t get_val(GetBitContext *s, unsigned n, int is_le)
 static inline unsigned show_val(const GetBitContext *s, unsigned n)
 {
 #ifdef BITSTREAM_READER_LE
-    return s->cache & ((UINT64_C(1) << n) - 1);
+    return s->cache & ((CACHE_TYPE(1) << n) - 1);
 #else
-    return s->cache >> (64 - n);
+    return s->cache >> (BITSTREAM_BITS - n);
 #endif
 }
-#endif
+#endif // ~CACHED_BITSTREAM_READER
 
 /**
  * Skips the specified number of bits.
@@ -384,11 +430,11 @@ 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_32(s, 1);
+        refill_half(s, 1);
 #else
-        refill_32(s, 0);
+        refill_half(s, 0);
 #endif
-        if (s->bits_left < 32)
+        if (s->bits_left < BITSTREAM_HBITS)
             s->bits_left = n;
     }
 
@@ -422,8 +468,8 @@ 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_32(s, 1);
-        if (s->bits_left < 32)
+        refill_half(s, 1);
+        if (s->bits_left < BITSTREAM_HBITS)
             s->bits_left = n;
     }
 
@@ -449,9 +495,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_32(s, 1);
+        refill_half(s, 1);
 #else
-        refill_32(s, 0);
+        refill_half(s, 0);
 #endif
 
     tmp = show_val(s, n);
@@ -474,16 +520,16 @@ static inline void skip_bits(GetBitContext *s, int n)
         s->cache = 0;
         s->bits_left = 0;
 
-        if (n >= 64) {
+        if (n >= BITSTREAM_BITS) {
             unsigned skip = (n / 8) * 8;
 
             n -= skip;
             s->index += skip;
         }
 #ifdef BITSTREAM_READER_LE
-        refill_64(s, 1);
+        refill_all(s, 1);
 #else
-        refill_64(s, 0);
+        refill_all(s, 0);
 #endif
         if (n)
             skip_remaining(s, n);
@@ -500,9 +546,9 @@ static inline unsigned int get_bits1(GetBitContext *s)
 #if CACHED_BITSTREAM_READER
     if (!s->bits_left)
 #ifdef BITSTREAM_READER_LE
-        refill_64(s, 1);
+        refill_all(s, 1);
 #else
-        refill_64(s, 0);
+        refill_all(s, 0);
 #endif
 
 #ifdef BITSTREAM_READER_LE
@@ -642,7 +688,7 @@ static inline int init_get_bits_xe(GetBitContext *s, const uint8_t *buffer,
 #if CACHED_BITSTREAM_READER
     s->cache              = 0;
     s->bits_left          = 0;
-    refill_64(s, is_le);
+    refill_all(s, is_le);
 #endif
 
     return ret;
diff --git a/libavcodec/mvha.c b/libavcodec/mvha.c
index c603ef6975..9d6dd9352a 100644
--- a/libavcodec/mvha.c
+++ b/libavcodec/mvha.c
@@ -24,7 +24,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#define CACHED_BITSTREAM_READER !ARCH_X86_32
+#define CACHED_BITSTREAM_READER ARCH_X86
 #include "libavutil/intreadwrite.h"
 
 #include "avcodec.h"
diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c
index 4da257fc61..36dd661e90 100644
--- a/libavcodec/utvideodec.c
+++ b/libavcodec/utvideodec.c
@@ -27,7 +27,7 @@
 #include <inttypes.h>
 #include <stdlib.h>
 
-#define CACHED_BITSTREAM_READER !ARCH_X86_32
+#define CACHED_BITSTREAM_READER ARCH_X86
 #define UNCHECKED_BITSTREAM_READER 1
 
 #include "libavutil/intreadwrite.h"
-- 
2.26.0



More information about the ffmpeg-devel mailing list