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