mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-28 14:38:21 +01:00
Merge "Move the HuffmanCost() function to dsp lib"
This commit is contained in:
commit
b1dabe3767
@ -1458,15 +1458,14 @@ void VP8LBundleColorMap(const uint8_t* const row, int width,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static double ExtraCost(const int* const population, int length) {
|
static double ExtraCost(const int* population, int length) {
|
||||||
int i;
|
int i;
|
||||||
double cost = 0.;
|
double cost = 0.;
|
||||||
for (i = 2; i < length - 2; ++i) cost += (i >> 1) * population[i + 2];
|
for (i = 2; i < length - 2; ++i) cost += (i >> 1) * population[i + 2];
|
||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double ExtraCostCombined(const int* const X, const int* const Y,
|
static double ExtraCostCombined(const int* X, const int* Y, int length) {
|
||||||
int length) {
|
|
||||||
int i;
|
int i;
|
||||||
double cost = 0.;
|
double cost = 0.;
|
||||||
for (i = 2; i < length - 2; ++i) {
|
for (i = 2; i < length - 2; ++i) {
|
||||||
@ -1476,6 +1475,53 @@ static double ExtraCostCombined(const int* const X, const int* const Y,
|
|||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the various RLE counts
|
||||||
|
static VP8LStreaks HuffmanCostCount(const int* population, int length) {
|
||||||
|
int i;
|
||||||
|
int streak = 0;
|
||||||
|
VP8LStreaks stats;
|
||||||
|
memset(&stats, 0, sizeof(stats));
|
||||||
|
for (i = 0; i < length - 1; ++i) {
|
||||||
|
++streak;
|
||||||
|
if (population[i] == population[i + 1]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
stats.counts[population[i] != 0] += (streak > 3);
|
||||||
|
stats.streaks[population[i] != 0][(streak > 3)] += streak;
|
||||||
|
streak = 0;
|
||||||
|
}
|
||||||
|
++streak;
|
||||||
|
stats.counts[population[i] != 0] += (streak > 3);
|
||||||
|
stats.streaks[population[i] != 0][(streak > 3)] += streak;
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VP8LStreaks HuffmanCostCombinedCount(const int* X, const int* Y,
|
||||||
|
int length) {
|
||||||
|
int i;
|
||||||
|
int streak = 0;
|
||||||
|
VP8LStreaks stats;
|
||||||
|
memset(&stats, 0, sizeof(stats));
|
||||||
|
for (i = 0; i < length - 1; ++i) {
|
||||||
|
const int xy = X[i] + Y[i];
|
||||||
|
const int xy_next = X[i + 1] + Y[i + 1];
|
||||||
|
++streak;
|
||||||
|
if (xy == xy_next) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
stats.counts[xy != 0] += (streak > 3);
|
||||||
|
stats.streaks[xy != 0][(streak > 3)] += streak;
|
||||||
|
streak = 0;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const int xy = X[i] + Y[i];
|
||||||
|
++streak;
|
||||||
|
stats.counts[xy != 0] += (streak > 3);
|
||||||
|
stats.streaks[xy != 0][(streak > 3)] += streak;
|
||||||
|
}
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed;
|
VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed;
|
||||||
@ -1497,6 +1543,9 @@ VP8LFastLog2SlowFunc VP8LFastSLog2Slow;
|
|||||||
VP8LCostFunc VP8LExtraCost;
|
VP8LCostFunc VP8LExtraCost;
|
||||||
VP8LCostCombinedFunc VP8LExtraCostCombined;
|
VP8LCostCombinedFunc VP8LExtraCostCombined;
|
||||||
|
|
||||||
|
VP8LCostCountFunc VP8LHuffmanCostCount;
|
||||||
|
VP8LCostCombinedCountFunc VP8LHuffmanCostCombinedCount;
|
||||||
|
|
||||||
extern void VP8LDspInitSSE2(void);
|
extern void VP8LDspInitSSE2(void);
|
||||||
extern void VP8LDspInitNEON(void);
|
extern void VP8LDspInitNEON(void);
|
||||||
extern void VP8LDspInitMIPS32(void);
|
extern void VP8LDspInitMIPS32(void);
|
||||||
@ -1522,6 +1571,9 @@ void VP8LDspInit(void) {
|
|||||||
VP8LExtraCost = ExtraCost;
|
VP8LExtraCost = ExtraCost;
|
||||||
VP8LExtraCostCombined = ExtraCostCombined;
|
VP8LExtraCostCombined = ExtraCostCombined;
|
||||||
|
|
||||||
|
VP8LHuffmanCostCount = HuffmanCostCount;
|
||||||
|
VP8LHuffmanCostCombinedCount = HuffmanCostCombinedCount;
|
||||||
|
|
||||||
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
|
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
|
||||||
if (VP8GetCPUInfo != NULL) {
|
if (VP8GetCPUInfo != NULL) {
|
||||||
#if defined(WEBP_USE_SSE2)
|
#if defined(WEBP_USE_SSE2)
|
||||||
|
@ -139,14 +139,24 @@ static WEBP_INLINE float VP8LFastSLog2(int v) {
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Huffman-cost related functions.
|
// Huffman-cost related functions.
|
||||||
|
|
||||||
typedef double (*VP8LCostFunc)(const int* const population, int length);
|
typedef double (*VP8LCostFunc)(const int* population, int length);
|
||||||
typedef double (*VP8LCostCombinedFunc)(const int* const X,
|
typedef double (*VP8LCostCombinedFunc)(const int* X, const int* Y, int length);
|
||||||
const int* const Y,
|
|
||||||
int length);
|
|
||||||
|
|
||||||
extern VP8LCostFunc VP8LExtraCost;
|
extern VP8LCostFunc VP8LExtraCost;
|
||||||
extern VP8LCostCombinedFunc VP8LExtraCostCombined;
|
extern VP8LCostCombinedFunc VP8LExtraCostCombined;
|
||||||
|
|
||||||
|
typedef struct { // small struct to hold counters
|
||||||
|
int counts[2]; // index: 0=zero steak, 1=non-zero streak
|
||||||
|
int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3]
|
||||||
|
} VP8LStreaks;
|
||||||
|
|
||||||
|
typedef VP8LStreaks (*VP8LCostCountFunc)(const int* population, int length);
|
||||||
|
typedef VP8LStreaks (*VP8LCostCombinedCountFunc)(const int* X, const int* Y,
|
||||||
|
int length);
|
||||||
|
|
||||||
|
extern VP8LCostCountFunc VP8LHuffmanCostCount;
|
||||||
|
extern VP8LCostCombinedCountFunc VP8LHuffmanCostCombinedCount;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// PrefixEncode()
|
// PrefixEncode()
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ static double BitsEntropyCombined(const int* const X, const int* const Y,
|
|||||||
return BitsEntropyRefine(nonzeros, sum, max_val, retval);
|
return BitsEntropyRefine(nonzeros, sum, max_val, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE double InitialHuffmanCost(void) {
|
static double InitialHuffmanCost(void) {
|
||||||
// Small bias because Huffman code length is typically not stored in
|
// Small bias because Huffman code length is typically not stored in
|
||||||
// full length.
|
// full length.
|
||||||
static const int kHuffmanCodeOfHuffmanCodeSize = CODE_LENGTH_CODES * 3;
|
static const int kHuffmanCodeOfHuffmanCodeSize = CODE_LENGTH_CODES * 3;
|
||||||
@ -188,66 +188,29 @@ static WEBP_INLINE double InitialHuffmanCost(void) {
|
|||||||
return kHuffmanCodeOfHuffmanCodeSize - kSmallBias;
|
return kHuffmanCodeOfHuffmanCodeSize - kSmallBias;
|
||||||
}
|
}
|
||||||
|
|
||||||
double VP8FinalHuffmanCost(int cnt_z, int streak_z_le3, int streak_z_gt3,
|
// Finalize the Huffman cost based on streak numbers and length type (<3 or >=3)
|
||||||
int cnt_nz, int streak_nz_le3, int streak_nz_gt3) {
|
static double FinalHuffmanCost(const VP8LStreaks* const stats) {
|
||||||
double retval = InitialHuffmanCost();
|
double retval = InitialHuffmanCost();
|
||||||
retval += cnt_z * 1.5625 + 0.234375 * streak_z_gt3;
|
retval += stats->counts[0] * 1.5625 + 0.234375 * stats->streaks[0][1];
|
||||||
retval += cnt_nz * 2.578125 + 0.703125 * streak_nz_gt3;
|
retval += stats->counts[1] * 2.578125 + 0.703125 * stats->streaks[1][1];
|
||||||
retval += 1.796875 * streak_z_le3;
|
retval += 1.796875 * stats->streaks[0][0];
|
||||||
retval += 3.28125 * streak_nz_le3;
|
retval += 3.28125 * stats->streaks[1][0];
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the cost encode the rle-encoded entropy code.
|
// Trampolines
|
||||||
// The constants in this function are experimental.
|
|
||||||
static double HuffmanCost(const int* const population, int length) {
|
static double HuffmanCost(const int* const population, int length) {
|
||||||
int cnts[2] = { 0, 0 };
|
const VP8LStreaks stats = VP8LHuffmanCostCount(population, length);
|
||||||
int streaks[2][2] = { { 0, 0 }, { 0, 0 } };
|
return FinalHuffmanCost(&stats);
|
||||||
int streak = 0;
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < length - 1; ++i) {
|
|
||||||
++streak;
|
|
||||||
if (population[i] == population[i + 1]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cnts[population[i] != 0] += (streak > 3);
|
|
||||||
streaks[population[i] != 0][(streak > 3)] += streak;
|
|
||||||
streak = 0;
|
|
||||||
}
|
|
||||||
++streak;
|
|
||||||
cnts[population[i] != 0] += (streak > 3);
|
|
||||||
streaks[population[i] != 0][(streak > 3)] += streak;
|
|
||||||
return VP8FinalHuffmanCost(cnts[0], streaks[0][0], streaks[0][1],
|
|
||||||
cnts[1], streaks[1][0], streaks[1][1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static double HuffmanCostCombined(const int* const X, const int* const Y,
|
static double HuffmanCostCombined(const int* const X, const int* const Y,
|
||||||
int length) {
|
int length) {
|
||||||
int cnts[2] = { 0, 0 };
|
const VP8LStreaks stats = VP8LHuffmanCostCombinedCount(X, Y, length);
|
||||||
int streaks[2][2] = { { 0, 0 }, { 0, 0 } };
|
return FinalHuffmanCost(&stats);
|
||||||
int streak = 0;
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < length - 1; ++i) {
|
|
||||||
const int xy = X[i] + Y[i];
|
|
||||||
const int xy_next = X[i + 1] + Y[i + 1];
|
|
||||||
++streak;
|
|
||||||
if (xy == xy_next) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cnts[xy != 0] += (streak > 3);
|
|
||||||
streaks[xy != 0][streak > 3] += streak;
|
|
||||||
streak = 0;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const int xy = X[i] + Y[i];
|
|
||||||
++streak;
|
|
||||||
cnts[xy != 0] += (streak > 3);
|
|
||||||
streaks[xy != 0][streak > 3] += streak;
|
|
||||||
}
|
|
||||||
return VP8FinalHuffmanCost(cnts[0], streaks[0][0], streaks[0][1],
|
|
||||||
cnts[1], streaks[1][0], streaks[1][1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Aggregated costs
|
||||||
static double PopulationCost(const int* const population, int length) {
|
static double PopulationCost(const int* const population, int length) {
|
||||||
return BitsEntropy(population, length) + HuffmanCost(population, length);
|
return BitsEntropy(population, length) + HuffmanCost(population, length);
|
||||||
}
|
}
|
||||||
|
@ -90,13 +90,6 @@ static WEBP_INLINE int VP8LHistogramNumCodes(int palette_code_bits) {
|
|||||||
((palette_code_bits > 0) ? (1 << palette_code_bits) : 0);
|
((palette_code_bits > 0) ? (1 << palette_code_bits) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used to finalized the Huffman cost:
|
|
||||||
// cnt_z / cnt_nz: counts the number of 0's and non-0's
|
|
||||||
// streak_{z,nz}_le3 / streak_{z,nz}_gt3: number of streaks larger than 3
|
|
||||||
// or less-or-equal than 3.
|
|
||||||
double VP8FinalHuffmanCost(int cnt_z, int streak_z_le3, int streak_z_gt3,
|
|
||||||
int cnt_nz, int streak_nz_le3, int streak_nz_gt3);
|
|
||||||
|
|
||||||
// Builds the histogram image.
|
// Builds the histogram image.
|
||||||
int VP8LGetHistoImageSymbols(int xsize, int ysize,
|
int VP8LGetHistoImageSymbols(int xsize, int ysize,
|
||||||
const VP8LBackwardRefs* const refs,
|
const VP8LBackwardRefs* const refs,
|
||||||
|
Loading…
Reference in New Issue
Block a user