Index: third_party/libwebp/enc/backward_references.c |
diff --git a/third_party/libwebp/enc/backward_references.c b/third_party/libwebp/enc/backward_references.c |
index db4f430df5e96438be54615945aec7da67a26f05..77b4be7432f0b909005a0999ee275e0aaa23bc91 100644 |
--- a/third_party/libwebp/enc/backward_references.c |
+++ b/third_party/libwebp/enc/backward_references.c |
@@ -156,14 +156,14 @@ static void GetParamsForHashChainFindCopy(int quality, int xsize, |
*window_size = (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE |
: max_window_size; |
*iter_pos = 8 + (quality >> 3); |
- // For lower entropy images, the rigourous search loop in HashChainFindCopy |
+ // For lower entropy images, the rigorous search loop in HashChainFindCopy |
// can be relaxed. |
*iter_limit = (cache_bits > 0) ? iter_neg : iter_neg / 2; |
} |
static int HashChainFindCopy(const HashChain* const p, |
int base_position, int xsize_signed, |
- const uint32_t* const argb, int maxlen, |
+ const uint32_t* const argb, int max_len, |
int window_size, int iter_pos, int iter_limit, |
int* const distance_ptr, |
int* const length_ptr) { |
@@ -176,25 +176,34 @@ static int HashChainFindCopy(const HashChain* const p, |
(base_position > window_size) ? base_position - window_size : 0; |
int pos; |
assert(xsize > 0); |
+ if (max_len > MAX_LENGTH) { |
+ max_len = MAX_LENGTH; |
+ } |
for (pos = p->hash_to_first_index_[GetPixPairHash64(argb_start)]; |
pos >= min_pos; |
pos = p->chain_[pos]) { |
uint64_t val; |
uint32_t curr_length; |
uint32_t distance; |
+ const uint64_t* const ptr1 = |
+ (const uint64_t*)(argb + pos + best_length - 1); |
+ const uint64_t* const ptr2 = |
+ (const uint64_t*)(argb_start + best_length - 1); |
+ |
if (iter_pos < 0) { |
if (iter_pos < iter_limit || best_val >= 0xff0000) { |
break; |
} |
} |
--iter_pos; |
- if (argb[pos + best_length - 1] != argb_start[best_length - 1]) { |
- continue; |
- } |
- curr_length = FindMatchLength(argb + pos, argb_start, maxlen); |
- if (curr_length < best_length) { |
- continue; |
- } |
+ |
+ // Before 'expensive' linear match, check if the two arrays match at the |
+ // current best length index and also for the succeeding elements. |
+ if (*ptr1 != *ptr2) continue; |
+ |
+ curr_length = FindMatchLength(argb + pos, argb_start, max_len); |
+ if (curr_length < best_length) continue; |
+ |
distance = (uint32_t)(base_position - pos); |
val = curr_length << 16; |
// Favoring 2d locality here gives savings for certain images. |
@@ -213,7 +222,7 @@ static int HashChainFindCopy(const HashChain* const p, |
best_val = val; |
best_length = curr_length; |
best_distance = distance; |
- if (curr_length >= MAX_LENGTH) { |
+ if (curr_length >= (uint32_t)max_len) { |
break; |
} |
if ((best_distance == 1 || distance == xsize) && |
@@ -291,11 +300,8 @@ static int BackwardReferencesHashChain(int xsize, int ysize, |
int offset = 0; |
int len = 0; |
if (i < pix_count - 1) { // FindCopy(i,..) reads pixels at [i] and [i + 1]. |
- int maxlen = pix_count - i; |
- if (maxlen > MAX_LENGTH) { |
- maxlen = MAX_LENGTH; |
- } |
- HashChainFindCopy(hash_chain, i, xsize, argb, maxlen, |
+ int max_len = pix_count - i; |
+ HashChainFindCopy(hash_chain, i, xsize, argb, max_len, |
window_size, iter_pos, iter_limit, |
&offset, &len); |
} |
@@ -307,11 +313,8 @@ static int BackwardReferencesHashChain(int xsize, int ysize, |
int k; |
HashChainInsert(hash_chain, &argb[i], i); |
if (i < pix_count - 2) { // FindCopy(i+1,..) reads [i + 1] and [i + 2]. |
- int maxlen = pix_count - (i + 1); |
- if (maxlen > MAX_LENGTH) { |
- maxlen = MAX_LENGTH; |
- } |
- HashChainFindCopy(hash_chain, i + 1, xsize, argb, maxlen, |
+ int max_len = pix_count - (i + 1); |
+ HashChainFindCopy(hash_chain, i + 1, xsize, argb, max_len, |
window_size, iter_pos, iter_limit, |
&offset2, &len2); |
if (len2 > len + 1) { |
@@ -321,10 +324,10 @@ static int BackwardReferencesHashChain(int xsize, int ysize, |
const int ix = VP8LColorCacheGetIndex(&hashers, pixel); |
refs->refs[refs->size] = PixOrCopyCreateCacheIdx(ix); |
} else { |
+ if (use_color_cache) VP8LColorCacheInsert(&hashers, pixel); |
refs->refs[refs->size] = PixOrCopyCreateLiteral(pixel); |
} |
++refs->size; |
- if (use_color_cache) VP8LColorCacheInsert(&hashers, pixel); |
i++; // Backward reference to be done for next pixel. |
len = len2; |
offset = offset2; |
@@ -354,10 +357,10 @@ static int BackwardReferencesHashChain(int xsize, int ysize, |
const int ix = VP8LColorCacheGetIndex(&hashers, pixel); |
refs->refs[refs->size] = PixOrCopyCreateCacheIdx(ix); |
} else { |
+ if (use_color_cache) VP8LColorCacheInsert(&hashers, pixel); |
refs->refs[refs->size] = PixOrCopyCreateLiteral(pixel); |
} |
++refs->size; |
- if (use_color_cache) VP8LColorCacheInsert(&hashers, pixel); |
if (i + 1 < pix_count) { |
HashChainInsert(hash_chain, &argb[i], i); |
} |
@@ -459,16 +462,16 @@ static WEBP_INLINE double GetCacheCost(const CostModel* const m, uint32_t idx) { |
static WEBP_INLINE double GetLengthCost(const CostModel* const m, |
uint32_t length) { |
- int code, extra_bits_count, extra_bits_value; |
- PrefixEncode(length, &code, &extra_bits_count, &extra_bits_value); |
- return m->literal_[VALUES_IN_BYTE + code] + extra_bits_count; |
+ int code, extra_bits; |
+ VP8LPrefixEncodeBits(length, &code, &extra_bits); |
+ return m->literal_[VALUES_IN_BYTE + code] + extra_bits; |
} |
static WEBP_INLINE double GetDistanceCost(const CostModel* const m, |
uint32_t distance) { |
- int code, extra_bits_count, extra_bits_value; |
- PrefixEncode(distance, &code, &extra_bits_count, &extra_bits_value); |
- return m->distance_[code] + extra_bits_count; |
+ int code, extra_bits; |
+ VP8LPrefixEncodeBits(distance, &code, &extra_bits); |
+ return m->distance_[code] + extra_bits; |
} |
static int BackwardReferencesHashChainDistanceOnly( |
@@ -522,11 +525,8 @@ static int BackwardReferencesHashChainDistanceOnly( |
int offset = 0; |
int len = 0; |
if (i < pix_count - 1) { // FindCopy reads pixels at [i] and [i + 1]. |
- int maxlen = shortmax ? 2 : MAX_LENGTH; |
- if (maxlen > pix_count - i) { |
- maxlen = pix_count - i; |
- } |
- HashChainFindCopy(hash_chain, i, xsize, argb, maxlen, |
+ int max_len = shortmax ? 2 : pix_count - i; |
+ HashChainFindCopy(hash_chain, i, xsize, argb, max_len, |
window_size, iter_pos, iter_limit, |
&offset, &len); |
} |
@@ -577,13 +577,13 @@ static int BackwardReferencesHashChainDistanceOnly( |
const int ix = VP8LColorCacheGetIndex(&hashers, argb[i]); |
cost_val += GetCacheCost(cost_model, ix) * mul0; |
} else { |
+ if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]); |
cost_val += GetLiteralCost(cost_model, argb[i]) * mul1; |
} |
if (cost[i] > cost_val) { |
cost[i] = (float)cost_val; |
dist_array[i] = 1; // only one is inserted. |
} |
- if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]); |
} |
next_symbol: ; |
} |
@@ -650,12 +650,12 @@ static int BackwardReferencesHashChainFollowChosenPath( |
for (ix = 0; ix < chosen_path_size; ++ix, ++size) { |
int offset = 0; |
int len = 0; |
- int maxlen = chosen_path[ix]; |
- if (maxlen != 1) { |
- HashChainFindCopy(hash_chain, i, xsize, argb, maxlen, |
+ int max_len = chosen_path[ix]; |
+ if (max_len != 1) { |
+ HashChainFindCopy(hash_chain, i, xsize, argb, max_len, |
window_size, iter_pos, iter_limit, |
&offset, &len); |
- assert(len == maxlen); |
+ assert(len == max_len); |
refs->refs[size] = PixOrCopyCreateCopy(offset, len); |
if (use_color_cache) { |
for (k = 0; k < len; ++k) { |
@@ -675,9 +675,9 @@ static int BackwardReferencesHashChainFollowChosenPath( |
const int idx = VP8LColorCacheGetIndex(&hashers, argb[i]); |
refs->refs[size] = PixOrCopyCreateCacheIdx(idx); |
} else { |
+ if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]); |
refs->refs[size] = PixOrCopyCreateLiteral(argb[i]); |
} |
- if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]); |
if (i + 1 < pix_count) { |
HashChainInsert(hash_chain, &argb[i], i); |
} |
@@ -780,8 +780,8 @@ int VP8LGetBackwardReferences(int width, int height, |
// Choose appropriate backward reference. |
if (lz77_is_useful) { |
- // TraceBackwards is costly. Don't execute it at lower quality (q <= 10). |
- const int try_lz77_trace_backwards = (quality > 10); |
+ // TraceBackwards is costly. Don't execute it at lower quality. |
+ const int try_lz77_trace_backwards = (quality >= 25); |
*best = refs_lz77; // default guess: lz77 is better |
VP8LClearBackwardRefs(&refs_rle); |
if (try_lz77_trace_backwards) { |