Speedup for decoding lossless WebP photographs:

use bit_pos instead num_bit to update the bit-reader
37.69 MB/s -> 39.79 MB/s, 5.6 %

Change-Id: Ica476cc3e2fc2db084d6961bea8586b050bb221d
This commit is contained in:
skal 2013-06-18 17:26:52 +02:00
parent 24ee098a00
commit 313d853fa9
4 changed files with 13 additions and 12 deletions

View File

@ -156,15 +156,15 @@ static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) {
static WEBP_INLINE int ReadSymbol(const HuffmanTree* tree, static WEBP_INLINE int ReadSymbol(const HuffmanTree* tree,
VP8LBitReader* const br) { VP8LBitReader* const br) {
const HuffmanTreeNode* node = tree->root_; const HuffmanTreeNode* node = tree->root_;
int num_bits = 0;
uint32_t bits = VP8LPrefetchBits(br); uint32_t bits = VP8LPrefetchBits(br);
int bitpos = br->bit_pos_;
assert(node != NULL); assert(node != NULL);
while (!HuffmanTreeNodeIsLeaf(node)) { while (HuffmanTreeNodeIsNotLeaf(node)) {
node = HuffmanTreeNextNode(node, bits & 1); node = HuffmanTreeNextNode(node, bits & 1);
bits >>= 1; bits >>= 1;
++num_bits; ++bitpos;
} }
VP8LDiscardBits(br, num_bits); VP8LSetBitPos(br, bitpos);
return node->symbol_; return node->symbol_;
} }

View File

@ -316,9 +316,10 @@ static WEBP_INLINE uint32_t VP8LPrefetchBits(VP8LBitReader* const br) {
return (uint32_t)(br->val_ >> br->bit_pos_); return (uint32_t)(br->val_ >> br->bit_pos_);
} }
// Discard 'num_bits' bits from the cache. // For jumping over a number of bits in the bit stream when accessed with
static WEBP_INLINE void VP8LDiscardBits(VP8LBitReader* const br, int num_bits) { // VP8LPrefetchBits and VP8LFillBitWindow.
br->bit_pos_ += num_bits; static WEBP_INLINE void VP8LSetBitPos(VP8LBitReader* const br, int val) {
br->bit_pos_ = val;
} }
// Advances the Read buffer by 4 bytes to make room for reading next 32 bits. // Advances the Read buffer by 4 bytes to make room for reading next 32 bits.

View File

@ -128,14 +128,14 @@ static int TreeAddSymbol(HuffmanTree* const tree,
if (NodeIsEmpty(node)) { if (NodeIsEmpty(node)) {
if (IsFull(tree)) return 0; // error: too many symbols. if (IsFull(tree)) return 0; // error: too many symbols.
AssignChildren(tree, node); AssignChildren(tree, node);
} else if (HuffmanTreeNodeIsLeaf(node)) { } else if (!HuffmanTreeNodeIsNotLeaf(node)) {
return 0; // leaf is already occupied. return 0; // leaf is already occupied.
} }
node += node->children_ + ((code >> code_length) & 1); node += node->children_ + ((code >> code_length) & 1);
} }
if (NodeIsEmpty(node)) { if (NodeIsEmpty(node)) {
node->children_ = 0; // turn newly created node into a leaf. node->children_ = 0; // turn newly created node into a leaf.
} else if (!HuffmanTreeNodeIsLeaf(node)) { } else if (HuffmanTreeNodeIsNotLeaf(node)) {
return 0; // trying to assign a symbol to already used code. return 0; // trying to assign a symbol to already used code.
} }
node->symbol_ = symbol; // Add symbol in this node. node->symbol_ = symbol; // Add symbol in this node.

View File

@ -35,10 +35,10 @@ struct HuffmanTree {
int num_nodes_; // number of currently occupied nodes int num_nodes_; // number of currently occupied nodes
}; };
// Returns true if the given node is a leaf of the Huffman tree. // Returns true if the given node is not a leaf of the Huffman tree.
static WEBP_INLINE int HuffmanTreeNodeIsLeaf( static WEBP_INLINE int HuffmanTreeNodeIsNotLeaf(
const HuffmanTreeNode* const node) { const HuffmanTreeNode* const node) {
return (node->children_ == 0); return node->children_;
} }
// Go down one level. Most critical function. 'right_child' must be 0 or 1. // Go down one level. Most critical function. 'right_child' must be 0 or 1.