From 699d80ea6bc393114e591a490d159eeb2c5b477a Mon Sep 17 00:00:00 2001 From: Jyrki Alakuijala Date: Thu, 27 Jun 2013 08:58:56 +0200 Subject: [PATCH] Jump-lookup for Huffman coding speeds up those codes that are not part of the main lookup. This gives a 10 % speedup for a photographic image. Change-Id: Ief54b0ad77db790a01314402ad351b40ac9a7be4 --- src/dec/vp8l.c | 4 ++++ src/utils/huffman.c | 11 ++++++++++- src/utils/huffman.h | 3 ++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/dec/vp8l.c b/src/dec/vp8l.c index 3185fe22..edca92b2 100644 --- a/src/dec/vp8l.c +++ b/src/dec/vp8l.c @@ -165,6 +165,10 @@ static WEBP_INLINE int ReadSymbol(const HuffmanTree* tree, VP8LSetBitPos(br, bitpos + lut_bits); return tree->lut_symbol_[lut_ix]; } + node += tree->lut_jump_[lut_ix]; + bitpos += HUFF_LUT_BITS; + bits >>= HUFF_LUT_BITS; + // Decode the value from a binary tree. assert(node != NULL); while (HuffmanTreeNodeIsNotLeaf(node)) { diff --git a/src/utils/huffman.c b/src/utils/huffman.c index a2f91c57..0ee38f59 100644 --- a/src/utils/huffman.c +++ b/src/utils/huffman.c @@ -63,6 +63,7 @@ static int TreeInit(HuffmanTree* const tree, int num_leaves) { TreeNodeInit(tree->root_); // Initialize root. tree->num_nodes_ = 1; memset(tree->lut_bits_, 255, sizeof(tree->lut_bits_)); + memset(tree->lut_jump_, 0, sizeof(tree->lut_jump_)); return 1; } @@ -154,16 +155,21 @@ static int ReverseBitsShort(int bits, int num_bits) { static int TreeAddSymbol(HuffmanTree* const tree, int symbol, int code, int code_length) { + int step = HUFF_LUT_BITS; + int base_code; HuffmanTreeNode* node = tree->root_; const HuffmanTreeNode* const max_node = tree->root_ + tree->max_nodes_; if (code_length <= HUFF_LUT_BITS) { - const int base_code = ReverseBitsShort(code, code_length); int i; + base_code = ReverseBitsShort(code, code_length); 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; } + } else { + base_code = ReverseBitsShort((code >> (code_length - HUFF_LUT_BITS)), + HUFF_LUT_BITS); } while (code_length-- > 0) { if (node >= max_node) { @@ -176,6 +182,9 @@ static int TreeAddSymbol(HuffmanTree* const tree, return 0; // leaf is already occupied. } node += node->children_ + ((code >> code_length) & 1); + if (--step == 0) { + tree->lut_jump_[base_code] = node - tree->root_; + } } if (NodeIsEmpty(node)) { node->children_ = 0; // turn newly created node into a leaf. diff --git a/src/utils/huffman.h b/src/utils/huffman.h index ae077f62..f219c541 100644 --- a/src/utils/huffman.h +++ b/src/utils/huffman.h @@ -34,7 +34,8 @@ typedef struct HuffmanTree HuffmanTree; struct HuffmanTree { // Fast lookup for short bit lengths. uint8_t lut_bits_[HUFF_LUT]; - int lut_symbol_[HUFF_LUT]; + int16_t lut_symbol_[HUFF_LUT]; + int16_t lut_jump_[HUFF_LUT]; // Complete tree for lookups. HuffmanTreeNode* root_; // all the nodes, starting at root. int max_nodes_; // max number of nodes