Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
5.3 KiB
196 lines
5.3 KiB
package brotli |
|
|
|
const fastOnePassCompressionQuality = 0 |
|
|
|
const fastTwoPassCompressionQuality = 1 |
|
|
|
const zopflificationQuality = 10 |
|
|
|
const hqZopflificationQuality = 11 |
|
|
|
const maxQualityForStaticEntropyCodes = 2 |
|
|
|
const minQualityForBlockSplit = 4 |
|
|
|
const minQualityForNonzeroDistanceParams = 4 |
|
|
|
const minQualityForOptimizeHistograms = 4 |
|
|
|
const minQualityForExtensiveReferenceSearch = 5 |
|
|
|
const minQualityForContextModeling = 5 |
|
|
|
const minQualityForHqContextModeling = 7 |
|
|
|
const minQualityForHqBlockSplitting = 10 |
|
|
|
/* For quality below MIN_QUALITY_FOR_BLOCK_SPLIT there is no block splitting, |
|
so we buffer at most this much literals and commands. */ |
|
const maxNumDelayedSymbols = 0x2FFF |
|
|
|
/* Returns hash-table size for quality levels 0 and 1. */ |
|
func maxHashTableSize(quality int) uint { |
|
if quality == fastOnePassCompressionQuality { |
|
return 1 << 15 |
|
} else { |
|
return 1 << 17 |
|
} |
|
} |
|
|
|
/* The maximum length for which the zopflification uses distinct distances. */ |
|
const maxZopfliLenQuality10 = 150 |
|
|
|
const maxZopfliLenQuality11 = 325 |
|
|
|
/* Do not thoroughly search when a long copy is found. */ |
|
const longCopyQuickStep = 16384 |
|
|
|
func maxZopfliLen(params *encoderParams) uint { |
|
if params.quality <= 10 { |
|
return maxZopfliLenQuality10 |
|
} else { |
|
return maxZopfliLenQuality11 |
|
} |
|
} |
|
|
|
/* Number of best candidates to evaluate to expand Zopfli chain. */ |
|
func maxZopfliCandidates(params *encoderParams) uint { |
|
if params.quality <= 10 { |
|
return 1 |
|
} else { |
|
return 5 |
|
} |
|
} |
|
|
|
func sanitizeParams(params *encoderParams) { |
|
params.quality = brotli_min_int(maxQuality, brotli_max_int(minQuality, params.quality)) |
|
if params.quality <= maxQualityForStaticEntropyCodes { |
|
params.large_window = false |
|
} |
|
|
|
if params.lgwin < minWindowBits { |
|
params.lgwin = minWindowBits |
|
} else { |
|
var max_lgwin int |
|
if params.large_window { |
|
max_lgwin = largeMaxWindowBits |
|
} else { |
|
max_lgwin = maxWindowBits |
|
} |
|
if params.lgwin > uint(max_lgwin) { |
|
params.lgwin = uint(max_lgwin) |
|
} |
|
} |
|
} |
|
|
|
/* Returns optimized lg_block value. */ |
|
func computeLgBlock(params *encoderParams) int { |
|
var lgblock int = params.lgblock |
|
if params.quality == fastOnePassCompressionQuality || params.quality == fastTwoPassCompressionQuality { |
|
lgblock = int(params.lgwin) |
|
} else if params.quality < minQualityForBlockSplit { |
|
lgblock = 14 |
|
} else if lgblock == 0 { |
|
lgblock = 16 |
|
if params.quality >= 9 && params.lgwin > uint(lgblock) { |
|
lgblock = brotli_min_int(18, int(params.lgwin)) |
|
} |
|
} else { |
|
lgblock = brotli_min_int(maxInputBlockBits, brotli_max_int(minInputBlockBits, lgblock)) |
|
} |
|
|
|
return lgblock |
|
} |
|
|
|
/* Returns log2 of the size of main ring buffer area. |
|
Allocate at least lgwin + 1 bits for the ring buffer so that the newly |
|
added block fits there completely and we still get lgwin bits and at least |
|
read_block_size_bits + 1 bits because the copy tail length needs to be |
|
smaller than ring-buffer size. */ |
|
func computeRbBits(params *encoderParams) int { |
|
return 1 + brotli_max_int(int(params.lgwin), params.lgblock) |
|
} |
|
|
|
func maxMetablockSize(params *encoderParams) uint { |
|
var bits int = brotli_min_int(computeRbBits(params), maxInputBlockBits) |
|
return uint(1) << uint(bits) |
|
} |
|
|
|
/* When searching for backward references and have not seen matches for a long |
|
time, we can skip some match lookups. Unsuccessful match lookups are very |
|
expensive and this kind of a heuristic speeds up compression quite a lot. |
|
At first 8 byte strides are taken and every second byte is put to hasher. |
|
After 4x more literals stride by 16 bytes, every put 4-th byte to hasher. |
|
Applied only to qualities 2 to 9. */ |
|
func literalSpreeLengthForSparseSearch(params *encoderParams) uint { |
|
if params.quality < 9 { |
|
return 64 |
|
} else { |
|
return 512 |
|
} |
|
} |
|
|
|
func chooseHasher(params *encoderParams, hparams *hasherParams) { |
|
if params.quality > 9 { |
|
hparams.type_ = 10 |
|
} else if params.quality == 4 && params.size_hint >= 1<<20 { |
|
hparams.type_ = 54 |
|
} else if params.quality < 5 { |
|
hparams.type_ = params.quality |
|
} else if params.lgwin <= 16 { |
|
if params.quality < 7 { |
|
hparams.type_ = 40 |
|
} else if params.quality < 9 { |
|
hparams.type_ = 41 |
|
} else { |
|
hparams.type_ = 42 |
|
} |
|
} else if params.size_hint >= 1<<20 && params.lgwin >= 19 { |
|
hparams.type_ = 6 |
|
hparams.block_bits = params.quality - 1 |
|
hparams.bucket_bits = 15 |
|
hparams.hash_len = 5 |
|
if params.quality < 7 { |
|
hparams.num_last_distances_to_check = 4 |
|
} else if params.quality < 9 { |
|
hparams.num_last_distances_to_check = 10 |
|
} else { |
|
hparams.num_last_distances_to_check = 16 |
|
} |
|
} else { |
|
hparams.type_ = 5 |
|
hparams.block_bits = params.quality - 1 |
|
if params.quality < 7 { |
|
hparams.bucket_bits = 14 |
|
} else { |
|
hparams.bucket_bits = 15 |
|
} |
|
if params.quality < 7 { |
|
hparams.num_last_distances_to_check = 4 |
|
} else if params.quality < 9 { |
|
hparams.num_last_distances_to_check = 10 |
|
} else { |
|
hparams.num_last_distances_to_check = 16 |
|
} |
|
} |
|
|
|
if params.lgwin > 24 { |
|
/* Different hashers for large window brotli: not for qualities <= 2, |
|
these are too fast for large window. Not for qualities >= 10: their |
|
hasher already works well with large window. So the changes are: |
|
H3 --> H35: for quality 3. |
|
H54 --> H55: for quality 4 with size hint > 1MB |
|
H6 --> H65: for qualities 5, 6, 7, 8, 9. */ |
|
if hparams.type_ == 3 { |
|
hparams.type_ = 35 |
|
} |
|
|
|
if hparams.type_ == 54 { |
|
hparams.type_ = 55 |
|
} |
|
|
|
if hparams.type_ == 6 { |
|
hparams.type_ = 65 |
|
} |
|
} |
|
}
|
|
|