mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-27 06:08:21 +01:00
~20% faster lossless decoding
We use help from small LUTs for Huffman decoding. Change-Id: I58db4ecd37282822094519f2aa14cf544beba975
This commit is contained in:
parent
313d853fa9
commit
24cc307ae3
@ -158,6 +158,14 @@ static WEBP_INLINE int ReadSymbol(const HuffmanTree* tree,
|
|||||||
const HuffmanTreeNode* node = tree->root_;
|
const HuffmanTreeNode* node = tree->root_;
|
||||||
uint32_t bits = VP8LPrefetchBits(br);
|
uint32_t bits = VP8LPrefetchBits(br);
|
||||||
int bitpos = br->bit_pos_;
|
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);
|
assert(node != NULL);
|
||||||
while (HuffmanTreeNodeIsNotLeaf(node)) {
|
while (HuffmanTreeNodeIsNotLeaf(node)) {
|
||||||
node = HuffmanTreeNextNode(node, bits & 1);
|
node = HuffmanTreeNextNode(node, bits & 1);
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include "./huffman.h"
|
#include "./huffman.h"
|
||||||
#include "../utils/utils.h"
|
#include "../utils/utils.h"
|
||||||
#include "../webp/format_constants.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;
|
if (tree->root_ == NULL) return 0;
|
||||||
TreeNodeInit(tree->root_); // Initialize root.
|
TreeNodeInit(tree->root_); // Initialize root.
|
||||||
tree->num_nodes_ = 1;
|
tree->num_nodes_ = 1;
|
||||||
|
memset(tree->lut_bits_, 255, sizeof(tree->lut_bits_));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,10 +119,30 @@ int HuffmanCodeLengthsToCodes(const int* const code_lengths,
|
|||||||
return 1;
|
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,
|
static int TreeAddSymbol(HuffmanTree* const tree,
|
||||||
int symbol, int code, int code_length) {
|
int symbol, int code, int code_length) {
|
||||||
HuffmanTreeNode* node = tree->root_;
|
HuffmanTreeNode* node = tree->root_;
|
||||||
const HuffmanTreeNode* const max_node = tree->root_ + tree->max_nodes_;
|
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) {
|
while (code_length-- > 0) {
|
||||||
if (node >= max_node) {
|
if (node >= max_node) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -28,8 +28,14 @@ typedef struct {
|
|||||||
} HuffmanTreeNode;
|
} HuffmanTreeNode;
|
||||||
|
|
||||||
// Huffman Tree.
|
// Huffman Tree.
|
||||||
|
#define HUFF_LUT_BITS 7
|
||||||
|
#define HUFF_LUT (1U << HUFF_LUT_BITS)
|
||||||
typedef struct HuffmanTree HuffmanTree;
|
typedef struct HuffmanTree HuffmanTree;
|
||||||
struct 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.
|
HuffmanTreeNode* root_; // all the nodes, starting at root.
|
||||||
int max_nodes_; // max number of nodes
|
int max_nodes_; // max number of nodes
|
||||||
int num_nodes_; // number of currently occupied nodes
|
int num_nodes_; // number of currently occupied nodes
|
||||||
|
Loading…
Reference in New Issue
Block a user