From e912bd55bee7b4b34a7b93f31a51723383768896 Mon Sep 17 00:00:00 2001 From: Vikas Arora Date: Thu, 23 Oct 2014 09:01:46 -0700 Subject: [PATCH] Fix bug in VP8LCalculateEstimateForCacheSize. The method VP8LCalculateEstimateForCacheSize is not evaluating the all possible range for cache_bits. Also added a small penality for choosing the larger cache-size. This is done to strike a balance between additional memory/CPU cost (with larger cache-size) and byte savings from smaller WebP lossless files. This change saves about 0.07% bytes and speeds up compression by 8% (default settings). There's small speedup at Q=50 along with byte savings as well. Compression at Quality=25 is not effected by this change. Change-Id: Id8f87dee6b5bccb2baa6dbdee479ee9cda8f4f77 --- src/enc/backward_references.c | 19 +++++++++++++++---- src/enc/vp8l.c | 14 ++++++-------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/enc/backward_references.c b/src/enc/backward_references.c index 4bbc8c07..337b58d1 100644 --- a/src/enc/backward_references.c +++ b/src/enc/backward_references.c @@ -927,33 +927,44 @@ int VP8LCalculateEstimateForCacheSize(const uint32_t* const argb, int eval_high = 1; double entropy_low = MAX_ENTROPY; double entropy_high = MAX_ENTROPY; + const double cost_mul = 5e-4; int cache_bits_low = 0; - int cache_bits_high = MAX_COLOR_CACHE_BITS; + int cache_bits_high = *best_cache_bits; + + assert(cache_bits_high <= MAX_COLOR_CACHE_BITS); + + if (cache_bits_high == 0) { + // Local color cache is disabled. + return 1; + } if (!BackwardReferencesHashChain(xsize, ysize, argb, 0, quality, hash_chain, refs)) { return 0; } // Do a binary search to find the optimal entropy for cache_bits. - while (cache_bits_high - cache_bits_low > 1) { + while (eval_low || eval_high) { if (eval_low) { entropy_low = ComputeCacheEntropy(argb, xsize, ysize, refs, cache_bits_low); + entropy_low += entropy_low * cache_bits_low * cost_mul; eval_low = 0; } if (eval_high) { entropy_high = ComputeCacheEntropy(argb, xsize, ysize, refs, cache_bits_high); + entropy_high += entropy_high * cache_bits_high * cost_mul; eval_high = 0; } if (entropy_high < entropy_low) { + const int prev_cache_bits_low = cache_bits_low; *best_cache_bits = cache_bits_high; cache_bits_low = (cache_bits_low + cache_bits_high) / 2; - eval_low = 1; + if (cache_bits_low != prev_cache_bits_low) eval_low = 1; } else { *best_cache_bits = cache_bits_low; cache_bits_high = (cache_bits_low + cache_bits_high) / 2; - eval_high = 1; + if (cache_bits_high != cache_bits_low) eval_high = 1; } } return 1; diff --git a/src/enc/vp8l.c b/src/enc/vp8l.c index 8b999ad5..4f5a745d 100644 --- a/src/enc/vp8l.c +++ b/src/enc/vp8l.c @@ -284,7 +284,7 @@ static int GetTransformBits(int method, int histo_bits) { static int GetCacheBits(int use_palette, float quality) { // Color cache is disabled for compression at lower quality or when a palette // is used. - return (use_palette || (quality <= 25.f)) ? 0 : 7; + return (use_palette || (quality <= 25.f)) ? 0 : MAX_COLOR_CACHE_BITS; } static int EvalSubtractGreenForPalette(int palette_size, float quality) { @@ -1309,13 +1309,11 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, // --------------------------------------------------------------------------- // Estimate the color cache size. - if (enc->cache_bits_ > 0) { - if (!VP8LCalculateEstimateForCacheSize(enc->argb_, enc->current_width_, - height, quality, &enc->hash_chain_, - &enc->refs_[0], &enc->cache_bits_)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } + if (!VP8LCalculateEstimateForCacheSize(enc->argb_, enc->current_width_, + height, quality, &enc->hash_chain_, + &enc->refs_[0], &enc->cache_bits_)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; } // ---------------------------------------------------------------------------