diff options
Diffstat (limited to 'enc/encode_parallel.cc')
-rw-r--r-- | enc/encode_parallel.cc | 237 |
1 files changed, 127 insertions, 110 deletions
diff --git a/enc/encode_parallel.cc b/enc/encode_parallel.cc index 6e4e8d5..6d7a4df 100644 --- a/enc/encode_parallel.cc +++ b/enc/encode_parallel.cc @@ -8,40 +8,34 @@ #include "./encode_parallel.h" -#include <algorithm> -#include <limits> +#include <vector> #include "./backward_references.h" -#include "./bit_cost.h" -#include "./block_splitter.h" #include "./brotli_bit_stream.h" -#include "./cluster.h" #include "./context.h" #include "./entropy_encode.h" #include "./fast_log.h" #include "./hash.h" -#include "./histogram.h" #include "./metablock.h" +#include "./port.h" #include "./prefix.h" -#include "./transform.h" #include "./utf8_util.h" -#include "./write_bits.h" namespace brotli { namespace { -void RecomputeDistancePrefixes(Command* cmds, size_t num_commands, - uint32_t num_direct_distance_codes, - uint32_t distance_postfix_bits) { +static void RecomputeDistancePrefixes(Command* cmds, size_t num_commands, + uint32_t num_direct_distance_codes, + uint32_t distance_postfix_bits) { if (num_direct_distance_codes == 0 && distance_postfix_bits == 0) { return; } for (size_t i = 0; i < num_commands; ++i) { Command* cmd = &cmds[i]; - if (cmd->copy_len() && cmd->cmd_prefix_ >= 128) { - PrefixEncodeCopyDistance(cmd->DistanceCode(), + if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) { + PrefixEncodeCopyDistance(CommandDistanceCode(cmd), num_direct_distance_codes, distance_postfix_bits, &cmd->dist_prefix_, @@ -50,102 +44,115 @@ void RecomputeDistancePrefixes(Command* cmds, size_t num_commands, } } -bool WriteMetaBlockParallel(const BrotliParams& params, - const uint32_t input_size, - const uint8_t* input_buffer, - const uint32_t prefix_size, - const uint8_t* prefix_buffer, - const bool is_first, - const bool is_last, - size_t* encoded_size, - uint8_t* encoded_buffer) { +/* Returns 1 on success, otherwise 0. */ +int WriteMetaBlockParallel(const BrotliParams& params, + const uint32_t input_size, + const uint8_t* input_buffer, + const uint32_t prefix_size, + const uint8_t* prefix_buffer, + const int is_first, + const int is_last, + size_t* encoded_size, + uint8_t* encoded_buffer) { if (input_size == 0) { - return false; + return 0; } + MemoryManager memory_manager; + MemoryManager* m = &memory_manager; + BrotliInitMemoryManager(m, 0, 0, 0); + + uint8_t* storage; + size_t storage_ix; + uint8_t first_byte; + size_t first_byte_bits; + size_t output_size; + uint32_t num_direct_distance_codes; + uint32_t distance_postfix_bits; + ContextType literal_context_mode; + size_t last_insert_len = 0; + size_t num_commands = 0; + size_t num_literals = 0; + int dist_cache[4] = { -4, -4, -4, -4 }; + Command* commands; + int hash_type = BROTLI_MIN(int, 10, params.quality); + Hashers* hashers; + int use_utf8_mode; + uint8_t prev_byte; + uint8_t prev_byte2; + const uint32_t mask = BROTLI_UINT32_MAX >> 1; + /* Copy prefix + next input block into a continuous area. */ uint32_t input_pos = prefix_size; /* CreateBackwardReferences reads up to 3 bytes past the end of input if the mask points past the end of input. FindMatchLengthWithLimit could do another 8 bytes look-forward. */ - std::vector<uint8_t> input(prefix_size + input_size + 4 + 8); - memcpy(&input[0], prefix_buffer, prefix_size); - memcpy(&input[input_pos], input_buffer, input_size); + uint8_t* input = BROTLI_ALLOC(m, uint8_t, prefix_size + input_size + 4 + 8); + if (BROTLI_IS_OOM(m)) goto oom; + memcpy(input, prefix_buffer, prefix_size); + memcpy(input + input_pos, input_buffer, input_size); /* Since we don't have a ringbuffer, masking is a no-op. We use one less bit than the full range because some of the code uses mask + 1 as the size of the ringbuffer. */ - const uint32_t mask = std::numeric_limits<uint32_t>::max() >> 1; - uint8_t prev_byte = input_pos > 0 ? input[(input_pos - 1) & mask] : 0; - uint8_t prev_byte2 = input_pos > 1 ? input[(input_pos - 2) & mask] : 0; + prev_byte = input_pos > 0 ? input[(input_pos - 1) & mask] : 0; + prev_byte2 = input_pos > 1 ? input[(input_pos - 2) & mask] : 0; /* Decide about UTF8 mode. */ static const double kMinUTF8Ratio = 0.75; - bool utf8_mode = IsMostlyUTF8(&input[0], input_pos, mask, input_size, - kMinUTF8Ratio); + use_utf8_mode = BrotliIsMostlyUTF8( + input, input_pos, mask, input_size, kMinUTF8Ratio); /* Initialize hashers. */ - int hash_type = std::min(10, params.quality); - Hashers* hashers = new Hashers(); - hashers->Init(hash_type); + hashers = BROTLI_ALLOC(m, Hashers, 1); + if (BROTLI_IS_OOM(m)) goto oom; + InitHashers(hashers); + HashersSetup(m, hashers, hash_type); + if (BROTLI_IS_OOM(m)) goto oom; /* Compute backward references. */ - size_t last_insert_len = 0; - size_t num_commands = 0; - size_t num_literals = 0; - int dist_cache[4] = { -4, -4, -4, -4 }; - Command* commands = static_cast<Command*>( - malloc(sizeof(Command) * ((input_size + 1) >> 1))); - if (commands == 0) { - delete hashers; - return false; - } - CreateBackwardReferences( - input_size, input_pos, is_last, - &input[0], mask, - params.quality, - params.lgwin, - hashers, - hash_type, - dist_cache, - &last_insert_len, - commands, - &num_commands, - &num_literals); - delete hashers; + commands = BROTLI_ALLOC(m, Command, ((input_size + 1) >> 1)); + if (BROTLI_IS_OOM(m)) goto oom; + BrotliCreateBackwardReferences(m, input_size, input_pos, is_last, input, + mask, params.quality, params.lgwin, hashers, hash_type, dist_cache, + &last_insert_len, commands, &num_commands, &num_literals); + if (BROTLI_IS_OOM(m)) goto oom; + DestroyHashers(m, hashers); + BROTLI_FREE(m, hashers); if (last_insert_len > 0) { - commands[num_commands++] = Command(last_insert_len); + InitInsertCommand(&commands[num_commands++], last_insert_len); num_literals += last_insert_len; } assert(num_commands != 0); /* Build the meta-block. */ MetaBlockSplit mb; - uint32_t num_direct_distance_codes = - params.mode == BrotliParams::MODE_FONT ? 12 : 0; - uint32_t distance_postfix_bits = - params.mode == BrotliParams::MODE_FONT ? 1 : 0; - ContextType literal_context_mode = utf8_mode ? CONTEXT_UTF8 : CONTEXT_SIGNED; + InitMetaBlockSplit(&mb); + num_direct_distance_codes = params.mode == BrotliParams::MODE_FONT ? 12 : 0; + distance_postfix_bits = params.mode == BrotliParams::MODE_FONT ? 1 : 0; + literal_context_mode = use_utf8_mode ? CONTEXT_UTF8 : CONTEXT_SIGNED; RecomputeDistancePrefixes(commands, num_commands, num_direct_distance_codes, distance_postfix_bits); if (params.quality <= 9) { - BuildMetaBlockGreedy(&input[0], input_pos, mask, + BrotliBuildMetaBlockGreedy(m, input, input_pos, mask, + commands, num_commands, + &mb); + if (BROTLI_IS_OOM(m)) goto oom; + } else { + BrotliBuildMetaBlock(m, input, input_pos, mask, params.quality, + prev_byte, prev_byte2, commands, num_commands, + literal_context_mode, &mb); - } else { - BuildMetaBlock(&input[0], input_pos, mask, - prev_byte, prev_byte2, - commands, num_commands, - literal_context_mode, - &mb); + if (BROTLI_IS_OOM(m)) goto oom; } /* Set up the temporary output storage. */ - const size_t max_out_size = 2 * input_size + 500; - std::vector<uint8_t> storage(max_out_size); - uint8_t first_byte = 0; - size_t first_byte_bits = 0; + storage = BROTLI_ALLOC(m, uint8_t, 2 * input_size + 500); + if (BROTLI_IS_OOM(m)) goto oom; + first_byte = 0; + first_byte_bits = 0; if (is_first) { if (params.lgwin == 16) { first_byte = 0; @@ -159,45 +166,55 @@ bool WriteMetaBlockParallel(const BrotliParams& params, } } storage[0] = static_cast<uint8_t>(first_byte); - size_t storage_ix = first_byte_bits; + storage_ix = first_byte_bits; /* Store the meta-block to the temporary output. */ - StoreMetaBlock(&input[0], input_pos, input_size, mask, - prev_byte, prev_byte2, - is_last, - num_direct_distance_codes, - distance_postfix_bits, - literal_context_mode, - commands, num_commands, - mb, - &storage_ix, &storage[0]); - free(commands); + BrotliStoreMetaBlock(m, input, input_pos, input_size, mask, + prev_byte, prev_byte2, + is_last, + num_direct_distance_codes, + distance_postfix_bits, + literal_context_mode, + commands, num_commands, + &mb, + &storage_ix, storage); + if (BROTLI_IS_OOM(m)) goto oom; + DestroyMetaBlockSplit(m, &mb); + BROTLI_FREE(m, commands); /* If this is not the last meta-block, store an empty metadata meta-block so that the meta-block will end at a byte boundary. */ if (!is_last) { - StoreSyncMetaBlock(&storage_ix, &storage[0]); + BrotliStoreSyncMetaBlock(&storage_ix, storage); } /* If the compressed data is too large, fall back to an uncompressed meta-block. */ - size_t output_size = storage_ix >> 3; + output_size = storage_ix >> 3; if (input_size + 4 < output_size) { storage[0] = static_cast<uint8_t>(first_byte); storage_ix = first_byte_bits; - StoreUncompressedMetaBlock(is_last, &input[0], input_pos, mask, - input_size, - &storage_ix, &storage[0]); + BrotliStoreUncompressedMetaBlock(is_last, input, input_pos, mask, + input_size, + &storage_ix, storage); output_size = storage_ix >> 3; } /* Copy the temporary output with size-check to the output. */ if (output_size > *encoded_size) { - return false; + BROTLI_FREE(m, storage); + BROTLI_FREE(m, input); + return 0; } - memcpy(encoded_buffer, &storage[0], output_size); + memcpy(encoded_buffer, storage, output_size); *encoded_size = output_size; - return true; + BROTLI_FREE(m, storage); + BROTLI_FREE(m, input); + return 1; + +oom: + BrotliWipeOutMemoryManager(m); + return 0; } } /* namespace */ @@ -217,20 +234,20 @@ int BrotliCompressBufferParallel(BrotliParams params, } /* Sanitize params. */ - if (params.lgwin < kMinWindowBits) { - params.lgwin = kMinWindowBits; - } else if (params.lgwin > kMaxWindowBits) { - params.lgwin = kMaxWindowBits; + if (params.lgwin < kBrotliMinWindowBits) { + params.lgwin = kBrotliMinWindowBits; + } else if (params.lgwin > kBrotliMaxWindowBits) { + params.lgwin = kBrotliMaxWindowBits; } if (params.lgblock == 0) { params.lgblock = 16; if (params.quality >= 9 && params.lgwin > params.lgblock) { - params.lgblock = std::min(21, params.lgwin); + params.lgblock = BROTLI_MIN(int, 21, params.lgwin); } - } else if (params.lgblock < kMinInputBlockBits) { - params.lgblock = kMinInputBlockBits; - } else if (params.lgblock > kMaxInputBlockBits) { - params.lgblock = kMaxInputBlockBits; + } else if (params.lgblock < kBrotliMinInputBlockBits) { + params.lgblock = kBrotliMinInputBlockBits; + } else if (params.lgblock > kBrotliMaxInputBlockBits) { + params.lgblock = kBrotliMaxInputBlockBits; } size_t max_input_block_size = 1 << params.lgblock; size_t max_prefix_size = 1u << params.lgwin; @@ -239,10 +256,10 @@ int BrotliCompressBufferParallel(BrotliParams params, /* Compress block-by-block independently. */ for (size_t pos = 0; pos < input_size; ) { - uint32_t input_block_size = - static_cast<uint32_t>(std::min(max_input_block_size, input_size - pos)); + uint32_t input_block_size = static_cast<uint32_t>( + BROTLI_MIN(size_t, max_input_block_size, input_size - pos)); uint32_t prefix_size = - static_cast<uint32_t>(std::min(max_prefix_size, pos)); + static_cast<uint32_t>(BROTLI_MIN(size_t, max_prefix_size, pos)); size_t out_size = input_block_size + (input_block_size >> 3) + 1024; std::vector<uint8_t> out(out_size); if (!WriteMetaBlockParallel(params, @@ -250,11 +267,11 @@ int BrotliCompressBufferParallel(BrotliParams params, &input_buffer[pos], prefix_size, &input_buffer[pos - prefix_size], - pos == 0, - pos + input_block_size == input_size, + (pos == 0) ? 1 : 0, + (pos + input_block_size == input_size) ? 1 : 0, &out_size, &out[0])) { - return false; + return 0; } out.resize(out_size); compressed_pieces.push_back(out); @@ -266,14 +283,14 @@ int BrotliCompressBufferParallel(BrotliParams params, for (size_t i = 0; i < compressed_pieces.size(); ++i) { const std::vector<uint8_t>& out = compressed_pieces[i]; if (out_pos + out.size() > *encoded_size) { - return false; + return 0; } memcpy(&encoded_buffer[out_pos], &out[0], out.size()); out_pos += out.size(); } *encoded_size = out_pos; - return true; + return 1; } } /* namespace brotli */ |