Merge "rationalize use of color-cache" into 0.2.0

This commit is contained in:
Pascal Massimino 2012-08-01 11:55:36 -07:00 committed by Gerrit Code Review
commit f1edf62fae
2 changed files with 70 additions and 40 deletions

View File

@ -256,8 +256,10 @@ static int BackwardReferencesHashChain(int xsize, int ysize,
VP8LColorCache hashers; VP8LColorCache hashers;
if (hash_chain == NULL) return 0; if (hash_chain == NULL) return 0;
cc_init = VP8LColorCacheInit(&hashers, cache_bits); if (use_color_cache) {
if (!cc_init) goto Error; cc_init = VP8LColorCacheInit(&hashers, cache_bits);
if (!cc_init) goto Error;
}
if (!HashChainInit(hash_chain, pix_count)) goto Error; if (!HashChainInit(hash_chain, pix_count)) goto Error;
@ -289,15 +291,16 @@ static int BackwardReferencesHashChain(int xsize, int ysize,
HashChainFindCopy(hash_chain, quality, HashChainFindCopy(hash_chain, quality,
i + 1, xsize, argb, maxlen, &offset2, &len2); i + 1, xsize, argb, maxlen, &offset2, &len2);
if (len2 > len + 1) { if (len2 > len + 1) {
const uint32_t pixel = argb[i];
// Alternative#2 is a better match. So push pixel at 'i' as literal. // Alternative#2 is a better match. So push pixel at 'i' as literal.
if (use_color_cache && VP8LColorCacheContains(&hashers, argb[i])) { if (use_color_cache && VP8LColorCacheContains(&hashers, pixel)) {
const int ix = VP8LColorCacheGetIndex(&hashers, argb[i]); const int ix = VP8LColorCacheGetIndex(&hashers, pixel);
refs->refs[refs->size] = PixOrCopyCreateCacheIdx(ix); refs->refs[refs->size] = PixOrCopyCreateCacheIdx(ix);
} else { } else {
refs->refs[refs->size] = PixOrCopyCreateLiteral(argb[i]); refs->refs[refs->size] = PixOrCopyCreateLiteral(pixel);
} }
++refs->size; ++refs->size;
VP8LColorCacheInsert(&hashers, argb[i]); if (use_color_cache) VP8LColorCacheInsert(&hashers, pixel);
i++; // Backward reference to be done for next pixel. i++; // Backward reference to be done for next pixel.
len = len2; len = len2;
offset = offset2; offset = offset2;
@ -307,24 +310,30 @@ static int BackwardReferencesHashChain(int xsize, int ysize,
len = MAX_LENGTH - 1; len = MAX_LENGTH - 1;
} }
refs->refs[refs->size++] = PixOrCopyCreateCopy(offset, len); refs->refs[refs->size++] = PixOrCopyCreateCopy(offset, len);
for (k = 0; k < len; ++k) { if (use_color_cache) {
VP8LColorCacheInsert(&hashers, argb[i + k]); for (k = 0; k < len; ++k) {
if (k != 0 && i + k + 1 < pix_count) { VP8LColorCacheInsert(&hashers, argb[i + k]);
// Add to the hash_chain (but cannot add the last pixel). }
}
// Add to the hash_chain (but cannot add the last pixel).
{
const int last = (len < pix_count - 1 - i) ? len : pix_count - 1 - i;
for (k = 1; k < last; ++k) {
HashChainInsert(hash_chain, &argb[i + k], i + k); HashChainInsert(hash_chain, &argb[i + k], i + k);
} }
} }
i += len; i += len;
} else { } else {
if (use_color_cache && VP8LColorCacheContains(&hashers, argb[i])) { const uint32_t pixel = argb[i];
if (use_color_cache && VP8LColorCacheContains(&hashers, pixel)) {
// push pixel as a PixOrCopyCreateCacheIdx pixel // push pixel as a PixOrCopyCreateCacheIdx pixel
int ix = VP8LColorCacheGetIndex(&hashers, argb[i]); const int ix = VP8LColorCacheGetIndex(&hashers, pixel);
refs->refs[refs->size] = PixOrCopyCreateCacheIdx(ix); refs->refs[refs->size] = PixOrCopyCreateCacheIdx(ix);
} else { } else {
refs->refs[refs->size] = PixOrCopyCreateLiteral(argb[i]); refs->refs[refs->size] = PixOrCopyCreateLiteral(pixel);
} }
++refs->size; ++refs->size;
VP8LColorCacheInsert(&hashers, argb[i]); if (use_color_cache) VP8LColorCacheInsert(&hashers, pixel);
if (i + 1 < pix_count) { if (i + 1 < pix_count) {
HashChainInsert(hash_chain, &argb[i], i); HashChainInsert(hash_chain, &argb[i], i);
} }
@ -437,8 +446,12 @@ static int BackwardReferencesHashChainDistanceOnly(
if (cost == NULL || cost_model == NULL || hash_chain == NULL) goto Error; if (cost == NULL || cost_model == NULL || hash_chain == NULL) goto Error;
cc_init = VP8LColorCacheInit(&hashers, cache_bits); if (!HashChainInit(hash_chain, pix_count)) goto Error;
if (!cc_init || !HashChainInit(hash_chain, pix_count)) goto Error;
if (use_color_cache) {
cc_init = VP8LColorCacheInit(&hashers, cache_bits);
if (!cc_init) goto Error;
}
if (!CostModelBuild(cost_model, xsize, ysize, recursive_cost_model, argb, if (!CostModelBuild(cost_model, xsize, ysize, recursive_cost_model, argb,
cache_bits)) { cache_bits)) {
@ -486,14 +499,20 @@ static int BackwardReferencesHashChainDistanceOnly(
// Long copy for short distances, let's skip the middle // Long copy for short distances, let's skip the middle
// lookups for better copies. // lookups for better copies.
// 1) insert the hashes. // 1) insert the hashes.
for (k = 0; k < len; ++k) { if (use_color_cache) {
VP8LColorCacheInsert(&hashers, argb[i + k]); for (k = 0; k < len; ++k) {
if (i + k + 1 < pix_count) { VP8LColorCacheInsert(&hashers, argb[i + k]);
// Add to the hash_chain (but cannot add the last pixel). }
}
// 2) Add to the hash_chain (but cannot add the last pixel)
{
const int last = (len < pix_count - 1 - i) ? len
: pix_count - 1 - i;
for (k = 0; k < last; ++k) {
HashChainInsert(hash_chain, &argb[i + k], i + k); HashChainInsert(hash_chain, &argb[i + k], i + k);
} }
} }
// 2) jump. // 3) jump.
i += len - 1; // for loop does ++i, thus -1 here. i += len - 1; // for loop does ++i, thus -1 here.
goto next_symbol; goto next_symbol;
} }
@ -515,7 +534,7 @@ static int BackwardReferencesHashChainDistanceOnly(
cost[i] = cost_val; cost[i] = cost_val;
dist_array[i] = 1; // only one is inserted. dist_array[i] = 1; // only one is inserted.
} }
VP8LColorCacheInsert(&hashers, argb[i]); if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]);
} }
next_symbol: ; next_symbol: ;
} }
@ -574,11 +593,13 @@ static int BackwardReferencesHashChainFollowChosenPath(
HashChain* hash_chain = (HashChain*)malloc(sizeof(*hash_chain)); HashChain* hash_chain = (HashChain*)malloc(sizeof(*hash_chain));
VP8LColorCache hashers; VP8LColorCache hashers;
if (hash_chain == NULL || if (hash_chain == NULL || !HashChainInit(hash_chain, pix_count)) {
!(cc_init = VP8LColorCacheInit(&hashers, cache_bits)) ||
!HashChainInit(hash_chain, pix_count)) {
goto Error; goto Error;
} }
if (use_color_cache) {
cc_init = VP8LColorCacheInit(&hashers, cache_bits);
if (!cc_init) goto Error;
}
refs->size = 0; refs->size = 0;
for (ix = 0; ix < chosen_path_size; ++ix, ++size) { for (ix = 0; ix < chosen_path_size; ++ix, ++size) {
@ -590,10 +611,14 @@ static int BackwardReferencesHashChainFollowChosenPath(
i, xsize, argb, maxlen, &offset, &len); i, xsize, argb, maxlen, &offset, &len);
assert(len == maxlen); assert(len == maxlen);
refs->refs[size] = PixOrCopyCreateCopy(offset, len); refs->refs[size] = PixOrCopyCreateCopy(offset, len);
for (k = 0; k < len; ++k) { if (use_color_cache) {
VP8LColorCacheInsert(&hashers, argb[i + k]); for (k = 0; k < len; ++k) {
if (i + k + 1 < pix_count) { VP8LColorCacheInsert(&hashers, argb[i + k]);
// Add to the hash_chain (but cannot add the last pixel). }
}
{
const int last = (len < pix_count - 1 - i) ? len : pix_count - 1 - i;
for (k = 0; k < last; ++k) {
HashChainInsert(hash_chain, &argb[i + k], i + k); HashChainInsert(hash_chain, &argb[i + k], i + k);
} }
} }
@ -606,7 +631,7 @@ static int BackwardReferencesHashChainFollowChosenPath(
} else { } else {
refs->refs[size] = PixOrCopyCreateLiteral(argb[i]); refs->refs[size] = PixOrCopyCreateLiteral(argb[i]);
} }
VP8LColorCacheInsert(&hashers, argb[i]); if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]);
if (i + 1 < pix_count) { if (i + 1 < pix_count) {
HashChainInsert(hash_chain, &argb[i], i); HashChainInsert(hash_chain, &argb[i], i);
} }
@ -755,13 +780,18 @@ static int ComputeCacheHistogram(const uint32_t* const argb,
int i; int i;
uint32_t k; uint32_t k;
VP8LColorCache hashers; VP8LColorCache hashers;
const int use_color_cache = (cache_bits > 0);
int cc_init = 0;
if (!VP8LColorCacheInit(&hashers, cache_bits)) return 0; if (use_color_cache) {
cc_init = VP8LColorCacheInit(&hashers, cache_bits);
if (!cc_init) return 0;
}
for (i = 0; i < refs->size; ++i) { for (i = 0; i < refs->size; ++i) {
const PixOrCopy* const v = &refs->refs[i]; const PixOrCopy* const v = &refs->refs[i];
if (PixOrCopyIsLiteral(v)) { if (PixOrCopyIsLiteral(v)) {
if (cache_bits != 0 && if (use_color_cache &&
VP8LColorCacheContains(&hashers, argb[pixel_index])) { VP8LColorCacheContains(&hashers, argb[pixel_index])) {
// push pixel as a cache index // push pixel as a cache index
const int ix = VP8LColorCacheGetIndex(&hashers, argb[pixel_index]); const int ix = VP8LColorCacheGetIndex(&hashers, argb[pixel_index]);
@ -773,15 +803,17 @@ static int ComputeCacheHistogram(const uint32_t* const argb,
} else { } else {
VP8LHistogramAddSinglePixOrCopy(histo, v); VP8LHistogramAddSinglePixOrCopy(histo, v);
} }
for (k = 0; k < PixOrCopyLength(v); ++k) { if (use_color_cache) {
VP8LColorCacheInsert(&hashers, argb[pixel_index]); for (k = 0; k < PixOrCopyLength(v); ++k) {
++pixel_index; VP8LColorCacheInsert(&hashers, argb[pixel_index + k]);
}
} }
pixel_index += PixOrCopyLength(v);
} }
assert(pixel_index == xsize * ysize); assert(pixel_index == xsize * ysize);
(void)xsize; // xsize is not used in non-debug compilations otherwise. (void)xsize; // xsize is not used in non-debug compilations otherwise.
(void)ysize; // ysize is not used in non-debug compilations otherwise. (void)ysize; // ysize is not used in non-debug compilations otherwise.
VP8LColorCacheClear(&hashers); if (cc_init) VP8LColorCacheClear(&hashers);
return 1; return 1;
} }

View File

@ -21,11 +21,9 @@ extern "C" {
// VP8LColorCache. // VP8LColorCache.
int VP8LColorCacheInit(VP8LColorCache* const cc, int hash_bits) { int VP8LColorCacheInit(VP8LColorCache* const cc, int hash_bits) {
int hash_size; const int hash_size = 1 << hash_bits;
assert(cc != NULL); assert(cc != NULL);
assert(hash_bits > 0);
if (hash_bits == 0) hash_bits = 1;
hash_size = 1 << hash_bits;
cc->colors_ = (uint32_t*)calloc(hash_size, sizeof(*cc->colors_)); cc->colors_ = (uint32_t*)calloc(hash_size, sizeof(*cc->colors_));
if (cc->colors_ == NULL) return 0; if (cc->colors_ == NULL) return 0;
cc->hash_shift_ = 32 - hash_bits; cc->hash_shift_ = 32 - hash_bits;