[FFmpeg-cvslog] Optimized base64 decode by writing 3 bytes at once.

Reimar Döffinger git at videolan.org
Sun Jan 22 14:42:00 CET 2012


ffmpeg | branch: master | Reimar Döffinger <Reimar.Doeffinger at gmx.de> | Sat Jan 21 22:52:56 2012 +0100| [daa47fdd2c46abdeab1991d4fb6a648651df0a22] | committer: Reimar Döffinger

Optimized base64 decode by writing 3 bytes at once.

About 25% faster.
decode: 248852 -> 200385 decicycles
(syntax check unchanged)

Signed-off-by: Reimar Döffinger <Reimar.Doeffinger at gmx.de>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=daa47fdd2c46abdeab1991d4fb6a648651df0a22
---

 libavutil/base64.c |   36 +++++++++++++++++++++++-------------
 1 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/libavutil/base64.c b/libavutil/base64.c
index 145bed6..1be7b7c 100644
--- a/libavutil/base64.c
+++ b/libavutil/base64.c
@@ -71,37 +71,41 @@ static const uint8_t map2[256] =
 #define BASE64_DEC_STEP(i) do { \
     bits = map2[in[i]]; \
     if (bits & 0x80) \
-        goto out; \
-    v = (v << 6) + bits; \
-    if (i & 3) \
-        *dst++ = v >> (6 - 2 * (i & 3)); \
+        goto out ## i; \
+    v = i ? (v << 6) + bits : bits; \
 } while(0)
 
 int av_base64_decode(uint8_t *out, const char *in_str, int out_size)
 {
-    int v;
     uint8_t *dst = out;
     uint8_t *end = out + out_size;
     // no sign extension
     const uint8_t *in = in_str;
     unsigned bits = 0xff;
+    unsigned v;
 
-    v = 0;
-    while (end - dst > 2) {
+    while (end - dst > 3) {
         BASE64_DEC_STEP(0);
         BASE64_DEC_STEP(1);
         BASE64_DEC_STEP(2);
         BASE64_DEC_STEP(3);
+        // Using AV_WB32 directly confuses compiler
+        v = av_be2ne32(v) >> 8;
+        AV_WN32(dst, v);
+        dst += 3;
         in += 4;
     }
     if (end - dst) {
         BASE64_DEC_STEP(0);
         BASE64_DEC_STEP(1);
-        if (end - dst) {
-            BASE64_DEC_STEP(2);
-            in++;
-        }
-        in += 2;
+        BASE64_DEC_STEP(2);
+        BASE64_DEC_STEP(3);
+        *dst++ = v >> 16;
+        if (end - dst)
+            *dst++ = v >> 8;
+        if (end - dst)
+            *dst++ = v;
+        in += 4;
     }
     while (1) {
         BASE64_DEC_STEP(0);
@@ -114,7 +118,13 @@ int av_base64_decode(uint8_t *out, const char *in_str, int out_size)
         in++;
     }
 
-out:
+out3:
+    *dst++ = v >> 10;
+    v <<= 2;
+out2:
+    *dst++ = v >> 4;
+out1:
+out0:
     return bits & 1 ? -1 : dst - out;
 }
 



More information about the ffmpeg-cvslog mailing list