diff --git a/src/enc/backward_references.c b/src/enc/backward_references.c index b4b77e9e..ab51336a 100644 --- a/src/enc/backward_references.c +++ b/src/enc/backward_references.c @@ -112,12 +112,7 @@ int VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src, // ----------------------------------------------------------------------------- // Hash chains -static WEBP_INLINE uint64_t GetPixPairHash64(const uint32_t* const argb) { - uint64_t key = ((uint64_t)(argb[1]) << 32) | argb[0]; - key = (key * HASH_MULTIPLIER) >> (64 - HASH_BITS); - return key; -} - +// initialize as empty static void HashChainInit(VP8LHashChain* const p) { int i; assert(p != NULL); @@ -129,26 +124,30 @@ static void HashChainInit(VP8LHashChain* const p) { } } -VP8LHashChain* VP8LHashChainNew(int size) { - VP8LHashChain* const p = (VP8LHashChain*)WebPSafeMalloc(1ULL, sizeof(*p)); - if (p == NULL) { - return NULL; - } +int VP8LHashChainInit(VP8LHashChain* const p, int size) { + assert(p->size_ == 0); + assert(p->chain_ == NULL); + assert(size > 0); p->chain_ = (int*)WebPSafeMalloc(size, sizeof(*p->chain_)); - if (p->chain_ == NULL) { - WebPSafeFree(p); - return NULL; - } + if (p->chain_ == NULL) return 0; p->size_ = size; HashChainInit(p); - return p; + return 1; } -void VP8LHashChainDelete(VP8LHashChain* const p) { - if (p != NULL) { - WebPSafeFree(p->chain_); - WebPSafeFree(p); - } +void VP8LHashChainClear(VP8LHashChain* const p) { + assert(p != NULL); + WebPSafeFree(p->chain_); + p->size_ = 0; + p->chain_ = NULL; +} + +// ----------------------------------------------------------------------------- + +static WEBP_INLINE uint64_t GetPixPairHash64(const uint32_t* const argb) { + uint64_t key = ((uint64_t)argb[1] << 32) | argb[0]; + key = (key * HASH_MULTIPLIER) >> (64 - HASH_BITS); + return key; } // Insertion of two pixels at a time. diff --git a/src/enc/backward_references.h b/src/enc/backward_references.h index 6cf33166..2774a3cf 100644 --- a/src/enc/backward_references.h +++ b/src/enc/backward_references.h @@ -130,8 +130,9 @@ struct VP8LHashChain { int size_; }; -VP8LHashChain* VP8LHashChainNew(int size); -void VP8LHashChainDelete(VP8LHashChain* const p); +// Must be called first, to set size. +int VP8LHashChainInit(VP8LHashChain* const p, int size); +void VP8LHashChainClear(VP8LHashChain* const p); // release memory typedef struct VP8LBackwardRefs VP8LBackwardRefs; struct VP8LBackwardRefs { diff --git a/src/enc/vp8l.c b/src/enc/vp8l.c index 18f0c7a9..7850c046 100644 --- a/src/enc/vp8l.c +++ b/src/enc/vp8l.c @@ -167,8 +167,7 @@ static int AnalyzeAndInit(VP8LEncoder* const enc, WebPImageHint image_hint) { } } } - enc->hash_chain_ = VP8LHashChainNew(pix_cnt); - if (enc->hash_chain_ == NULL) return 0; + if (!VP8LHashChainInit(&enc->hash_chain_, pix_cnt)) return 0; enc->refs_[0] = VP8LBackwardRefsNew(pix_cnt); enc->refs_[1] = VP8LBackwardRefsNew(pix_cnt); @@ -739,7 +738,8 @@ static int ApplyPredictFilter(const VP8LEncoder* const enc, VP8LWriteBits(bw, 2, PREDICTOR_TRANSFORM); assert(pred_bits >= 2); VP8LWriteBits(bw, 3, pred_bits - 2); - if (!EncodeImageNoHuffman(bw, enc->transform_data_, enc->hash_chain_, + if (!EncodeImageNoHuffman(bw, enc->transform_data_, + (VP8LHashChain*)&enc->hash_chain_, enc->refs_, transform_width, transform_height, quality)) { return 0; @@ -760,7 +760,8 @@ static int ApplyCrossColorFilter(const VP8LEncoder* const enc, VP8LWriteBits(bw, 2, CROSS_COLOR_TRANSFORM); assert(ccolor_transform_bits >= 2); VP8LWriteBits(bw, 3, ccolor_transform_bits - 2); - if (!EncodeImageNoHuffman(bw, enc->transform_data_, enc->hash_chain_, + if (!EncodeImageNoHuffman(bw, enc->transform_data_, + (VP8LHashChain*)&enc->hash_chain_, enc->refs_, transform_width, transform_height, quality)) { return 0; @@ -960,7 +961,7 @@ static WebPEncodingError EncodePalette(VP8LBitWriter* const bw, for (i = palette_size - 1; i >= 1; --i) { palette[i] = VP8LSubPixels(palette[i], palette[i - 1]); } - if (!EncodeImageNoHuffman(bw, palette, enc->hash_chain_, enc->refs_, + if (!EncodeImageNoHuffman(bw, palette, &enc->hash_chain_, enc->refs_, palette_size, 1, quality)) { err = VP8_ENC_ERROR_INVALID_CONFIGURATION; goto Error; @@ -1027,7 +1028,7 @@ static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config, static void VP8LEncoderDelete(VP8LEncoder* enc) { if (enc != NULL) { - VP8LHashChainDelete(enc->hash_chain_); + VP8LHashChainClear(&enc->hash_chain_); VP8LBackwardRefsDelete(enc->refs_[0]); VP8LBackwardRefsDelete(enc->refs_[1]); WebPSafeFree(enc->argb_); @@ -1112,7 +1113,7 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, if (enc->cache_bits_ > 0) { if (!VP8LCalculateEstimateForCacheSize(enc->argb_, enc->current_width_, - height, quality, enc->hash_chain_, + height, quality, &enc->hash_chain_, enc->refs_[0], &enc->cache_bits_)) { err = VP8_ENC_ERROR_INVALID_CONFIGURATION; goto Error; @@ -1122,7 +1123,7 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, // --------------------------------------------------------------------------- // Encode and write the transformed image. - if (!EncodeImageInternal(bw, enc->argb_, enc->hash_chain_, enc->refs_, + if (!EncodeImageInternal(bw, enc->argb_, &enc->hash_chain_, enc->refs_, enc->current_width_, height, quality, enc->cache_bits_, enc->histo_bits_)) { err = VP8_ENC_ERROR_OUT_OF_MEMORY; diff --git a/src/enc/vp8li.h b/src/enc/vp8li.h index 7db49f7a..8be971e5 100644 --- a/src/enc/vp8li.h +++ b/src/enc/vp8li.h @@ -14,6 +14,7 @@ #ifndef WEBP_ENC_VP8LI_H_ #define WEBP_ENC_VP8LI_H_ +#include "./backward_references.h" #include "./histogram.h" #include "../utils/bit_writer.h" #include "../webp/encode.h" @@ -23,8 +24,6 @@ extern "C" { #endif -struct VP8LHashChain; // Defined in backward_references.h - typedef struct { const WebPConfig* config_; // user configuration and parameters const WebPPicture* pic_; // input picture. @@ -35,11 +34,6 @@ typedef struct { uint32_t* transform_data_; // Scratch memory for transform data. int current_width_; // Corresponds to packed image width. - struct VP8LHashChain* hash_chain_; // HashChain data for constructing - // backward references. - struct VP8LBackwardRefs* refs_[2]; // Backward Refs array corresponding to - // LZ77 & RLE coding. - // Encoding parameters derived from quality parameter. int histo_bits_; int transform_bits_; @@ -52,6 +46,12 @@ typedef struct { int use_palette_; int palette_size_; uint32_t palette_[MAX_PALETTE_SIZE]; + + // Some 'scratch' (potentially large) objects. + struct VP8LBackwardRefs* refs_[2]; // Backward Refs array corresponding to + // LZ77 & RLE coding. + VP8LHashChain hash_chain_; // HashChain data for constructing + // backward references. } VP8LEncoder; //------------------------------------------------------------------------------