mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 13:48:21 +01:00
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:
parent
974aaff360
commit
1336fa719d
@ -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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user