diff --git a/src/enc/cost.c b/src/enc/cost.c index 14b357ba..92e0cc71 100644 --- a/src/enc/cost.c +++ b/src/enc/cost.c @@ -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; } //------------------------------------------------------------------------------ diff --git a/src/enc/frame.c b/src/enc/frame.c index f7b44d2b..27fd8bec 100644 --- a/src/enc/frame.c +++ b/src/enc/frame.c @@ -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); diff --git a/src/enc/quant.c b/src/enc/quant.c index 3dc1042b..64695204 100644 --- a/src/enc/quant.c +++ b/src/enc/quant.c @@ -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 diff --git a/src/enc/tree.c b/src/enc/tree.c index 06c1d579..8b25e5e4 100644 --- a/src/enc/tree.c +++ b/src/enc/tree.c @@ -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. diff --git a/src/enc/vp8enci.h b/src/enc/vp8enci.h index 8b43be1d..35295eee 100644 --- a/src/enc/vp8enci.h +++ b/src/enc/vp8enci.h @@ -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;