Only recompute level_cost_[] when needed

Add a dirty_ flag to keep track of updated probabilities and the need to
recompute the level costs.
This only makes a difference for "-m 2" method which was sub-optimal.
But it's overall cleaner to have this flag.

Change-Id: I21c71201e1d07a923d97a3adf2fbbd7d67d35433
This commit is contained in:
Pascal Massimino 2012-01-25 07:45:34 -08:00
parent 974aaff360
commit 1336fa719d
5 changed files with 19 additions and 8 deletions

View File

@ -354,6 +354,9 @@ static int VariableLevelCost(int level, const uint8_t probas[NUM_PROBAS]) {
void VP8CalculateLevelCosts(VP8Proba* const proba) {
int ctype, band, ctx;
if (!proba->dirty_) return; // nothing to do.
for (ctype = 0; ctype < NUM_TYPES; ++ctype) {
for (band = 0; band < NUM_BANDS; ++band) {
for(ctx = 0; ctx < NUM_CTX; ++ctx) {
@ -370,6 +373,7 @@ void VP8CalculateLevelCosts(VP8Proba* const proba) {
}
}
}
proba->dirty_ = 0;
}
//------------------------------------------------------------------------------

View File

@ -54,9 +54,9 @@ static const uint8_t kCat6[] =
//------------------------------------------------------------------------------
// Reset the statistics about: number of skips, token proba, level cost,...
static void ResetStats(VP8Encoder* const enc, int precalc_cost) {
static void ResetStats(VP8Encoder* const enc) {
VP8Proba* const proba = &enc->proba_;
if (precalc_cost) VP8CalculateLevelCosts(proba);
VP8CalculateLevelCosts(proba);
proba->nb_skip_ = 0;
}
@ -123,7 +123,7 @@ static int RecordCoeffs(int ctx, const VP8Residual* const res) {
Record(1, s + 0);
while ((v = res->coeffs[n++]) == 0) {
Record(0, s + 1);
s = res->stats[VP8EncBands[n]][0];
s = res->stats[VP8EncBands[n]][0];
}
Record(1, s + 1);
if (!Record(2u < (unsigned int)(v + 1), s + 2)) { // v = -1 or 1
@ -176,6 +176,7 @@ static int BranchCost(int nb, int total, int proba) {
static int FinalizeTokenProbas(VP8Encoder* const enc) {
VP8Proba* const proba = &enc->proba_;
int has_changed = 0;
int size = 0;
int t, b, c, p;
for (t = 0; t < NUM_TYPES; ++t) {
@ -197,6 +198,7 @@ static int FinalizeTokenProbas(VP8Encoder* const enc) {
size += VP8BitCost(use_new_p, update_proba);
if (use_new_p) { // only use proba that seem meaningful enough.
proba->coeffs_[t][b][c][p] = new_p;
has_changed |= (new_p != old_p);
size += 8 * 256;
} else {
proba->coeffs_[t][b][c][p] = old_p;
@ -205,6 +207,7 @@ static int FinalizeTokenProbas(VP8Encoder* const enc) {
}
}
}
proba->dirty_ = has_changed;
return size;
}
@ -773,7 +776,7 @@ int VP8EncLoop(VP8Encoder* const enc) {
VP8BitWriterInit(enc->parts_ + p, bytes_per_parts);
}
ResetStats(enc, rd_opt != 0);
ResetStats(enc);
ResetSSE(enc);
VP8IteratorInit(enc, &it);
@ -845,7 +848,7 @@ static int OneStatPass(VP8Encoder* const enc, float q, int rd_opt, int nb_mbs,
VP8SetSegmentParams(enc, q); // setup segment quantizations and filters
ResetStats(enc, rd_opt != 0);
ResetStats(enc);
ResetTokenStats(enc);
VP8IteratorInit(enc, &it);

View File

@ -421,8 +421,8 @@ static int TrellisQuantizeBlock(const VP8EncIterator* const it,
int ctx0, int coeff_type,
const VP8Matrix* const mtx,
int lambda) {
ProbaArray* const last_costs = it->enc_->proba_.coeffs_[coeff_type];
CostArray* const costs = it->enc_->proba_.level_cost_[coeff_type];
const ProbaArray* const last_costs = it->enc_->proba_.coeffs_[coeff_type];
const CostArray* const costs = it->enc_->proba_.level_cost_[coeff_type];
const int first = (coeff_type == 0) ? 1 : 0;
Node nodes[17][NUM_NODES];
int best_path[3] = {-1, -1, -1}; // store best-last/best-level/best-previous

View File

@ -158,9 +158,12 @@ const uint8_t
void VP8DefaultProbas(VP8Encoder* const enc) {
VP8Proba* const probas = &enc->proba_;
probas->use_skip_proba_ = 0;
memset(probas->segments_, 255u, sizeof(probas->segments_));
memcpy(probas->coeffs_, VP8CoeffsProba0, sizeof(VP8CoeffsProba0));
probas->use_skip_proba_ = 0;
// Note: we could hard-code the level_costs_ corresponding to VP8CoeffsProba0,
// but that's ~11k of static data. Better call VP8CalculateLevelCosts() later.
probas->dirty_ = 1;
}
// Paragraph 11.5. 900bytes.

View File

@ -188,6 +188,7 @@ typedef struct {
ProbaArray coeffs_[NUM_TYPES][NUM_BANDS]; // 924 bytes
StatsArray stats_[NUM_TYPES][NUM_BANDS]; // 4224 bytes
CostArray level_cost_[NUM_TYPES][NUM_BANDS]; // 11.4k
int dirty_; // if true, need to call VP8CalculateLevelCosts()
int use_skip_proba_; // Note: we always use skip_proba for now.
int nb_skip_; // number of skipped blocks
} VP8Proba;