15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2011 Google Inc. All Rights Reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// that can be found in the COPYING file in the root of the source
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// tree. An additional intellectual property rights grant can be found
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// in the file PATENTS. All contributing project authors may
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// be found in the AUTHORS file in the root of the source tree.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   frame coding and analysis
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Skal (pascal.massimino@gmail.com)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "./vp8enci.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "./cost.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "../webp/format_constants.h"  // RIFF constants
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SEGMENT_VISU 0
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEBUG_SEARCH 0    // useful to track search convergence
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// multi-pass convergence
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define HEADER_SIZE_ESTIMATE (RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE +  \
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              VP8_FRAME_HEADER_SIZE)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define DQ_LIMIT 0.4  // convergence is considered reached if dq < DQ_LIMIT
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// we allow 2k of extra head-room in PARTITION0 limit.
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define PARTITION0_SIZE_LIMIT ((VP8_MAX_PARTITION0_SIZE - 2048ULL) << 11)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef struct {  // struct for organizing convergence in either size or PSNR
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int is_first;
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  float dq;
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  float q, last_q;
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  double value, last_value;   // PSNR or size
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  double target;
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int do_size_search;
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} PassStats;
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static int InitPassStats(const VP8Encoder* const enc, PassStats* const s) {
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const uint64_t target_size = (uint64_t)enc->config_->target_size;
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int do_size_search = (target_size != 0);
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const float target_PSNR = enc->config_->target_PSNR;
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  s->is_first = 1;
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  s->dq = 10.f;
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  s->q = s->last_q = enc->config_->quality;
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  s->target = do_size_search ? (double)target_size
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            : (target_PSNR > 0.) ? target_PSNR
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            : 40.;   // default, just in case
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  s->value = s->last_value = 0.;
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  s->do_size_search = do_size_search;
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return do_size_search;
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static float Clamp(float v, float min, float max) {
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return (v < min) ? min : (v > max) ? max : v;
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static float ComputeNextQ(PassStats* const s) {
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  float dq;
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (s->is_first) {
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dq = (s->value > s->target) ? -s->dq : s->dq;
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    s->is_first = 0;
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (s->value != s->last_value) {
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const double slope = (s->target - s->value) / (s->last_value - s->value);
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dq = (float)(slope * (s->last_q - s->q));
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dq = 0.;  // we're done?!
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Limit variable to avoid large swings.
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  s->dq = Clamp(dq, -30.f, 30.f);
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  s->last_q = s->q;
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  s->last_value = s->value;
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  s->q = Clamp(s->q + s->dq, 0.f, 100.f);
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return s->q;
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//------------------------------------------------------------------------------
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tables for level coding
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint8_t VP8EncBands[16 + 1] = {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0  // sentinel
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const uint8_t VP8Cat3[] = { 173, 148, 140 };
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const uint8_t VP8Cat4[] = { 176, 155, 140, 135 };
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const uint8_t VP8Cat5[] = { 180, 157, 141, 134, 130 };
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const uint8_t VP8Cat6[] =
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 };
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reset the statistics about: number of skips, token proba, level cost,...
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void ResetStats(VP8Encoder* const enc) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8Proba* const proba = &enc->proba_;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VP8CalculateLevelCosts(proba);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proba->nb_skip_ = 0;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Skip decision probability
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SKIP_PROBA_THRESHOLD 250  // value below which using skip_proba is OK.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int CalcSkipProba(uint64_t nb, uint64_t total) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (int)(total ? (total - nb) * 255 / total : 255);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the bit-cost for coding the skip probability.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int FinalizeSkipProba(VP8Encoder* const enc) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8Proba* const proba = &enc->proba_;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int nb_mbs = enc->mb_w_ * enc->mb_h_;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int nb_events = proba->nb_skip_;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int size;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proba->skip_proba_ = CalcSkipProba(nb_events, nb_mbs);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proba->use_skip_proba_ = (proba->skip_proba_ < SKIP_PROBA_THRESHOLD);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size = 256;   // 'use_skip_proba' bit
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proba->use_skip_proba_) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size +=  nb_events * VP8BitCost(1, proba->skip_proba_)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         + (nb_mbs - nb_events) * VP8BitCost(0, proba->skip_proba_);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size += 8 * 256;   // cost of signaling the skip_proba_ itself.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return size;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Collect statistics and deduce probabilities for next coding pass.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return the total bit-cost for coding the probability updates.
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int CalcTokenProba(int nb, int total) {
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(nb <= total);
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return nb ? (255 - nb * 255 / total) : 255;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Cost of coding 'nb' 1's and 'total-nb' 0's using 'proba' probability.
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int BranchCost(int nb, int total, int proba) {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return nb * VP8BitCost(1, proba) + (total - nb) * VP8BitCost(0, proba);
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void ResetTokenStats(VP8Encoder* const enc) {
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8Proba* const proba = &enc->proba_;
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  memset(proba->stats_, 0, sizeof(proba->stats_));
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int FinalizeTokenProbas(VP8Proba* const proba) {
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int has_changed = 0;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int size = 0;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int t, b, c, p;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (t = 0; t < NUM_TYPES; ++t) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (b = 0; b < NUM_BANDS; ++b) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (c = 0; c < NUM_CTX; ++c) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (p = 0; p < NUM_PROBAS; ++p) {
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          const proba_t stats = proba->stats_[t][b][c][p];
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          const int nb = (stats >> 0) & 0xffff;
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          const int total = (stats >> 16) & 0xffff;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const int update_proba = VP8CoeffsUpdateProba[t][b][c][p];
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const int old_p = VP8CoeffsProba0[t][b][c][p];
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          const int new_p = CalcTokenProba(nb, total);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          const int old_cost = BranchCost(nb, total, old_p)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             + VP8BitCost(0, update_proba);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          const int new_cost = BranchCost(nb, total, new_p)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             + VP8BitCost(1, update_proba)
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             + 8 * 256;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const int use_new_p = (old_cost > new_cost);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          size += VP8BitCost(use_new_p, update_proba);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (use_new_p) {  // only use proba that seem meaningful enough.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            proba->coeffs_[t][b][c][p] = new_p;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            has_changed |= (new_p != old_p);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            size += 8 * 256;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            proba->coeffs_[t][b][c][p] = old_p;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  proba->dirty_ = has_changed;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return size;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Finalize Segment probability based on the coding tree
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int GetProba(int a, int b) {
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int total = a + b;
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (total == 0) ? 255     // that's the default probability.
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      : (255 * a + total / 2) / total;  // rounded proba
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void SetSegmentProbas(VP8Encoder* const enc) {
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int p[NUM_MB_SEGMENTS] = { 0 };
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int n;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) {
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const VP8MBInfo* const mb = &enc->mb_info_[n];
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    p[mb->segment_]++;
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (enc->pic_->stats != NULL) {
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (n = 0; n < NUM_MB_SEGMENTS; ++n) {
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      enc->pic_->stats->segment_size[n] = p[n];
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (enc->segment_hdr_.num_segments_ > 1) {
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint8_t* const probas = enc->proba_.segments_;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    probas[0] = GetProba(p[0] + p[1], p[2] + p[3]);
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    probas[1] = GetProba(p[0], p[1]);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    probas[2] = GetProba(p[2], p[3]);
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    enc->segment_hdr_.update_map_ =
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255);
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    enc->segment_hdr_.size_ =
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) +
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) +
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) +
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2]));
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    enc->segment_hdr_.update_map_ = 0;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    enc->segment_hdr_.size_ = 0;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Coefficient coding
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n = res->first;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const uint8_t* p = res->prob[n][ctx];
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!VP8PutBit(bw, res->last >= 0, p[0])) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (n < 16) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int c = res->coeffs[n++];
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int sign = c < 0;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int v = sign ? -c : c;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!VP8PutBit(bw, v != 0, p[1])) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p = res->prob[VP8EncBands[n]][0];
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!VP8PutBit(bw, v > 1, p[2])) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p = res->prob[VP8EncBands[n]][1];
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!VP8PutBit(bw, v > 4, p[3])) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (VP8PutBit(bw, v != 2, p[4]))
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VP8PutBit(bw, v == 4, p[5]);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (!VP8PutBit(bw, v > 10, p[6])) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!VP8PutBit(bw, v > 6, p[7])) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VP8PutBit(bw, v == 6, 159);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VP8PutBit(bw, v >= 9, 165);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VP8PutBit(bw, !(v & 1), 145);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int mask;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const uint8_t* tab;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (v < 3 + (8 << 1)) {          // VP8Cat3  (3b)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VP8PutBit(bw, 0, p[8]);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VP8PutBit(bw, 0, p[9]);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          v -= 3 + (8 << 0);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          mask = 1 << 2;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tab = VP8Cat3;
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else if (v < 3 + (8 << 2)) {   // VP8Cat4  (4b)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VP8PutBit(bw, 0, p[8]);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VP8PutBit(bw, 1, p[9]);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          v -= 3 + (8 << 1);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          mask = 1 << 3;
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tab = VP8Cat4;
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else if (v < 3 + (8 << 3)) {   // VP8Cat5  (5b)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VP8PutBit(bw, 1, p[8]);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VP8PutBit(bw, 0, p[10]);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          v -= 3 + (8 << 2);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          mask = 1 << 4;
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tab = VP8Cat5;
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else {                         // VP8Cat6 (11b)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VP8PutBit(bw, 1, p[8]);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VP8PutBit(bw, 1, p[10]);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          v -= 3 + (8 << 3);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          mask = 1 << 10;
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tab = VP8Cat6;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (mask) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VP8PutBit(bw, !!(v & mask), *tab++);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          mask >>= 1;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p = res->prob[VP8EncBands[n]][2];
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8PutBitUniform(bw, sign);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (n == 16 || !VP8PutBit(bw, n <= res->last, p[0])) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 1;   // EOB
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void CodeResiduals(VP8BitWriter* const bw, VP8EncIterator* const it,
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const VP8ModeScore* const rd) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int x, y, ch;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8Residual res;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t pos1, pos2, pos3;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int i16 = (it->mb_->type_ == 1);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int segment = it->mb_->segment_;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8Encoder* const enc = it->enc_;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8IteratorNzToBytes(it);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos1 = VP8BitWriterPos(bw);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i16) {
3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8InitResidual(0, 1, enc, &res);
3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8SetResidualCoeffs(rd->y_dc_levels, &res);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->top_nz_[8] = it->left_nz_[8] =
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PutCoeffs(bw, it->top_nz_[8] + it->left_nz_[8], &res);
3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8InitResidual(1, 0, enc, &res);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8InitResidual(0, 3, enc, &res);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // luma-AC
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (y = 0; y < 4; ++y) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (x = 0; x < 4; ++x) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int ctx = it->top_nz_[x] + it->left_nz_[y];
3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      it->top_nz_[x] = it->left_nz_[y] = PutCoeffs(bw, ctx, &res);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos2 = VP8BitWriterPos(bw);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // U/V
3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8InitResidual(0, 2, enc, &res);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ch = 0; ch <= 2; ch += 2) {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (y = 0; y < 2; ++y) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (x = 0; x < 2; ++x) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PutCoeffs(bw, ctx, &res);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos3 = VP8BitWriterPos(bw);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->luma_bits_ = pos2 - pos1;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->uv_bits_ = pos3 - pos2;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->bit_count_[segment][i16] += it->luma_bits_;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->bit_count_[segment][2] += it->uv_bits_;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8IteratorBytesToNz(it);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Same as CodeResiduals, but doesn't actually write anything.
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Instead, it just records the event distribution.
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void RecordResiduals(VP8EncIterator* const it,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const VP8ModeScore* const rd) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int x, y, ch;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8Residual res;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8Encoder* const enc = it->enc_;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8IteratorNzToBytes(it);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it->mb_->type_ == 1) {   // i16x16
3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8InitResidual(0, 1, enc, &res);
3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8SetResidualCoeffs(rd->y_dc_levels, &res);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->top_nz_[8] = it->left_nz_[8] =
3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      VP8RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res);
3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8InitResidual(1, 0, enc, &res);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8InitResidual(0, 3, enc, &res);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // luma-AC
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (y = 0; y < 4; ++y) {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (x = 0; x < 4; ++x) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int ctx = it->top_nz_[x] + it->left_nz_[y];
3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      it->top_nz_[x] = it->left_nz_[y] = VP8RecordCoeffs(ctx, &res);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // U/V
3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8InitResidual(0, 2, enc, &res);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ch = 0; ch <= 2; ch += 2) {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (y = 0; y < 2; ++y) {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (x = 0; x < 2; ++x) {
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            VP8RecordCoeffs(ctx, &res);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8IteratorBytesToNz(it);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Token buffer
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(DISABLE_TOKEN_BUFFER)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int RecordTokens(VP8EncIterator* const it, const VP8ModeScore* const rd,
4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        VP8TBuffer* const tokens) {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int x, y, ch;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8Residual res;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8Encoder* const enc = it->enc_;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8IteratorNzToBytes(it);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it->mb_->type_ == 1) {   // i16x16
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const int ctx = it->top_nz_[8] + it->left_nz_[8];
4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8InitResidual(0, 1, enc, &res);
4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8SetResidualCoeffs(rd->y_dc_levels, &res);
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    it->top_nz_[8] = it->left_nz_[8] =
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        VP8RecordCoeffTokens(ctx, 1,
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             res.first, res.last, res.coeffs, tokens);
4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8RecordCoeffs(ctx, &res);
4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8InitResidual(1, 0, enc, &res);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8InitResidual(0, 3, enc, &res);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // luma-AC
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (y = 0; y < 4; ++y) {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (x = 0; x < 4; ++x) {
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int ctx = it->top_nz_[x] + it->left_nz_[y];
4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      it->top_nz_[x] = it->left_nz_[y] =
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          VP8RecordCoeffTokens(ctx, res.coeff_type,
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               res.first, res.last, res.coeffs, tokens);
4295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      VP8RecordCoeffs(ctx, &res);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // U/V
4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8InitResidual(0, 2, enc, &res);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ch = 0; ch <= 2; ch += 2) {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (y = 0; y < 2; ++y) {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (x = 0; x < 2; ++x) {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            VP8RecordCoeffTokens(ctx, 2,
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 res.first, res.last, res.coeffs, tokens);
4435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        VP8RecordCoeffs(ctx, &res);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VP8IteratorBytesToNz(it);
4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return !tokens->error_;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif    // !DISABLE_TOKEN_BUFFER
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ExtraInfo map / Debug function
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SEGMENT_VISU
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void SetBlock(uint8_t* p, int value, int size) {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int y;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (y = 0; y < size; ++y) {
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(p, value, size);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p += BPS;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ResetSSE(VP8Encoder* const enc) {
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  enc->sse_[0] = 0;
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  enc->sse_[1] = 0;
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  enc->sse_[2] = 0;
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note: enc->sse_[3] is managed by alpha.c
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enc->sse_count_ = 0;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void StoreSSE(const VP8EncIterator* const it) {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8Encoder* const enc = it->enc_;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8_t* const in = it->yuv_in_;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8_t* const out = it->yuv_out_;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: not totally accurate at boundary. And doesn't include in-loop filter.
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enc->sse_[0] += VP8SSE16x16(in + Y_OFF, out + Y_OFF);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enc->sse_[1] += VP8SSE8x8(in + U_OFF, out + U_OFF);
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enc->sse_[2] += VP8SSE8x8(in + V_OFF, out + V_OFF);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enc->sse_count_ += 16 * 16;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void StoreSideInfo(const VP8EncIterator* const it) {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8Encoder* const enc = it->enc_;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const VP8MBInfo* const mb = it->mb_;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebPPicture* const pic = enc->pic_;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pic->stats != NULL) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StoreSSE(it);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enc->block_count_[0] += (mb->type_ == 0);
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enc->block_count_[1] += (mb->type_ == 1);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enc->block_count_[2] += (mb->skip_ != 0);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pic->extra_info != NULL) {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t* const info = &pic->extra_info[it->x_ + it->y_ * enc->mb_w_];
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (pic->extra_info_type) {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 1: *info = mb->type_; break;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 2: *info = mb->segment_; break;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 3: *info = enc->dqm_[mb->segment_].quant_; break;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 4: *info = (mb->type_ == 1) ? it->preds_[0] : 0xff; break;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 5: *info = mb->uv_mode_; break;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 6: {
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *info = (b > 255) ? 255 : b; break;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case 7: *info = mb->alpha_; break;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default: *info = 0; break;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SEGMENT_VISU  // visualize segments and prediction modes
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetBlock(it->yuv_out_ + Y_OFF, mb->segment_ * 64, 16);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetBlock(it->yuv_out_ + U_OFF, it->preds_[0] * 64, 8);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetBlock(it->yuv_out_ + V_OFF, mb->uv_mode_ * 64, 8);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static double GetPSNR(uint64_t mse, uint64_t size) {
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return (mse > 0 && size > 0) ? 10. * log10(255. * 255. * size / mse) : 99;
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//  StatLoop(): only collect statistics (number of skips, token usage, ...).
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//  This is used for deciding optimal probabilities. It also modifies the
5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//  quantizer value if some target (size, PSNR) was specified.
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void SetLoopParams(VP8Encoder* const enc, float q) {
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure the quality parameter is inside valid bounds
5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  q = Clamp(q, 0.f, 100.f);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8SetSegmentParams(enc, q);      // setup segment quantizations and filters
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetSegmentProbas(enc);            // compute segment probabilities
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResetStats(enc);
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResetSSE(enc);
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static uint64_t OneStatPass(VP8Encoder* const enc, VP8RDLevel rd_opt,
5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            int nb_mbs, int percent_delta,
5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            PassStats* const s) {
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VP8EncIterator it;
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint64_t size = 0;
5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint64_t size_p0 = 0;
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint64_t distortion = 0;
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const uint64_t pixel_count = nb_mbs * 384;
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8IteratorInit(enc, &it);
5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetLoopParams(enc, s->q);
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8ModeScore info;
5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    VP8IteratorImport(&it, NULL);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (VP8Decimate(&it, &info, rd_opt)) {
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Just record the number of skips and act like skip_proba is not used.
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      enc->proba_.nb_skip_++;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RecordResiduals(&it, &info);
5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    size += info.R + info.H;
5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    size_p0 += info.H;
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    distortion += info.D;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (percent_delta && !VP8IteratorProgress(&it, percent_delta))
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    VP8IteratorSaveBoundary(&it);
5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } while (VP8IteratorNext(&it) && --nb_mbs > 0);
5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  size_p0 += enc->segment_hdr_.size_;
5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (s->do_size_search) {
5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    size += FinalizeSkipProba(enc);
5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    size += FinalizeTokenProbas(&enc->proba_);
5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    size = ((size + size_p0 + 1024) >> 11) + HEADER_SIZE_ESTIMATE;
5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    s->value = (double)size;
5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    s->value = GetPSNR(distortion, pixel_count);
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return size_p0;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int StatLoop(VP8Encoder* const enc) {
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int method = enc->method_;
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int do_search = enc->do_search_;
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int fast_probe = ((method == 0 || method == 3) && !do_search);
5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int num_pass_left = enc->config_->pass;
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int task_percent = 20;
5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int percent_per_pass =
5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (task_percent + num_pass_left / 2) / num_pass_left;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int final_percent = enc->percent_ + task_percent;
5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const VP8RDLevel rd_opt =
5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (method >= 3 || do_search) ? RD_OPT_BASIC : RD_OPT_NONE;
5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int nb_mbs = enc->mb_w_ * enc->mb_h_;
5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PassStats stats;
5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  InitPassStats(enc, &stats);
5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ResetTokenStats(enc);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fast mode: quick analysis pass over few mbs. Better than nothing.
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fast_probe) {
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (method == 3) {  // we need more stats for method 3 to be reliable.
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nb_mbs = (nb_mbs > 200) ? nb_mbs >> 1 : 100;
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      nb_mbs = (nb_mbs > 200) ? nb_mbs >> 2 : 50;
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (num_pass_left-- > 0) {
6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) ||
6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             (num_pass_left == 0) ||
6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             (enc->max_i4_header_bits_ == 0);
6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const uint64_t size_p0 =
6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        OneStatPass(enc, rd_opt, nb_mbs, percent_per_pass, &stats);
6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (size_p0 == 0) return 0;
6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if (DEBUG_SEARCH > 0)
6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    printf("#%d value:%.1lf -> %.1lf   q:%.2f -> %.2f\n",
6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           num_pass_left, stats.last_value, stats.value, stats.last_q, stats.q);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (enc->max_i4_header_bits_ > 0 && size_p0 > PARTITION0_SIZE_LIMIT) {
6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ++num_pass_left;
6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      enc->max_i4_header_bits_ >>= 1;  // strengthen header bit limitation...
6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      continue;                        // ...and start over
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (is_last_pass) {
6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If no target size: just do several pass without changing 'q'
6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (do_search) {
6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ComputeNextQ(&stats);
6275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (fabs(stats.dq) <= DQ_LIMIT) break;
6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
6305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!do_search || !stats.do_size_search) {
6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Need to finalize probas now, since it wasn't done during the search.
6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FinalizeSkipProba(enc);
6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FinalizeTokenProbas(&enc->proba_);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VP8CalculateLevelCosts(&enc->proba_);  // finalize costs
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return WebPReportProgress(enc->pic_, final_percent, &enc->percent_);
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Main loops
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kAverageBytesPerMB[8] = { 50, 24, 16, 9, 7, 5, 3, 2 };
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int PreLoopInitialize(VP8Encoder* const enc) {
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int p;
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int ok = 1;
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int average_bytes_per_MB = kAverageBytesPerMB[enc->base_quant_ >> 4];
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int bytes_per_parts =
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      enc->mb_w_ * enc->mb_h_ * average_bytes_per_MB / enc->num_parts_;
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Initialize the bit-writers
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (p = 0; ok && p < enc->num_parts_; ++p) {
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ok = VP8BitWriterInit(enc->parts_ + p, bytes_per_parts);
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!ok) {
6565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8EncFreeBitWriters(enc);  // malloc error occurred
6575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
6585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ok;
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int PostLoopFinalize(VP8EncIterator* const it, int ok) {
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VP8Encoder* const enc = it->enc_;
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ok) {      // Finalize the partitions, check for extra errors.
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int p;
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (p = 0; p < enc->num_parts_; ++p) {
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      VP8BitWriterFinish(enc->parts_ + p);
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ok &= !enc->parts_[p].error_;
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ok) {      // All good. Finish up.
6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (enc->pic_->stats != NULL) {  // finalize byte counters...
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int i, s;
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (i = 0; i <= 2; ++i) {
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          enc->residual_bytes_[i][s] = (int)((it->bit_count_[s][i] + 7) >> 3);
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VP8AdjustFilterStrength(it);     // ...and store filter stats.
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Something bad happened -> need to do some memory cleanup.
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VP8EncFreeBitWriters(enc);
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ok;
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//  VP8EncLoop(): does the final bitstream coding.
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void ResetAfterSkip(VP8EncIterator* const it) {
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it->mb_->type_ == 1) {
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *it->nz_ = 0;  // reset all predictors
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    it->left_nz_[8] = 0;
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *it->nz_ &= (1 << 24);  // preserve the dc_nz bit
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int VP8EncLoop(VP8Encoder* const enc) {
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VP8EncIterator it;
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int ok = PreLoopInitialize(enc);
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!ok) return 0;
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StatLoop(enc);  // stats-collection loop
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VP8IteratorInit(enc, &it);
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VP8InitFilter(&it);
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  do {
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VP8ModeScore info;
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const int dont_use_skip = !enc->proba_.use_skip_proba_;
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const VP8RDLevel rd_opt = enc->rd_opt_level_;
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    VP8IteratorImport(&it, NULL);
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Warning! order is important: first call VP8Decimate() and
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // *then* decide how to code the skip decision if there's one.
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) {
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CodeResiduals(it.bw_, &it, &info);
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {   // reset predictors after a skip
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ResetAfterSkip(&it);
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StoreSideInfo(&it);
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VP8StoreFilterStats(&it);
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VP8IteratorExport(&it);
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ok = VP8IteratorProgress(&it, 20);
7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    VP8IteratorSaveBoundary(&it);
7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } while (ok && VP8IteratorNext(&it));
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PostLoopFinalize(&it, ok);
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Single pass using Token Buffer.
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(DISABLE_TOKEN_BUFFER)
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define MIN_COUNT 96  // minimum number of macroblocks before updating stats
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int VP8EncTokenLoop(VP8Encoder* const enc) {
7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Roughly refresh the proba eight times per pass
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int max_count = (enc->mb_w_ * enc->mb_h_) >> 3;
7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int num_pass_left = enc->config_->pass;
7445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int do_search = enc->do_search_;
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VP8EncIterator it;
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VP8Proba* const proba = &enc->proba_;
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const VP8RDLevel rd_opt = enc->rd_opt_level_;
7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const uint64_t pixel_count = enc->mb_w_ * enc->mb_h_ * 384;
7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PassStats stats;
7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int ok;
7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  InitPassStats(enc, &stats);
7535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ok = PreLoopInitialize(enc);
7545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ok) return 0;
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (max_count < MIN_COUNT) max_count = MIN_COUNT;
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(enc->num_parts_ == 1);
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(enc->use_tokens_);
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(proba->use_skip_proba_ == 0);
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(rd_opt >= RD_OPT_BASIC);   // otherwise, token-buffer won't be useful
7625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(num_pass_left > 0);
7635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (ok && num_pass_left-- > 0) {
7655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) ||
7665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             (num_pass_left == 0) ||
7675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             (enc->max_i4_header_bits_ == 0);
7685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    uint64_t size_p0 = 0;
7695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    uint64_t distortion = 0;
7705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int cnt = max_count;
7715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    VP8IteratorInit(enc, &it);
7725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SetLoopParams(enc, stats.q);
7735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (is_last_pass) {
7745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ResetTokenStats(enc);
7755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      VP8InitFilter(&it);  // don't collect stats until last pass (too costly)
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    VP8TBufferClear(&enc->tokens_);
7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    do {
7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      VP8ModeScore info;
7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      VP8IteratorImport(&it, NULL);
7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (--cnt < 0) {
7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        FinalizeTokenProbas(proba);
7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        VP8CalculateLevelCosts(proba);  // refresh cost tables for rd-opt
7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        cnt = max_count;
7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      VP8Decimate(&it, &info, rd_opt);
7875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ok = RecordTokens(&it, &info, &enc->tokens_);
7885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (!ok) {
7895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
7905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        break;
7915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      size_p0 += info.H;
7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      distortion += info.D;
7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (is_last_pass) {
7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        StoreSideInfo(&it);
7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        VP8StoreFilterStats(&it);
7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        VP8IteratorExport(&it);
7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ok = VP8IteratorProgress(&it, 20);
7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      VP8IteratorSaveBoundary(&it);
8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } while (ok && VP8IteratorNext(&it));
8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!ok) break;
8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    size_p0 += enc->segment_hdr_.size_;
8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (stats.do_size_search) {
8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      uint64_t size = FinalizeTokenProbas(&enc->proba_);
8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      size += VP8EstimateTokenSize(&enc->tokens_,
8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   (const uint8_t*)proba->coeffs_);
8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      size = (size + size_p0 + 1024) >> 11;  // -> size in bytes
8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      size += HEADER_SIZE_ESTIMATE;
8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      stats.value = (double)size;
8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {  // compute and store PSNR
8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      stats.value = GetPSNR(distortion, pixel_count);
8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if (DEBUG_SEARCH > 0)
8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    printf("#%2d metric:%.1lf -> %.1lf   last_q=%.2lf q=%.2lf dq=%.2lf\n",
8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           num_pass_left, stats.last_value, stats.value,
8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           stats.last_q, stats.q, stats.dq);
8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (size_p0 > PARTITION0_SIZE_LIMIT) {
8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ++num_pass_left;
8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      enc->max_i4_header_bits_ >>= 1;  // strengthen header bit limitation...
8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      continue;                        // ...and start over
8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (is_last_pass) {
8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;   // done
8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
8295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (do_search) {
8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ComputeNextQ(&stats);  // Adjust q
8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ok) {
8345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!stats.do_size_search) {
8355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FinalizeTokenProbas(&enc->proba_);
8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ok = VP8EmitTokens(&enc->tokens_, enc->parts_ + 0,
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       (const uint8_t*)proba->coeffs_, 1);
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ok = ok && WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_);
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PostLoopFinalize(&it, ok);
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int VP8EncTokenLoop(VP8Encoder* const enc) {
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  (void)enc;
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;   // we shouldn't be here.
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif    // DISABLE_TOKEN_BUFFER
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855