mirror of
https://github.com/webmproject/libwebp.git
synced 2025-04-25 10:16:45 +02:00
encoder speed-up: hardcode special level values
1-3% faster Change-Id: Ib2131989fbf819bcbfa6456adbeea0ba27c914f7
This commit is contained in:
parent
c558bdad28
commit
c915fb2aa7
@ -55,7 +55,7 @@ const uint16_t VP8EntropyCost[256] = {
|
|||||||
// For each given level, the following table given the pattern of contexts
|
// For each given level, the following table given the pattern of contexts
|
||||||
// to use for coding it (in [][0]) as well as the bit value to use for
|
// to use for coding it (in [][0]) as well as the bit value to use for
|
||||||
// each context (in [][1]).
|
// each context (in [][1]).
|
||||||
static const uint16_t kLevelCodes[MAX_VARIABLE_LEVEL][2] = {
|
const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2] = {
|
||||||
{0x001, 0x000}, {0x007, 0x001}, {0x00f, 0x005},
|
{0x001, 0x000}, {0x007, 0x001}, {0x00f, 0x005},
|
||||||
{0x00f, 0x00d}, {0x033, 0x003}, {0x033, 0x003}, {0x033, 0x023},
|
{0x00f, 0x00d}, {0x033, 0x003}, {0x033, 0x003}, {0x033, 0x023},
|
||||||
{0x033, 0x023}, {0x033, 0x023}, {0x033, 0x023}, {0x0d3, 0x013},
|
{0x033, 0x023}, {0x033, 0x023}, {0x033, 0x023}, {0x0d3, 0x013},
|
||||||
@ -337,8 +337,8 @@ const uint16_t VP8LevelFixedCosts[2048] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int VariableLevelCost(int level, const uint8_t probas[NUM_PROBAS]) {
|
static int VariableLevelCost(int level, const uint8_t probas[NUM_PROBAS]) {
|
||||||
int pattern = kLevelCodes[level - 1][0];
|
int pattern = VP8LevelCodes[level - 1][0];
|
||||||
int bits = kLevelCodes[level - 1][1];
|
int bits = VP8LevelCodes[level - 1][1];
|
||||||
int cost = 0;
|
int cost = 0;
|
||||||
int i;
|
int i;
|
||||||
for (i = 2; pattern; ++i) {
|
for (i = 2; pattern; ++i) {
|
||||||
|
@ -33,6 +33,7 @@ static inline uint64_t VP8BranchCost(uint64_t nb, uint64_t total,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Level cost calculations
|
// Level cost calculations
|
||||||
|
extern const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2];
|
||||||
void VP8CalculateLevelCosts(VP8Proba* const proba);
|
void VP8CalculateLevelCosts(VP8Proba* const proba);
|
||||||
static inline int VP8LevelCost(const uint16_t* const table, int level) {
|
static inline int VP8LevelCost(const uint16_t* const table, int level) {
|
||||||
return VP8LevelFixedCosts[level]
|
return VP8LevelFixedCosts[level]
|
||||||
|
@ -101,6 +101,9 @@ static int Record(int bit, uint64_t* const stats) {
|
|||||||
return bit;
|
return bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We keep the table free variant around for reference, in case.
|
||||||
|
#define USE_LEVEL_CODE_TABLE
|
||||||
|
|
||||||
// Simulate block coding, but only record statistics.
|
// Simulate block coding, but only record statistics.
|
||||||
// Note: no need to record the fixed probas.
|
// Note: no need to record the fixed probas.
|
||||||
static int RecordCoeffs(int ctx, VP8Residual* res) {
|
static int RecordCoeffs(int ctx, VP8Residual* res) {
|
||||||
@ -111,14 +114,16 @@ static int RecordCoeffs(int ctx, VP8Residual* res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
const int v = abs(res->coeffs[n++]);
|
int v = res->coeffs[n++];
|
||||||
if (!Record(v != 0, s[1])) {
|
if (!Record(v != 0, s[1])) {
|
||||||
s = res->stats[VP8EncBands[n]][0];
|
s = res->stats[VP8EncBands[n]][0];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!Record(v > 1, s[2])) {
|
if (!Record(2u < (unsigned int)(v + 1), s[2])) { // v = -1 or 1
|
||||||
s = res->stats[VP8EncBands[n]][1];
|
s = res->stats[VP8EncBands[n]][1];
|
||||||
} else {
|
} else {
|
||||||
|
v = abs(v);
|
||||||
|
#if !defined(USE_LEVEL_CODE_TABLE)
|
||||||
if (!Record(v > 4, s[3])) {
|
if (!Record(v > 4, s[3])) {
|
||||||
if (Record(v != 2, s[4]))
|
if (Record(v != 2, s[4]))
|
||||||
Record(v == 4, s[5]);
|
Record(v == 4, s[5]);
|
||||||
@ -129,6 +134,20 @@ static int RecordCoeffs(int ctx, VP8Residual* res) {
|
|||||||
} else {
|
} else {
|
||||||
Record((v >= 3 + (8 << 3)), s[10]);
|
Record((v >= 3 + (8 << 3)), s[10]);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (v > MAX_VARIABLE_LEVEL)
|
||||||
|
v = MAX_VARIABLE_LEVEL;
|
||||||
|
|
||||||
|
{
|
||||||
|
const int bits = VP8LevelCodes[v - 1][1];
|
||||||
|
int pattern = VP8LevelCodes[v - 1][0];
|
||||||
|
int i;
|
||||||
|
for (i = 0; (pattern >>= 1) != 0; ++i) {
|
||||||
|
const int mask = 2 << i;
|
||||||
|
if (pattern & 1) Record(!!(bits & mask), s[3 + i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
s = res->stats[VP8EncBands[n]][2];
|
s = res->stats[VP8EncBands[n]][2];
|
||||||
}
|
}
|
||||||
if (n == 16 || !Record(n <= res->last, s[0])) {
|
if (n == 16 || !Record(n <= res->last, s[0])) {
|
||||||
@ -213,16 +232,18 @@ static int GetResidualCost(int ctx, const VP8Residual* const res) {
|
|||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
while (n <= res->last) {
|
while (n <= res->last) {
|
||||||
const int v = abs(res->coeffs[n++]);
|
const int v = res->coeffs[n++];
|
||||||
cost += VP8LevelCost(t, v);
|
|
||||||
if (v == 0) {
|
if (v == 0) {
|
||||||
|
cost += VP8LevelCost(t, 0);
|
||||||
p = res->prob[VP8EncBands[n]][0];
|
p = res->prob[VP8EncBands[n]][0];
|
||||||
t = res->cost[VP8EncBands[n]][0];
|
t = res->cost[VP8EncBands[n]][0];
|
||||||
continue;
|
continue;
|
||||||
} else if (v == 1) {
|
} else if (2u >= (unsigned int)(v + 1)) { // v = -1 or 1
|
||||||
|
cost += VP8LevelCost(t, 1);
|
||||||
p = res->prob[VP8EncBands[n]][1];
|
p = res->prob[VP8EncBands[n]][1];
|
||||||
t = res->cost[VP8EncBands[n]][1];
|
t = res->cost[VP8EncBands[n]][1];
|
||||||
} else {
|
} else {
|
||||||
|
cost += VP8LevelCost(t, abs(v));
|
||||||
p = res->prob[VP8EncBands[n]][2];
|
p = res->prob[VP8EncBands[n]][2];
|
||||||
t = res->cost[VP8EncBands[n]][2];
|
t = res->cost[VP8EncBands[n]][2];
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user