mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-27 22:28:22 +01:00
Optmize VP8LGetBackwardReferences LZ77 references.
Use the refs_lz77 computed (with cache_bits=0) in the method 'CalculateBestCacheSize' to regenerate the LZ77 references corresponding to the optimum cache_bits and avoid calling costly 'BackwardReferencesLz77' one extra time. This change leaves the compression density unchanged and speeds up compression by 10-15%. Change-Id: I5a92e11788d3c3f656aa7e1fba54fb5d96ee0027
This commit is contained in:
parent
2f0e2ba826
commit
fdaac8e0ca
@ -814,31 +814,84 @@ static int CalculateBestCacheSize(const uint32_t* const argb,
|
|||||||
int xsize, int ysize, int quality,
|
int xsize, int ysize, int quality,
|
||||||
VP8LHashChain* const hash_chain,
|
VP8LHashChain* const hash_chain,
|
||||||
VP8LBackwardRefs* const refs,
|
VP8LBackwardRefs* const refs,
|
||||||
|
int* const lz77_computed,
|
||||||
int* const best_cache_bits);
|
int* const best_cache_bits);
|
||||||
|
|
||||||
|
// Create the backward references for specified cache_bits from a source
|
||||||
|
// backward refs that is created without local color cache.
|
||||||
|
static int BackwardRefsWithLocalCache(const uint32_t* const argb,
|
||||||
|
int cache_bits,
|
||||||
|
const VP8LBackwardRefs* const refs_src,
|
||||||
|
VP8LBackwardRefs* const refs_dst) {
|
||||||
|
int pixel_index = 0;
|
||||||
|
VP8LColorCache hashers;
|
||||||
|
VP8LRefsCursor c = VP8LRefsCursorInit(refs_src);
|
||||||
|
if (!VP8LColorCacheInit(&hashers, cache_bits)) return 0;
|
||||||
|
|
||||||
|
ClearBackwardRefs(refs_dst);
|
||||||
|
while (VP8LRefsCursorOk(&c)) {
|
||||||
|
const PixOrCopy* const v_src = c.cur_pos;
|
||||||
|
if (PixOrCopyIsLiteral(v_src)) {
|
||||||
|
const uint32_t argb_literal = v_src->argb_or_distance;
|
||||||
|
if (VP8LColorCacheContains(&hashers, argb_literal)) {
|
||||||
|
const int ix = VP8LColorCacheGetIndex(&hashers, argb_literal);
|
||||||
|
BackwardRefsCursorAdd(refs_dst, PixOrCopyCreateCacheIdx(ix));
|
||||||
|
} else {
|
||||||
|
VP8LColorCacheInsert(&hashers, argb_literal);
|
||||||
|
BackwardRefsCursorAdd(refs_dst, *v_src);
|
||||||
|
}
|
||||||
|
++pixel_index;
|
||||||
|
} else {
|
||||||
|
// refs_src was created without local cache, so it can not have cache
|
||||||
|
// indexes.
|
||||||
|
int k;
|
||||||
|
assert(PixOrCopyIsCopy(v_src));
|
||||||
|
for (k = 0; k < v_src->len; ++k) {
|
||||||
|
VP8LColorCacheInsert(&hashers, argb[pixel_index++]);
|
||||||
|
}
|
||||||
|
BackwardRefsCursorAdd(refs_dst, *v_src);
|
||||||
|
}
|
||||||
|
VP8LRefsCursorNext(&c);
|
||||||
|
}
|
||||||
|
VP8LColorCacheClear(&hashers);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
VP8LBackwardRefs* VP8LGetBackwardReferences(
|
VP8LBackwardRefs* VP8LGetBackwardReferences(
|
||||||
int width, int height, const uint32_t* const argb, int quality,
|
int width, int height, const uint32_t* const argb, int quality,
|
||||||
int* cache_bits, VP8LHashChain* const hash_chain,
|
int* cache_bits, VP8LHashChain* const hash_chain,
|
||||||
VP8LBackwardRefs refs_array[2]) {
|
VP8LBackwardRefs refs_array[2]) {
|
||||||
int lz77_is_useful;
|
int lz77_is_useful;
|
||||||
|
int lz77_computed;
|
||||||
double bit_cost_lz77, bit_cost_rle;
|
double bit_cost_lz77, bit_cost_rle;
|
||||||
VP8LBackwardRefs* best = NULL;
|
VP8LBackwardRefs* best = NULL;
|
||||||
VP8LBackwardRefs* const refs_lz77 = &refs_array[0];
|
VP8LBackwardRefs* refs_lz77 = &refs_array[0];
|
||||||
VP8LBackwardRefs* const refs_rle = &refs_array[1];
|
VP8LBackwardRefs* refs_rle = &refs_array[1];
|
||||||
VP8LHistogram* histo = NULL;
|
VP8LHistogram* histo = NULL;
|
||||||
|
|
||||||
if (!CalculateBestCacheSize(argb, width, height, quality, hash_chain,
|
if (!CalculateBestCacheSize(argb, width, height, quality, hash_chain,
|
||||||
refs_lz77, cache_bits)) {
|
refs_lz77, &lz77_computed, cache_bits)) {
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(vikasa): Use the refs_lz77 computed (with cache_bits=0) in the method
|
if (lz77_computed) {
|
||||||
// 'CalculateBestCacheSize' to regenerate the lz77 references corresponding to
|
// Transform refs_lz77 for the optimized cache_bits.
|
||||||
// the optimum cache_bits and avoid calling 'BackwardReferencesLz77' here.
|
if (*cache_bits > 0) {
|
||||||
if (!BackwardReferencesLz77(width, height, argb, *cache_bits, quality,
|
if (!BackwardRefsWithLocalCache(argb, *cache_bits, refs_lz77, refs_rle)) {
|
||||||
hash_chain, refs_lz77)) {
|
goto Error;
|
||||||
goto Error;
|
}
|
||||||
|
// Swap refs_lz77 and refs_rle.
|
||||||
|
best = refs_lz77;
|
||||||
|
refs_lz77 = refs_rle;
|
||||||
|
refs_rle = best;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!BackwardReferencesLz77(width, height, argb, *cache_bits, quality,
|
||||||
|
hash_chain, refs_lz77)) {
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!BackwardReferencesRle(width, height, argb, *cache_bits, refs_rle)) {
|
if (!BackwardReferencesRle(width, height, argb, *cache_bits, refs_rle)) {
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
@ -863,7 +916,7 @@ VP8LBackwardRefs* VP8LGetBackwardReferences(
|
|||||||
const int try_lz77_trace_backwards = (quality >= 25);
|
const int try_lz77_trace_backwards = (quality >= 25);
|
||||||
best = refs_lz77; // default guess: lz77 is better
|
best = refs_lz77; // default guess: lz77 is better
|
||||||
if (try_lz77_trace_backwards) {
|
if (try_lz77_trace_backwards) {
|
||||||
VP8LBackwardRefs* const refs_trace = &refs_array[1];
|
VP8LBackwardRefs* const refs_trace = refs_rle;
|
||||||
if (!VP8LBackwardRefsCopy(refs_lz77, refs_trace)) {
|
if (!VP8LBackwardRefsCopy(refs_lz77, refs_trace)) {
|
||||||
best = NULL;
|
best = NULL;
|
||||||
goto Error;
|
goto Error;
|
||||||
@ -955,6 +1008,7 @@ static int CalculateBestCacheSize(const uint32_t* const argb,
|
|||||||
int xsize, int ysize, int quality,
|
int xsize, int ysize, int quality,
|
||||||
VP8LHashChain* const hash_chain,
|
VP8LHashChain* const hash_chain,
|
||||||
VP8LBackwardRefs* const refs,
|
VP8LBackwardRefs* const refs,
|
||||||
|
int* const lz77_computed,
|
||||||
int* const best_cache_bits) {
|
int* const best_cache_bits) {
|
||||||
int eval_low = 1;
|
int eval_low = 1;
|
||||||
int eval_high = 1;
|
int eval_high = 1;
|
||||||
@ -966,6 +1020,7 @@ static int CalculateBestCacheSize(const uint32_t* const argb,
|
|||||||
|
|
||||||
assert(cache_bits_high <= MAX_COLOR_CACHE_BITS);
|
assert(cache_bits_high <= MAX_COLOR_CACHE_BITS);
|
||||||
|
|
||||||
|
*lz77_computed = 0;
|
||||||
if (cache_bits_high == 0) {
|
if (cache_bits_high == 0) {
|
||||||
*best_cache_bits = 0;
|
*best_cache_bits = 0;
|
||||||
// Local color cache is disabled.
|
// Local color cache is disabled.
|
||||||
@ -1000,5 +1055,6 @@ static int CalculateBestCacheSize(const uint32_t* const argb,
|
|||||||
if (cache_bits_high != cache_bits_low) eval_high = 1;
|
if (cache_bits_high != cache_bits_low) eval_high = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*lz77_computed = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user