diff --git a/src/enc/cost.c b/src/enc/cost.c index f765598a..0f7ee722 100644 --- a/src/enc/cost.c +++ b/src/enc/cost.c @@ -55,7 +55,7 @@ const uint16_t VP8EntropyCost[256] = { // 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 // 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}, {0x00f, 0x00d}, {0x033, 0x003}, {0x033, 0x003}, {0x033, 0x023}, {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]) { - int pattern = kLevelCodes[level - 1][0]; - int bits = kLevelCodes[level - 1][1]; + int pattern = VP8LevelCodes[level - 1][0]; + int bits = VP8LevelCodes[level - 1][1]; int cost = 0; int i; for (i = 2; pattern; ++i) { diff --git a/src/enc/cost.h b/src/enc/cost.h index 287091c6..6b83c832 100644 --- a/src/enc/cost.h +++ b/src/enc/cost.h @@ -33,6 +33,7 @@ static inline uint64_t VP8BranchCost(uint64_t nb, uint64_t total, } // Level cost calculations +extern const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2]; void VP8CalculateLevelCosts(VP8Proba* const proba); static inline int VP8LevelCost(const uint16_t* const table, int level) { return VP8LevelFixedCosts[level] diff --git a/src/enc/frame.c b/src/enc/frame.c index 1934b02d..5bc0731c 100644 --- a/src/enc/frame.c +++ b/src/enc/frame.c @@ -101,6 +101,9 @@ static int Record(int bit, uint64_t* const stats) { 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. // Note: no need to record the fixed probas. static int RecordCoeffs(int ctx, VP8Residual* res) { @@ -111,14 +114,16 @@ static int RecordCoeffs(int ctx, VP8Residual* res) { } while (1) { - const int v = abs(res->coeffs[n++]); + int v = res->coeffs[n++]; if (!Record(v != 0, s[1])) { s = res->stats[VP8EncBands[n]][0]; 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]; } else { + v = abs(v); +#if !defined(USE_LEVEL_CODE_TABLE) if (!Record(v > 4, s[3])) { if (Record(v != 2, s[4])) Record(v == 4, s[5]); @@ -129,6 +134,20 @@ static int RecordCoeffs(int ctx, VP8Residual* res) { } else { 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]; } if (n == 16 || !Record(n <= res->last, s[0])) { @@ -213,16 +232,18 @@ static int GetResidualCost(int ctx, const VP8Residual* const res) { return cost; } while (n <= res->last) { - const int v = abs(res->coeffs[n++]); - cost += VP8LevelCost(t, v); + const int v = res->coeffs[n++]; if (v == 0) { + cost += VP8LevelCost(t, 0); p = res->prob[VP8EncBands[n]][0]; t = res->cost[VP8EncBands[n]][0]; 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]; t = res->cost[VP8EncBands[n]][1]; } else { + cost += VP8LevelCost(t, abs(v)); p = res->prob[VP8EncBands[n]][2]; t = res->cost[VP8EncBands[n]][2]; }