1 /* Copyright 2015 Google Inc. All Rights Reserved.
2
3 Distributed under MIT license.
4 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5 */
6
7 /* Function for fast encoding of an input fragment, independently from the input
8 history. This function uses two-pass processing: in the first pass we save
9 the found backward matches and literal bytes into a buffer, and in the
10 second pass we emit them into the bit stream using prefix codes built based
11 on the actual command and literal byte histograms. */
12
13 #include "compress_fragment_two_pass.h"
14
15 #include <string.h> /* memcmp, memcpy, memset */
16
17 #include "../common/constants.h"
18 #include "../common/platform.h"
19 #include <brotli/types.h>
20 #include "bit_cost.h"
21 #include "brotli_bit_stream.h"
22 #include "entropy_encode.h"
23 #include "fast_log.h"
24 #include "find_match_length.h"
25 #include "write_bits.h"
26
27 #if defined(__cplusplus) || defined(c_plusplus)
28 extern "C" {
29 #endif
30
31 #define MAX_DISTANCE (long)BROTLI_MAX_BACKWARD_LIMIT(18)
32
33 /* kHashMul32 multiplier has these properties:
34 * The multiplier must be odd. Otherwise we may lose the highest bit.
35 * No long streaks of ones or zeros.
36 * There is no effort to ensure that it is a prime, the oddity is enough
37 for this use.
38 * The number has been tuned heuristically against compression benchmarks. */
39 static const uint32_t kHashMul32 = 0x1E35A7BD;
40
Hash(const uint8_t * p,size_t shift,size_t length)41 static BROTLI_INLINE uint32_t Hash(const uint8_t* p,
42 size_t shift, size_t length) {
43 const uint64_t h =
44 (BROTLI_UNALIGNED_LOAD64LE(p) << ((8 - length) * 8)) * kHashMul32;
45 return (uint32_t)(h >> shift);
46 }
47
HashBytesAtOffset(uint64_t v,size_t offset,size_t shift,size_t length)48 static BROTLI_INLINE uint32_t HashBytesAtOffset(uint64_t v, size_t offset,
49 size_t shift, size_t length) {
50 BROTLI_DCHECK(offset <= 8 - length);
51 {
52 const uint64_t h = ((v >> (8 * offset)) << ((8 - length) * 8)) * kHashMul32;
53 return (uint32_t)(h >> shift);
54 }
55 }
56
IsMatch(const uint8_t * p1,const uint8_t * p2,size_t length)57 static BROTLI_INLINE BROTLI_BOOL IsMatch(const uint8_t* p1, const uint8_t* p2,
58 size_t length) {
59 if (BrotliUnalignedRead32(p1) == BrotliUnalignedRead32(p2)) {
60 if (length == 4) return BROTLI_TRUE;
61 return TO_BROTLI_BOOL(p1[4] == p2[4] && p1[5] == p2[5]);
62 }
63 return BROTLI_FALSE;
64 }
65
66 /* Builds a command and distance prefix code (each 64 symbols) into "depth" and
67 "bits" based on "histogram" and stores it into the bit stream. */
BuildAndStoreCommandPrefixCode(BrotliTwoPassArena * s,size_t * storage_ix,uint8_t * storage)68 static void BuildAndStoreCommandPrefixCode(BrotliTwoPassArena* s,
69 size_t* storage_ix,
70 uint8_t* storage) {
71 /* Tree size for building a tree over 64 symbols is 2 * 64 + 1. */
72 /* TODO(eustas): initialize once. */
73 memset(s->tmp_depth, 0, sizeof(s->tmp_depth));
74 BrotliCreateHuffmanTree(s->cmd_histo, 64, 15, s->tmp_tree, s->cmd_depth);
75 BrotliCreateHuffmanTree(&s->cmd_histo[64], 64, 14, s->tmp_tree,
76 &s->cmd_depth[64]);
77 /* We have to jump through a few hoops here in order to compute
78 the command bits because the symbols are in a different order than in
79 the full alphabet. This looks complicated, but having the symbols
80 in this order in the command bits saves a few branches in the Emit*
81 functions. */
82 memcpy(s->tmp_depth, s->cmd_depth + 24, 24);
83 memcpy(s->tmp_depth + 24, s->cmd_depth, 8);
84 memcpy(s->tmp_depth + 32, s->cmd_depth + 48, 8);
85 memcpy(s->tmp_depth + 40, s->cmd_depth + 8, 8);
86 memcpy(s->tmp_depth + 48, s->cmd_depth + 56, 8);
87 memcpy(s->tmp_depth + 56, s->cmd_depth + 16, 8);
88 BrotliConvertBitDepthsToSymbols(s->tmp_depth, 64, s->tmp_bits);
89 memcpy(s->cmd_bits, s->tmp_bits + 24, 16);
90 memcpy(s->cmd_bits + 8, s->tmp_bits + 40, 16);
91 memcpy(s->cmd_bits + 16, s->tmp_bits + 56, 16);
92 memcpy(s->cmd_bits + 24, s->tmp_bits, 48);
93 memcpy(s->cmd_bits + 48, s->tmp_bits + 32, 16);
94 memcpy(s->cmd_bits + 56, s->tmp_bits + 48, 16);
95 BrotliConvertBitDepthsToSymbols(&s->cmd_depth[64], 64, &s->cmd_bits[64]);
96 {
97 /* Create the bit length array for the full command alphabet. */
98 size_t i;
99 memset(s->tmp_depth, 0, 64); /* only 64 first values were used */
100 memcpy(s->tmp_depth, s->cmd_depth + 24, 8);
101 memcpy(s->tmp_depth + 64, s->cmd_depth + 32, 8);
102 memcpy(s->tmp_depth + 128, s->cmd_depth + 40, 8);
103 memcpy(s->tmp_depth + 192, s->cmd_depth + 48, 8);
104 memcpy(s->tmp_depth + 384, s->cmd_depth + 56, 8);
105 for (i = 0; i < 8; ++i) {
106 s->tmp_depth[128 + 8 * i] = s->cmd_depth[i];
107 s->tmp_depth[256 + 8 * i] = s->cmd_depth[8 + i];
108 s->tmp_depth[448 + 8 * i] = s->cmd_depth[16 + i];
109 }
110 BrotliStoreHuffmanTree(s->tmp_depth, BROTLI_NUM_COMMAND_SYMBOLS,
111 s->tmp_tree, storage_ix, storage);
112 }
113 BrotliStoreHuffmanTree(&s->cmd_depth[64], 64, s->tmp_tree, storage_ix,
114 storage);
115 }
116
EmitInsertLen(uint32_t insertlen,uint32_t ** commands)117 static BROTLI_INLINE void EmitInsertLen(
118 uint32_t insertlen, uint32_t** commands) {
119 if (insertlen < 6) {
120 **commands = insertlen;
121 } else if (insertlen < 130) {
122 const uint32_t tail = insertlen - 2;
123 const uint32_t nbits = Log2FloorNonZero(tail) - 1u;
124 const uint32_t prefix = tail >> nbits;
125 const uint32_t inscode = (nbits << 1) + prefix + 2;
126 const uint32_t extra = tail - (prefix << nbits);
127 **commands = inscode | (extra << 8);
128 } else if (insertlen < 2114) {
129 const uint32_t tail = insertlen - 66;
130 const uint32_t nbits = Log2FloorNonZero(tail);
131 const uint32_t code = nbits + 10;
132 const uint32_t extra = tail - (1u << nbits);
133 **commands = code | (extra << 8);
134 } else if (insertlen < 6210) {
135 const uint32_t extra = insertlen - 2114;
136 **commands = 21 | (extra << 8);
137 } else if (insertlen < 22594) {
138 const uint32_t extra = insertlen - 6210;
139 **commands = 22 | (extra << 8);
140 } else {
141 const uint32_t extra = insertlen - 22594;
142 **commands = 23 | (extra << 8);
143 }
144 ++(*commands);
145 }
146
EmitCopyLen(size_t copylen,uint32_t ** commands)147 static BROTLI_INLINE void EmitCopyLen(size_t copylen, uint32_t** commands) {
148 if (copylen < 10) {
149 **commands = (uint32_t)(copylen + 38);
150 } else if (copylen < 134) {
151 const size_t tail = copylen - 6;
152 const size_t nbits = Log2FloorNonZero(tail) - 1;
153 const size_t prefix = tail >> nbits;
154 const size_t code = (nbits << 1) + prefix + 44;
155 const size_t extra = tail - (prefix << nbits);
156 **commands = (uint32_t)(code | (extra << 8));
157 } else if (copylen < 2118) {
158 const size_t tail = copylen - 70;
159 const size_t nbits = Log2FloorNonZero(tail);
160 const size_t code = nbits + 52;
161 const size_t extra = tail - ((size_t)1 << nbits);
162 **commands = (uint32_t)(code | (extra << 8));
163 } else {
164 const size_t extra = copylen - 2118;
165 **commands = (uint32_t)(63 | (extra << 8));
166 }
167 ++(*commands);
168 }
169
EmitCopyLenLastDistance(size_t copylen,uint32_t ** commands)170 static BROTLI_INLINE void EmitCopyLenLastDistance(
171 size_t copylen, uint32_t** commands) {
172 if (copylen < 12) {
173 **commands = (uint32_t)(copylen + 20);
174 ++(*commands);
175 } else if (copylen < 72) {
176 const size_t tail = copylen - 8;
177 const size_t nbits = Log2FloorNonZero(tail) - 1;
178 const size_t prefix = tail >> nbits;
179 const size_t code = (nbits << 1) + prefix + 28;
180 const size_t extra = tail - (prefix << nbits);
181 **commands = (uint32_t)(code | (extra << 8));
182 ++(*commands);
183 } else if (copylen < 136) {
184 const size_t tail = copylen - 8;
185 const size_t code = (tail >> 5) + 54;
186 const size_t extra = tail & 31;
187 **commands = (uint32_t)(code | (extra << 8));
188 ++(*commands);
189 **commands = 64;
190 ++(*commands);
191 } else if (copylen < 2120) {
192 const size_t tail = copylen - 72;
193 const size_t nbits = Log2FloorNonZero(tail);
194 const size_t code = nbits + 52;
195 const size_t extra = tail - ((size_t)1 << nbits);
196 **commands = (uint32_t)(code | (extra << 8));
197 ++(*commands);
198 **commands = 64;
199 ++(*commands);
200 } else {
201 const size_t extra = copylen - 2120;
202 **commands = (uint32_t)(63 | (extra << 8));
203 ++(*commands);
204 **commands = 64;
205 ++(*commands);
206 }
207 }
208
EmitDistance(uint32_t distance,uint32_t ** commands)209 static BROTLI_INLINE void EmitDistance(uint32_t distance, uint32_t** commands) {
210 uint32_t d = distance + 3;
211 uint32_t nbits = Log2FloorNonZero(d) - 1;
212 const uint32_t prefix = (d >> nbits) & 1;
213 const uint32_t offset = (2 + prefix) << nbits;
214 const uint32_t distcode = 2 * (nbits - 1) + prefix + 80;
215 uint32_t extra = d - offset;
216 **commands = distcode | (extra << 8);
217 ++(*commands);
218 }
219
220 /* REQUIRES: len <= 1 << 24. */
BrotliStoreMetaBlockHeader(size_t len,BROTLI_BOOL is_uncompressed,size_t * storage_ix,uint8_t * storage)221 static void BrotliStoreMetaBlockHeader(
222 size_t len, BROTLI_BOOL is_uncompressed, size_t* storage_ix,
223 uint8_t* storage) {
224 size_t nibbles = 6;
225 /* ISLAST */
226 BrotliWriteBits(1, 0, storage_ix, storage);
227 if (len <= (1U << 16)) {
228 nibbles = 4;
229 } else if (len <= (1U << 20)) {
230 nibbles = 5;
231 }
232 BrotliWriteBits(2, nibbles - 4, storage_ix, storage);
233 BrotliWriteBits(nibbles * 4, len - 1, storage_ix, storage);
234 /* ISUNCOMPRESSED */
235 BrotliWriteBits(1, (uint64_t)is_uncompressed, storage_ix, storage);
236 }
237
CreateCommands(const uint8_t * input,size_t block_size,size_t input_size,const uint8_t * base_ip,int * table,size_t table_bits,size_t min_match,uint8_t ** literals,uint32_t ** commands)238 static BROTLI_INLINE void CreateCommands(const uint8_t* input,
239 size_t block_size, size_t input_size, const uint8_t* base_ip, int* table,
240 size_t table_bits, size_t min_match,
241 uint8_t** literals, uint32_t** commands) {
242 /* "ip" is the input pointer. */
243 const uint8_t* ip = input;
244 const size_t shift = 64u - table_bits;
245 const uint8_t* ip_end = input + block_size;
246 /* "next_emit" is a pointer to the first byte that is not covered by a
247 previous copy. Bytes between "next_emit" and the start of the next copy or
248 the end of the input will be emitted as literal bytes. */
249 const uint8_t* next_emit = input;
250
251 int last_distance = -1;
252 const size_t kInputMarginBytes = BROTLI_WINDOW_GAP;
253
254 if (BROTLI_PREDICT_TRUE(block_size >= kInputMarginBytes)) {
255 /* For the last block, we need to keep a 16 bytes margin so that we can be
256 sure that all distances are at most window size - 16.
257 For all other blocks, we only need to keep a margin of 5 bytes so that
258 we don't go over the block size with a copy. */
259 const size_t len_limit = BROTLI_MIN(size_t, block_size - min_match,
260 input_size - kInputMarginBytes);
261 const uint8_t* ip_limit = input + len_limit;
262
263 uint32_t next_hash;
264 for (next_hash = Hash(++ip, shift, min_match); ; ) {
265 /* Step 1: Scan forward in the input looking for a 6-byte-long match.
266 If we get close to exhausting the input then goto emit_remainder.
267
268 Heuristic match skipping: If 32 bytes are scanned with no matches
269 found, start looking only at every other byte. If 32 more bytes are
270 scanned, look at every third byte, etc.. When a match is found,
271 immediately go back to looking at every byte. This is a small loss
272 (~5% performance, ~0.1% density) for compressible data due to more
273 bookkeeping, but for non-compressible data (such as JPEG) it's a huge
274 win since the compressor quickly "realizes" the data is incompressible
275 and doesn't bother looking for matches everywhere.
276
277 The "skip" variable keeps track of how many bytes there are since the
278 last match; dividing it by 32 (ie. right-shifting by five) gives the
279 number of bytes to move ahead for each iteration. */
280 uint32_t skip = 32;
281
282 const uint8_t* next_ip = ip;
283 const uint8_t* candidate;
284
285 BROTLI_DCHECK(next_emit < ip);
286 trawl:
287 do {
288 uint32_t hash = next_hash;
289 uint32_t bytes_between_hash_lookups = skip++ >> 5;
290 ip = next_ip;
291 BROTLI_DCHECK(hash == Hash(ip, shift, min_match));
292 next_ip = ip + bytes_between_hash_lookups;
293 if (BROTLI_PREDICT_FALSE(next_ip > ip_limit)) {
294 goto emit_remainder;
295 }
296 next_hash = Hash(next_ip, shift, min_match);
297 candidate = ip - last_distance;
298 if (IsMatch(ip, candidate, min_match)) {
299 if (BROTLI_PREDICT_TRUE(candidate < ip)) {
300 table[hash] = (int)(ip - base_ip);
301 break;
302 }
303 }
304 candidate = base_ip + table[hash];
305 BROTLI_DCHECK(candidate >= base_ip);
306 BROTLI_DCHECK(candidate < ip);
307
308 table[hash] = (int)(ip - base_ip);
309 } while (BROTLI_PREDICT_TRUE(!IsMatch(ip, candidate, min_match)));
310
311 /* Check copy distance. If candidate is not feasible, continue search.
312 Checking is done outside of hot loop to reduce overhead. */
313 if (ip - candidate > MAX_DISTANCE) goto trawl;
314
315 /* Step 2: Emit the found match together with the literal bytes from
316 "next_emit", and then see if we can find a next match immediately
317 afterwards. Repeat until we find no match for the input
318 without emitting some literal bytes. */
319
320 {
321 /* We have a 6-byte match at ip, and we need to emit bytes in
322 [next_emit, ip). */
323 const uint8_t* base = ip;
324 size_t matched = min_match + FindMatchLengthWithLimit(
325 candidate + min_match, ip + min_match,
326 (size_t)(ip_end - ip) - min_match);
327 int distance = (int)(base - candidate); /* > 0 */
328 int insert = (int)(base - next_emit);
329 ip += matched;
330 BROTLI_DCHECK(0 == memcmp(base, candidate, matched));
331 EmitInsertLen((uint32_t)insert, commands);
332 BROTLI_LOG(("[CompressFragment] pos = %d insert = %d copy = %d\n",
333 (int)(next_emit - base_ip), insert, 2));
334 memcpy(*literals, next_emit, (size_t)insert);
335 *literals += insert;
336 if (distance == last_distance) {
337 **commands = 64;
338 ++(*commands);
339 } else {
340 EmitDistance((uint32_t)distance, commands);
341 last_distance = distance;
342 }
343 EmitCopyLenLastDistance(matched, commands);
344 BROTLI_LOG(("[CompressFragment] pos = %d distance = %d\n"
345 "[CompressFragment] pos = %d insert = %d copy = %d\n"
346 "[CompressFragment] pos = %d distance = %d\n",
347 (int)(base - base_ip), (int)distance,
348 (int)(base - base_ip) + 2, 0, (int)matched - 2,
349 (int)(base - base_ip) + 2, (int)distance));
350
351 next_emit = ip;
352 if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) {
353 goto emit_remainder;
354 }
355 {
356 /* We could immediately start working at ip now, but to improve
357 compression we first update "table" with the hashes of some
358 positions within the last copy. */
359 uint64_t input_bytes;
360 uint32_t cur_hash;
361 uint32_t prev_hash;
362 if (min_match == 4) {
363 input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3);
364 cur_hash = HashBytesAtOffset(input_bytes, 3, shift, min_match);
365 prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);
366 table[prev_hash] = (int)(ip - base_ip - 3);
367 prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);
368 table[prev_hash] = (int)(ip - base_ip - 2);
369 prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);
370 table[prev_hash] = (int)(ip - base_ip - 1);
371 } else {
372 input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 5);
373 prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);
374 table[prev_hash] = (int)(ip - base_ip - 5);
375 prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);
376 table[prev_hash] = (int)(ip - base_ip - 4);
377 prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);
378 table[prev_hash] = (int)(ip - base_ip - 3);
379 input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 2);
380 cur_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);
381 prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);
382 table[prev_hash] = (int)(ip - base_ip - 2);
383 prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);
384 table[prev_hash] = (int)(ip - base_ip - 1);
385 }
386
387 candidate = base_ip + table[cur_hash];
388 table[cur_hash] = (int)(ip - base_ip);
389 }
390 }
391
392 while (ip - candidate <= MAX_DISTANCE &&
393 IsMatch(ip, candidate, min_match)) {
394 /* We have a 6-byte match at ip, and no need to emit any
395 literal bytes prior to ip. */
396 const uint8_t* base = ip;
397 size_t matched = min_match + FindMatchLengthWithLimit(
398 candidate + min_match, ip + min_match,
399 (size_t)(ip_end - ip) - min_match);
400 ip += matched;
401 last_distance = (int)(base - candidate); /* > 0 */
402 BROTLI_DCHECK(0 == memcmp(base, candidate, matched));
403 EmitCopyLen(matched, commands);
404 EmitDistance((uint32_t)last_distance, commands);
405 BROTLI_LOG(("[CompressFragment] pos = %d insert = %d copy = %d\n"
406 "[CompressFragment] pos = %d distance = %d\n",
407 (int)(base - base_ip), 0, (int)matched,
408 (int)(base - base_ip), (int)last_distance));
409
410 next_emit = ip;
411 if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) {
412 goto emit_remainder;
413 }
414 {
415 /* We could immediately start working at ip now, but to improve
416 compression we first update "table" with the hashes of some
417 positions within the last copy. */
418 uint64_t input_bytes;
419 uint32_t cur_hash;
420 uint32_t prev_hash;
421 if (min_match == 4) {
422 input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3);
423 cur_hash = HashBytesAtOffset(input_bytes, 3, shift, min_match);
424 prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);
425 table[prev_hash] = (int)(ip - base_ip - 3);
426 prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);
427 table[prev_hash] = (int)(ip - base_ip - 2);
428 prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);
429 table[prev_hash] = (int)(ip - base_ip - 1);
430 } else {
431 input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 5);
432 prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);
433 table[prev_hash] = (int)(ip - base_ip - 5);
434 prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);
435 table[prev_hash] = (int)(ip - base_ip - 4);
436 prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);
437 table[prev_hash] = (int)(ip - base_ip - 3);
438 input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 2);
439 cur_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);
440 prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);
441 table[prev_hash] = (int)(ip - base_ip - 2);
442 prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);
443 table[prev_hash] = (int)(ip - base_ip - 1);
444 }
445
446 candidate = base_ip + table[cur_hash];
447 table[cur_hash] = (int)(ip - base_ip);
448 }
449 }
450
451 next_hash = Hash(++ip, shift, min_match);
452 }
453 }
454
455 emit_remainder:
456 BROTLI_DCHECK(next_emit <= ip_end);
457 /* Emit the remaining bytes as literals. */
458 if (next_emit < ip_end) {
459 const uint32_t insert = (uint32_t)(ip_end - next_emit);
460 EmitInsertLen(insert, commands);
461 BROTLI_LOG(("[CompressFragment] pos = %d insert = %d copy = %d\n",
462 (int)(next_emit - base_ip), insert, 2));
463 memcpy(*literals, next_emit, insert);
464 *literals += insert;
465 }
466 }
467
StoreCommands(BrotliTwoPassArena * s,const uint8_t * literals,const size_t num_literals,const uint32_t * commands,const size_t num_commands,size_t * storage_ix,uint8_t * storage)468 static void StoreCommands(BrotliTwoPassArena* s,
469 const uint8_t* literals, const size_t num_literals,
470 const uint32_t* commands, const size_t num_commands,
471 size_t* storage_ix, uint8_t* storage) {
472 static const uint32_t kNumExtraBits[128] = {
473 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5,
474 6, 7, 8, 9, 10, 12, 14, 24, 0, 0, 0, 0, 0, 0, 0, 0,
475 1, 1, 2, 2, 3, 3, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0,
476 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 24,
477 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
478 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
479 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16,
480 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24,
481 };
482 static const uint32_t kInsertOffset[24] = {
483 0, 1, 2, 3, 4, 5, 6, 8, 10, 14, 18, 26,
484 34, 50, 66, 98, 130, 194, 322, 578, 1090, 2114, 6210, 22594,
485 };
486
487 size_t i;
488 memset(s->lit_histo, 0, sizeof(s->lit_histo));
489 /* TODO(eustas): is that necessary? */
490 memset(s->cmd_depth, 0, sizeof(s->cmd_depth));
491 /* TODO(eustas): is that necessary? */
492 memset(s->cmd_bits, 0, sizeof(s->cmd_bits));
493 memset(s->cmd_histo, 0, sizeof(s->cmd_histo));
494 for (i = 0; i < num_literals; ++i) {
495 ++s->lit_histo[literals[i]];
496 }
497 BrotliBuildAndStoreHuffmanTreeFast(s->tmp_tree, s->lit_histo, num_literals,
498 /* max_bits = */ 8, s->lit_depth,
499 s->lit_bits, storage_ix, storage);
500
501 for (i = 0; i < num_commands; ++i) {
502 const uint32_t code = commands[i] & 0xFF;
503 BROTLI_DCHECK(code < 128);
504 ++s->cmd_histo[code];
505 }
506 s->cmd_histo[1] += 1;
507 s->cmd_histo[2] += 1;
508 s->cmd_histo[64] += 1;
509 s->cmd_histo[84] += 1;
510 BuildAndStoreCommandPrefixCode(s, storage_ix, storage);
511
512 for (i = 0; i < num_commands; ++i) {
513 const uint32_t cmd = commands[i];
514 const uint32_t code = cmd & 0xFF;
515 const uint32_t extra = cmd >> 8;
516 BROTLI_DCHECK(code < 128);
517 BrotliWriteBits(s->cmd_depth[code], s->cmd_bits[code], storage_ix, storage);
518 BrotliWriteBits(kNumExtraBits[code], extra, storage_ix, storage);
519 if (code < 24) {
520 const uint32_t insert = kInsertOffset[code] + extra;
521 uint32_t j;
522 for (j = 0; j < insert; ++j) {
523 const uint8_t lit = *literals;
524 BrotliWriteBits(s->lit_depth[lit], s->lit_bits[lit], storage_ix,
525 storage);
526 ++literals;
527 }
528 }
529 }
530 }
531
532 /* Acceptable loss for uncompressible speedup is 2% */
533 #define MIN_RATIO 0.98
534 #define SAMPLE_RATE 43
535
ShouldCompress(BrotliTwoPassArena * s,const uint8_t * input,size_t input_size,size_t num_literals)536 static BROTLI_BOOL ShouldCompress(BrotliTwoPassArena* s,
537 const uint8_t* input, size_t input_size, size_t num_literals) {
538 double corpus_size = (double)input_size;
539 if ((double)num_literals < MIN_RATIO * corpus_size) {
540 return BROTLI_TRUE;
541 } else {
542 const double max_total_bit_cost = corpus_size * 8 * MIN_RATIO / SAMPLE_RATE;
543 size_t i;
544 memset(s->lit_histo, 0, sizeof(s->lit_histo));
545 for (i = 0; i < input_size; i += SAMPLE_RATE) {
546 ++s->lit_histo[input[i]];
547 }
548 return TO_BROTLI_BOOL(BitsEntropy(s->lit_histo, 256) < max_total_bit_cost);
549 }
550 }
551
RewindBitPosition(const size_t new_storage_ix,size_t * storage_ix,uint8_t * storage)552 static void RewindBitPosition(const size_t new_storage_ix,
553 size_t* storage_ix, uint8_t* storage) {
554 const size_t bitpos = new_storage_ix & 7;
555 const size_t mask = (1u << bitpos) - 1;
556 storage[new_storage_ix >> 3] &= (uint8_t)mask;
557 *storage_ix = new_storage_ix;
558 }
559
EmitUncompressedMetaBlock(const uint8_t * input,size_t input_size,size_t * storage_ix,uint8_t * storage)560 static void EmitUncompressedMetaBlock(const uint8_t* input, size_t input_size,
561 size_t* storage_ix, uint8_t* storage) {
562 BrotliStoreMetaBlockHeader(input_size, 1, storage_ix, storage);
563 *storage_ix = (*storage_ix + 7u) & ~7u;
564 memcpy(&storage[*storage_ix >> 3], input, input_size);
565 *storage_ix += input_size << 3;
566 storage[*storage_ix >> 3] = 0;
567 }
568
BrotliCompressFragmentTwoPassImpl(BrotliTwoPassArena * s,const uint8_t * input,size_t input_size,BROTLI_BOOL is_last,uint32_t * command_buf,uint8_t * literal_buf,int * table,size_t table_bits,size_t min_match,size_t * storage_ix,uint8_t * storage)569 static BROTLI_INLINE void BrotliCompressFragmentTwoPassImpl(
570 BrotliTwoPassArena* s, const uint8_t* input, size_t input_size,
571 BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf,
572 int* table, size_t table_bits, size_t min_match,
573 size_t* storage_ix, uint8_t* storage) {
574 /* Save the start of the first block for position and distance computations.
575 */
576 const uint8_t* base_ip = input;
577 BROTLI_UNUSED(is_last);
578
579 while (input_size > 0) {
580 size_t block_size =
581 BROTLI_MIN(size_t, input_size, kCompressFragmentTwoPassBlockSize);
582 uint32_t* commands = command_buf;
583 uint8_t* literals = literal_buf;
584 size_t num_literals;
585 CreateCommands(input, block_size, input_size, base_ip, table,
586 table_bits, min_match, &literals, &commands);
587 num_literals = (size_t)(literals - literal_buf);
588 if (ShouldCompress(s, input, block_size, num_literals)) {
589 const size_t num_commands = (size_t)(commands - command_buf);
590 BrotliStoreMetaBlockHeader(block_size, 0, storage_ix, storage);
591 /* No block splits, no contexts. */
592 BrotliWriteBits(13, 0, storage_ix, storage);
593 StoreCommands(s, literal_buf, num_literals, command_buf, num_commands,
594 storage_ix, storage);
595 } else {
596 /* Since we did not find many backward references and the entropy of
597 the data is close to 8 bits, we can simply emit an uncompressed block.
598 This makes compression speed of uncompressible data about 3x faster. */
599 EmitUncompressedMetaBlock(input, block_size, storage_ix, storage);
600 }
601 input += block_size;
602 input_size -= block_size;
603 }
604 }
605
606 #define FOR_TABLE_BITS_(X) \
607 X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17)
608
609 #define BAKE_METHOD_PARAM_(B) \
610 static BROTLI_NOINLINE void BrotliCompressFragmentTwoPassImpl ## B( \
611 BrotliTwoPassArena* s, const uint8_t* input, size_t input_size, \
612 BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf, \
613 int* table, size_t* storage_ix, uint8_t* storage) { \
614 size_t min_match = (B <= 15) ? 4 : 6; \
615 BrotliCompressFragmentTwoPassImpl(s, input, input_size, is_last, command_buf,\
616 literal_buf, table, B, min_match, storage_ix, storage); \
617 }
FOR_TABLE_BITS_(BAKE_METHOD_PARAM_)618 FOR_TABLE_BITS_(BAKE_METHOD_PARAM_)
619 #undef BAKE_METHOD_PARAM_
620
621 void BrotliCompressFragmentTwoPass(
622 BrotliTwoPassArena* s, const uint8_t* input, size_t input_size,
623 BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf,
624 int* table, size_t table_size, size_t* storage_ix, uint8_t* storage) {
625 const size_t initial_storage_ix = *storage_ix;
626 const size_t table_bits = Log2FloorNonZero(table_size);
627 switch (table_bits) {
628 #define CASE_(B) \
629 case B: \
630 BrotliCompressFragmentTwoPassImpl ## B( \
631 s, input, input_size, is_last, command_buf, \
632 literal_buf, table, storage_ix, storage); \
633 break;
634 FOR_TABLE_BITS_(CASE_)
635 #undef CASE_
636 default: BROTLI_DCHECK(0); break;
637 }
638
639 /* If output is larger than single uncompressed block, rewrite it. */
640 if (*storage_ix - initial_storage_ix > 31 + (input_size << 3)) {
641 RewindBitPosition(initial_storage_ix, storage_ix, storage);
642 EmitUncompressedMetaBlock(input, input_size, storage_ix, storage);
643 }
644
645 if (is_last) {
646 BrotliWriteBits(1, 1, storage_ix, storage); /* islast */
647 BrotliWriteBits(1, 1, storage_ix, storage); /* isempty */
648 *storage_ix = (*storage_ix + 7u) & ~7u;
649 }
650 }
651
652 #undef FOR_TABLE_BITS_
653
654 #if defined(__cplusplus) || defined(c_plusplus)
655 } /* extern "C" */
656 #endif
657