mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-31 02:15:42 +01:00 
			
		
		
		
	Do a binary search to get the optimum cache bits.
This speeds up the lossless encoder by a bit (1-2%), without impacting the compression density. Change-Id: Ied6fb38fab58eef9ded078697e0463fe7c560b26
This commit is contained in:
		| @@ -12,7 +12,6 @@ | |||||||
|  |  | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
| #include <math.h> | #include <math.h> | ||||||
| #include <stdio.h> |  | ||||||
|  |  | ||||||
| #include "./backward_references.h" | #include "./backward_references.h" | ||||||
| #include "./histogram.h" | #include "./histogram.h" | ||||||
| @@ -26,6 +25,8 @@ | |||||||
| #define HASH_SIZE (1 << HASH_BITS) | #define HASH_SIZE (1 << HASH_BITS) | ||||||
| #define HASH_MULTIPLIER (0xc6a4a7935bd1e995ULL) | #define HASH_MULTIPLIER (0xc6a4a7935bd1e995ULL) | ||||||
|  |  | ||||||
|  | #define MAX_ENTROPY    (1e30f) | ||||||
|  |  | ||||||
| // 1M window (4M bytes) minus 120 special codes for short distances. | // 1M window (4M bytes) minus 120 special codes for short distances. | ||||||
| #define WINDOW_SIZE ((1 << 20) - 120) | #define WINDOW_SIZE ((1 << 20) - 120) | ||||||
|  |  | ||||||
| @@ -833,7 +834,7 @@ static double ComputeCacheEntropy(const uint32_t* const argb, | |||||||
|  |  | ||||||
|   if (use_color_cache) { |   if (use_color_cache) { | ||||||
|     cc_init = VP8LColorCacheInit(&hashers, cache_bits); |     cc_init = VP8LColorCacheInit(&hashers, cache_bits); | ||||||
|     if (!cc_init) return 1e99; |     if (!cc_init) return MAX_ENTROPY; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   VP8LHistogramInit(&histo, cache_bits); |   VP8LHistogramInit(&histo, cache_bits); | ||||||
| @@ -873,27 +874,38 @@ int VP8LCalculateEstimateForCacheSize(const uint32_t* const argb, | |||||||
|                                       int xsize, int ysize, int quality, |                                       int xsize, int ysize, int quality, | ||||||
|                                       int* const best_cache_bits) { |                                       int* const best_cache_bits) { | ||||||
|   int ok = 0; |   int ok = 0; | ||||||
|   int cache_bits; |   int eval_low = 1; | ||||||
|   // Number of tries to get optimal cache-bits after finding a local minima. |   int eval_high = 1; | ||||||
|   const int max_tries_after_min = 3 + (quality >> 4); |   double entropy_low = MAX_ENTROPY; | ||||||
|   int num_tries_after_min = 0; |   double entropy_high = MAX_ENTROPY; | ||||||
|   double lowest_entropy = 1e99; |   int cache_bits_low = 0; | ||||||
|  |   int cache_bits_high = MAX_COLOR_CACHE_BITS; | ||||||
|   VP8LBackwardRefs refs; |   VP8LBackwardRefs refs; | ||||||
|  |  | ||||||
|   if (!VP8LBackwardRefsAlloc(&refs, xsize * ysize) || |   if (!VP8LBackwardRefsAlloc(&refs, xsize * ysize) || | ||||||
|       !BackwardReferencesHashChain(xsize, ysize, argb, 0, quality, &refs)) { |       !BackwardReferencesHashChain(xsize, ysize, argb, 0, quality, &refs)) { | ||||||
|     goto Error; |     goto Error; | ||||||
|   } |   } | ||||||
|   // The entropy is generally lower for higher cache_bits. Start searching from |   // Do a binary search to find the optimal entropy for cache_bits. | ||||||
|   // the highest value and settle for a local minima. |   while (cache_bits_high - cache_bits_low > 1) { | ||||||
|   for (cache_bits = MAX_COLOR_CACHE_BITS; |     if (eval_low) { | ||||||
|        cache_bits >= 0 && num_tries_after_min < max_tries_after_min; |       entropy_low = | ||||||
|        --cache_bits, ++num_tries_after_min) { |           ComputeCacheEntropy(argb, xsize, ysize, &refs, cache_bits_low); | ||||||
|     const double cur_entropy = ComputeCacheEntropy(argb, xsize, ysize, |       eval_low = 0; | ||||||
|                                                    &refs, cache_bits); |     } | ||||||
|     if (cur_entropy < lowest_entropy) { |     if (eval_high) { | ||||||
|       *best_cache_bits = cache_bits; |       entropy_high = | ||||||
|       lowest_entropy = cur_entropy; |           ComputeCacheEntropy(argb, xsize, ysize, &refs, cache_bits_high); | ||||||
|       num_tries_after_min = 0; |       eval_high = 0; | ||||||
|  |     } | ||||||
|  |     if (entropy_high < entropy_low) { | ||||||
|  |       *best_cache_bits = cache_bits_high; | ||||||
|  |       cache_bits_low = (cache_bits_low + cache_bits_high) / 2; | ||||||
|  |       eval_low = 1; | ||||||
|  |     } else { | ||||||
|  |       *best_cache_bits = cache_bits_low; | ||||||
|  |       cache_bits_high = (cache_bits_low + cache_bits_high) / 2; | ||||||
|  |       eval_high = 1; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   ok = 1; |   ok = 1; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user