mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 13:48:21 +01:00
Speed-up: Make sure we only initialize histograms when needed.
Also, histograms in a HistogramSet can be initialized all
at once.
Change-Id: Ibbfa6034dce58dca8bb9113487e2ae507222ce7d
(cherry picked from commit 6752904b2f
)
This commit is contained in:
parent
0c57031629
commit
d61385db35
@ -67,7 +67,7 @@ static int CostModelBuild(CostModel* const m, int xsize, int cache_bits,
|
|||||||
|
|
||||||
// The following code is similar to VP8LHistogramCreate but converts the
|
// The following code is similar to VP8LHistogramCreate but converts the
|
||||||
// distance to plane code.
|
// distance to plane code.
|
||||||
VP8LHistogramInit(histo, cache_bits);
|
VP8LHistogramInit(histo, cache_bits, /*init_arrays=*/ 1);
|
||||||
while (VP8LRefsCursorOk(&c)) {
|
while (VP8LRefsCursorOk(&c)) {
|
||||||
VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos, VP8LDistanceToPlaneCode,
|
VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos, VP8LDistanceToPlaneCode,
|
||||||
xsize);
|
xsize);
|
||||||
|
@ -715,6 +715,7 @@ static int CalculateBestCacheSize(const uint32_t* argb, int quality,
|
|||||||
for (i = 0; i <= cache_bits_max; ++i) {
|
for (i = 0; i <= cache_bits_max; ++i) {
|
||||||
histos[i] = VP8LAllocateHistogram(i);
|
histos[i] = VP8LAllocateHistogram(i);
|
||||||
if (histos[i] == NULL) goto Error;
|
if (histos[i] == NULL) goto Error;
|
||||||
|
VP8LHistogramInit(histos[i], i, /*init_arrays=*/ 1);
|
||||||
if (i == 0) continue;
|
if (i == 0) continue;
|
||||||
cc_init[i] = VP8LColorCacheInit(&hashers[i], i);
|
cc_init[i] = VP8LColorCacheInit(&hashers[i], i);
|
||||||
if (!cc_init[i]) goto Error;
|
if (!cc_init[i]) goto Error;
|
||||||
|
@ -93,9 +93,19 @@ void VP8LHistogramCreate(VP8LHistogram* const p,
|
|||||||
VP8LHistogramStoreRefs(refs, p);
|
VP8LHistogramStoreRefs(refs, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits) {
|
void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits,
|
||||||
|
int init_arrays) {
|
||||||
p->palette_code_bits_ = palette_code_bits;
|
p->palette_code_bits_ = palette_code_bits;
|
||||||
HistogramClear(p);
|
if (init_arrays) {
|
||||||
|
HistogramClear(p);
|
||||||
|
} else {
|
||||||
|
p->trivial_symbol_ = 0;
|
||||||
|
p->bit_cost_ = 0.;
|
||||||
|
p->literal_cost_ = 0.;
|
||||||
|
p->red_cost_ = 0.;
|
||||||
|
p->blue_cost_ = 0.;
|
||||||
|
memset(p->is_used_, 0, sizeof(p->is_used_));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VP8LHistogram* VP8LAllocateHistogram(int cache_bits) {
|
VP8LHistogram* VP8LAllocateHistogram(int cache_bits) {
|
||||||
@ -106,37 +116,70 @@ VP8LHistogram* VP8LAllocateHistogram(int cache_bits) {
|
|||||||
histo = (VP8LHistogram*)memory;
|
histo = (VP8LHistogram*)memory;
|
||||||
// literal_ won't necessary be aligned.
|
// literal_ won't necessary be aligned.
|
||||||
histo->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram));
|
histo->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram));
|
||||||
VP8LHistogramInit(histo, cache_bits);
|
VP8LHistogramInit(histo, cache_bits, /*init_arrays=*/ 0);
|
||||||
return histo;
|
return histo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resets the pointers of the histograms to point to the bit buffer in the set.
|
||||||
|
static void HistogramSetResetPointers(VP8LHistogramSet* const set,
|
||||||
|
int cache_bits) {
|
||||||
|
int i;
|
||||||
|
const int histo_size = VP8LGetHistogramSize(cache_bits);
|
||||||
|
uint8_t* memory = (uint8_t*) (set->histograms);
|
||||||
|
memory += set->max_size * sizeof(*set->histograms);
|
||||||
|
for (i = 0; i < set->max_size; ++i) {
|
||||||
|
memory = (uint8_t*) WEBP_ALIGN(memory);
|
||||||
|
set->histograms[i] = (VP8LHistogram*) memory;
|
||||||
|
// literal_ won't necessary be aligned.
|
||||||
|
set->histograms[i]->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram));
|
||||||
|
memory += histo_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the total size of the VP8LHistogramSet.
|
||||||
|
static size_t HistogramSetTotalSize(int size, int cache_bits) {
|
||||||
|
const int histo_size = VP8LGetHistogramSize(cache_bits);
|
||||||
|
return (sizeof(VP8LHistogramSet) + size * (sizeof(VP8LHistogram*) +
|
||||||
|
histo_size + WEBP_ALIGN_CST));
|
||||||
|
}
|
||||||
|
|
||||||
VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) {
|
VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) {
|
||||||
int i;
|
int i;
|
||||||
VP8LHistogramSet* set;
|
VP8LHistogramSet* set;
|
||||||
const int histo_size = VP8LGetHistogramSize(cache_bits);
|
const size_t total_size = HistogramSetTotalSize(size, cache_bits);
|
||||||
const size_t total_size =
|
|
||||||
sizeof(*set) + size * (sizeof(*set->histograms) +
|
|
||||||
histo_size + WEBP_ALIGN_CST);
|
|
||||||
uint8_t* memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory));
|
uint8_t* memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory));
|
||||||
if (memory == NULL) return NULL;
|
if (memory == NULL) return NULL;
|
||||||
|
|
||||||
set = (VP8LHistogramSet*)memory;
|
set = (VP8LHistogramSet*)memory;
|
||||||
memory += sizeof(*set);
|
memory += sizeof(*set);
|
||||||
set->histograms = (VP8LHistogram**)memory;
|
set->histograms = (VP8LHistogram**)memory;
|
||||||
memory += size * sizeof(*set->histograms);
|
|
||||||
set->max_size = size;
|
set->max_size = size;
|
||||||
set->size = size;
|
set->size = size;
|
||||||
|
HistogramSetResetPointers(set, cache_bits);
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < size; ++i) {
|
||||||
memory = (uint8_t*)WEBP_ALIGN(memory);
|
VP8LHistogramInit(set->histograms[i], cache_bits, /*init_arrays=*/ 0);
|
||||||
set->histograms[i] = (VP8LHistogram*)memory;
|
|
||||||
// literal_ won't necessary be aligned.
|
|
||||||
set->histograms[i]->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram));
|
|
||||||
VP8LHistogramInit(set->histograms[i], cache_bits);
|
|
||||||
memory += histo_size;
|
|
||||||
}
|
}
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VP8LHistogramSetClear(VP8LHistogramSet* const set) {
|
||||||
|
int i;
|
||||||
|
const int cache_bits = set->histograms[0]->palette_code_bits_;
|
||||||
|
const int size = set->size;
|
||||||
|
const size_t total_size = HistogramSetTotalSize(size, cache_bits);
|
||||||
|
uint8_t* memory = (uint8_t*)set;
|
||||||
|
|
||||||
|
memset(memory, 0, total_size);
|
||||||
|
memory += sizeof(*set);
|
||||||
|
set->histograms = (VP8LHistogram**)memory;
|
||||||
|
set->max_size = size;
|
||||||
|
set->size = size;
|
||||||
|
HistogramSetResetPointers(set, cache_bits);
|
||||||
|
for (i = 0; i < size; ++i) {
|
||||||
|
set->histograms[i]->palette_code_bits_ = cache_bits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo,
|
void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo,
|
||||||
@ -503,6 +546,7 @@ static void HistogramBuild(
|
|||||||
VP8LHistogram** const histograms = image_histo->histograms;
|
VP8LHistogram** const histograms = image_histo->histograms;
|
||||||
VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs);
|
VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs);
|
||||||
assert(histo_bits > 0);
|
assert(histo_bits > 0);
|
||||||
|
VP8LHistogramSetClear(image_histo);
|
||||||
while (VP8LRefsCursorOk(&c)) {
|
while (VP8LRefsCursorOk(&c)) {
|
||||||
const PixOrCopy* const v = c.cur_pos;
|
const PixOrCopy* const v = c.cur_pos;
|
||||||
const int ix = (y >> histo_bits) * histo_xsize + (x >> histo_bits);
|
const int ix = (y >> histo_bits) * histo_xsize + (x >> histo_bits);
|
||||||
|
@ -68,7 +68,9 @@ void VP8LHistogramCreate(VP8LHistogram* const p,
|
|||||||
int VP8LGetHistogramSize(int palette_code_bits);
|
int VP8LGetHistogramSize(int palette_code_bits);
|
||||||
|
|
||||||
// Set the palette_code_bits and reset the stats.
|
// Set the palette_code_bits and reset the stats.
|
||||||
void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits);
|
// If init_arrays is true, the arrays are also filled with 0's.
|
||||||
|
void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits,
|
||||||
|
int init_arrays);
|
||||||
|
|
||||||
// Collect all the references into a histogram (without reset)
|
// Collect all the references into a histogram (without reset)
|
||||||
void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs,
|
void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs,
|
||||||
@ -84,6 +86,9 @@ void VP8LFreeHistogramSet(VP8LHistogramSet* const histo);
|
|||||||
// using 'cache_bits'. Return NULL in case of memory error.
|
// using 'cache_bits'. Return NULL in case of memory error.
|
||||||
VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits);
|
VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits);
|
||||||
|
|
||||||
|
// Set the histograms in set to 0.
|
||||||
|
void VP8LHistogramSetClear(VP8LHistogramSet* const set);
|
||||||
|
|
||||||
// Allocate and initialize histogram object with specified 'cache_bits'.
|
// Allocate and initialize histogram object with specified 'cache_bits'.
|
||||||
// Returns NULL in case of memory error.
|
// Returns NULL in case of memory error.
|
||||||
// Special case of VP8LAllocateHistogramSet, with size equals 1.
|
// Special case of VP8LAllocateHistogramSet, with size equals 1.
|
||||||
|
@ -809,6 +809,7 @@ static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw,
|
|||||||
err = VP8_ENC_ERROR_OUT_OF_MEMORY;
|
err = VP8_ENC_ERROR_OUT_OF_MEMORY;
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
|
VP8LHistogramSetClear(histogram_image);
|
||||||
|
|
||||||
// Build histogram image and symbols from backward references.
|
// Build histogram image and symbols from backward references.
|
||||||
VP8LHistogramStoreRefs(refs, histogram_image->histograms[0]);
|
VP8LHistogramStoreRefs(refs, histogram_image->histograms[0]);
|
||||||
|
Loading…
Reference in New Issue
Block a user