From ea08466d34c43c04efbd73a4b9279b8a8711bede Mon Sep 17 00:00:00 2001 From: Vikas Arora Date: Mon, 22 Dec 2014 17:00:30 +0000 Subject: [PATCH] Tune BackwardReferencesLz77 for low_effort (m=0). - Lower the threshold parameters for HashChainFindCopy. For 1000 image PNG corpus (m=0), this change yields speedup of 15-20% at lower quality range (0.25% drop in compression density) and about 10% for higher quality range without any drop in the compression density. Following is the compression stats (before/after) for method = 0: Before After bpp/MPs bpp/MPs q=0 2.8615/18.000 2.8651/18.631 q=5 2.8615/18.216 2.8650/20.517 q=10 2.8572/18.070 2.8650/21.992 q=15 2.8519/18.371 2.8584/21.747 q=20 2.8454/18.975 2.8515/20.448 q=25 2.8230/8.531 2.8253/9.585 // Compression density remains same for q-range [30-100] q=30 2.7310/7.706 2.7310/8.028 q=35 2.7253/6.855 2.7253/7.184 q=40 2.7231/6.364 2.7231/6.604 q=45 2.7216/5.844 2.7216/6.223 q=50 2.7196/5.210 2.7196/5.731 q=55 2.7208/4.766 2.7208/4.970 q=60 2.7195/4.495 2.7195/4.602 q=65 2.7185/4.024 2.7185/4.236 q=70 2.7174/3.699 2.7174/3.861 q=75 2.7164/3.449 2.7164/3.605 q=80 2.7161/3.222 2.7161/3.038 q=85 2.7153/2.919 2.7153/2.946 q=90 2.7145/2.766 2.7145/2.771 q=95 2.7124/2.548 2.7124/2.575 q=100 2.6873/2.253 2.6873/2.335 Change-Id: I0e17581fb71f6094032ad06c6203350bd502f9a1 --- src/enc/backward_references.c | 25 ++++++++++++++++--------- src/enc/backward_references.h | 2 +- src/enc/vp8l.c | 5 +++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/enc/backward_references.c b/src/enc/backward_references.c index d7201aa1..1ceae04b 100644 --- a/src/enc/backward_references.c +++ b/src/enc/backward_references.c @@ -58,6 +58,8 @@ static int DistanceToPlaneCode(int xsize, int dist) { return dist + 120; } +// TODO(vikasa): Evaluate loading (and comparing) 32/64 bits for the inner while +// loop. static WEBP_INLINE int FindMatchLength(const uint32_t* const array1, const uint32_t* const array2, int best_len_match, @@ -228,9 +230,13 @@ static void HashChainInsert(VP8LHashChain* const p, } static void GetParamsForHashChainFindCopy( - int quality, int* iter_max, int* len_for_unit_dist) { + int quality, int low_effort, int* iter_max, int* len_for_unit_dist) { *iter_max = 8 + (quality * quality) / 40; *len_for_unit_dist = 32 + (96 * quality) / 100; + if (low_effort) { + *iter_max -= 2; + *len_for_unit_dist /= 4; + } } static int GetWindowSizeForHashChain(int quality, int xsize) { @@ -370,8 +376,8 @@ static int BackwardReferencesRle(int xsize, int ysize, } static int BackwardReferencesLz77(int xsize, int ysize, - const uint32_t* const argb, - int cache_bits, int quality, + const uint32_t* const argb, int cache_bits, + int quality, int low_effort, VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs) { int i; @@ -382,7 +388,8 @@ static int BackwardReferencesLz77(int xsize, int ysize, VP8LColorCache hashers; int iter_max, len_for_unit_dist; const int window_size = GetWindowSizeForHashChain(quality, xsize); - GetParamsForHashChainFindCopy(quality, &iter_max, &len_for_unit_dist); + GetParamsForHashChainFindCopy(quality, low_effort, &iter_max, + &len_for_unit_dist); if (use_color_cache) { cc_init = VP8LColorCacheInit(&hashers, cache_bits); @@ -402,7 +409,7 @@ static int BackwardReferencesLz77(int xsize, int ysize, int len2 = 0; int k; HashChainInsert(hash_chain, &argb[i], i); - if (len < (max_len >> 2)) { + if ((len < (max_len >> 2)) && !low_effort) { // Evaluate Alternative#2: Insert the pixel at 'i' as literal, and code // the pixels starting at 'i + 1' using backward reference. HashChainFindCopy(hash_chain, i + 1, xsize, argb, max_len - 1, @@ -582,7 +589,7 @@ static int BackwardReferencesHashChainDistanceOnly( const int min_distance_code = 2; int iter_max, len_for_unit_dist; const int window_size = GetWindowSizeForHashChain(quality, xsize); - GetParamsForHashChainFindCopy(quality, &iter_max, &len_for_unit_dist); + GetParamsForHashChainFindCopy(quality, 0, &iter_max, &len_for_unit_dist); if (cost == NULL || cost_model == NULL) goto Error; @@ -892,7 +899,7 @@ static int CalculateBestCacheSize(const uint32_t* const argb, // Local color cache is disabled. return 1; } - if (!BackwardReferencesLz77(xsize, ysize, argb, cache_bits_low, quality, + if (!BackwardReferencesLz77(xsize, ysize, argb, cache_bits_low, quality, 0, hash_chain, refs)) { return 0; } @@ -961,7 +968,7 @@ static int BackwardRefsWithLocalCache(const uint32_t* const argb, VP8LBackwardRefs* VP8LGetBackwardReferences( int width, int height, const uint32_t* const argb, int quality, - int* cache_bits, VP8LHashChain* const hash_chain, + int low_effort, int* cache_bits, VP8LHashChain* const hash_chain, VP8LBackwardRefs refs_array[2]) { int lz77_is_useful; int lz77_computed; @@ -985,7 +992,7 @@ VP8LBackwardRefs* VP8LGetBackwardReferences( } } else { if (!BackwardReferencesLz77(width, height, argb, *cache_bits, quality, - hash_chain, refs_lz77)) { + low_effort, hash_chain, refs_lz77)) { goto Error; } } diff --git a/src/enc/backward_references.h b/src/enc/backward_references.h index ddab9c00..de79b2db 100644 --- a/src/enc/backward_references.h +++ b/src/enc/backward_references.h @@ -192,7 +192,7 @@ static WEBP_INLINE void VP8LRefsCursorNext(VP8LRefsCursor* const c) { // refs[0] or refs[1]. VP8LBackwardRefs* VP8LGetBackwardReferences( int width, int height, const uint32_t* const argb, int quality, - int* cache_bits, VP8LHashChain* const hash_chain, + int low_effort, int* cache_bits, VP8LHashChain* const hash_chain, VP8LBackwardRefs refs[2]); #ifdef __cplusplus diff --git a/src/enc/vp8l.c b/src/enc/vp8l.c index a7ce9d44..60f13ca0 100644 --- a/src/enc/vp8l.c +++ b/src/enc/vp8l.c @@ -685,7 +685,7 @@ static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw, } // Calculate backward references from ARGB image. - refs = VP8LGetBackwardReferences(width, height, argb, quality, &cache_bits, + refs = VP8LGetBackwardReferences(width, height, argb, quality, 0, &cache_bits, hash_chain, refs_array); if (refs == NULL) { err = VP8_ENC_ERROR_OUT_OF_MEMORY; @@ -785,7 +785,8 @@ static WebPEncodingError EncodeImageInternal(VP8LBitWriter* const bw, // of refs_array[0] or refs_array[1]. // Calculate backward references from ARGB image. best_refs = VP8LGetBackwardReferences(width, height, argb, quality, - cache_bits, hash_chain, refs_array); + low_effort, cache_bits, hash_chain, + refs_array); if (best_refs == NULL || !VP8LBackwardRefsCopy(best_refs, &refs)) { err = VP8_ENC_ERROR_OUT_OF_MEMORY; goto Error;