further simplification for the meta-Huffman coding

* don't transmit the number of Huffman tree group explicitly
* move color-cache information before the meta-Huffman block

* also add a check that color_cache_bits is in [1..11] range, as per spec.

Change-Id: I81d7711068653b509cdbc1151d93e229c4254580
This commit is contained in:
Pascal Massimino
2012-04-25 09:40:41 +00:00
committed by James Zern
parent e491729905
commit 8415ddf3be
2 changed files with 58 additions and 72 deletions

View File

@ -31,6 +31,7 @@ static const int kCodeLengthRepeatOffsets[3] = { 3, 3, 11 };
#define NUM_LENGTH_CODES 24
#define NUM_DISTANCE_CODES 40
#define DEFAULT_CODE_LENGTH 8
#define MAX_CACHE_BITS 11
// -----------------------------------------------------------------------------
// Five Huffman codes are used at each meta code:
@ -307,10 +308,9 @@ static void DeleteHtreeGroups(HTreeGroup* htree_groups, int num_htree_groups) {
}
static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
int* const color_cache_bits_ptr) {
int color_cache_bits) {
int ok = 0;
int i, j;
int color_cache_size;
VP8LBitReader* const br = &dec->br_;
VP8LMetadata* const hdr = &dec->hdr_;
uint32_t* huffman_image = NULL;
@ -318,11 +318,11 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
int num_htree_groups = 1;
if (VP8LReadBits(br, 1)) { // use meta Huffman codes
int meta_codes_nbits;
const int huffman_precision = VP8LReadBits(br, 4);
const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);
const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);
const int huffman_pixs = huffman_xsize * huffman_ysize;
if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec,
&huffman_image)) {
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
@ -331,19 +331,12 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
hdr->huffman_subsample_bits_ = huffman_precision;
for (i = 0; i < huffman_pixs; ++i) {
// The huffman data is stored in red and green bytes.
huffman_image[i] = (huffman_image[i] >> 8) & 0xffff;
const int index = (huffman_image[i] >> 8) & 0xffff;
huffman_image[i] = index;
if (index >= num_htree_groups) {
num_htree_groups = index + 1;
}
}
meta_codes_nbits = VP8LReadBits(br, 4);
num_htree_groups = 2 + VP8LReadBits(br, meta_codes_nbits);
}
if (VP8LReadBits(br, 1)) { // use color cache
*color_cache_bits_ptr = VP8LReadBits(br, 4);
color_cache_size = 1 << *color_cache_bits_ptr;
} else {
*color_cache_bits_ptr = 0;
color_cache_size = 0;
}
htree_groups = (HTreeGroup*)calloc(num_htree_groups, sizeof(*htree_groups));
@ -357,10 +350,10 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
HuffmanTree* const htrees = htree_groups[i].htrees_;
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
if (j == 0) {
alphabet_size += color_cache_size;
if (j == 0 && color_cache_bits > 0) {
alphabet_size += 1 << color_cache_bits;
}
ok = ReadHuffmanCode(alphabet_size, dec, &htrees[j]);
ok = ReadHuffmanCode(alphabet_size, dec, htrees + j);
ok = ok && !br->error_;
}
}
@ -835,29 +828,38 @@ static int DecodeImageStream(int xsize, int ysize,
int ok = 1;
int transform_xsize = xsize;
int transform_ysize = ysize;
VP8LBitReader* const br = &dec->br_;
VP8LMetadata* const hdr = &dec->hdr_;
uint32_t* data = NULL;
const int transform_start_idx = dec->next_transform_;
int color_cache_bits = 0;
VP8LBitReader* const br = &dec->br_;
int transform_start_idx = dec->next_transform_;
// Step#1: Read the transforms (may recurse).
// Read the transforms (may recurse).
if (is_level0) {
while (ok && VP8LReadBits(br, 1)) {
ok = ReadTransform(&transform_xsize, &transform_ysize, dec);
}
}
// Step#2: Read the Huffman codes (may recurse).
ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,
&color_cache_bits);
// Color cache
if (ok && VP8LReadBits(br, 1)) {
color_cache_bits = VP8LReadBits(br, 4);
ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS);
if (!ok) {
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
goto End;
}
}
// Read the Huffman codes (may recurse).
ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,
color_cache_bits);
if (!ok) {
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
goto End;
}
// Finish setting up the color-cache
if (color_cache_bits > 0) {
hdr->color_cache_size_ = 1 << color_cache_bits;
hdr->color_cache_ = (VP8LColorCache*)malloc(sizeof(*hdr->color_cache_));
@ -868,7 +870,6 @@ static int DecodeImageStream(int xsize, int ysize,
goto End;
}
}
UpdateDecoder(dec, transform_xsize, transform_ysize);
if (is_level0) { // level 0 complete
@ -883,11 +884,11 @@ static int DecodeImageStream(int xsize, int ysize,
goto End;
}
// Step#3: Use the Huffman trees to decode the LZ77 encoded data.
// Use the Huffman trees to decode the LZ77 encoded data.
ok = DecodeImageData(dec, data, transform_xsize, transform_ysize, 0);
ok = ok && !br->error_;
// Step#4: Apply transforms on the decoded data.
// Apply transforms on the decoded data.
if (ok) ApplyInverseTransforms(dec, transform_start_idx, data);
End: