Allocate single memory in GetHuffBitLengthsAndCodes.

Allocate big chunk of memory in GetHuffBitLengthsAndCodes, instead of allocating in a loop.
Also fixed the potential memleak.

Change-Id: Idc23ffa306f76100217304444191a8d2fef9c44a
This commit is contained in:
Vikas Arora 2012-05-14 13:00:00 +05:30
parent 2924a5aee6
commit 41d8049451

View File

@ -271,21 +271,51 @@ static int GetHuffBitLengthsAndCodes(
uint16_t** const bit_codes, uint8_t** const bit_lengths) { uint16_t** const bit_codes, uint8_t** const bit_lengths) {
int i, k; int i, k;
int ok = 1; int ok = 1;
int total_length_size = 0;
uint8_t* mem_buf = NULL;
const int histogram_image_size = histogram_image->size; const int histogram_image_size = histogram_image->size;
// Iterate over all histograms and get the aggregate number of codes used.
for (i = 0; i < histogram_image_size; ++i) { for (i = 0; i < histogram_image_size; ++i) {
VP8LHistogram* const histo = histogram_image->histograms[i]; VP8LHistogram* const histo = histogram_image->histograms[i];
const int num_literals = VP8LHistogramNumCodes(histo); const int num_literals = VP8LHistogramNumCodes(histo);
k = 0; k = 0;
// TODO(vikasa): Alloc one big buffer instead of allocating in the loop.
bit_length_sizes[5 * i] = num_literals; bit_length_sizes[5 * i] = num_literals;
bit_lengths[5 * i] = (uint8_t*)calloc(num_literals, 1); total_length_size += num_literals;
bit_codes[5 * i] = (uint16_t*) for (k = 1; k < 5; ++k) {
malloc(num_literals * sizeof(*bit_codes[5 * i])); const int val = (k == 4) ? DISTANCE_CODES_MAX : 256;
if (bit_lengths[5 * i] == NULL || bit_codes[5 * i] == NULL) { bit_length_sizes[5 * i + k] = val;
ok = 0; total_length_size += val;
goto Error; }
} }
// Allocate and Set bit_lengths and bit_codes.
{
uint16_t* codes;
uint8_t* lengths;
const size_t total_buf_size = total_length_size * sizeof(*lengths)
+ total_length_size * sizeof(*codes);
mem_buf = (uint8_t*)calloc(total_buf_size, 1);
if (mem_buf == NULL) {
ok = 0;
goto End;
}
codes = (uint16_t*)mem_buf;
lengths = (uint8_t*)&codes[total_length_size];
for (i = 0; i < 5 * histogram_image_size; ++i) {
const int bit_length = bit_length_sizes[i];
bit_codes[i] = codes;
bit_lengths[i] = lengths;
codes += bit_length;
lengths += bit_length;
}
}
// Create Huffman trees.
for (i = 0; i < histogram_image_size; ++i) {
const int ix = 5 * i;
VP8LHistogram* const histo = histogram_image->histograms[i];
const int num_literals = bit_length_sizes[ix];
// For each component, optimize histogram for Huffman with RLE compression. // For each component, optimize histogram for Huffman with RLE compression.
ok = ok && OptimizeHuffmanForRle(num_literals, histo->literal_); ok = ok && OptimizeHuffmanForRle(num_literals, histo->literal_);
if (!use_color_cache) { if (!use_color_cache) {
@ -295,54 +325,37 @@ static int GetHuffBitLengthsAndCodes(
// palette entry, so zero it out. // palette entry, so zero it out.
histo->literal_[256 + kLengthCodes] = 0; histo->literal_[256 + kLengthCodes] = 0;
} }
ok = ok && OptimizeHuffmanForRle(256, histo->red_);
ok = ok && OptimizeHuffmanForRle(256, histo->blue_);
ok = ok && OptimizeHuffmanForRle(256, histo->alpha_);
ok = ok && OptimizeHuffmanForRle(DISTANCE_CODES_MAX, histo->distance_);
// Create a Huffman tree (in the form of bit lengths) for each component. // Create a Huffman tree (in the form of bit lengths) for each component.
ok = ok && VP8LCreateHuffmanTree(histo->literal_, num_literals, ok = ok && VP8LCreateHuffmanTree(histo->literal_, num_literals, 15,
15, bit_lengths[5 * i]); bit_lengths[ix]);
for (k = 1; k < 5; ++k) {
const int val = (k == 4) ? DISTANCE_CODES_MAX : 256; ok = ok && OptimizeHuffmanForRle(256, histo->red_);
bit_length_sizes[5 * i + k] = val; ok = ok && VP8LCreateHuffmanTree(histo->red_, 256, 15,
bit_lengths[5 * i + k] = (uint8_t*)calloc(val, 1); bit_lengths[ix + 1]);
bit_codes[5 * i + k] = (uint16_t*)calloc(val, sizeof(*bit_codes[0]));
if (bit_lengths[5 * i + k] == NULL || ok = ok && OptimizeHuffmanForRle(256, histo->blue_);
bit_codes[5 * i + k] == NULL) { ok = ok && VP8LCreateHuffmanTree(histo->blue_, 256, 15,
ok = 0; bit_lengths[ix + 2]);
goto Error;
} ok = ok && OptimizeHuffmanForRle(256, histo->alpha_);
} ok = ok && VP8LCreateHuffmanTree(histo->alpha_, 256, 15,
ok = ok && bit_lengths[ix + 3]);
VP8LCreateHuffmanTree(histo->red_, 256, 15,
bit_lengths[5 * i + 1]) && ok = ok && OptimizeHuffmanForRle(DISTANCE_CODES_MAX, histo->distance_);
VP8LCreateHuffmanTree(histo->blue_, 256, 15, ok = ok && VP8LCreateHuffmanTree(histo->distance_, DISTANCE_CODES_MAX, 15,
bit_lengths[5 * i + 2]) && bit_lengths[ix + 4]);
VP8LCreateHuffmanTree(histo->alpha_, 256, 15,
bit_lengths[5 * i + 3]) &&
VP8LCreateHuffmanTree(histo->distance_, DISTANCE_CODES_MAX, 15,
bit_lengths[5 * i + 4]);
// Create the actual bit codes for the bit lengths. // Create the actual bit codes for the bit lengths.
for (k = 0; k < 5; ++k) { for (k = 0; k < 5; ++k) {
int ix = 5 * i + k; VP8LConvertBitDepthsToSymbols(bit_lengths[ix + k],
VP8LConvertBitDepthsToSymbols(bit_lengths[ix], bit_length_sizes[ix], bit_length_sizes[ix + k],
bit_codes[ix]); bit_codes[ix + k]);
} }
} }
return ok;
Error: End:
{ if (!ok) free(mem_buf);
int idx; return ok;
for (idx = 0; idx <= 5 * i + k; ++idx) {
free(bit_lengths[idx]);
free(bit_codes[idx]);
bit_lengths[idx] = NULL;
bit_codes[idx] = NULL;
}
}
return 0;
} }
static void ClearHuffmanTreeIfOnlyOneSymbol(const int num_symbols, static void ClearHuffmanTreeIfOnlyOneSymbol(const int num_symbols,
@ -688,12 +701,9 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
if (!ok) free(histogram_image); if (!ok) free(histogram_image);
VP8LClearBackwardRefs(&refs); VP8LClearBackwardRefs(&refs);
for (i = 0; i < bit_array_size; ++i) {
free(bit_lengths[i]);
free(bit_codes[i]);
}
free(bit_lengths_sizes); free(bit_lengths_sizes);
free(bit_lengths); free(bit_lengths);
free(*bit_codes);
free(bit_codes); free(bit_codes);
free(histogram_symbols); free(histogram_symbols);
return ok; return ok;