use WebPSafe[CM]alloc/WebPSafeFree instead of [cm]alloc/free

there's still some malloc/free in the external example
This is an encoder API change because of the introduction
of WebPMemoryWriterClear() for symmetry reasons.

The MemoryWriter object should probably go in examples/ instead
of being in the main lib, though.
mux_types.h stil contain some inlined free()/malloc() that are
harder to remove (we need to put them in the libwebputils lib
and make sure link is ok). Left as a TODO for now.

Also: WebPDecodeRGB*() function are still returning a pointer
that needs to be free()'d. We should call WebPSafeFree() on
these, but it means exposing the whole mechanism. TODO(later).

Change-Id: Iad2c9060f7fa6040e3ba489c8b07f4caadfab77b
This commit is contained in:
skal
2014-03-27 23:27:32 +01:00
committed by Gerrit Code Review
parent 51f406a5d7
commit af93bdd6bc
32 changed files with 168 additions and 134 deletions

View File

@ -17,6 +17,7 @@
#include "./vp8enci.h"
#include "../utils/filters.h"
#include "../utils/quant_levels.h"
#include "../utils/utils.h"
#include "../webp/format_constants.h"
// -----------------------------------------------------------------------------
@ -34,7 +35,7 @@
//
// 'output' corresponds to the buffer containing compressed alpha data.
// This buffer is allocated by this method and caller should call
// free(*output) when done.
// WebPSafeFree(*output) when done.
// 'output_size' corresponds to size of this compressed alpha buffer.
//
// Returns 1 on successfully encoding the alpha and
@ -231,7 +232,7 @@ static int ApplyFiltersAndEncode(const uint8_t* alpha, int width, int height,
GetFilterMap(alpha, width, height, filter, effort_level);
InitFilterTrial(&best);
if (try_map != FILTER_TRY_NONE) {
uint8_t* filtered_alpha = (uint8_t*)malloc(data_size);
uint8_t* filtered_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size);
if (filtered_alpha == NULL) return 0;
for (filter = WEBP_FILTER_NONE; ok && try_map; ++filter, try_map >>= 1) {
@ -248,7 +249,7 @@ static int ApplyFiltersAndEncode(const uint8_t* alpha, int width, int height,
}
}
}
free(filtered_alpha);
WebPSafeFree(filtered_alpha);
} else {
ok = EncodeAlphaInternal(alpha, width, height, method, WEBP_FILTER_NONE,
reduce_levels, effort_level, NULL, &best);
@ -298,7 +299,7 @@ static int EncodeAlpha(VP8Encoder* const enc,
filter = WEBP_FILTER_NONE;
}
quant_alpha = (uint8_t*)malloc(data_size);
quant_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size);
if (quant_alpha == NULL) {
return 0;
}
@ -325,7 +326,7 @@ static int EncodeAlpha(VP8Encoder* const enc,
}
}
free(quant_alpha);
WebPSafeFree(quant_alpha);
return ok;
}
@ -346,7 +347,7 @@ static int CompressAlphaJob(VP8Encoder* const enc, void* dummy) {
return 0;
}
if (alpha_size != (uint32_t)alpha_size) { // Sanity check.
free(alpha_data);
WebPSafeFree(alpha_data);
return 0;
}
enc->alpha_data_size_ = (uint32_t)alpha_size;
@ -401,7 +402,7 @@ int VP8EncDeleteAlpha(VP8Encoder* const enc) {
ok = WebPWorkerSync(worker); // finish anything left in flight
WebPWorkerEnd(worker); // still need to end the worker, even if !ok
}
free(enc->alpha_data_);
WebPSafeFree(enc->alpha_data_);
enc->alpha_data_ = NULL;
enc->alpha_data_size_ = 0;
enc->has_alpha_ = 0;

View File

@ -63,7 +63,7 @@ static void SmoothSegmentMap(VP8Encoder* const enc) {
mb->segment_ = tmp[x + y * w];
}
}
free(tmp);
WebPSafeFree(tmp);
}
//------------------------------------------------------------------------------

View File

@ -89,7 +89,7 @@ void VP8LInitBackwardRefs(VP8LBackwardRefs* const refs) {
void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs) {
if (refs != NULL) {
free(refs->refs);
WebPSafeFree(refs->refs);
VP8LInitBackwardRefs(refs);
}
}
@ -116,13 +116,13 @@ static WEBP_INLINE uint64_t GetPixPairHash64(const uint32_t* const argb) {
static HashChain* HashChainNew(int size) {
int i;
HashChain* const p = (HashChain*)malloc(sizeof(*p));
HashChain* const p = (HashChain*)WebPSafeMalloc(1ULL, sizeof(*p));
if (p == NULL) {
return NULL;
}
p->chain_ = (int*)WebPSafeMalloc((uint64_t)size, sizeof(*p->chain_));
if (p->chain_ == NULL) {
free(p);
WebPSafeFree(p);
return NULL;
}
for (i = 0; i < size; ++i) {
@ -136,8 +136,8 @@ static HashChain* HashChainNew(int size) {
static void HashChainDelete(HashChain* const p) {
if (p != NULL) {
free(p->chain_);
free(p);
WebPSafeFree(p->chain_);
WebPSafeFree(p);
}
}
@ -490,7 +490,7 @@ static int BackwardReferencesHashChainDistanceOnly(
const int use_color_cache = (cache_bits > 0);
float* const cost =
(float*)WebPSafeMalloc((uint64_t)pix_count, sizeof(*cost));
CostModel* cost_model = (CostModel*)malloc(sizeof(*cost_model));
CostModel* cost_model = (CostModel*)WebPSafeMalloc(1ULL, sizeof(*cost_model));
HashChain* hash_chain = HashChainNew(pix_count);
VP8LColorCache hashers;
const double mul0 = (recursive_cost_model != 0) ? 1.0 : 0.68;
@ -597,8 +597,8 @@ static int BackwardReferencesHashChainDistanceOnly(
Error:
if (cc_init) VP8LColorCacheClear(&hashers);
HashChainDelete(hash_chain);
free(cost_model);
free(cost);
WebPSafeFree(cost_model);
WebPSafeFree(cost);
return ok;
}
@ -724,7 +724,7 @@ static int BackwardReferencesTraceBackwards(int xsize, int ysize,
}
ok = 1;
Error:
free(dist_array);
WebPSafeFree(dist_array);
return ok;
}
@ -768,7 +768,8 @@ int VP8LGetBackwardReferences(int width, int height,
{
double bit_cost_lz77, bit_cost_rle;
VP8LHistogram* const histo = (VP8LHistogram*)malloc(sizeof(*histo));
VP8LHistogram* const histo =
(VP8LHistogram*)WebPSafeMalloc(1ULL, sizeof(*histo));
if (histo == NULL) goto Error1;
// Evaluate lz77 coding
VP8LHistogramCreate(histo, &refs_lz77, cache_bits);
@ -778,7 +779,7 @@ int VP8LGetBackwardReferences(int width, int height,
bit_cost_rle = VP8LHistogramEstimateBits(histo);
// Decide if LZ77 is useful.
lz77_is_useful = (bit_cost_lz77 < bit_cost_rle);
free(histo);
WebPSafeFree(histo);
}
// Choose appropriate backward reference.

View File

@ -162,7 +162,7 @@ static int Record(int bit, proba_t* const stats) {
return bit;
}
// We keep the table free variant around for reference, in case.
// We keep the table-free variant around for reference, in case.
#define USE_LEVEL_CODE_TABLE
// Simulate block coding, but only record statistics.

View File

@ -723,7 +723,8 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize,
// bin_map[n][num_histo + 1] ... bin_map[n][bin_depth - 1] = un-used indices.
const int bin_depth = histo_image_raw_size + 1;
int16_t* bin_map = NULL;
VP8LHistogram* const histos = (VP8LHistogram*)malloc(2 * sizeof(*histos));
VP8LHistogram* const histos =
(VP8LHistogram*)WebPSafeMalloc(2ULL, sizeof(*histos));
VP8LHistogramSet* const init_histo =
VP8LAllocateHistogramSet(histo_image_raw_size, cache_bits);
@ -760,8 +761,8 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize,
ok = 1;
Error:
free(bin_map);
free(init_histo);
free(histos);
WebPSafeFree(bin_map);
WebPSafeFree(init_histo);
WebPSafeFree(histos);
return ok;
}

View File

@ -46,7 +46,7 @@ typedef struct {
} VP8LHistogram;
// Collection of histograms with fixed capacity, allocated as one
// big memory chunk. Can be destroyed by simply calling 'free()'.
// big memory chunk. Can be destroyed by calling WebPSafeFree().
typedef struct {
int size; // number of slots currently in use
int max_size; // maximum capacity

View File

@ -14,6 +14,7 @@
#include <stdlib.h>
#include "./vp8enci.h"
#include "../utils/utils.h"
//------------------------------------------------------------------------------
@ -39,6 +40,5 @@ int VP8EncFinishLayer(VP8Encoder* const enc) {
}
void VP8EncDeleteLayer(VP8Encoder* enc) {
free(enc->layer_data_);
WebPSafeFree(enc->layer_data_);
}

View File

@ -175,7 +175,7 @@ static void WebPPictureGrabSpecs(const WebPPicture* const src,
// the other YUV(A) buffer.
static int PictureAllocARGB(WebPPicture* const picture) {
WebPPicture tmp;
free(picture->memory_argb_);
WebPSafeFree(picture->memory_argb_);
PictureResetARGB(picture);
picture->use_argb = 1;
WebPPictureGrabSpecs(picture, &tmp);
@ -191,8 +191,8 @@ static int PictureAllocARGB(WebPPicture* const picture) {
// Release memory owned by 'picture' (both YUV and ARGB buffers).
void WebPPictureFree(WebPPicture* picture) {
if (picture != NULL) {
free(picture->memory_);
free(picture->memory_argb_);
WebPSafeFree(picture->memory_);
WebPSafeFree(picture->memory_argb_);
PictureResetYUVA(picture);
PictureResetARGB(picture);
}
@ -504,7 +504,7 @@ int WebPPictureRescale(WebPPicture* pic, int width, int height) {
AlphaMultiplyARGB(&tmp, 1);
}
WebPPictureFree(pic);
free(work);
WebPSafeFree(work);
*pic = tmp;
return 1;
}
@ -538,7 +538,7 @@ int WebPMemoryWrite(const uint8_t* data, size_t data_size,
if (w->size > 0) {
memcpy(new_mem, w->mem, w->size);
}
free(w->mem);
WebPSafeFree(w->mem);
w->mem = new_mem;
// down-cast is ok, thanks to WebPSafeMalloc
w->max_size = (size_t)next_max_size;
@ -550,6 +550,15 @@ int WebPMemoryWrite(const uint8_t* data, size_t data_size,
return 1;
}
void WebPMemoryWriterClear(WebPMemoryWriter* writer) {
if (writer != NULL) {
WebPSafeFree(writer->mem);
writer->mem = NULL;
writer->size = 0;
writer->max_size = 0;
}
}
//------------------------------------------------------------------------------
// Detection of non-trivial transparency
@ -1323,7 +1332,7 @@ static size_t Encode(const uint8_t* rgba, int width, int height, int stride,
ok = import(&pic, rgba, stride) && WebPEncode(&config, &pic);
WebPPictureFree(&pic);
if (!ok) {
free(wrt.mem);
WebPMemoryWriterClear(&wrt);
*output = NULL;
return 0;
}

View File

@ -22,6 +22,7 @@
#include "./cost.h"
#include "./vp8enci.h"
#include "../utils/utils.h"
#if !defined(DISABLE_TOKEN_BUFFER)
@ -51,7 +52,7 @@ void VP8TBufferClear(VP8TBuffer* const b) {
const VP8Tokens* p = b->pages_;
while (p != NULL) {
const VP8Tokens* const next = p->next_;
free((void*)p);
WebPSafeFree((void*)p);
p = next;
}
VP8TBufferInit(b);
@ -59,7 +60,8 @@ void VP8TBufferClear(VP8TBuffer* const b) {
}
static int TBufferNewPage(VP8TBuffer* const b) {
VP8Tokens* const page = b->error_ ? NULL : (VP8Tokens*)malloc(sizeof(*page));
VP8Tokens* const page =
b->error_ ? NULL : (VP8Tokens*)WebPSafeMalloc(1ULL, sizeof(*page));
if (page == NULL) {
b->error_ = 1;
return 0;
@ -228,7 +230,7 @@ int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw,
VP8PutBit(bw, bit, probas[token & 0x3fffu]);
}
}
if (final_pass) free((void*)p);
if (final_pass) WebPSafeFree((void*)p);
p = next;
}
if (final_pass) b->pages_ = NULL;

View File

@ -108,7 +108,7 @@ static int AnalyzeEntropy(const uint32_t* argb,
VP8LHistogram* nonpredicted = NULL;
VP8LHistogram* predicted =
(VP8LHistogram*)malloc(2 * sizeof(*predicted));
(VP8LHistogram*)WebPSafeMalloc(2ULL, sizeof(*predicted));
if (predicted == NULL) return 0;
nonpredicted = predicted + 1;
@ -135,7 +135,7 @@ static int AnalyzeEntropy(const uint32_t* argb,
}
*nonpredicted_bits = VP8LHistogramEstimateBitsBulk(nonpredicted);
*predicted_bits = VP8LHistogramEstimateBitsBulk(predicted);
free(predicted);
WebPSafeFree(predicted);
return 1;
}
@ -228,7 +228,7 @@ static int GetHuffBitLengthsAndCodes(
End:
if (!ok) {
free(mem_buf);
WebPSafeFree(mem_buf);
// If one VP8LCreateHuffmanTree() above fails, we need to clean up behind.
memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes));
}
@ -362,7 +362,7 @@ static int StoreFullHuffmanCode(VP8LBitWriter* const bw,
}
ok = 1;
End:
free(tokens);
WebPSafeFree(tokens);
return ok;
}
@ -503,9 +503,9 @@ static int EncodeImageNoHuffman(VP8LBitWriter* const bw,
ok = 1;
Error:
free(histogram_image);
WebPSafeFree(histogram_image);
VP8LClearBackwardRefs(&refs);
free(huffman_codes[0].codes);
WebPSafeFree(huffman_codes[0].codes);
return ok;
}
@ -532,8 +532,8 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
assert(histogram_bits <= MAX_HUFFMAN_BITS);
if (histogram_image == NULL || histogram_symbols == NULL) {
free(histogram_image);
free(histogram_symbols);
WebPSafeFree(histogram_image);
WebPSafeFree(histogram_symbols);
return 0;
}
@ -559,7 +559,7 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
goto Error;
}
// Free combined histograms.
free(histogram_image);
WebPSafeFree(histogram_image);
histogram_image = NULL;
// Color Cache parameters.
@ -593,7 +593,7 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
VP8LSubSampleSize(width, histogram_bits),
VP8LSubSampleSize(height, histogram_bits),
quality);
free(histogram_argb);
WebPSafeFree(histogram_argb);
if (!ok) goto Error;
}
}
@ -614,14 +614,14 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
ok = 1;
Error:
free(histogram_image);
WebPSafeFree(histogram_image);
VP8LClearBackwardRefs(&refs);
if (huffman_codes != NULL) {
free(huffman_codes->codes);
free(huffman_codes);
WebPSafeFree(huffman_codes->codes);
WebPSafeFree(huffman_codes);
}
free(histogram_symbols);
WebPSafeFree(histogram_symbols);
return ok;
}
@ -637,7 +637,8 @@ static int EvalAndApplySubtractGreen(VP8LEncoder* const enc,
int i;
const uint32_t* const argb = enc->argb_;
double bit_cost_before, bit_cost_after;
VP8LHistogram* const histo = (VP8LHistogram*)malloc(sizeof(*histo));
VP8LHistogram* const histo =
(VP8LHistogram*)WebPSafeMalloc(1ULL, sizeof(*histo));
if (histo == NULL) return 0;
VP8LHistogramInit(histo, 1);
@ -656,7 +657,7 @@ static int EvalAndApplySubtractGreen(VP8LEncoder* const enc,
++histo->blue_[((c >> 0) - green) & 0xff];
}
bit_cost_after = VP8LHistogramEstimateBits(histo);
free(histo);
WebPSafeFree(histo);
// Check if subtracting green yields low entropy.
enc->use_subtract_green_ = (bit_cost_after < bit_cost_before);
@ -907,7 +908,7 @@ static WebPEncodingError EncodePalette(VP8LBitWriter* const bw,
}
Error:
free(row);
WebPSafeFree(row);
return err;
}
@ -944,7 +945,7 @@ static void FinishEncParams(VP8LEncoder* const enc) {
static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config,
const WebPPicture* const picture) {
VP8LEncoder* const enc = (VP8LEncoder*)calloc(1, sizeof(*enc));
VP8LEncoder* const enc = (VP8LEncoder*)WebPSafeCalloc(1ULL, sizeof(*enc));
if (enc == NULL) {
WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
return NULL;
@ -959,9 +960,9 @@ static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config,
static void VP8LEncoderDelete(VP8LEncoder* enc) {
if (enc != NULL) {
free(enc->argb_);
WebPSafeFree(enc->argb_);
WebPSafeFree(enc);
}
free(enc);
}
// -----------------------------------------------------------------------------

View File

@ -269,7 +269,7 @@ static int DeleteVP8Encoder(VP8Encoder* enc) {
VP8EncDeleteLayer(enc);
#endif
VP8TBufferClear(&enc->tokens_);
free(enc);
WebPSafeFree(enc);
}
return ok;
}