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:

   * Updated spec
   * Changed Huffman code length alphabet to use run length codes more
     efficiently, based on a suggestion by Robert Obryk
   * Changed encoding of the number of Huffman code lengths (HLEN)
   * Changed encoding of the number of Huffman trees (NTREES)
   * Added support for uncompressed meta-blocks
This commit is contained in:
Zoltan Szabadka
2013-12-12 13:18:04 +01:00
parent fe79fac8da
commit e70949119a
11 changed files with 411 additions and 263 deletions
+43 -40
View File
@@ -157,6 +157,17 @@ void CreateHuffmanTree(const int *data,
}
}
void Reverse(uint8_t* v, int start, int end) {
--end;
while (start < end) {
int tmp = v[start];
v[start] = v[end];
v[end] = tmp;
++start;
--end;
}
}
void WriteHuffmanTreeRepetitions(
const int previous_value,
const int value,
@@ -170,26 +181,24 @@ void WriteHuffmanTreeRepetitions(
++(*tree_size);
--repetitions;
}
while (repetitions >= 1) {
if (repetitions < 3) {
for (int i = 0; i < repetitions; ++i) {
tree[*tree_size] = value;
extra_bits[*tree_size] = 0;
++(*tree_size);
}
return;
} else if (repetitions < 7) {
// 3 to 6 left.
tree[*tree_size] = 16;
extra_bits[*tree_size] = repetitions - 3;
if (repetitions < 3) {
for (int i = 0; i < repetitions; ++i) {
tree[*tree_size] = value;
extra_bits[*tree_size] = 0;
++(*tree_size);
return;
} else {
tree[*tree_size] = 16;
extra_bits[*tree_size] = 3;
++(*tree_size);
repetitions -= 6;
}
} else {
repetitions -= 3;
int start = *tree_size;
while (repetitions >= 0) {
tree[*tree_size] = 16;
extra_bits[*tree_size] = repetitions & 0x3;
++(*tree_size);
repetitions >>= 2;
--repetitions;
}
Reverse(tree, start, *tree_size);
Reverse(extra_bits, start, *tree_size);
}
}
@@ -198,30 +207,24 @@ void WriteHuffmanTreeRepetitionsZeros(
uint8_t* tree,
uint8_t* extra_bits,
int* tree_size) {
while (repetitions >= 1) {
if (repetitions < 3) {
for (int i = 0; i < repetitions; ++i) {
tree[*tree_size] = 0;
extra_bits[*tree_size] = 0;
++(*tree_size);
}
return;
} else if (repetitions < 11) {
tree[*tree_size] = 17;
extra_bits[*tree_size] = repetitions - 3;
if (repetitions < 3) {
for (int i = 0; i < repetitions; ++i) {
tree[*tree_size] = 0;
extra_bits[*tree_size] = 0;
++(*tree_size);
return;
} else if (repetitions < 139) {
tree[*tree_size] = 18;
extra_bits[*tree_size] = repetitions - 11;
++(*tree_size);
return;
} else {
tree[*tree_size] = 18;
extra_bits[*tree_size] = 0x7f; // 138 repeated 0s
++(*tree_size);
repetitions -= 138;
}
} else {
repetitions -= 3;
int start = *tree_size;
while (repetitions >= 0) {
tree[*tree_size] = 17;
extra_bits[*tree_size] = repetitions & 0x7;
++(*tree_size);
repetitions >>= 3;
--repetitions;
}
Reverse(tree, start, *tree_size);
Reverse(extra_bits, start, *tree_size);
}
}