blob: 6603eecdf7ccc6097e63c70da6886e61a25c2e56 [file] [log] [blame]
Zoltan Szabadka79e99af2013-10-23 13:06:13 +02001// Copyright 2013 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// Implementation of Brotli compressor.
16
17#include "./encode.h"
18
19#include <algorithm>
20#include <limits>
21
22#include "./backward_references.h"
23#include "./bit_cost.h"
24#include "./block_splitter.h"
25#include "./cluster.h"
26#include "./context.h"
27#include "./entropy_encode.h"
28#include "./fast_log.h"
Zoltan Szabadka1571db32013-11-15 19:02:17 +010029#include "./hash.h"
Zoltan Szabadka79e99af2013-10-23 13:06:13 +020030#include "./histogram.h"
Zoltan Szabadka1571db32013-11-15 19:02:17 +010031#include "./literal_cost.h"
Zoltan Szabadka79e99af2013-10-23 13:06:13 +020032#include "./prefix.h"
33#include "./write_bits.h"
34
35namespace brotli {
36
Roderick Sheeter437bbad2013-11-19 14:32:56 -080037static const int kWindowBits = 22;
38// To make decoding faster, we allow the decoder to write 16 bytes ahead in
39// its ringbuffer, therefore the encoder has to decrease max distance by this
40// amount.
41static const int kDecoderRingBufferWriteAheadSlack = 16;
42static const int kMaxBackwardDistance =
43 (1 << kWindowBits) - kDecoderRingBufferWriteAheadSlack;
44
45static const int kMetaBlockSizeBits = 21;
46static const int kRingBufferBits = 23;
47static const int kRingBufferMask = (1 << kRingBufferBits) - 1;
48
Zoltan Szabadka79e99af2013-10-23 13:06:13 +020049template<int kSize>
50double Entropy(const std::vector<Histogram<kSize> >& histograms) {
51 double retval = 0;
52 for (int i = 0; i < histograms.size(); ++i) {
53 retval += histograms[i].EntropyBitCost();
54 }
55 return retval;
56}
57
Zoltan Szabadka1571db32013-11-15 19:02:17 +010058template<int kSize>
59double TotalBitCost(const std::vector<Histogram<kSize> >& histograms) {
60 double retval = 0;
61 for (int i = 0; i < histograms.size(); ++i) {
62 retval += PopulationCost(histograms[i]);
63 }
64 return retval;
65}
66
Zoltan Szabadkae7094912013-12-12 13:18:04 +010067void EncodeVarLenUint8(int n, int* storage_ix, uint8_t* storage) {
68 if (n == 0) {
69 WriteBits(1, 0, storage_ix, storage);
70 } else {
71 WriteBits(1, 1, storage_ix, storage);
72 int nbits = Log2Floor(n);
73 WriteBits(3, nbits, storage_ix, storage);
74 if (nbits > 0) {
75 WriteBits(nbits, n - (1 << nbits), storage_ix, storage);
76 }
Zoltan Szabadka79e99af2013-10-23 13:06:13 +020077 }
78}
79
Zoltan Szabadkacbd5cb52014-02-14 15:04:23 +010080int ParseAsUTF8(int* symbol, const uint8_t* input, int size) {
81 // ASCII
82 if ((input[0] & 0x80) == 0) {
83 *symbol = input[0];
84 if (*symbol > 0) {
85 return 1;
86 }
87 }
88 // 2-byte UTF8
89 if (size > 1 &&
90 (input[0] & 0xe0) == 0xc0 &&
91 (input[1] & 0xc0) == 0x80) {
92 *symbol = (((input[0] & 0x1f) << 6) |
93 (input[1] & 0x3f));
94 if (*symbol > 0x7f) {
95 return 2;
96 }
97 }
98 // 3-byte UFT8
99 if (size > 2 &&
100 (input[0] & 0xf0) == 0xe0 &&
101 (input[1] & 0xc0) == 0x80 &&
102 (input[2] & 0xc0) == 0x80) {
103 *symbol = (((input[0] & 0x0f) << 12) |
104 ((input[1] & 0x3f) << 6) |
105 (input[2] & 0x3f));
106 if (*symbol > 0x7ff) {
107 return 3;
108 }
109 }
110 // 4-byte UFT8
111 if (size > 3 &&
112 (input[0] & 0xf8) == 0xf0 &&
113 (input[1] & 0xc0) == 0x80 &&
114 (input[2] & 0xc0) == 0x80 &&
115 (input[3] & 0xc0) == 0x80) {
116 *symbol = (((input[0] & 0x07) << 18) |
117 ((input[1] & 0x3f) << 12) |
118 ((input[2] & 0x3f) << 6) |
119 (input[3] & 0x3f));
120 if (*symbol > 0xffff && *symbol <= 0x10ffff) {
121 return 4;
122 }
123 }
124 // Not UTF8, emit a special symbol above the UTF8-code space
125 *symbol = 0x110000 | input[0];
126 return 1;
127}
128
129// Returns true if at least min_fraction of the data is UTF8-encoded.
130bool IsMostlyUTF8(const uint8_t* data, size_t length, double min_fraction) {
131 size_t size_utf8 = 0;
132 size_t pos = 0;
133 while (pos < length) {
134 int symbol;
135 int bytes_read = ParseAsUTF8(&symbol, data + pos, length - pos);
136 pos += bytes_read;
137 if (symbol < 0x110000) size_utf8 += bytes_read;
138 }
139 return size_utf8 > min_fraction * length;
140}
141
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100142void EncodeMetaBlockLength(size_t meta_block_size,
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100143 bool is_last,
144 bool is_uncompressed,
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200145 int* storage_ix, uint8_t* storage) {
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100146 WriteBits(1, is_last, storage_ix, storage);
147 if (is_last) {
148 if (meta_block_size == 0) {
149 WriteBits(1, 1, storage_ix, storage);
150 return;
151 }
152 WriteBits(1, 0, storage_ix, storage);
153 }
154 --meta_block_size;
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100155 int num_bits = Log2Floor(meta_block_size) + 1;
Zoltan Szabadkafe79fac2013-11-28 17:37:13 +0100156 if (num_bits < 16) {
157 num_bits = 16;
158 }
159 WriteBits(2, (num_bits - 13) >> 2, storage_ix, storage);
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100160 while (num_bits > 0) {
161 WriteBits(4, meta_block_size & 0xf, storage_ix, storage);
162 meta_block_size >>= 4;
163 num_bits -= 4;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200164 }
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100165 if (!is_last) {
166 WriteBits(1, is_uncompressed, storage_ix, storage);
167 }
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200168}
169
170template<int kSize>
171void EntropyEncode(int val, const EntropyCode<kSize>& code,
172 int* storage_ix, uint8_t* storage) {
173 if (code.count_ <= 1) {
174 return;
175 };
176 WriteBits(code.depth_[val], code.bits_[val], storage_ix, storage);
177}
178
179void StoreHuffmanTreeOfHuffmanTreeToBitMask(
180 const uint8_t* code_length_bitdepth,
181 int* storage_ix, uint8_t* storage) {
182 static const uint8_t kStorageOrder[kCodeLengthCodes] = {
Zoltan Szabadkacbd5cb52014-02-14 15:04:23 +0100183 1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15,
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200184 };
185 // Throw away trailing zeros:
186 int codes_to_store = kCodeLengthCodes;
Zoltan Szabadkab89f3be2013-12-17 17:17:57 +0100187 for (; codes_to_store > 0; --codes_to_store) {
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200188 if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) {
189 break;
190 }
191 }
Zoltan Szabadkab89f3be2013-12-17 17:17:57 +0100192 int num_codes = 0;
193 for (int i = 0; i < codes_to_store; ++i) {
194 if (code_length_bitdepth[kStorageOrder[i]] != 0) {
195 ++num_codes;
196 }
197 }
198 if (num_codes == 1) {
199 codes_to_store = kCodeLengthCodes;
200 }
Zoltan Szabadka4c8c7fd2014-01-08 12:28:28 +0100201 int skip_some = 0; // skips none.
202 if (code_length_bitdepth[kStorageOrder[0]] == 0 &&
203 code_length_bitdepth[kStorageOrder[1]] == 0) {
204 skip_some = 2; // skips two.
205 if (code_length_bitdepth[kStorageOrder[2]] == 0) {
206 skip_some = 3; // skips three.
207 }
208 }
209 WriteBits(2, skip_some, storage_ix, storage);
210 for (int i = skip_some; i < codes_to_store; ++i) {
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100211 uint8_t len[] = { 2, 4, 3, 2, 2, 4 };
Zoltan Szabadkacbd5cb52014-02-14 15:04:23 +0100212 uint8_t bits[] = { 0, 7, 3, 2, 1, 15 };
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100213 int v = code_length_bitdepth[kStorageOrder[i]];
214 WriteBits(len[v], bits[v], storage_ix, storage);
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200215 }
216}
217
218void StoreHuffmanTreeToBitMask(
219 const uint8_t* huffman_tree,
220 const uint8_t* huffman_tree_extra_bits,
221 const int huffman_tree_size,
222 const EntropyCode<kCodeLengthCodes>& entropy,
223 int* storage_ix, uint8_t* storage) {
224 for (int i = 0; i < huffman_tree_size; ++i) {
225 const int ix = huffman_tree[i];
226 const int extra_bits = huffman_tree_extra_bits[i];
227 EntropyEncode(ix, entropy, storage_ix, storage);
228 switch (ix) {
229 case 16:
230 WriteBits(2, extra_bits, storage_ix, storage);
231 break;
232 case 17:
233 WriteBits(3, extra_bits, storage_ix, storage);
234 break;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200235 }
236 }
237}
238
239template<int kSize>
Zoltan Szabadkacbd5cb52014-02-14 15:04:23 +0100240void StoreHuffmanCodeSimple(
241 const EntropyCode<kSize>& code, int alphabet_size,
242 int max_bits,
243 int* storage_ix, uint8_t* storage) {
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100244 const uint8_t *depth = &code.depth_[0];
Zoltan Szabadkacbd5cb52014-02-14 15:04:23 +0100245 int symbols[4];
246 // Quadratic sort.
247 int k, j;
248 for (k = 0; k < code.count_; ++k) {
249 symbols[k] = code.symbols_[k];
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100250 }
Zoltan Szabadkacbd5cb52014-02-14 15:04:23 +0100251 for (k = 0; k < code.count_; ++k) {
252 for (j = k + 1; j < code.count_; ++j) {
253 if (depth[symbols[j]] < depth[symbols[k]]) {
254 int t = symbols[k];
255 symbols[k] = symbols[j];
256 symbols[j] = t;
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100257 }
258 }
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200259 }
Zoltan Szabadkacbd5cb52014-02-14 15:04:23 +0100260 // Small tree marker to encode 1-4 symbols.
261 WriteBits(2, 1, storage_ix, storage);
262 WriteBits(2, code.count_ - 1, storage_ix, storage);
263 for (int i = 0; i < code.count_; ++i) {
264 WriteBits(max_bits, symbols[i], storage_ix, storage);
265 }
266 if (code.count_ == 4) {
267 if (depth[symbols[0]] == 2 &&
268 depth[symbols[1]] == 2 &&
269 depth[symbols[2]] == 2 &&
270 depth[symbols[3]] == 2) {
271 WriteBits(1, 0, storage_ix, storage);
272 } else {
273 WriteBits(1, 1, storage_ix, storage);
274 }
275 }
276}
277
278template<int kSize>
279void StoreHuffmanCodeComplex(
280 const EntropyCode<kSize>& code, int alphabet_size,
281 int* storage_ix, uint8_t* storage) {
282 const uint8_t *depth = &code.depth_[0];
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200283 uint8_t huffman_tree[kSize];
284 uint8_t huffman_tree_extra_bits[kSize];
285 int huffman_tree_size = 0;
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100286 WriteHuffmanTree(depth,
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200287 alphabet_size,
288 &huffman_tree[0],
289 &huffman_tree_extra_bits[0],
290 &huffman_tree_size);
291 Histogram<kCodeLengthCodes> huffman_tree_histogram;
292 memset(huffman_tree_histogram.data_, 0, sizeof(huffman_tree_histogram.data_));
293 for (int i = 0; i < huffman_tree_size; ++i) {
294 huffman_tree_histogram.Add(huffman_tree[i]);
295 }
296 EntropyCode<kCodeLengthCodes> huffman_tree_entropy;
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100297 BuildEntropyCode(huffman_tree_histogram, 5, kCodeLengthCodes,
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200298 &huffman_tree_entropy);
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200299 StoreHuffmanTreeOfHuffmanTreeToBitMask(
300 &huffman_tree_entropy.depth_[0], storage_ix, storage);
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200301 StoreHuffmanTreeToBitMask(&huffman_tree[0], &huffman_tree_extra_bits[0],
302 huffman_tree_size, huffman_tree_entropy,
303 storage_ix, storage);
304}
305
Zoltan Szabadkacbd5cb52014-02-14 15:04:23 +0100306
307template<int kSize>
308void StoreHuffmanCode(const EntropyCode<kSize>& code, int alphabet_size,
309 int* storage_ix, uint8_t* storage) {
310 int max_bits_counter = alphabet_size - 1;
311 int max_bits = 0;
312 while (max_bits_counter) {
313 max_bits_counter >>= 1;
314 ++max_bits;
315 }
316 if (code.count_ == 0) {
317 // Emit a minimal tree for empty cases.
318 // bits: small tree marker: 1, count-1: 0, max_bits-sized encoding for 0
319 WriteBits(4 + max_bits, 0x1, storage_ix, storage);
320 } else if (code.count_ <= 4) {
321 StoreHuffmanCodeSimple(
322 code, alphabet_size, max_bits,
323 storage_ix, storage);
324 } else {
325 StoreHuffmanCodeComplex(
326 code, alphabet_size,
327 storage_ix, storage);
328 }
329}
330
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200331template<int kSize>
332void StoreHuffmanCodes(const std::vector<EntropyCode<kSize> >& codes,
333 int alphabet_size,
334 int* storage_ix, uint8_t* storage) {
335 for (int i = 0; i < codes.size(); ++i) {
336 StoreHuffmanCode(codes[i], alphabet_size, storage_ix, storage);
337 }
338}
339
340void EncodeCommand(const Command& cmd,
341 const EntropyCodeCommand& entropy,
342 int* storage_ix, uint8_t* storage) {
343 int code = cmd.command_prefix_;
344 EntropyEncode(code, entropy, storage_ix, storage);
345 if (code >= 128) {
346 code -= 128;
347 }
348 int insert_extra_bits = InsertLengthExtraBits(code);
349 uint64_t insert_extra_bits_val =
350 cmd.insert_length_ - InsertLengthOffset(code);
351 int copy_extra_bits = CopyLengthExtraBits(code);
Roderick Sheeter437bbad2013-11-19 14:32:56 -0800352 uint64_t copy_extra_bits_val = cmd.copy_length_code_ - CopyLengthOffset(code);
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200353 if (insert_extra_bits > 0) {
354 WriteBits(insert_extra_bits, insert_extra_bits_val, storage_ix, storage);
355 }
356 if (copy_extra_bits > 0) {
357 WriteBits(copy_extra_bits, copy_extra_bits_val, storage_ix, storage);
358 }
359}
360
361void EncodeCopyDistance(const Command& cmd, const EntropyCodeDistance& entropy,
362 int* storage_ix, uint8_t* storage) {
363 int code = cmd.distance_prefix_;
364 int extra_bits = cmd.distance_extra_bits_;
365 uint64_t extra_bits_val = cmd.distance_extra_bits_value_;
366 EntropyEncode(code, entropy, storage_ix, storage);
367 if (extra_bits > 0) {
368 WriteBits(extra_bits, extra_bits_val, storage_ix, storage);
369 }
370}
371
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100372void ComputeDistanceShortCodes(std::vector<Command>* cmds,
373 int* dist_ringbuffer,
374 size_t* ringbuffer_idx) {
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200375 static const int kIndexOffset[16] = {
376 3, 2, 1, 0, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2
377 };
378 static const int kValueOffset[16] = {
379 0, 0, 0, 0, -1, 1, -2, 2, -3, 3, -1, 1, -2, 2, -3, 3
380 };
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200381 for (int i = 0; i < cmds->size(); ++i) {
382 int cur_dist = (*cmds)[i].copy_distance_;
383 if (cur_dist == 0) break;
384 int dist_code = cur_dist + 16;
Zoltan Szabadkab89f3be2013-12-17 17:17:57 +0100385 int limits[16] = { 0, 4, 10, 11,
386 6, 6, 11, 11,
387 11, 11, 11, 11,
388 12, 12, 12, 12 };
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200389 for (int k = 0; k < 16; ++k) {
390 // Only accept more popular choices.
Zoltan Szabadkab89f3be2013-12-17 17:17:57 +0100391 if (cur_dist < limits[k]) {
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200392 // Typically unpopular ranges, don't replace a short distance
393 // with them.
394 continue;
395 }
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100396 int comp = (dist_ringbuffer[(*ringbuffer_idx + kIndexOffset[k]) & 3] +
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200397 kValueOffset[k]);
398 if (cur_dist == comp) {
399 dist_code = k + 1;
400 break;
401 }
402 }
403 if (dist_code > 1) {
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100404 dist_ringbuffer[*ringbuffer_idx & 3] = cur_dist;
405 ++(*ringbuffer_idx);
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200406 }
407 (*cmds)[i].distance_code_ = dist_code;
408 }
409}
410
411void ComputeCommandPrefixes(std::vector<Command>* cmds,
412 int num_direct_distance_codes,
413 int distance_postfix_bits) {
414 for (int i = 0; i < cmds->size(); ++i) {
415 Command* cmd = &(*cmds)[i];
416 cmd->command_prefix_ = CommandPrefix(cmd->insert_length_,
Roderick Sheeter437bbad2013-11-19 14:32:56 -0800417 cmd->copy_length_code_);
418 if (cmd->copy_length_code_ > 0) {
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200419 PrefixEncodeCopyDistance(cmd->distance_code_,
420 num_direct_distance_codes,
421 distance_postfix_bits,
422 &cmd->distance_prefix_,
423 &cmd->distance_extra_bits_,
424 &cmd->distance_extra_bits_value_);
425 }
426 if (cmd->command_prefix_ < 128 && cmd->distance_prefix_ == 0) {
427 cmd->distance_prefix_ = 0xffff;
428 } else {
429 cmd->command_prefix_ += 128;
430 }
431 }
432}
433
434int IndexOf(const std::vector<int>& v, int value) {
435 for (int i = 0; i < v.size(); ++i) {
436 if (v[i] == value) return i;
437 }
438 return -1;
439}
440
441void MoveToFront(std::vector<int>* v, int index) {
442 int value = (*v)[index];
443 for (int i = index; i > 0; --i) {
444 (*v)[i] = (*v)[i - 1];
445 }
446 (*v)[0] = value;
447}
448
449std::vector<int> MoveToFrontTransform(const std::vector<int>& v) {
450 if (v.empty()) return v;
451 std::vector<int> mtf(*max_element(v.begin(), v.end()) + 1);
452 for (int i = 0; i < mtf.size(); ++i) mtf[i] = i;
453 std::vector<int> result(v.size());
454 for (int i = 0; i < v.size(); ++i) {
455 int index = IndexOf(mtf, v[i]);
456 result[i] = index;
457 MoveToFront(&mtf, index);
458 }
459 return result;
460}
461
462// Finds runs of zeros in v_in and replaces them with a prefix code of the run
463// length plus extra bits in *v_out and *extra_bits. Non-zero values in v_in are
464// shifted by *max_length_prefix. Will not create prefix codes bigger than the
465// initial value of *max_run_length_prefix. The prefix code of run length L is
466// simply Log2Floor(L) and the number of extra bits is the same as the prefix
467// code.
468void RunLengthCodeZeros(const std::vector<int>& v_in,
469 int* max_run_length_prefix,
470 std::vector<int>* v_out,
471 std::vector<int>* extra_bits) {
472 int max_reps = 0;
473 for (int i = 0; i < v_in.size();) {
474 for (; i < v_in.size() && v_in[i] != 0; ++i) ;
475 int reps = 0;
476 for (; i < v_in.size() && v_in[i] == 0; ++i) {
477 ++reps;
478 }
479 max_reps = std::max(reps, max_reps);
480 }
481 int max_prefix = max_reps > 0 ? Log2Floor(max_reps) : 0;
482 *max_run_length_prefix = std::min(max_prefix, *max_run_length_prefix);
483 for (int i = 0; i < v_in.size();) {
484 if (v_in[i] != 0) {
485 v_out->push_back(v_in[i] + *max_run_length_prefix);
486 extra_bits->push_back(0);
487 ++i;
488 } else {
489 int reps = 1;
490 for (uint32_t k = i + 1; k < v_in.size() && v_in[k] == 0; ++k) {
491 ++reps;
492 }
493 i += reps;
494 while (reps) {
495 if (reps < (2 << *max_run_length_prefix)) {
496 int run_length_prefix = Log2Floor(reps);
497 v_out->push_back(run_length_prefix);
498 extra_bits->push_back(reps - (1 << run_length_prefix));
499 break;
500 } else {
501 v_out->push_back(*max_run_length_prefix);
502 extra_bits->push_back((1 << *max_run_length_prefix) - 1);
503 reps -= (2 << *max_run_length_prefix) - 1;
504 }
505 }
506 }
507 }
508}
509
510// Returns a maximum zero-run-length-prefix value such that run-length coding
511// zeros in v with this maximum prefix value and then encoding the resulting
512// histogram and entropy-coding v produces the least amount of bits.
513int BestMaxZeroRunLengthPrefix(const std::vector<int>& v) {
514 int min_cost = std::numeric_limits<int>::max();
515 int best_max_prefix = 0;
516 for (int max_prefix = 0; max_prefix <= 16; ++max_prefix) {
517 std::vector<int> rle_symbols;
518 std::vector<int> extra_bits;
519 int max_run_length_prefix = max_prefix;
520 RunLengthCodeZeros(v, &max_run_length_prefix, &rle_symbols, &extra_bits);
521 if (max_run_length_prefix < max_prefix) break;
522 HistogramLiteral histogram;
523 for (int i = 0; i < rle_symbols.size(); ++i) {
524 histogram.Add(rle_symbols[i]);
525 }
526 int bit_cost = PopulationCost(histogram);
527 if (max_prefix > 0) {
528 bit_cost += 4;
529 }
530 for (int i = 1; i <= max_prefix; ++i) {
531 bit_cost += histogram.data_[i] * i; // extra bits
532 }
533 if (bit_cost < min_cost) {
534 min_cost = bit_cost;
535 best_max_prefix = max_prefix;
536 }
537 }
538 return best_max_prefix;
539}
540
541void EncodeContextMap(const std::vector<int>& context_map,
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200542 int num_clusters,
543 int* storage_ix, uint8_t* storage) {
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100544 EncodeVarLenUint8(num_clusters - 1, storage_ix, storage);
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200545
Roderick Sheeter437bbad2013-11-19 14:32:56 -0800546 if (num_clusters == 1) {
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200547 return;
548 }
549
550 std::vector<int> transformed_symbols = MoveToFrontTransform(context_map);
551 std::vector<int> rle_symbols;
552 std::vector<int> extra_bits;
553 int max_run_length_prefix = BestMaxZeroRunLengthPrefix(transformed_symbols);
554 RunLengthCodeZeros(transformed_symbols, &max_run_length_prefix,
555 &rle_symbols, &extra_bits);
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100556 HistogramContextMap symbol_histogram;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200557 for (int i = 0; i < rle_symbols.size(); ++i) {
558 symbol_histogram.Add(rle_symbols[i]);
559 }
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100560 EntropyCodeContextMap symbol_code;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200561 BuildEntropyCode(symbol_histogram, 15, num_clusters + max_run_length_prefix,
562 &symbol_code);
563 bool use_rle = max_run_length_prefix > 0;
564 WriteBits(1, use_rle, storage_ix, storage);
565 if (use_rle) {
566 WriteBits(4, max_run_length_prefix - 1, storage_ix, storage);
567 }
568 StoreHuffmanCode(symbol_code, num_clusters + max_run_length_prefix,
569 storage_ix, storage);
570 for (int i = 0; i < rle_symbols.size(); ++i) {
571 EntropyEncode(rle_symbols[i], symbol_code, storage_ix, storage);
572 if (rle_symbols[i] > 0 && rle_symbols[i] <= max_run_length_prefix) {
573 WriteBits(rle_symbols[i], extra_bits[i], storage_ix, storage);
574 }
575 }
576 WriteBits(1, 1, storage_ix, storage); // use move-to-front
577}
578
579template<int kSize>
580void BuildEntropyCodes(const std::vector<Histogram<kSize> >& histograms,
581 int alphabet_size,
582 std::vector<EntropyCode<kSize> >* entropy_codes) {
583 entropy_codes->resize(histograms.size());
584 for (int i = 0; i < histograms.size(); ++i) {
585 BuildEntropyCode(histograms[i], 15, alphabet_size, &(*entropy_codes)[i]);
586 }
587}
588
589struct BlockSplitCode {
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100590 EntropyCodeBlockType block_type_code;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200591 EntropyCodeBlockLength block_len_code;
592};
593
594void EncodeBlockLength(const EntropyCodeBlockLength& entropy,
595 int length,
596 int* storage_ix, uint8_t* storage) {
597 int len_code = BlockLengthPrefix(length);
598 int extra_bits = BlockLengthExtraBits(len_code);
599 int extra_bits_value = length - BlockLengthOffset(len_code);
600 EntropyEncode(len_code, entropy, storage_ix, storage);
601
602 if (extra_bits > 0) {
603 WriteBits(extra_bits, extra_bits_value, storage_ix, storage);
604 }
605}
606
607void ComputeBlockTypeShortCodes(BlockSplit* split) {
608 if (split->num_types_ <= 1) {
609 split->num_types_ = 1;
610 return;
611 }
612 int ringbuffer[2] = { 0, 1 };
613 size_t index = 0;
614 for (int i = 0; i < split->types_.size(); ++i) {
615 int type = split->types_[i];
616 int type_code;
617 if (type == ringbuffer[index & 1]) {
618 type_code = 0;
619 } else if (type == ringbuffer[(index - 1) & 1] + 1) {
620 type_code = 1;
621 } else {
622 type_code = type + 2;
623 }
624 ringbuffer[index & 1] = type;
625 ++index;
626 split->type_codes_.push_back(type_code);
627 }
628}
629
630void BuildAndEncodeBlockSplitCode(const BlockSplit& split,
631 BlockSplitCode* code,
632 int* storage_ix, uint8_t* storage) {
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100633 EncodeVarLenUint8(split.num_types_ - 1, storage_ix, storage);
634 if (split.num_types_ == 1) {
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200635 return;
636 }
Zoltan Szabadkafe79fac2013-11-28 17:37:13 +0100637
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100638 HistogramBlockType type_histo;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200639 for (int i = 0; i < split.type_codes_.size(); ++i) {
640 type_histo.Add(split.type_codes_[i]);
641 }
642 BuildEntropyCode(type_histo, 15, split.num_types_ + 2,
643 &code->block_type_code);
644 HistogramBlockLength length_histo;
645 for (int i = 0; i < split.lengths_.size(); ++i) {
646 length_histo.Add(BlockLengthPrefix(split.lengths_[i]));
647 }
648 BuildEntropyCode(length_histo, 15, kNumBlockLenPrefixes,
649 &code->block_len_code);
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200650 StoreHuffmanCode(code->block_type_code, split.num_types_ + 2,
651 storage_ix, storage);
652 StoreHuffmanCode(code->block_len_code, kNumBlockLenPrefixes,
653 storage_ix, storage);
654 EncodeBlockLength(code->block_len_code, split.lengths_[0],
655 storage_ix, storage);
656}
657
658void MoveAndEncode(const BlockSplitCode& code,
659 BlockSplitIterator* it,
660 int* storage_ix, uint8_t* storage) {
661 if (it->length_ == 0) {
662 ++it->idx_;
663 it->type_ = it->split_.types_[it->idx_];
664 it->length_ = it->split_.lengths_[it->idx_];
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100665 int type_code = it->split_.type_codes_[it->idx_];
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200666 EntropyEncode(type_code, code.block_type_code, storage_ix, storage);
667 EncodeBlockLength(code.block_len_code, it->length_, storage_ix, storage);
668 }
669 --it->length_;
670}
671
672struct EncodingParams {
673 int num_direct_distance_codes;
674 int distance_postfix_bits;
675 int literal_context_mode;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200676};
677
678struct MetaBlock {
679 std::vector<Command> cmds;
680 EncodingParams params;
681 BlockSplit literal_split;
682 BlockSplit command_split;
683 BlockSplit distance_split;
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100684 std::vector<int> literal_context_modes;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200685 std::vector<int> literal_context_map;
686 std::vector<int> distance_context_map;
687 std::vector<HistogramLiteral> literal_histograms;
688 std::vector<HistogramCommand> command_histograms;
689 std::vector<HistogramDistance> distance_histograms;
690};
691
692void BuildMetaBlock(const EncodingParams& params,
693 const std::vector<Command>& cmds,
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100694 const uint8_t* ringbuffer,
695 const size_t pos,
696 const size_t mask,
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200697 MetaBlock* mb) {
698 mb->cmds = cmds;
699 mb->params = params;
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100700 if (cmds.empty()) {
701 return;
702 }
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200703 ComputeCommandPrefixes(&mb->cmds,
704 mb->params.num_direct_distance_codes,
705 mb->params.distance_postfix_bits);
706 SplitBlock(mb->cmds,
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100707 &ringbuffer[pos & mask],
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200708 &mb->literal_split,
709 &mb->command_split,
710 &mb->distance_split);
711 ComputeBlockTypeShortCodes(&mb->literal_split);
712 ComputeBlockTypeShortCodes(&mb->command_split);
713 ComputeBlockTypeShortCodes(&mb->distance_split);
714
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100715 mb->literal_context_modes.resize(mb->literal_split.num_types_,
716 mb->params.literal_context_mode);
717
718
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200719 int num_literal_contexts =
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100720 mb->literal_split.num_types_ << kLiteralContextBits;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200721 int num_distance_contexts =
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100722 mb->distance_split.num_types_ << kDistanceContextBits;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200723 std::vector<HistogramLiteral> literal_histograms(num_literal_contexts);
724 mb->command_histograms.resize(mb->command_split.num_types_);
725 std::vector<HistogramDistance> distance_histograms(num_distance_contexts);
726 BuildHistograms(mb->cmds,
727 mb->literal_split,
728 mb->command_split,
729 mb->distance_split,
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100730 ringbuffer,
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200731 pos,
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100732 mask,
733 mb->literal_context_modes,
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200734 &literal_histograms,
735 &mb->command_histograms,
736 &distance_histograms);
737
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100738 // Histogram ids need to fit in one byte.
739 static const int kMaxNumberOfHistograms = 256;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200740
741 mb->literal_histograms = literal_histograms;
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100742 ClusterHistograms(literal_histograms,
743 1 << kLiteralContextBits,
744 mb->literal_split.num_types_,
745 kMaxNumberOfHistograms,
746 &mb->literal_histograms,
747 &mb->literal_context_map);
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200748
749 mb->distance_histograms = distance_histograms;
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100750 ClusterHistograms(distance_histograms,
751 1 << kDistanceContextBits,
752 mb->distance_split.num_types_,
753 kMaxNumberOfHistograms,
754 &mb->distance_histograms,
755 &mb->distance_context_map);
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200756}
757
758size_t MetaBlockLength(const std::vector<Command>& cmds) {
759 size_t length = 0;
760 for (int i = 0; i < cmds.size(); ++i) {
761 const Command& cmd = cmds[i];
762 length += cmd.insert_length_ + cmd.copy_length_;
763 }
764 return length;
765}
766
767void StoreMetaBlock(const MetaBlock& mb,
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100768 const bool is_last,
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100769 const uint8_t* ringbuffer,
770 const size_t mask,
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200771 size_t* pos,
772 int* storage_ix, uint8_t* storage) {
773 size_t length = MetaBlockLength(mb.cmds);
774 const size_t end_pos = *pos + length;
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100775 EncodeMetaBlockLength(length,
776 is_last,
777 false,
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200778 storage_ix, storage);
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100779 if (length == 0) {
780 return;
781 }
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200782 BlockSplitCode literal_split_code;
783 BlockSplitCode command_split_code;
784 BlockSplitCode distance_split_code;
785 BuildAndEncodeBlockSplitCode(mb.literal_split, &literal_split_code,
786 storage_ix, storage);
787 BuildAndEncodeBlockSplitCode(mb.command_split, &command_split_code,
788 storage_ix, storage);
789 BuildAndEncodeBlockSplitCode(mb.distance_split, &distance_split_code,
790 storage_ix, storage);
791 WriteBits(2, mb.params.distance_postfix_bits, storage_ix, storage);
792 WriteBits(4,
793 mb.params.num_direct_distance_codes >>
794 mb.params.distance_postfix_bits, storage_ix, storage);
795 int num_distance_codes =
796 kNumDistanceShortCodes + mb.params.num_direct_distance_codes +
797 (48 << mb.params.distance_postfix_bits);
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100798 for (int i = 0; i < mb.literal_split.num_types_; ++i) {
799 WriteBits(2, mb.literal_context_modes[i], storage_ix, storage);
800 }
801 EncodeContextMap(mb.literal_context_map, mb.literal_histograms.size(), storage_ix, storage);
802 EncodeContextMap(mb.distance_context_map, mb.distance_histograms.size(), storage_ix, storage);
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200803 std::vector<EntropyCodeLiteral> literal_codes;
804 std::vector<EntropyCodeCommand> command_codes;
805 std::vector<EntropyCodeDistance> distance_codes;
806 BuildEntropyCodes(mb.literal_histograms, 256, &literal_codes);
807 BuildEntropyCodes(mb.command_histograms, kNumCommandPrefixes,
808 &command_codes);
809 BuildEntropyCodes(mb.distance_histograms, num_distance_codes,
810 &distance_codes);
811 StoreHuffmanCodes(literal_codes, 256, storage_ix, storage);
812 StoreHuffmanCodes(command_codes, kNumCommandPrefixes, storage_ix, storage);
813 StoreHuffmanCodes(distance_codes, num_distance_codes, storage_ix, storage);
814 BlockSplitIterator literal_it(mb.literal_split);
815 BlockSplitIterator command_it(mb.command_split);
816 BlockSplitIterator distance_it(mb.distance_split);
817 for (int i = 0; i < mb.cmds.size(); ++i) {
818 const Command& cmd = mb.cmds[i];
819 MoveAndEncode(command_split_code, &command_it, storage_ix, storage);
820 EncodeCommand(cmd, command_codes[command_it.type_], storage_ix, storage);
821 for (int j = 0; j < cmd.insert_length_; ++j) {
822 MoveAndEncode(literal_split_code, &literal_it, storage_ix, storage);
823 int histogram_idx = literal_it.type_;
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100824 uint8_t prev_byte = *pos > 0 ? ringbuffer[(*pos - 1) & mask] : 0;
825 uint8_t prev_byte2 = *pos > 1 ? ringbuffer[(*pos - 2) & mask] : 0;
826 int context = ((literal_it.type_ << kLiteralContextBits) +
827 Context(prev_byte, prev_byte2,
828 mb.literal_context_modes[literal_it.type_]));
829 histogram_idx = mb.literal_context_map[context];
830 EntropyEncode(ringbuffer[*pos & mask],
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200831 literal_codes[histogram_idx], storage_ix, storage);
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100832 ++(*pos);
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200833 }
834 if (*pos < end_pos && cmd.distance_prefix_ != 0xffff) {
835 MoveAndEncode(distance_split_code, &distance_it, storage_ix, storage);
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100836 int context = (distance_it.type_ << 2) +
Roderick Sheeter437bbad2013-11-19 14:32:56 -0800837 ((cmd.copy_length_code_ > 4) ? 3 : cmd.copy_length_code_ - 2);
838 int histogram_index = mb.distance_context_map[context];
839 size_t max_distance = std::min(*pos, (size_t)kMaxBackwardDistance);
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200840 EncodeCopyDistance(cmd, distance_codes[histogram_index],
841 storage_ix, storage);
842 }
843 *pos += cmd.copy_length_;
844 }
845}
846
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100847BrotliCompressor::BrotliCompressor()
Roderick Sheeter437bbad2013-11-19 14:32:56 -0800848 : window_bits_(kWindowBits),
849 hasher_(new Hasher),
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100850 dist_ringbuffer_idx_(0),
851 input_pos_(0),
852 ringbuffer_(kRingBufferBits, kMetaBlockSizeBits),
853 literal_cost_(1 << kRingBufferBits),
854 storage_ix_(0),
855 storage_(new uint8_t[2 << kMetaBlockSizeBits]) {
Zoltan Szabadkafe79fac2013-11-28 17:37:13 +0100856 dist_ringbuffer_[0] = 16;
857 dist_ringbuffer_[1] = 15;
858 dist_ringbuffer_[2] = 11;
859 dist_ringbuffer_[3] = 4;
Roderick Sheeter437bbad2013-11-19 14:32:56 -0800860 storage_[0] = 0;
861}
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100862
863BrotliCompressor::~BrotliCompressor() {
864 delete hasher_;
865 delete[] storage_;
866}
867
868void BrotliCompressor::WriteStreamHeader() {
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100869 // Encode window size.
Roderick Sheeter437bbad2013-11-19 14:32:56 -0800870 if (window_bits_ == 16) {
871 WriteBits(1, 0, &storage_ix_, storage_);
872 } else {
873 WriteBits(1, 1, &storage_ix_, storage_);
874 WriteBits(3, window_bits_ - 17, &storage_ix_, storage_);
875 }
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100876}
877
878void BrotliCompressor::WriteMetaBlock(const size_t input_size,
879 const uint8_t* input_buffer,
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100880 const bool is_last,
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100881 size_t* encoded_size,
882 uint8_t* encoded_buffer) {
Zoltan Szabadkacbd5cb52014-02-14 15:04:23 +0100883 static const double kMinUTF8Ratio = 0.75;
884 bool utf8_mode = false;
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100885 std::vector<Command> commands;
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100886 if (input_size > 0) {
887 ringbuffer_.Write(input_buffer, input_size);
Zoltan Szabadkacbd5cb52014-02-14 15:04:23 +0100888 utf8_mode = IsMostlyUTF8(
889 &ringbuffer_.start()[input_pos_ & kRingBufferMask],
890 input_size, kMinUTF8Ratio);
891 if (utf8_mode) {
892 EstimateBitCostsForLiteralsUTF8(input_pos_, input_size,
893 kRingBufferMask, ringbuffer_.start(),
894 &literal_cost_[0]);
895 } else {
896 EstimateBitCostsForLiterals(input_pos_, input_size,
897 kRingBufferMask, ringbuffer_.start(),
898 &literal_cost_[0]);
899 }
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100900 CreateBackwardReferences(input_size, input_pos_,
901 ringbuffer_.start(),
902 &literal_cost_[0],
903 kRingBufferMask, kMaxBackwardDistance,
904 hasher_,
905 &commands);
906 ComputeDistanceShortCodes(&commands, dist_ringbuffer_,
907 &dist_ringbuffer_idx_);
908 }
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100909 EncodingParams params;
910 params.num_direct_distance_codes = 12;
911 params.distance_postfix_bits = 1;
912 params.literal_context_mode = CONTEXT_SIGNED;
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100913 const int storage_ix0 = storage_ix_;
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100914 MetaBlock mb;
915 BuildMetaBlock(params, commands, ringbuffer_.start(), input_pos_,
916 kRingBufferMask, &mb);
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100917 StoreMetaBlock(mb, is_last, ringbuffer_.start(), kRingBufferMask,
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100918 &input_pos_, &storage_ix_, storage_);
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100919 size_t output_size = is_last ? ((storage_ix_ + 7) >> 3) : (storage_ix_ >> 3);
920 if (input_size + 4 < output_size) {
921 storage_ix_ = storage_ix0;
922 storage_[storage_ix_ >> 3] &= (1 << (storage_ix_ & 7)) - 1;
923 EncodeMetaBlockLength(input_size, false, true, &storage_ix_, storage_);
924 size_t hdr_size = (storage_ix_ + 7) >> 3;
925 memcpy(encoded_buffer, storage_, hdr_size);
926 memcpy(encoded_buffer + hdr_size, input_buffer, input_size);
927 *encoded_size = hdr_size + input_size;
928 if (is_last) {
929 encoded_buffer[*encoded_size] = 0x3; // ISLAST, ISEMPTY
930 ++(*encoded_size);
931 }
932 storage_ix_ = 0;
933 storage_[0] = 0;
934 } else {
935 memcpy(encoded_buffer, storage_, output_size);
936 *encoded_size = output_size;
937 if (is_last) {
938 storage_ix_ = 0;
939 storage_[0] = 0;
940 } else {
941 storage_ix_ -= output_size << 3;
942 storage_[storage_ix_ >> 3] = storage_[output_size];
943 }
944 }
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100945}
946
947void BrotliCompressor::FinishStream(
948 size_t* encoded_size, uint8_t* encoded_buffer) {
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100949 WriteMetaBlock(0, NULL, true, encoded_size, encoded_buffer);
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100950}
951
952
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200953int BrotliCompressBuffer(size_t input_size,
954 const uint8_t* input_buffer,
955 size_t* encoded_size,
956 uint8_t* encoded_buffer) {
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200957 if (input_size == 0) {
Zoltan Szabadkafe79fac2013-11-28 17:37:13 +0100958 encoded_buffer[0] = 6;
959 *encoded_size = 1;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200960 return 1;
961 }
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200962
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100963 BrotliCompressor compressor;
964 compressor.WriteStreamHeader();
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200965
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100966 const int max_block_size = 1 << kMetaBlockSizeBits;
967 size_t max_output_size = *encoded_size;
968 const uint8_t* input_end = input_buffer + input_size;
969 *encoded_size = 0;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200970
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100971 while (input_buffer < input_end) {
972 int block_size = max_block_size;
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100973 bool is_last = false;
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100974 if (block_size >= input_end - input_buffer) {
975 block_size = input_end - input_buffer;
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100976 is_last = true;
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100977 }
978 size_t output_size = max_output_size;
Zoltan Szabadkae7094912013-12-12 13:18:04 +0100979 compressor.WriteMetaBlock(block_size, input_buffer, is_last,
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100980 &output_size, &encoded_buffer[*encoded_size]);
981 input_buffer += block_size;
982 *encoded_size += output_size;
983 max_output_size -= output_size;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200984 }
985
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200986 return 1;
987}
988
989} // namespace brotli