Updates to Brotli compression format, decoder and encoder

This commit contains a batch of changes that were made to the Brotli
compression algorithm in the last month. Most important changes:

   * Format change: don't push distances representing static dictionary words to the distance cache.
   * Fix decoder invalid memory access bug caused by building a non-complete Huffman tree.
   * Add a mode parameter to the encoder interface.
   * Use different hashers for text and font mode.
   * Add a heuristics to the hasher for skipping non-compressible data.
   * Exhaustive search of static dictionary during backward reference search.
This commit is contained in:
Zoltan Szabadka
2014-03-20 14:32:35 +01:00
parent 7f848593bd
commit 278b89484f
14 changed files with 546 additions and 280 deletions
+21 -6
View File
@@ -247,12 +247,23 @@ static int ReadHuffmanCode(int alphabet_size,
code_lengths[symbols[0]] = 1;
switch (num_symbols) {
case 1:
break;
case 3:
ok = ((symbols[0] != symbols[1]) &&
(symbols[0] != symbols[2]) &&
(symbols[1] != symbols[2]));
break;
case 2:
ok = (symbols[0] != symbols[1]);
code_lengths[symbols[1]] = 1;
break;
case 4:
ok = ((symbols[0] != symbols[1]) &&
(symbols[0] != symbols[2]) &&
(symbols[0] != symbols[3]) &&
(symbols[1] != symbols[2]) &&
(symbols[1] != symbols[3]) &&
(symbols[2] != symbols[3]));
if (BrotliReadBits(br, 1)) {
code_lengths[symbols[2]] = 3;
code_lengths[symbols[3]] = 3;
@@ -266,6 +277,7 @@ static int ReadHuffmanCode(int alphabet_size,
int i;
uint8_t code_length_code_lengths[CODE_LENGTH_CODES] = { 0 };
int space = 32;
int num_codes = 0;
/* Static Huffman code for the code length code lengths */
static const HuffmanCode huff[16] = {
{2, 0}, {2, 4}, {2, 3}, {3, 2}, {2, 0}, {2, 4}, {2, 3}, {4, 1},
@@ -283,10 +295,12 @@ static int ReadHuffmanCode(int alphabet_size,
BROTLI_LOG_ARRAY_INDEX(code_length_code_lengths, code_len_idx);
if (v != 0) {
space -= (32 >> v);
++num_codes;
}
}
ok = ReadHuffmanCodeLengths(code_length_code_lengths,
alphabet_size, code_lengths, br);
ok = (num_codes == 1 || space == 0) &&
ReadHuffmanCodeLengths(code_length_code_lengths,
alphabet_size, code_lengths, br);
}
if (ok) {
table_size = BrotliBuildHuffmanTable(table, HUFFMAN_TABLE_BITS,
@@ -961,10 +975,6 @@ int BrotliDecompress(BrotliInput input, BrotliOutput output) {
ok = 0;
goto End;
}
if (distance_code > 0) {
dist_rb[dist_rb_idx & 3] = distance;
++dist_rb_idx;
}
BROTLI_LOG_UINT(distance);
if (pos < max_backward_distance &&
@@ -1016,6 +1026,11 @@ int BrotliDecompress(BrotliInput input, BrotliOutput output) {
goto End;
}
} else {
if (distance_code > 0) {
dist_rb[dist_rb_idx & 3] = distance;
++dist_rb_idx;
}
if (copy_length > meta_block_remaining_len) {
printf("Invalid backward reference. pos: %d distance: %d "
"len: %d bytes left: %d\n", pos, distance, copy_length,