mirror of
https://github.com/google/brotli.git
synced 2024-12-29 11:11:09 +00:00
Encoder support for new empty meta-block format.
Changed the parallel implementation to sync meta-blocks to byte boundary by emitting empty meta-blocks.
This commit is contained in:
parent
098c928864
commit
2fd80cdc9a
@ -36,7 +36,7 @@ namespace brotli {
|
||||
bool EncodeMlen(size_t length, int* bits, int* numbits, int* nibblesbits) {
|
||||
length--; // MLEN - 1 is encoded
|
||||
int lg = length == 0 ? 1 : Log2Floor(length) + 1;
|
||||
if (lg > 28) return false;
|
||||
if (lg > 24) return false;
|
||||
int mnibbles = (lg < 16 ? 16 : (lg + 3)) / 4;
|
||||
*nibblesbits = mnibbles - 4;
|
||||
*numbits = mnibbles * 4;
|
||||
@ -828,4 +828,15 @@ bool StoreUncompressedMetaBlock(bool final_block,
|
||||
return true;
|
||||
}
|
||||
|
||||
void StoreSyncMetaBlock(int * __restrict storage_ix,
|
||||
uint8_t * __restrict storage) {
|
||||
// Empty metadata meta-block bit pattern:
|
||||
// 1 bit: is_last (0)
|
||||
// 2 bits: num nibbles (3)
|
||||
// 1 bit: reserved (0)
|
||||
// 2 bits: metadata length bytes (0)
|
||||
WriteBits(6, 6, storage_ix, storage);
|
||||
JumpToByteBoundary(storage_ix, storage);
|
||||
}
|
||||
|
||||
} // namespace brotli
|
||||
|
@ -130,6 +130,9 @@ bool StoreUncompressedMetaBlock(bool final_block,
|
||||
int* storage_ix,
|
||||
uint8_t* storage);
|
||||
|
||||
// Stores an empty metadata meta-block and syncs to a byte boundary.
|
||||
void StoreSyncMetaBlock(int* storage_ix, uint8_t* storage);
|
||||
|
||||
} // namespace brotli
|
||||
|
||||
#endif // BROTLI_ENC_BROTLI_BIT_STREAM_H_
|
||||
|
@ -467,6 +467,39 @@ bool BrotliCompressor::WriteMetaBlock(const size_t input_size,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BrotliCompressor::WriteMetadata(const size_t input_size,
|
||||
const uint8_t* input_buffer,
|
||||
const bool is_last,
|
||||
size_t* encoded_size,
|
||||
uint8_t* encoded_buffer) {
|
||||
if (input_size > (1 << 24) || input_size + 6 > *encoded_size) {
|
||||
return false;
|
||||
}
|
||||
int storage_ix = last_byte_bits_;
|
||||
encoded_buffer[0] = last_byte_;
|
||||
WriteBits(1, 0, &storage_ix, encoded_buffer);
|
||||
WriteBits(2, 3, &storage_ix, encoded_buffer);
|
||||
WriteBits(1, 0, &storage_ix, encoded_buffer);
|
||||
if (input_size == 0) {
|
||||
WriteBits(2, 0, &storage_ix, encoded_buffer);
|
||||
*encoded_size = (storage_ix + 7) >> 3;
|
||||
} else {
|
||||
size_t nbits = Log2Floor(input_size - 1) + 1;
|
||||
size_t nbytes = (nbits + 7) / 8;
|
||||
WriteBits(2, nbytes, &storage_ix, encoded_buffer);
|
||||
WriteBits(8 * nbytes, input_size - 1, &storage_ix, encoded_buffer);
|
||||
size_t hdr_size = (storage_ix + 7) >> 3;
|
||||
memcpy(&encoded_buffer[hdr_size], input_buffer, input_size);
|
||||
*encoded_size = hdr_size + input_size;
|
||||
}
|
||||
if (is_last) {
|
||||
encoded_buffer[(*encoded_size)++] = 3;
|
||||
}
|
||||
last_byte_ = 0;
|
||||
last_byte_bits_ = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BrotliCompressor::FinishStream(
|
||||
size_t* encoded_size, uint8_t* encoded_buffer) {
|
||||
return WriteMetaBlock(0, NULL, true, encoded_size, encoded_buffer);
|
||||
|
12
enc/encode.h
12
enc/encode.h
@ -85,6 +85,18 @@ class BrotliCompressor {
|
||||
size_t* encoded_size,
|
||||
uint8_t* encoded_buffer);
|
||||
|
||||
// Writes a metadata meta-block containing the given input to encoded_buffer.
|
||||
// *encoded_size should be set to the size of the encoded_buffer.
|
||||
// Sets *encoded_size to the number of bytes that was written.
|
||||
// Note that the given input data will not be part of the sliding window and
|
||||
// thus no backward references can be made to this data from subsequent
|
||||
// metablocks.
|
||||
bool WriteMetadata(const size_t input_size,
|
||||
const uint8_t* input_buffer,
|
||||
const bool is_last,
|
||||
size_t* encoded_size,
|
||||
uint8_t* encoded_buffer);
|
||||
|
||||
// Writes a zero-length meta-block with end-of-input bit set to the
|
||||
// internal output buffer and copies the output buffer to encoded_buffer
|
||||
// (*encoded_size should be set to the size of encoded_buffer) and sets
|
||||
|
@ -129,10 +129,10 @@ bool WriteMetaBlockParallel(const BrotliParams& params,
|
||||
const bool is_last,
|
||||
size_t* encoded_size,
|
||||
uint8_t* encoded_buffer) {
|
||||
if (block_size == 0 || (!is_last && block_size == 1)) {
|
||||
if (block_size == 0) {
|
||||
return false;
|
||||
}
|
||||
const size_t input_size = is_last ? block_size : block_size - 1;
|
||||
const size_t input_size = block_size;
|
||||
|
||||
// Copy prefix + next input block into a continuous area.
|
||||
size_t input_pos = prefix_size;
|
||||
@ -246,13 +246,10 @@ bool WriteMetaBlockParallel(const BrotliParams& params,
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this is not the last meta-block, store a one-byte uncompressed
|
||||
// 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 &&
|
||||
!StoreUncompressedMetaBlock(is_last, &input_buffer[input_size],
|
||||
0, mask, 1,
|
||||
&storage_ix, &storage[0])) {
|
||||
return false;
|
||||
if (!is_last) {
|
||||
StoreSyncMetaBlock(&storage_ix, &storage[0]);
|
||||
}
|
||||
|
||||
// If the compressed data is too large, fall back to an uncompressed
|
||||
|
Loading…
Reference in New Issue
Block a user