From 24cc307ae321bde5226f5f671a1fe632232ca1e7 Mon Sep 17 00:00:00 2001 From: skal Date: Thu, 20 Jun 2013 09:41:29 +0200 Subject: [PATCH] ~20% faster lossless decoding We use help from small LUTs for Huffman decoding. Change-Id: I58db4ecd37282822094519f2aa14cf544beba975 --- src/dec/vp8l.c | 8 ++++++++ src/utils/huffman.c | 22 ++++++++++++++++++++++ src/utils/huffman.h | 6 ++++++ 3 files changed, 36 insertions(+) diff --git a/src/dec/vp8l.c b/src/dec/vp8l.c index e941a6a4..b3c2e86e 100644 --- a/src/dec/vp8l.c +++ b/src/dec/vp8l.c @@ -158,6 +158,14 @@ static WEBP_INLINE int ReadSymbol(const HuffmanTree* tree, const HuffmanTreeNode* node = tree->root_; uint32_t bits = VP8LPrefetchBits(br); int bitpos = br->bit_pos_; + // Check if we find the bit combination from the Huffman lookup table. + const int lut_ix = bits & (HUFF_LUT - 1); + const int lut_bits = tree->lut_bits_[lut_ix]; + if (lut_bits <= HUFF_LUT_BITS) { + VP8LSetBitPos(br, bitpos + lut_bits); + return tree->lut_symbol_[lut_ix]; + } + // Decode the value from a binary tree. assert(node != NULL); while (HuffmanTreeNodeIsNotLeaf(node)) { node = HuffmanTreeNextNode(node, bits & 1); diff --git a/src/utils/huffman.c b/src/utils/huffman.c index 82dabf75..542af25d 100644 --- a/src/utils/huffman.c +++ b/src/utils/huffman.c @@ -13,6 +13,7 @@ #include #include +#include #include "./huffman.h" #include "../utils/utils.h" #include "../webp/format_constants.h" @@ -57,6 +58,7 @@ static int TreeInit(HuffmanTree* const tree, int num_leaves) { if (tree->root_ == NULL) return 0; TreeNodeInit(tree->root_); // Initialize root. tree->num_nodes_ = 1; + memset(tree->lut_bits_, 255, sizeof(tree->lut_bits_)); return 1; } @@ -117,10 +119,30 @@ int HuffmanCodeLengthsToCodes(const int* const code_lengths, return 1; } +static int ReverseBits(int bits, int num_bits) { + int retval = 0; + int i; + for (i = 0; i < num_bits; ++i) { + retval <<= 1; + retval |= bits & 1; + bits >>= 1; + } + return retval; +} + static int TreeAddSymbol(HuffmanTree* const tree, int symbol, int code, int code_length) { HuffmanTreeNode* node = tree->root_; const HuffmanTreeNode* const max_node = tree->root_ + tree->max_nodes_; + if (code_length <= HUFF_LUT_BITS) { + const int base_code = ReverseBits(code, code_length); + int i; + for (i = 0; i < (1 << (HUFF_LUT_BITS - code_length)); ++i) { + const int idx = base_code | (i << code_length); + tree->lut_symbol_[idx] = symbol; + tree->lut_bits_[idx] = code_length; + } + } while (code_length-- > 0) { if (node >= max_node) { return 0; diff --git a/src/utils/huffman.h b/src/utils/huffman.h index 4182ca21..ae077f62 100644 --- a/src/utils/huffman.h +++ b/src/utils/huffman.h @@ -28,8 +28,14 @@ typedef struct { } HuffmanTreeNode; // Huffman Tree. +#define HUFF_LUT_BITS 7 +#define HUFF_LUT (1U << HUFF_LUT_BITS) typedef struct HuffmanTree HuffmanTree; struct HuffmanTree { + // Fast lookup for short bit lengths. + uint8_t lut_bits_[HUFF_LUT]; + int lut_symbol_[HUFF_LUT]; + // Complete tree for lookups. HuffmanTreeNode* root_; // all the nodes, starting at root. int max_nodes_; // max number of nodes int num_nodes_; // number of currently occupied nodes