brotli 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/brotli/brotli.cc +114 -24
- data/ext/brotli/brotli.h +0 -1
- data/ext/brotli/extconf.rb +30 -23
- data/lib/brotli/version.rb +1 -1
- data/vendor/brotli/LICENSE +1 -1
- data/vendor/brotli/dec/Makefile +1 -1
- data/vendor/brotli/dec/bit_reader.c +3 -3
- data/vendor/brotli/dec/bit_reader.h +25 -27
- data/vendor/brotli/dec/context.h +4 -4
- data/vendor/brotli/dec/decode.c +410 -486
- data/vendor/brotli/dec/decode.h +101 -105
- data/vendor/brotli/dec/dictionary.c +1 -1
- data/vendor/brotli/dec/dictionary.h +7 -8
- data/vendor/brotli/dec/huffman.c +103 -105
- data/vendor/brotli/dec/huffman.h +18 -18
- data/vendor/brotli/dec/port.h +52 -40
- data/vendor/brotli/dec/prefix.h +2 -0
- data/vendor/brotli/dec/state.c +13 -19
- data/vendor/brotli/dec/state.h +25 -39
- data/vendor/brotli/dec/transform.h +38 -44
- data/vendor/brotli/dec/types.h +2 -2
- data/vendor/brotli/enc/Makefile +1 -1
- data/vendor/brotli/enc/backward_references.cc +455 -359
- data/vendor/brotli/enc/backward_references.h +79 -3
- data/vendor/brotli/enc/bit_cost.h +54 -32
- data/vendor/brotli/enc/block_splitter.cc +285 -193
- data/vendor/brotli/enc/block_splitter.h +4 -12
- data/vendor/brotli/enc/brotli_bit_stream.cc +623 -324
- data/vendor/brotli/enc/brotli_bit_stream.h +76 -37
- data/vendor/brotli/enc/cluster.h +161 -120
- data/vendor/brotli/enc/command.h +60 -37
- data/vendor/brotli/enc/compress_fragment.cc +701 -0
- data/vendor/brotli/enc/compress_fragment.h +47 -0
- data/vendor/brotli/enc/compress_fragment_two_pass.cc +524 -0
- data/vendor/brotli/enc/compress_fragment_two_pass.h +40 -0
- data/vendor/brotli/enc/compressor.h +15 -0
- data/vendor/brotli/enc/context.h +1 -1
- data/vendor/brotli/enc/dictionary.h +2 -2
- data/vendor/brotli/enc/encode.cc +819 -286
- data/vendor/brotli/enc/encode.h +38 -15
- data/vendor/brotli/enc/encode_parallel.cc +40 -42
- data/vendor/brotli/enc/entropy_encode.cc +144 -147
- data/vendor/brotli/enc/entropy_encode.h +32 -8
- data/vendor/brotli/enc/entropy_encode_static.h +572 -0
- data/vendor/brotli/enc/fast_log.h +7 -40
- data/vendor/brotli/enc/find_match_length.h +9 -9
- data/vendor/brotli/enc/hash.h +462 -154
- data/vendor/brotli/enc/histogram.cc +6 -6
- data/vendor/brotli/enc/histogram.h +13 -13
- data/vendor/brotli/enc/literal_cost.cc +45 -45
- data/vendor/brotli/enc/metablock.cc +92 -89
- data/vendor/brotli/enc/metablock.h +12 -12
- data/vendor/brotli/enc/port.h +7 -16
- data/vendor/brotli/enc/prefix.h +23 -22
- data/vendor/brotli/enc/ringbuffer.h +75 -29
- data/vendor/brotli/enc/static_dict.cc +56 -48
- data/vendor/brotli/enc/static_dict.h +5 -5
- data/vendor/brotli/enc/streams.cc +1 -1
- data/vendor/brotli/enc/streams.h +5 -5
- data/vendor/brotli/enc/transform.h +40 -35
- data/vendor/brotli/enc/types.h +2 -0
- data/vendor/brotli/enc/utf8_util.cc +3 -2
- data/vendor/brotli/enc/write_bits.h +6 -6
- metadata +9 -5
- data/vendor/brotli/dec/streams.c +0 -102
- data/vendor/brotli/dec/streams.h +0 -95
@@ -10,7 +10,6 @@
|
|
10
10
|
|
11
11
|
#include <algorithm>
|
12
12
|
#include <limits>
|
13
|
-
#include <vector>
|
14
13
|
#include <cstdlib>
|
15
14
|
|
16
15
|
#include "./histogram.h"
|
@@ -19,24 +18,6 @@
|
|
19
18
|
|
20
19
|
namespace brotli {
|
21
20
|
|
22
|
-
namespace {
|
23
|
-
|
24
|
-
struct HuffmanTree {
|
25
|
-
HuffmanTree(int count, int16_t left, int16_t right)
|
26
|
-
: total_count_(count),
|
27
|
-
index_left_(left),
|
28
|
-
index_right_or_value_(right) {
|
29
|
-
}
|
30
|
-
int total_count_;
|
31
|
-
int16_t index_left_;
|
32
|
-
int16_t index_right_or_value_;
|
33
|
-
};
|
34
|
-
|
35
|
-
// Sort the root nodes, least popular first.
|
36
|
-
bool SortHuffmanTree(const HuffmanTree &v0, const HuffmanTree &v1) {
|
37
|
-
return v0.total_count_ < v1.total_count_;
|
38
|
-
}
|
39
|
-
|
40
21
|
void SetDepth(const HuffmanTree &p,
|
41
22
|
HuffmanTree *pool,
|
42
23
|
uint8_t *depth,
|
@@ -50,7 +31,14 @@ void SetDepth(const HuffmanTree &p,
|
|
50
31
|
}
|
51
32
|
}
|
52
33
|
|
53
|
-
|
34
|
+
// Sort the root nodes, least popular first.
|
35
|
+
static inline bool SortHuffmanTree(const HuffmanTree& v0,
|
36
|
+
const HuffmanTree& v1) {
|
37
|
+
if (v0.total_count_ != v1.total_count_) {
|
38
|
+
return v0.total_count_ < v1.total_count_;
|
39
|
+
}
|
40
|
+
return v0.index_right_or_value_ > v1.index_right_or_value_;
|
41
|
+
}
|
54
42
|
|
55
43
|
// This function will create a Huffman tree.
|
56
44
|
//
|
@@ -67,32 +55,31 @@ void SetDepth(const HuffmanTree &p,
|
|
67
55
|
// we are not planning to use this with extremely long blocks.
|
68
56
|
//
|
69
57
|
// See http://en.wikipedia.org/wiki/Huffman_coding
|
70
|
-
void CreateHuffmanTree(const
|
71
|
-
const
|
58
|
+
void CreateHuffmanTree(const uint32_t *data,
|
59
|
+
const size_t length,
|
72
60
|
const int tree_limit,
|
61
|
+
HuffmanTree* tree,
|
73
62
|
uint8_t *depth) {
|
74
63
|
// For block sizes below 64 kB, we never need to do a second iteration
|
75
64
|
// of this loop. Probably all of our block sizes will be smaller than
|
76
65
|
// that, so this loop is mostly of academic interest. If we actually
|
77
66
|
// would need this, we would be better off with the Katajainen algorithm.
|
78
|
-
for (
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
for (int i = length - 1; i >= 0; --i) {
|
67
|
+
for (uint32_t count_limit = 1; ; count_limit *= 2) {
|
68
|
+
size_t n = 0;
|
69
|
+
for (size_t i = length; i != 0;) {
|
70
|
+
--i;
|
83
71
|
if (data[i]) {
|
84
|
-
const
|
85
|
-
tree
|
72
|
+
const uint32_t count = std::max(data[i], count_limit);
|
73
|
+
tree[n++] = HuffmanTree(count, -1, static_cast<int16_t>(i));
|
86
74
|
}
|
87
75
|
}
|
88
76
|
|
89
|
-
const int n = static_cast<int>(tree.size());
|
90
77
|
if (n == 1) {
|
91
78
|
depth[tree[0].index_right_or_value_] = 1; // Only one element.
|
92
79
|
break;
|
93
80
|
}
|
94
81
|
|
95
|
-
std::
|
82
|
+
std::sort(tree, tree + n, SortHuffmanTree);
|
96
83
|
|
97
84
|
// The nodes are:
|
98
85
|
// [0, n): the sorted leaf nodes that we start with.
|
@@ -101,14 +88,14 @@ void CreateHuffmanTree(const int *data,
|
|
101
88
|
// (n+1). These are naturally in ascending order.
|
102
89
|
// [2n]: we add a sentinel at the end as well.
|
103
90
|
// There will be (2n+1) elements at the end.
|
104
|
-
const HuffmanTree sentinel(std::numeric_limits<
|
105
|
-
tree
|
106
|
-
tree
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
for (
|
111
|
-
|
91
|
+
const HuffmanTree sentinel(std::numeric_limits<uint32_t>::max(), -1, -1);
|
92
|
+
tree[n] = sentinel;
|
93
|
+
tree[n + 1] = sentinel;
|
94
|
+
|
95
|
+
size_t i = 0; // Points to the next leaf node.
|
96
|
+
size_t j = n + 1; // Points to the next non-leaf node.
|
97
|
+
for (size_t k = n - 1; k != 0; --k) {
|
98
|
+
size_t left, right;
|
112
99
|
if (tree[i].total_count_ <= tree[j].total_count_) {
|
113
100
|
left = i;
|
114
101
|
++i;
|
@@ -125,16 +112,15 @@ void CreateHuffmanTree(const int *data,
|
|
125
112
|
}
|
126
113
|
|
127
114
|
// The sentinel node becomes the parent node.
|
128
|
-
|
115
|
+
size_t j_end = 2 * n - k;
|
129
116
|
tree[j_end].total_count_ =
|
130
117
|
tree[left].total_count_ + tree[right].total_count_;
|
131
118
|
tree[j_end].index_left_ = static_cast<int16_t>(left);
|
132
119
|
tree[j_end].index_right_or_value_ = static_cast<int16_t>(right);
|
133
120
|
|
134
121
|
// Add back the last sentinel node.
|
135
|
-
tree
|
122
|
+
tree[j_end + 1] = sentinel;
|
136
123
|
}
|
137
|
-
BROTLI_DCHECK(tree.size() == 2 * n + 1);
|
138
124
|
SetDepth(tree[2 * n - 1], &tree[0], depth, 0);
|
139
125
|
|
140
126
|
// We need to pack the Huffman tree in tree_limit bits.
|
@@ -146,108 +132,123 @@ void CreateHuffmanTree(const int *data,
|
|
146
132
|
}
|
147
133
|
}
|
148
134
|
|
149
|
-
void Reverse(
|
135
|
+
static void Reverse(uint8_t* v, size_t start, size_t end) {
|
150
136
|
--end;
|
151
137
|
while (start < end) {
|
152
|
-
uint8_t tmp =
|
153
|
-
|
154
|
-
|
138
|
+
uint8_t tmp = v[start];
|
139
|
+
v[start] = v[end];
|
140
|
+
v[end] = tmp;
|
155
141
|
++start;
|
156
142
|
--end;
|
157
143
|
}
|
158
144
|
}
|
159
145
|
|
160
|
-
void WriteHuffmanTreeRepetitions(
|
146
|
+
static void WriteHuffmanTreeRepetitions(
|
161
147
|
const uint8_t previous_value,
|
162
148
|
const uint8_t value,
|
163
|
-
|
164
|
-
|
165
|
-
|
149
|
+
size_t repetitions,
|
150
|
+
size_t* tree_size,
|
151
|
+
uint8_t* tree,
|
152
|
+
uint8_t* extra_bits_data) {
|
153
|
+
assert(repetitions > 0);
|
166
154
|
if (previous_value != value) {
|
167
|
-
tree
|
168
|
-
extra_bits_data
|
155
|
+
tree[*tree_size] = value;
|
156
|
+
extra_bits_data[*tree_size] = 0;
|
157
|
+
++(*tree_size);
|
169
158
|
--repetitions;
|
170
159
|
}
|
171
160
|
if (repetitions == 7) {
|
172
|
-
tree
|
173
|
-
extra_bits_data
|
161
|
+
tree[*tree_size] = value;
|
162
|
+
extra_bits_data[*tree_size] = 0;
|
163
|
+
++(*tree_size);
|
174
164
|
--repetitions;
|
175
165
|
}
|
176
166
|
if (repetitions < 3) {
|
177
|
-
for (
|
178
|
-
tree
|
179
|
-
extra_bits_data
|
167
|
+
for (size_t i = 0; i < repetitions; ++i) {
|
168
|
+
tree[*tree_size] = value;
|
169
|
+
extra_bits_data[*tree_size] = 0;
|
170
|
+
++(*tree_size);
|
180
171
|
}
|
181
172
|
} else {
|
182
173
|
repetitions -= 3;
|
183
|
-
|
184
|
-
while (
|
185
|
-
tree
|
186
|
-
extra_bits_data
|
174
|
+
size_t start = *tree_size;
|
175
|
+
while (true) {
|
176
|
+
tree[*tree_size] = 16;
|
177
|
+
extra_bits_data[*tree_size] = repetitions & 0x3;
|
178
|
+
++(*tree_size);
|
187
179
|
repetitions >>= 2;
|
180
|
+
if (repetitions == 0) {
|
181
|
+
break;
|
182
|
+
}
|
188
183
|
--repetitions;
|
189
184
|
}
|
190
|
-
Reverse(tree, start,
|
191
|
-
Reverse(extra_bits_data, start,
|
185
|
+
Reverse(tree, start, *tree_size);
|
186
|
+
Reverse(extra_bits_data, start, *tree_size);
|
192
187
|
}
|
193
188
|
}
|
194
189
|
|
195
|
-
void WriteHuffmanTreeRepetitionsZeros(
|
196
|
-
|
197
|
-
|
198
|
-
|
190
|
+
static void WriteHuffmanTreeRepetitionsZeros(
|
191
|
+
size_t repetitions,
|
192
|
+
size_t* tree_size,
|
193
|
+
uint8_t* tree,
|
194
|
+
uint8_t* extra_bits_data) {
|
199
195
|
if (repetitions == 11) {
|
200
|
-
tree
|
201
|
-
extra_bits_data
|
196
|
+
tree[*tree_size] = 0;
|
197
|
+
extra_bits_data[*tree_size] = 0;
|
198
|
+
++(*tree_size);
|
202
199
|
--repetitions;
|
203
200
|
}
|
204
201
|
if (repetitions < 3) {
|
205
|
-
for (
|
206
|
-
tree
|
207
|
-
extra_bits_data
|
202
|
+
for (size_t i = 0; i < repetitions; ++i) {
|
203
|
+
tree[*tree_size] = 0;
|
204
|
+
extra_bits_data[*tree_size] = 0;
|
205
|
+
++(*tree_size);
|
208
206
|
}
|
209
207
|
} else {
|
210
208
|
repetitions -= 3;
|
211
|
-
|
212
|
-
while (
|
213
|
-
tree
|
214
|
-
extra_bits_data
|
209
|
+
size_t start = *tree_size;
|
210
|
+
while (true) {
|
211
|
+
tree[*tree_size] = 17;
|
212
|
+
extra_bits_data[*tree_size] = repetitions & 0x7;
|
213
|
+
++(*tree_size);
|
215
214
|
repetitions >>= 3;
|
215
|
+
if (repetitions == 0) {
|
216
|
+
break;
|
217
|
+
}
|
216
218
|
--repetitions;
|
217
219
|
}
|
218
|
-
Reverse(tree, start,
|
219
|
-
Reverse(extra_bits_data, start,
|
220
|
+
Reverse(tree, start, *tree_size);
|
221
|
+
Reverse(extra_bits_data, start, *tree_size);
|
220
222
|
}
|
221
223
|
}
|
222
224
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
225
|
+
void OptimizeHuffmanCountsForRle(size_t length, uint32_t* counts,
|
226
|
+
uint8_t* good_for_rle) {
|
227
|
+
size_t nonzero_count = 0;
|
228
|
+
size_t stride;
|
229
|
+
size_t limit;
|
230
|
+
size_t sum;
|
231
|
+
const size_t streak_limit = 1240;
|
229
232
|
// Let's make the Huffman code more compatible with rle encoding.
|
230
|
-
|
233
|
+
size_t i;
|
231
234
|
for (i = 0; i < length; i++) {
|
232
235
|
if (counts[i]) {
|
233
236
|
++nonzero_count;
|
234
237
|
}
|
235
238
|
}
|
236
239
|
if (nonzero_count < 16) {
|
237
|
-
return
|
240
|
+
return;
|
238
241
|
}
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
// Now counts[0..length - 1] does not have trailing zeros.
|
245
|
-
break;
|
246
|
-
}
|
242
|
+
while (length != 0 && counts[length - 1] == 0) {
|
243
|
+
--length;
|
244
|
+
}
|
245
|
+
if (length == 0) {
|
246
|
+
return; // All zeros.
|
247
247
|
}
|
248
|
+
// Now counts[0..length - 1] does not have trailing zeros.
|
248
249
|
{
|
249
|
-
|
250
|
-
|
250
|
+
size_t nonzeros = 0;
|
251
|
+
uint32_t smallest_nonzero = 1 << 30;
|
251
252
|
for (i = 0; i < length; ++i) {
|
252
253
|
if (counts[i] != 0) {
|
253
254
|
++nonzeros;
|
@@ -258,9 +259,9 @@ int OptimizeHuffmanCountsForRle(int length, int* counts) {
|
|
258
259
|
}
|
259
260
|
if (nonzeros < 5) {
|
260
261
|
// Small histogram will model it well.
|
261
|
-
return
|
262
|
+
return;
|
262
263
|
}
|
263
|
-
|
264
|
+
size_t zeros = length - nonzeros;
|
264
265
|
if (smallest_nonzero < 4) {
|
265
266
|
if (zeros < 6) {
|
266
267
|
for (i = 1; i < length - 1; ++i) {
|
@@ -271,54 +272,50 @@ int OptimizeHuffmanCountsForRle(int length, int* counts) {
|
|
271
272
|
}
|
272
273
|
}
|
273
274
|
if (nonzeros < 28) {
|
274
|
-
return
|
275
|
+
return;
|
275
276
|
}
|
276
277
|
}
|
277
278
|
// 2) Let's mark all population counts that already can be encoded
|
278
279
|
// with an rle code.
|
279
|
-
good_for_rle
|
280
|
-
if (good_for_rle == NULL) {
|
281
|
-
return 0;
|
282
|
-
}
|
280
|
+
memset(good_for_rle, 0, length);
|
283
281
|
{
|
284
282
|
// Let's not spoil any of the existing good rle codes.
|
285
283
|
// Mark any seq of 0's that is longer as 5 as a good_for_rle.
|
286
284
|
// Mark any seq of non-0's that is longer as 7 as a good_for_rle.
|
287
|
-
|
288
|
-
|
289
|
-
for (i = 0; i
|
285
|
+
uint32_t symbol = counts[0];
|
286
|
+
size_t step = 0;
|
287
|
+
for (i = 0; i <= length; ++i) {
|
290
288
|
if (i == length || counts[i] != symbol) {
|
291
|
-
if ((symbol == 0 &&
|
292
|
-
(symbol != 0 &&
|
293
|
-
|
294
|
-
for (k = 0; k <
|
289
|
+
if ((symbol == 0 && step >= 5) ||
|
290
|
+
(symbol != 0 && step >= 7)) {
|
291
|
+
size_t k;
|
292
|
+
for (k = 0; k < step; ++k) {
|
295
293
|
good_for_rle[i - k - 1] = 1;
|
296
294
|
}
|
297
295
|
}
|
298
|
-
|
296
|
+
step = 1;
|
299
297
|
if (i != length) {
|
300
298
|
symbol = counts[i];
|
301
299
|
}
|
302
300
|
} else {
|
303
|
-
++
|
301
|
+
++step;
|
304
302
|
}
|
305
303
|
}
|
306
304
|
}
|
307
305
|
// 3) Let's replace those population counts that lead to more rle codes.
|
308
306
|
// Math here is in 24.8 fixed point representation.
|
309
|
-
const int streak_limit = 1240;
|
310
307
|
stride = 0;
|
311
308
|
limit = 256 * (counts[0] + counts[1] + counts[2]) / 3 + 420;
|
312
309
|
sum = 0;
|
313
|
-
for (i = 0; i
|
310
|
+
for (i = 0; i <= length; ++i) {
|
314
311
|
if (i == length || good_for_rle[i] ||
|
315
312
|
(i != 0 && good_for_rle[i - 1]) ||
|
316
|
-
|
313
|
+
(256 * counts[i] - limit + streak_limit) >= 2 * streak_limit) {
|
317
314
|
if (stride >= 4 || (stride >= 3 && sum == 0)) {
|
318
|
-
|
315
|
+
size_t k;
|
319
316
|
// The stride must end, collapse what we have, if we have enough (4).
|
320
|
-
|
321
|
-
if (count
|
317
|
+
size_t count = (sum + stride / 2) / stride;
|
318
|
+
if (count == 0) {
|
322
319
|
count = 1;
|
323
320
|
}
|
324
321
|
if (sum == 0) {
|
@@ -328,7 +325,7 @@ int OptimizeHuffmanCountsForRle(int length, int* counts) {
|
|
328
325
|
for (k = 0; k < stride; ++k) {
|
329
326
|
// We don't want to change value at counts[i],
|
330
327
|
// that is already belonging to the next stride. Thus - 1.
|
331
|
-
counts[i - k - 1] = count;
|
328
|
+
counts[i - k - 1] = static_cast<uint32_t>(count);
|
332
329
|
}
|
333
330
|
}
|
334
331
|
stride = 0;
|
@@ -354,21 +351,19 @@ int OptimizeHuffmanCountsForRle(int length, int* counts) {
|
|
354
351
|
}
|
355
352
|
}
|
356
353
|
}
|
357
|
-
free(good_for_rle);
|
358
|
-
return 1;
|
359
354
|
}
|
360
355
|
|
361
|
-
static void DecideOverRleUse(const uint8_t* depth, const
|
356
|
+
static void DecideOverRleUse(const uint8_t* depth, const size_t length,
|
362
357
|
bool *use_rle_for_non_zero,
|
363
358
|
bool *use_rle_for_zero) {
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
for (
|
369
|
-
const
|
370
|
-
|
371
|
-
for (
|
359
|
+
size_t total_reps_zero = 0;
|
360
|
+
size_t total_reps_non_zero = 0;
|
361
|
+
size_t count_reps_zero = 1;
|
362
|
+
size_t count_reps_non_zero = 1;
|
363
|
+
for (size_t i = 0; i < length;) {
|
364
|
+
const uint8_t value = depth[i];
|
365
|
+
size_t reps = 1;
|
366
|
+
for (size_t k = i + 1; k < length && depth[k] == value; ++k) {
|
372
367
|
++reps;
|
373
368
|
}
|
374
369
|
if (reps >= 3 && value == 0) {
|
@@ -381,21 +376,20 @@ static void DecideOverRleUse(const uint8_t* depth, const int length,
|
|
381
376
|
}
|
382
377
|
i += reps;
|
383
378
|
}
|
384
|
-
total_reps_non_zero
|
385
|
-
total_reps_zero
|
386
|
-
*use_rle_for_non_zero = total_reps_non_zero > 2;
|
387
|
-
*use_rle_for_zero = total_reps_zero > 2;
|
379
|
+
*use_rle_for_non_zero = total_reps_non_zero > count_reps_non_zero * 2;
|
380
|
+
*use_rle_for_zero = total_reps_zero > count_reps_zero * 2;
|
388
381
|
}
|
389
382
|
|
390
383
|
void WriteHuffmanTree(const uint8_t* depth,
|
391
|
-
|
392
|
-
|
393
|
-
|
384
|
+
size_t length,
|
385
|
+
size_t* tree_size,
|
386
|
+
uint8_t* tree,
|
387
|
+
uint8_t* extra_bits_data) {
|
394
388
|
uint8_t previous_value = 8;
|
395
389
|
|
396
390
|
// Throw away trailing zeros.
|
397
|
-
|
398
|
-
for (
|
391
|
+
size_t new_length = length;
|
392
|
+
for (size_t i = 0; i < length; ++i) {
|
399
393
|
if (depth[length - i - 1] == 0) {
|
400
394
|
--new_length;
|
401
395
|
} else {
|
@@ -414,20 +408,21 @@ void WriteHuffmanTree(const uint8_t* depth,
|
|
414
408
|
}
|
415
409
|
|
416
410
|
// Actual rle coding.
|
417
|
-
for (
|
411
|
+
for (size_t i = 0; i < new_length;) {
|
418
412
|
const uint8_t value = depth[i];
|
419
|
-
|
413
|
+
size_t reps = 1;
|
420
414
|
if ((value != 0 && use_rle_for_non_zero) ||
|
421
415
|
(value == 0 && use_rle_for_zero)) {
|
422
|
-
for (
|
416
|
+
for (size_t k = i + 1; k < new_length && depth[k] == value; ++k) {
|
423
417
|
++reps;
|
424
418
|
}
|
425
419
|
}
|
426
420
|
if (value == 0) {
|
427
|
-
WriteHuffmanTreeRepetitionsZeros(reps, tree, extra_bits_data);
|
421
|
+
WriteHuffmanTreeRepetitionsZeros(reps, tree_size, tree, extra_bits_data);
|
428
422
|
} else {
|
429
423
|
WriteHuffmanTreeRepetitions(previous_value,
|
430
|
-
value, reps,
|
424
|
+
value, reps, tree_size,
|
425
|
+
tree, extra_bits_data);
|
431
426
|
previous_value = value;
|
432
427
|
}
|
433
428
|
i += reps;
|
@@ -453,13 +448,15 @@ uint16_t ReverseBits(int num_bits, uint16_t bits) {
|
|
453
448
|
|
454
449
|
} // namespace
|
455
450
|
|
456
|
-
void ConvertBitDepthsToSymbols(const uint8_t *depth,
|
451
|
+
void ConvertBitDepthsToSymbols(const uint8_t *depth,
|
452
|
+
size_t len,
|
453
|
+
uint16_t *bits) {
|
457
454
|
// In Brotli, all bit depths are [1..15]
|
458
455
|
// 0 bit depth means that the symbol does not exist.
|
459
456
|
const int kMaxBits = 16; // 0..15 are values for bits
|
460
457
|
uint16_t bl_count[kMaxBits] = { 0 };
|
461
458
|
{
|
462
|
-
for (
|
459
|
+
for (size_t i = 0; i < len; ++i) {
|
463
460
|
++bl_count[depth[i]];
|
464
461
|
}
|
465
462
|
bl_count[0] = 0;
|
@@ -473,7 +470,7 @@ void ConvertBitDepthsToSymbols(const uint8_t *depth, int len, uint16_t *bits) {
|
|
473
470
|
next_code[bits] = static_cast<uint16_t>(code);
|
474
471
|
}
|
475
472
|
}
|
476
|
-
for (
|
473
|
+
for (size_t i = 0; i < len; ++i) {
|
477
474
|
if (depth[i]) {
|
478
475
|
bits[i] = ReverseBits(depth[i], next_code[depth[i]]++);
|
479
476
|
}
|
@@ -10,13 +10,28 @@
|
|
10
10
|
#define BROTLI_ENC_ENTROPY_ENCODE_H_
|
11
11
|
|
12
12
|
#include <string.h>
|
13
|
-
#include <vector>
|
14
13
|
#include "./histogram.h"
|
15
14
|
#include "./prefix.h"
|
16
15
|
#include "./types.h"
|
17
16
|
|
18
17
|
namespace brotli {
|
19
18
|
|
19
|
+
// A node of a Huffman tree.
|
20
|
+
struct HuffmanTree {
|
21
|
+
HuffmanTree() {}
|
22
|
+
HuffmanTree(uint32_t count, int16_t left, int16_t right)
|
23
|
+
: total_count_(count),
|
24
|
+
index_left_(left),
|
25
|
+
index_right_or_value_(right) {
|
26
|
+
}
|
27
|
+
uint32_t total_count_;
|
28
|
+
int16_t index_left_;
|
29
|
+
int16_t index_right_or_value_;
|
30
|
+
};
|
31
|
+
|
32
|
+
void SetDepth(const HuffmanTree &p, HuffmanTree *pool,
|
33
|
+
uint8_t *depth, uint8_t level);
|
34
|
+
|
20
35
|
// This function will create a Huffman tree.
|
21
36
|
//
|
22
37
|
// The (data,length) contains the population counts.
|
@@ -25,10 +40,14 @@ namespace brotli {
|
|
25
40
|
// The depth contains the tree, i.e., how many bits are used for
|
26
41
|
// the symbol.
|
27
42
|
//
|
43
|
+
// The actual Huffman tree is constructed in the tree[] array, which has to
|
44
|
+
// be at least 2 * length + 1 long.
|
45
|
+
//
|
28
46
|
// See http://en.wikipedia.org/wiki/Huffman_coding
|
29
|
-
void CreateHuffmanTree(const
|
30
|
-
const
|
47
|
+
void CreateHuffmanTree(const uint32_t *data,
|
48
|
+
const size_t length,
|
31
49
|
const int tree_limit,
|
50
|
+
HuffmanTree* tree,
|
32
51
|
uint8_t *depth);
|
33
52
|
|
34
53
|
// Change the population counts in a way that the consequent
|
@@ -37,18 +56,23 @@ void CreateHuffmanTree(const int *data,
|
|
37
56
|
//
|
38
57
|
// length contains the size of the histogram.
|
39
58
|
// counts contains the population counts.
|
40
|
-
|
59
|
+
// good_for_rle is a buffer of at least length size
|
60
|
+
void OptimizeHuffmanCountsForRle(size_t length, uint32_t* counts,
|
61
|
+
uint8_t* good_for_rle);
|
41
62
|
|
42
63
|
// Write a Huffman tree from bit depths into the bitstream representation
|
43
64
|
// of a Huffman tree. The generated Huffman tree is to be compressed once
|
44
65
|
// more using a Huffman tree
|
45
66
|
void WriteHuffmanTree(const uint8_t* depth,
|
46
|
-
|
47
|
-
|
48
|
-
|
67
|
+
size_t num,
|
68
|
+
size_t* tree_size,
|
69
|
+
uint8_t* tree,
|
70
|
+
uint8_t* extra_bits_data);
|
49
71
|
|
50
72
|
// Get the actual bit values for a tree of bit depths.
|
51
|
-
void ConvertBitDepthsToSymbols(const uint8_t *depth,
|
73
|
+
void ConvertBitDepthsToSymbols(const uint8_t *depth,
|
74
|
+
size_t len,
|
75
|
+
uint16_t *bits);
|
52
76
|
|
53
77
|
template<int kSize>
|
54
78
|
struct EntropyCode {
|