source: code/trunk/vendor/github.com/andybalholm/brotli/metablock.go@ 145

Last change on this file since 145 was 145, checked in by Izuru Yakumo, 22 months ago

Updated the Makefile and vendored depedencies

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 20.8 KB
RevLine 
[145]1package brotli
2
3import (
4 "sync"
5)
6
7/* Copyright 2014 Google Inc. All Rights Reserved.
8
9 Distributed under MIT license.
10 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
11*/
12
13/* Algorithms for distributing the literals and commands of a metablock between
14 block types and contexts. */
15
16type metaBlockSplit struct {
17 literal_split blockSplit
18 command_split blockSplit
19 distance_split blockSplit
20 literal_context_map []uint32
21 literal_context_map_size uint
22 distance_context_map []uint32
23 distance_context_map_size uint
24 literal_histograms []histogramLiteral
25 literal_histograms_size uint
26 command_histograms []histogramCommand
27 command_histograms_size uint
28 distance_histograms []histogramDistance
29 distance_histograms_size uint
30}
31
32var metaBlockPool sync.Pool
33
34func getMetaBlockSplit() *metaBlockSplit {
35 mb, _ := metaBlockPool.Get().(*metaBlockSplit)
36
37 if mb == nil {
38 mb = &metaBlockSplit{}
39 } else {
40 initBlockSplit(&mb.literal_split)
41 initBlockSplit(&mb.command_split)
42 initBlockSplit(&mb.distance_split)
43 mb.literal_context_map = mb.literal_context_map[:0]
44 mb.literal_context_map_size = 0
45 mb.distance_context_map = mb.distance_context_map[:0]
46 mb.distance_context_map_size = 0
47 mb.literal_histograms = mb.literal_histograms[:0]
48 mb.command_histograms = mb.command_histograms[:0]
49 mb.distance_histograms = mb.distance_histograms[:0]
50 }
51 return mb
52}
53
54func freeMetaBlockSplit(mb *metaBlockSplit) {
55 metaBlockPool.Put(mb)
56}
57
58func initDistanceParams(params *encoderParams, npostfix uint32, ndirect uint32) {
59 var dist_params *distanceParams = &params.dist
60 var alphabet_size uint32
61 var max_distance uint32
62
63 dist_params.distance_postfix_bits = npostfix
64 dist_params.num_direct_distance_codes = ndirect
65
66 alphabet_size = uint32(distanceAlphabetSize(uint(npostfix), uint(ndirect), maxDistanceBits))
67 max_distance = ndirect + (1 << (maxDistanceBits + npostfix + 2)) - (1 << (npostfix + 2))
68
69 if params.large_window {
70 var bound = [maxNpostfix + 1]uint32{0, 4, 12, 28}
71 var postfix uint32 = 1 << npostfix
72 alphabet_size = uint32(distanceAlphabetSize(uint(npostfix), uint(ndirect), largeMaxDistanceBits))
73
74 /* The maximum distance is set so that no distance symbol used can encode
75 a distance larger than BROTLI_MAX_ALLOWED_DISTANCE with all
76 its extra bits set. */
77 if ndirect < bound[npostfix] {
78 max_distance = maxAllowedDistance - (bound[npostfix] - ndirect)
79 } else if ndirect >= bound[npostfix]+postfix {
80 max_distance = (3 << 29) - 4 + (ndirect - bound[npostfix])
81 } else {
82 max_distance = maxAllowedDistance
83 }
84 }
85
86 dist_params.alphabet_size = alphabet_size
87 dist_params.max_distance = uint(max_distance)
88}
89
90func recomputeDistancePrefixes(cmds []command, orig_params *distanceParams, new_params *distanceParams) {
91 if orig_params.distance_postfix_bits == new_params.distance_postfix_bits && orig_params.num_direct_distance_codes == new_params.num_direct_distance_codes {
92 return
93 }
94
95 for i := range cmds {
96 var cmd *command = &cmds[i]
97 if commandCopyLen(cmd) != 0 && cmd.cmd_prefix_ >= 128 {
98 prefixEncodeCopyDistance(uint(commandRestoreDistanceCode(cmd, orig_params)), uint(new_params.num_direct_distance_codes), uint(new_params.distance_postfix_bits), &cmd.dist_prefix_, &cmd.dist_extra_)
99 }
100 }
101}
102
103func computeDistanceCost(cmds []command, orig_params *distanceParams, new_params *distanceParams, cost *float64) bool {
104 var equal_params bool = false
105 var dist_prefix uint16
106 var dist_extra uint32
107 var extra_bits float64 = 0.0
108 var histo histogramDistance
109 histogramClearDistance(&histo)
110
111 if orig_params.distance_postfix_bits == new_params.distance_postfix_bits && orig_params.num_direct_distance_codes == new_params.num_direct_distance_codes {
112 equal_params = true
113 }
114
115 for i := range cmds {
116 cmd := &cmds[i]
117 if commandCopyLen(cmd) != 0 && cmd.cmd_prefix_ >= 128 {
118 if equal_params {
119 dist_prefix = cmd.dist_prefix_
120 } else {
121 var distance uint32 = commandRestoreDistanceCode(cmd, orig_params)
122 if distance > uint32(new_params.max_distance) {
123 return false
124 }
125
126 prefixEncodeCopyDistance(uint(distance), uint(new_params.num_direct_distance_codes), uint(new_params.distance_postfix_bits), &dist_prefix, &dist_extra)
127 }
128
129 histogramAddDistance(&histo, uint(dist_prefix)&0x3FF)
130 extra_bits += float64(dist_prefix >> 10)
131 }
132 }
133
134 *cost = populationCostDistance(&histo) + extra_bits
135 return true
136}
137
138var buildMetaBlock_kMaxNumberOfHistograms uint = 256
139
140func buildMetaBlock(ringbuffer []byte, pos uint, mask uint, params *encoderParams, prev_byte byte, prev_byte2 byte, cmds []command, literal_context_mode int, mb *metaBlockSplit) {
141 var distance_histograms []histogramDistance
142 var literal_histograms []histogramLiteral
143 var literal_context_modes []int = nil
144 var literal_histograms_size uint
145 var distance_histograms_size uint
146 var i uint
147 var literal_context_multiplier uint = 1
148 var npostfix uint32
149 var ndirect_msb uint32 = 0
150 var check_orig bool = true
151 var best_dist_cost float64 = 1e99
152 var orig_params encoderParams = *params
153 /* Histogram ids need to fit in one byte. */
154
155 var new_params encoderParams = *params
156
157 for npostfix = 0; npostfix <= maxNpostfix; npostfix++ {
158 for ; ndirect_msb < 16; ndirect_msb++ {
159 var ndirect uint32 = ndirect_msb << npostfix
160 var skip bool
161 var dist_cost float64
162 initDistanceParams(&new_params, npostfix, ndirect)
163 if npostfix == orig_params.dist.distance_postfix_bits && ndirect == orig_params.dist.num_direct_distance_codes {
164 check_orig = false
165 }
166
167 skip = !computeDistanceCost(cmds, &orig_params.dist, &new_params.dist, &dist_cost)
168 if skip || (dist_cost > best_dist_cost) {
169 break
170 }
171
172 best_dist_cost = dist_cost
173 params.dist = new_params.dist
174 }
175
176 if ndirect_msb > 0 {
177 ndirect_msb--
178 }
179 ndirect_msb /= 2
180 }
181
182 if check_orig {
183 var dist_cost float64
184 computeDistanceCost(cmds, &orig_params.dist, &orig_params.dist, &dist_cost)
185 if dist_cost < best_dist_cost {
186 /* NB: currently unused; uncomment when more param tuning is added. */
187 /* best_dist_cost = dist_cost; */
188 params.dist = orig_params.dist
189 }
190 }
191
192 recomputeDistancePrefixes(cmds, &orig_params.dist, &params.dist)
193
194 splitBlock(cmds, ringbuffer, pos, mask, params, &mb.literal_split, &mb.command_split, &mb.distance_split)
195
196 if !params.disable_literal_context_modeling {
197 literal_context_multiplier = 1 << literalContextBits
198 literal_context_modes = make([]int, (mb.literal_split.num_types))
199 for i = 0; i < mb.literal_split.num_types; i++ {
200 literal_context_modes[i] = literal_context_mode
201 }
202 }
203
204 literal_histograms_size = mb.literal_split.num_types * literal_context_multiplier
205 literal_histograms = make([]histogramLiteral, literal_histograms_size)
206 clearHistogramsLiteral(literal_histograms, literal_histograms_size)
207
208 distance_histograms_size = mb.distance_split.num_types << distanceContextBits
209 distance_histograms = make([]histogramDistance, distance_histograms_size)
210 clearHistogramsDistance(distance_histograms, distance_histograms_size)
211
212 mb.command_histograms_size = mb.command_split.num_types
213 if cap(mb.command_histograms) < int(mb.command_histograms_size) {
214 mb.command_histograms = make([]histogramCommand, (mb.command_histograms_size))
215 } else {
216 mb.command_histograms = mb.command_histograms[:mb.command_histograms_size]
217 }
218 clearHistogramsCommand(mb.command_histograms, mb.command_histograms_size)
219
220 buildHistogramsWithContext(cmds, &mb.literal_split, &mb.command_split, &mb.distance_split, ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_modes, literal_histograms, mb.command_histograms, distance_histograms)
221 literal_context_modes = nil
222
223 mb.literal_context_map_size = mb.literal_split.num_types << literalContextBits
224 if cap(mb.literal_context_map) < int(mb.literal_context_map_size) {
225 mb.literal_context_map = make([]uint32, (mb.literal_context_map_size))
226 } else {
227 mb.literal_context_map = mb.literal_context_map[:mb.literal_context_map_size]
228 }
229
230 mb.literal_histograms_size = mb.literal_context_map_size
231 if cap(mb.literal_histograms) < int(mb.literal_histograms_size) {
232 mb.literal_histograms = make([]histogramLiteral, (mb.literal_histograms_size))
233 } else {
234 mb.literal_histograms = mb.literal_histograms[:mb.literal_histograms_size]
235 }
236
237 clusterHistogramsLiteral(literal_histograms, literal_histograms_size, buildMetaBlock_kMaxNumberOfHistograms, mb.literal_histograms, &mb.literal_histograms_size, mb.literal_context_map)
238 literal_histograms = nil
239
240 if params.disable_literal_context_modeling {
241 /* Distribute assignment to all contexts. */
242 for i = mb.literal_split.num_types; i != 0; {
243 var j uint = 0
244 i--
245 for ; j < 1<<literalContextBits; j++ {
246 mb.literal_context_map[(i<<literalContextBits)+j] = mb.literal_context_map[i]
247 }
248 }
249 }
250
251 mb.distance_context_map_size = mb.distance_split.num_types << distanceContextBits
252 if cap(mb.distance_context_map) < int(mb.distance_context_map_size) {
253 mb.distance_context_map = make([]uint32, (mb.distance_context_map_size))
254 } else {
255 mb.distance_context_map = mb.distance_context_map[:mb.distance_context_map_size]
256 }
257
258 mb.distance_histograms_size = mb.distance_context_map_size
259 if cap(mb.distance_histograms) < int(mb.distance_histograms_size) {
260 mb.distance_histograms = make([]histogramDistance, (mb.distance_histograms_size))
261 } else {
262 mb.distance_histograms = mb.distance_histograms[:mb.distance_histograms_size]
263 }
264
265 clusterHistogramsDistance(distance_histograms, mb.distance_context_map_size, buildMetaBlock_kMaxNumberOfHistograms, mb.distance_histograms, &mb.distance_histograms_size, mb.distance_context_map)
266 distance_histograms = nil
267}
268
269const maxStaticContexts = 13
270
271/* Greedy block splitter for one block category (literal, command or distance).
272 Gathers histograms for all context buckets. */
273type contextBlockSplitter struct {
274 alphabet_size_ uint
275 num_contexts_ uint
276 max_block_types_ uint
277 min_block_size_ uint
278 split_threshold_ float64
279 num_blocks_ uint
280 split_ *blockSplit
281 histograms_ []histogramLiteral
282 histograms_size_ *uint
283 target_block_size_ uint
284 block_size_ uint
285 curr_histogram_ix_ uint
286 last_histogram_ix_ [2]uint
287 last_entropy_ [2 * maxStaticContexts]float64
288 merge_last_count_ uint
289}
290
291func initContextBlockSplitter(self *contextBlockSplitter, alphabet_size uint, num_contexts uint, min_block_size uint, split_threshold float64, num_symbols uint, split *blockSplit, histograms *[]histogramLiteral, histograms_size *uint) {
292 var max_num_blocks uint = num_symbols/min_block_size + 1
293 var max_num_types uint
294 assert(num_contexts <= maxStaticContexts)
295
296 self.alphabet_size_ = alphabet_size
297 self.num_contexts_ = num_contexts
298 self.max_block_types_ = maxNumberOfBlockTypes / num_contexts
299 self.min_block_size_ = min_block_size
300 self.split_threshold_ = split_threshold
301 self.num_blocks_ = 0
302 self.split_ = split
303 self.histograms_size_ = histograms_size
304 self.target_block_size_ = min_block_size
305 self.block_size_ = 0
306 self.curr_histogram_ix_ = 0
307 self.merge_last_count_ = 0
308
309 /* We have to allocate one more histogram than the maximum number of block
310 types for the current histogram when the meta-block is too big. */
311 max_num_types = brotli_min_size_t(max_num_blocks, self.max_block_types_+1)
312
313 brotli_ensure_capacity_uint8_t(&split.types, &split.types_alloc_size, max_num_blocks)
314 brotli_ensure_capacity_uint32_t(&split.lengths, &split.lengths_alloc_size, max_num_blocks)
315 split.num_blocks = max_num_blocks
316 *histograms_size = max_num_types * num_contexts
317 if histograms == nil || cap(*histograms) < int(*histograms_size) {
318 *histograms = make([]histogramLiteral, (*histograms_size))
319 } else {
320 *histograms = (*histograms)[:*histograms_size]
321 }
322 self.histograms_ = *histograms
323
324 /* Clear only current histogram. */
325 clearHistogramsLiteral(self.histograms_[0:], num_contexts)
326
327 self.last_histogram_ix_[1] = 0
328 self.last_histogram_ix_[0] = self.last_histogram_ix_[1]
329}
330
331/* Does either of three things:
332 (1) emits the current block with a new block type;
333 (2) emits the current block with the type of the second last block;
334 (3) merges the current block with the last block. */
335func contextBlockSplitterFinishBlock(self *contextBlockSplitter, is_final bool) {
336 var split *blockSplit = self.split_
337 var num_contexts uint = self.num_contexts_
338 var last_entropy []float64 = self.last_entropy_[:]
339 var histograms []histogramLiteral = self.histograms_
340
341 if self.block_size_ < self.min_block_size_ {
342 self.block_size_ = self.min_block_size_
343 }
344
345 if self.num_blocks_ == 0 {
346 var i uint
347
348 /* Create first block. */
349 split.lengths[0] = uint32(self.block_size_)
350
351 split.types[0] = 0
352
353 for i = 0; i < num_contexts; i++ {
354 last_entropy[i] = bitsEntropy(histograms[i].data_[:], self.alphabet_size_)
355 last_entropy[num_contexts+i] = last_entropy[i]
356 }
357
358 self.num_blocks_++
359 split.num_types++
360 self.curr_histogram_ix_ += num_contexts
361 if self.curr_histogram_ix_ < *self.histograms_size_ {
362 clearHistogramsLiteral(self.histograms_[self.curr_histogram_ix_:], self.num_contexts_)
363 }
364
365 self.block_size_ = 0
366 } else if self.block_size_ > 0 {
367 var entropy [maxStaticContexts]float64
368 var combined_histo []histogramLiteral = make([]histogramLiteral, (2 * num_contexts))
369 var combined_entropy [2 * maxStaticContexts]float64
370 var diff = [2]float64{0.0}
371 /* Try merging the set of histograms for the current block type with the
372 respective set of histograms for the last and second last block types.
373 Decide over the split based on the total reduction of entropy across
374 all contexts. */
375
376 var i uint
377 for i = 0; i < num_contexts; i++ {
378 var curr_histo_ix uint = self.curr_histogram_ix_ + i
379 var j uint
380 entropy[i] = bitsEntropy(histograms[curr_histo_ix].data_[:], self.alphabet_size_)
381 for j = 0; j < 2; j++ {
382 var jx uint = j*num_contexts + i
383 var last_histogram_ix uint = self.last_histogram_ix_[j] + i
384 combined_histo[jx] = histograms[curr_histo_ix]
385 histogramAddHistogramLiteral(&combined_histo[jx], &histograms[last_histogram_ix])
386 combined_entropy[jx] = bitsEntropy(combined_histo[jx].data_[0:], self.alphabet_size_)
387 diff[j] += combined_entropy[jx] - entropy[i] - last_entropy[jx]
388 }
389 }
390
391 if split.num_types < self.max_block_types_ && diff[0] > self.split_threshold_ && diff[1] > self.split_threshold_ {
392 /* Create new block. */
393 split.lengths[self.num_blocks_] = uint32(self.block_size_)
394
395 split.types[self.num_blocks_] = byte(split.num_types)
396 self.last_histogram_ix_[1] = self.last_histogram_ix_[0]
397 self.last_histogram_ix_[0] = split.num_types * num_contexts
398 for i = 0; i < num_contexts; i++ {
399 last_entropy[num_contexts+i] = last_entropy[i]
400 last_entropy[i] = entropy[i]
401 }
402
403 self.num_blocks_++
404 split.num_types++
405 self.curr_histogram_ix_ += num_contexts
406 if self.curr_histogram_ix_ < *self.histograms_size_ {
407 clearHistogramsLiteral(self.histograms_[self.curr_histogram_ix_:], self.num_contexts_)
408 }
409
410 self.block_size_ = 0
411 self.merge_last_count_ = 0
412 self.target_block_size_ = self.min_block_size_
413 } else if diff[1] < diff[0]-20.0 {
414 split.lengths[self.num_blocks_] = uint32(self.block_size_)
415 split.types[self.num_blocks_] = split.types[self.num_blocks_-2]
416 /* Combine this block with second last block. */
417
418 var tmp uint = self.last_histogram_ix_[0]
419 self.last_histogram_ix_[0] = self.last_histogram_ix_[1]
420 self.last_histogram_ix_[1] = tmp
421 for i = 0; i < num_contexts; i++ {
422 histograms[self.last_histogram_ix_[0]+i] = combined_histo[num_contexts+i]
423 last_entropy[num_contexts+i] = last_entropy[i]
424 last_entropy[i] = combined_entropy[num_contexts+i]
425 histogramClearLiteral(&histograms[self.curr_histogram_ix_+i])
426 }
427
428 self.num_blocks_++
429 self.block_size_ = 0
430 self.merge_last_count_ = 0
431 self.target_block_size_ = self.min_block_size_
432 } else {
433 /* Combine this block with last block. */
434 split.lengths[self.num_blocks_-1] += uint32(self.block_size_)
435
436 for i = 0; i < num_contexts; i++ {
437 histograms[self.last_histogram_ix_[0]+i] = combined_histo[i]
438 last_entropy[i] = combined_entropy[i]
439 if split.num_types == 1 {
440 last_entropy[num_contexts+i] = last_entropy[i]
441 }
442
443 histogramClearLiteral(&histograms[self.curr_histogram_ix_+i])
444 }
445
446 self.block_size_ = 0
447 self.merge_last_count_++
448 if self.merge_last_count_ > 1 {
449 self.target_block_size_ += self.min_block_size_
450 }
451 }
452
453 combined_histo = nil
454 }
455
456 if is_final {
457 *self.histograms_size_ = split.num_types * num_contexts
458 split.num_blocks = self.num_blocks_
459 }
460}
461
462/* Adds the next symbol to the current block type and context. When the
463 current block reaches the target size, decides on merging the block. */
464func contextBlockSplitterAddSymbol(self *contextBlockSplitter, symbol uint, context uint) {
465 histogramAddLiteral(&self.histograms_[self.curr_histogram_ix_+context], symbol)
466 self.block_size_++
467 if self.block_size_ == self.target_block_size_ {
468 contextBlockSplitterFinishBlock(self, false) /* is_final = */
469 }
470}
471
472func mapStaticContexts(num_contexts uint, static_context_map []uint32, mb *metaBlockSplit) {
473 var i uint
474 mb.literal_context_map_size = mb.literal_split.num_types << literalContextBits
475 if cap(mb.literal_context_map) < int(mb.literal_context_map_size) {
476 mb.literal_context_map = make([]uint32, (mb.literal_context_map_size))
477 } else {
478 mb.literal_context_map = mb.literal_context_map[:mb.literal_context_map_size]
479 }
480
481 for i = 0; i < mb.literal_split.num_types; i++ {
482 var offset uint32 = uint32(i * num_contexts)
483 var j uint
484 for j = 0; j < 1<<literalContextBits; j++ {
485 mb.literal_context_map[(i<<literalContextBits)+j] = offset + static_context_map[j]
486 }
487 }
488}
489
490func buildMetaBlockGreedyInternal(ringbuffer []byte, pos uint, mask uint, prev_byte byte, prev_byte2 byte, literal_context_lut contextLUT, num_contexts uint, static_context_map []uint32, commands []command, mb *metaBlockSplit) {
491 var lit_blocks struct {
492 plain blockSplitterLiteral
493 ctx contextBlockSplitter
494 }
495 var cmd_blocks blockSplitterCommand
496 var dist_blocks blockSplitterDistance
497 var num_literals uint = 0
498 for i := range commands {
499 num_literals += uint(commands[i].insert_len_)
500 }
501
502 if num_contexts == 1 {
503 initBlockSplitterLiteral(&lit_blocks.plain, 256, 512, 400.0, num_literals, &mb.literal_split, &mb.literal_histograms, &mb.literal_histograms_size)
504 } else {
505 initContextBlockSplitter(&lit_blocks.ctx, 256, num_contexts, 512, 400.0, num_literals, &mb.literal_split, &mb.literal_histograms, &mb.literal_histograms_size)
506 }
507
508 initBlockSplitterCommand(&cmd_blocks, numCommandSymbols, 1024, 500.0, uint(len(commands)), &mb.command_split, &mb.command_histograms, &mb.command_histograms_size)
509 initBlockSplitterDistance(&dist_blocks, 64, 512, 100.0, uint(len(commands)), &mb.distance_split, &mb.distance_histograms, &mb.distance_histograms_size)
510
511 for _, cmd := range commands {
512 var j uint
513 blockSplitterAddSymbolCommand(&cmd_blocks, uint(cmd.cmd_prefix_))
514 for j = uint(cmd.insert_len_); j != 0; j-- {
515 var literal byte = ringbuffer[pos&mask]
516 if num_contexts == 1 {
517 blockSplitterAddSymbolLiteral(&lit_blocks.plain, uint(literal))
518 } else {
519 var context uint = uint(getContext(prev_byte, prev_byte2, literal_context_lut))
520 contextBlockSplitterAddSymbol(&lit_blocks.ctx, uint(literal), uint(static_context_map[context]))
521 }
522
523 prev_byte2 = prev_byte
524 prev_byte = literal
525 pos++
526 }
527
528 pos += uint(commandCopyLen(&cmd))
529 if commandCopyLen(&cmd) != 0 {
530 prev_byte2 = ringbuffer[(pos-2)&mask]
531 prev_byte = ringbuffer[(pos-1)&mask]
532 if cmd.cmd_prefix_ >= 128 {
533 blockSplitterAddSymbolDistance(&dist_blocks, uint(cmd.dist_prefix_)&0x3FF)
534 }
535 }
536 }
537
538 if num_contexts == 1 {
539 blockSplitterFinishBlockLiteral(&lit_blocks.plain, true) /* is_final = */
540 } else {
541 contextBlockSplitterFinishBlock(&lit_blocks.ctx, true) /* is_final = */
542 }
543
544 blockSplitterFinishBlockCommand(&cmd_blocks, true) /* is_final = */
545 blockSplitterFinishBlockDistance(&dist_blocks, true) /* is_final = */
546
547 if num_contexts > 1 {
548 mapStaticContexts(num_contexts, static_context_map, mb)
549 }
550}
551
552func buildMetaBlockGreedy(ringbuffer []byte, pos uint, mask uint, prev_byte byte, prev_byte2 byte, literal_context_lut contextLUT, num_contexts uint, static_context_map []uint32, commands []command, mb *metaBlockSplit) {
553 if num_contexts == 1 {
554 buildMetaBlockGreedyInternal(ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_lut, 1, nil, commands, mb)
555 } else {
556 buildMetaBlockGreedyInternal(ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_lut, num_contexts, static_context_map, commands, mb)
557 }
558}
559
560func optimizeHistograms(num_distance_codes uint32, mb *metaBlockSplit) {
561 var good_for_rle [numCommandSymbols]byte
562 var i uint
563 for i = 0; i < mb.literal_histograms_size; i++ {
564 optimizeHuffmanCountsForRLE(256, mb.literal_histograms[i].data_[:], good_for_rle[:])
565 }
566
567 for i = 0; i < mb.command_histograms_size; i++ {
568 optimizeHuffmanCountsForRLE(numCommandSymbols, mb.command_histograms[i].data_[:], good_for_rle[:])
569 }
570
571 for i = 0; i < mb.distance_histograms_size; i++ {
572 optimizeHuffmanCountsForRLE(uint(num_distance_codes), mb.distance_histograms[i].data_[:], good_for_rle[:])
573 }
574}
Note: See TracBrowser for help on using the repository browser.