15a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Copyright 2011 Google Inc. All Rights Reserved.
27c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//
37c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// This code is licensed under the same terms as WebM:
47c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  Software License Agreement:  http://www.webmproject.org/license/software/
57c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  Additional IP Rights Grant:  http://www.webmproject.org/license/additional/
67c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// -----------------------------------------------------------------------------
77c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//
87c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//   frame coding and analysis
97c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//
107c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Author: Skal (pascal.massimino@gmail.com)
117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include <assert.h>
137c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#include <stdlib.h>
147c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#include <string.h>
157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#include <math.h>
167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "./vp8enci.h"
185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "./cost.h"
197c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
207c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#if defined(__cplusplus) || defined(c_plusplus)
217c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroraextern "C" {
227c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#endif
237c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
247c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#define SEGMENT_VISU 0
257c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#define DEBUG_SEARCH 0    // useful to track search convergence
267c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
277c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// On-the-fly info about the current set of residuals. Handy to avoid
287c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// passing zillions of params.
297c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroratypedef struct {
307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int first;
317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int last;
327c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const int16_t* coeffs;
337c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
347c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int coeff_type;
357c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  ProbaArray* prob;
367c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  StatsArray* stats;
377c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  CostArray*  cost;
387c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} VP8Residual;
397c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
417c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Tables for level coding
427c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroraconst uint8_t VP8EncBands[16 + 1] = {
447c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7,
457c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  0  // sentinel
467c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora};
477c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
487c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic const uint8_t kCat3[] = { 173, 148, 140 };
497c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic const uint8_t kCat4[] = { 176, 155, 140, 135 };
507c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic const uint8_t kCat5[] = { 180, 157, 141, 134, 130 };
517c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic const uint8_t kCat6[] =
527c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 };
537c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
557c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Reset the statistics about: number of skips, token proba, level cost,...
567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
575a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void ResetStats(VP8Encoder* const enc) {
587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8Proba* const proba = &enc->proba_;
595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  VP8CalculateLevelCosts(proba);
607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  proba->nb_skip_ = 0;
617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
627c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
647c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Skip decision probability
657c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#define SKIP_PROBA_THRESHOLD 250  // value below which using skip_proba is OK.
675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
687c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic int CalcSkipProba(uint64_t nb, uint64_t total) {
697c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  return (int)(total ? (total - nb) * 255 / total : 255);
707c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
727c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Returns the bit-cost for coding the skip probability.
737c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic int FinalizeSkipProba(VP8Encoder* const enc) {
747c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8Proba* const proba = &enc->proba_;
757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const int nb_mbs = enc->mb_w_ * enc->mb_h_;
767c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const int nb_events = proba->nb_skip_;
777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int size;
787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  proba->skip_proba_ = CalcSkipProba(nb_events, nb_mbs);
795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  proba->use_skip_proba_ = (proba->skip_proba_ < SKIP_PROBA_THRESHOLD);
807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  size = 256;   // 'use_skip_proba' bit
817c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (proba->use_skip_proba_) {
827c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    size +=  nb_events * VP8BitCost(1, proba->skip_proba_)
837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora         + (nb_mbs - nb_events) * VP8BitCost(0, proba->skip_proba_);
847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    size += 8 * 256;   // cost of signaling the skip_proba_ itself.
857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
867c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  return size;
877c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
887c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
907c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Recording of token probabilities.
917c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
927c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void ResetTokenStats(VP8Encoder* const enc) {
937c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8Proba* const proba = &enc->proba_;
947c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  memset(proba->stats_, 0, sizeof(proba->stats_));
957c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
967c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
977c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Record proba context used
985a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int Record(int bit, proba_t* const stats) {
995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  proba_t p = *stats;
1005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (p >= 0xffff0000u) {               // an overflow is inbound.
1015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    p = ((p + 1u) >> 1) & 0x7fff7fffu;  // -> divide the stats by 2.
1025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
1035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  // record bit count (lower 16 bits) and increment total count (upper 16 bits).
1045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  p += 0x00010000u + bit;
1055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  *stats = p;
1067c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  return bit;
1077c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
1087c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
109466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// We keep the table free variant around for reference, in case.
110466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#define USE_LEVEL_CODE_TABLE
111466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
1127c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Simulate block coding, but only record statistics.
1137c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Note: no need to record the fixed probas.
1145a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int RecordCoeffs(int ctx, const VP8Residual* const res) {
1157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int n = res->first;
1165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  proba_t* s = res->stats[VP8EncBands[n]][ctx];
1175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (res->last  < 0) {
1185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    Record(0, s + 0);
1197c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    return 0;
1207c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
1215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  while (n <= res->last) {
1225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int v;
1235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    Record(1, s + 0);
1245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    while ((v = res->coeffs[n++]) == 0) {
1255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      Record(0, s + 1);
1267c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      s = res->stats[VP8EncBands[n]][0];
1277c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
1285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    Record(1, s + 1);
1295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if (!Record(2u < (unsigned int)(v + 1), s + 2)) {  // v = -1 or 1
1307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      s = res->stats[VP8EncBands[n]][1];
1317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    } else {
132466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora      v = abs(v);
133466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#if !defined(USE_LEVEL_CODE_TABLE)
1345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (!Record(v > 4, s + 3)) {
1355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        if (Record(v != 2, s + 4))
1365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          Record(v == 4, s + 5);
1375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      } else if (!Record(v > 10, s + 6)) {
1385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        Record(v > 6, s + 7);
1395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      } else if (!Record((v >= 3 + (8 << 2)), s + 8)) {
1405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        Record((v >= 3 + (8 << 1)), s + 9);
1417c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      } else {
1425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        Record((v >= 3 + (8 << 3)), s + 10);
1437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      }
144466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#else
145466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora      if (v > MAX_VARIABLE_LEVEL)
146466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora        v = MAX_VARIABLE_LEVEL;
147466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
148466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora      {
149466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora        const int bits = VP8LevelCodes[v - 1][1];
150466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora        int pattern = VP8LevelCodes[v - 1][0];
151466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora        int i;
152466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora        for (i = 0; (pattern >>= 1) != 0; ++i) {
153466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora          const int mask = 2 << i;
1545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          if (pattern & 1) Record(!!(bits & mask), s + 3 + i);
155466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora        }
156466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora      }
157466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#endif
1587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      s = res->stats[VP8EncBands[n]][2];
1597c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
1607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
1615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (n < 16) Record(0, s + 0);
1625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return 1;
1637c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
1647c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
1657c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Collect statistics and deduce probabilities for next coding pass.
1667c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Return the total bit-cost for coding the probability updates.
1675a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int CalcTokenProba(int nb, int total) {
1685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  assert(nb <= total);
1695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return nb ? (255 - nb * 255 / total) : 255;
1705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
1715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
1725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Cost of coding 'nb' 1's and 'total-nb' 0's using 'proba' probability.
1735a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int BranchCost(int nb, int total, int proba) {
1745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return nb * VP8BitCost(1, proba) + (total - nb) * VP8BitCost(0, proba);
1757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
1767c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
1777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic int FinalizeTokenProbas(VP8Encoder* const enc) {
1787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8Proba* const proba = &enc->proba_;
1795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int has_changed = 0;
1807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int size = 0;
1817c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int t, b, c, p;
1827c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  for (t = 0; t < NUM_TYPES; ++t) {
1837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    for (b = 0; b < NUM_BANDS; ++b) {
1847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      for (c = 0; c < NUM_CTX; ++c) {
1857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        for (p = 0; p < NUM_PROBAS; ++p) {
1865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          const proba_t stats = proba->stats_[t][b][c][p];
1875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          const int nb = (stats >> 0) & 0xffff;
1885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          const int total = (stats >> 16) & 0xffff;
1897c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          const int update_proba = VP8CoeffsUpdateProba[t][b][c][p];
1907c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          const int old_p = VP8CoeffsProba0[t][b][c][p];
1915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          const int new_p = CalcTokenProba(nb, total);
1925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          const int old_cost = BranchCost(nb, total, old_p)
1935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                             + VP8BitCost(0, update_proba);
1945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          const int new_cost = BranchCost(nb, total, new_p)
1955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                             + VP8BitCost(1, update_proba)
1965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                             + 8 * 256;
1977c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          const int use_new_p = (old_cost > new_cost);
1987c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          size += VP8BitCost(use_new_p, update_proba);
1997c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          if (use_new_p) {  // only use proba that seem meaningful enough.
2007c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora            proba->coeffs_[t][b][c][p] = new_p;
2015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora            has_changed |= (new_p != old_p);
2027c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora            size += 8 * 256;
2037c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          } else {
2047c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora            proba->coeffs_[t][b][c][p] = old_p;
2057c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          }
2067c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        }
2077c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      }
2087c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
2097c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
2105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  proba->dirty_ = has_changed;
2117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  return size;
2127c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
2137c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
2157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// helper functions for residuals struct VP8Residual.
2167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void InitResidual(int first, int coeff_type,
2187c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora                         VP8Encoder* const enc, VP8Residual* const res) {
2197c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  res->coeff_type = coeff_type;
2207c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  res->prob  = enc->proba_.coeffs_[coeff_type];
2217c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  res->stats = enc->proba_.stats_[coeff_type];
2227c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  res->cost  = enc->proba_.level_cost_[coeff_type];
2237c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  res->first = first;
2247c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
2257c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2267c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void SetResidualCoeffs(const int16_t* const coeffs,
2277c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora                              VP8Residual* const res) {
2287c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int n;
2297c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  res->last = -1;
2307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  for (n = 15; n >= res->first; --n) {
2317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    if (coeffs[n]) {
2327c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      res->last = n;
2337c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      break;
2347c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
2357c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
2367c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  res->coeffs = coeffs;
2377c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
2387c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
2407c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Mode costs
2417c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2427c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic int GetResidualCost(int ctx, const VP8Residual* const res) {
2437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int n = res->first;
2445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int p0 = res->prob[VP8EncBands[n]][ctx][0];
2455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint16_t* t = res->cost[VP8EncBands[n]][ctx];
2467c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int cost;
2477c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2487c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (res->last < 0) {
2495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    return VP8BitCost(0, p0);
2507c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
2515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  cost = 0;
2527c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  while (n <= res->last) {
2535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int v = res->coeffs[n];
2545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int b = VP8EncBands[n + 1];
2555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    ++n;
2567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    if (v == 0) {
2575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      // short-case for VP8LevelCost(t, 0) (note: VP8LevelFixedCosts[0] == 0):
2585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      cost += t[0];
2595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      t = res->cost[b][0];
2607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      continue;
2615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
2625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    cost += VP8BitCost(1, p0);
2635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if (2u >= (unsigned int)(v + 1)) {   // v = -1 or 1
2645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      // short-case for "VP8LevelCost(t, 1)" (256 is VP8LevelFixedCosts[1]):
2655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      cost += 256 + t[1];
2665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      p0 = res->prob[b][1][0];
2675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      t = res->cost[b][1];
2687c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    } else {
269466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora      cost += VP8LevelCost(t, abs(v));
2705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      p0 = res->prob[b][2][0];
2715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      t = res->cost[b][2];
2727c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
2737c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
2745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (n < 16) cost += VP8BitCost(0, p0);
2757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  return cost;
2767c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
2777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroraint VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]) {
2797c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const int x = (it->i4_ & 3), y = (it->i4_ >> 2);
2807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8Residual res;
2815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  VP8Encoder* const enc = it->enc_;
2827c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int R = 0;
2837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int ctx;
2847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  InitResidual(0, 3, enc, &res);
2867c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  ctx = it->top_nz_[x] + it->left_nz_[y];
2877c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  SetResidualCoeffs(levels, &res);
2887c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  R += GetResidualCost(ctx, &res);
2897c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  return R;
2907c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
2917c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2927c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroraint VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd) {
2937c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8Residual res;
2945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  VP8Encoder* const enc = it->enc_;
2957c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int x, y;
2967c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int R = 0;
2977c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2987c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8IteratorNzToBytes(it);   // re-import the non-zero context
2997c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3007c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // DC
3015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  InitResidual(0, 1, enc, &res);
3027c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  SetResidualCoeffs(rd->y_dc_levels, &res);
3037c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  R += GetResidualCost(it->top_nz_[8] + it->left_nz_[8], &res);
3047c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3057c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // AC
3065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  InitResidual(1, 0, enc, &res);
3077c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  for (y = 0; y < 4; ++y) {
3087c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    for (x = 0; x < 4; ++x) {
3097c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      const int ctx = it->top_nz_[x] + it->left_nz_[y];
3107c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
3117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      R += GetResidualCost(ctx, &res);
3127c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      it->top_nz_[x] = it->left_nz_[y] = (res.last >= 0);
3137c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
3147c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
3157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  return R;
3167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
3177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3187c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroraint VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd) {
3197c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8Residual res;
3205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  VP8Encoder* const enc = it->enc_;
3217c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int ch, x, y;
3227c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int R = 0;
3237c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3247c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8IteratorNzToBytes(it);  // re-import the non-zero context
3257c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  InitResidual(0, 2, enc, &res);
3277c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  for (ch = 0; ch <= 2; ch += 2) {
3287c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    for (y = 0; y < 2; ++y) {
3297c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      for (x = 0; x < 2; ++x) {
3307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
3317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
3327c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        R += GetResidualCost(ctx, &res);
3337c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = (res.last >= 0);
3347c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      }
3357c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
3367c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
3377c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  return R;
3387c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
3397c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
3417c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Coefficient coding
3427c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) {
3447c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int n = res->first;
3457c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const uint8_t* p = res->prob[VP8EncBands[n]][ctx];
3467c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (!VP8PutBit(bw, res->last >= 0, p[0])) {
3477c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    return 0;
3487c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
3497c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3507c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  while (n < 16) {
3517c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    const int c = res->coeffs[n++];
3527c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    const int sign = c < 0;
3537c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    int v = sign ? -c : c;
3547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    if (!VP8PutBit(bw, v != 0, p[1])) {
3557c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      p = res->prob[VP8EncBands[n]][0];
3567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      continue;
3577c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
3587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    if (!VP8PutBit(bw, v > 1, p[2])) {
3597c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      p = res->prob[VP8EncBands[n]][1];
3607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    } else {
3617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      if (!VP8PutBit(bw, v > 4, p[3])) {
3627c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        if (VP8PutBit(bw, v != 2, p[4]))
3637c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          VP8PutBit(bw, v == 4, p[5]);
3647c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      } else if (!VP8PutBit(bw, v > 10, p[6])) {
3657c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        if (!VP8PutBit(bw, v > 6, p[7])) {
3667c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          VP8PutBit(bw, v == 6, 159);
3677c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        } else {
3687c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          VP8PutBit(bw, v >= 9, 165);
3697c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          VP8PutBit(bw, !(v & 1), 145);
3707c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        }
3717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      } else {
3727c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        int mask;
3737c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        const uint8_t* tab;
3747c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        if (v < 3 + (8 << 1)) {          // kCat3  (3b)
3757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          VP8PutBit(bw, 0, p[8]);
3767c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          VP8PutBit(bw, 0, p[9]);
3777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          v -= 3 + (8 << 0);
3787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          mask = 1 << 2;
3797c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          tab = kCat3;
3807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        } else if (v < 3 + (8 << 2)) {   // kCat4  (4b)
3817c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          VP8PutBit(bw, 0, p[8]);
3827c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          VP8PutBit(bw, 1, p[9]);
3837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          v -= 3 + (8 << 1);
3847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          mask = 1 << 3;
3857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          tab = kCat4;
3867c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        } else if (v < 3 + (8 << 3)) {   // kCat5  (5b)
3877c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          VP8PutBit(bw, 1, p[8]);
3887c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          VP8PutBit(bw, 0, p[10]);
3897c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          v -= 3 + (8 << 2);
3907c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          mask = 1 << 4;
3917c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          tab = kCat5;
3927c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        } else {                         // kCat6 (11b)
3937c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          VP8PutBit(bw, 1, p[8]);
3947c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          VP8PutBit(bw, 1, p[10]);
3957c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          v -= 3 + (8 << 3);
3967c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          mask = 1 << 10;
3977c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          tab = kCat6;
3987c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        }
3997c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        while (mask) {
4007c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          VP8PutBit(bw, !!(v & mask), *tab++);
4017c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora          mask >>= 1;
4027c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        }
4037c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      }
4047c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      p = res->prob[VP8EncBands[n]][2];
4057c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
4067c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    VP8PutBitUniform(bw, sign);
4077c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    if (n == 16 || !VP8PutBit(bw, n <= res->last, p[0])) {
4087c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      return 1;   // EOB
4097c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
4107c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
4117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  return 1;
4127c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
4137c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
4147c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void CodeResiduals(VP8BitWriter* const bw,
4157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora                          VP8EncIterator* const it,
4167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora                          const VP8ModeScore* const rd) {
4177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int x, y, ch;
4187c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8Residual res;
4197c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  uint64_t pos1, pos2, pos3;
4207c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const int i16 = (it->mb_->type_ == 1);
4217c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const int segment = it->mb_->segment_;
4225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  VP8Encoder* const enc = it->enc_;
4237c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
4247c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8IteratorNzToBytes(it);
4257c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
4267c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  pos1 = VP8BitWriterPos(bw);
4277c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (i16) {
4285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    InitResidual(0, 1, enc, &res);
4297c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    SetResidualCoeffs(rd->y_dc_levels, &res);
4307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    it->top_nz_[8] = it->left_nz_[8] =
4317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      PutCoeffs(bw, it->top_nz_[8] + it->left_nz_[8], &res);
4325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    InitResidual(1, 0, enc, &res);
4337c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  } else {
4345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    InitResidual(0, 3, enc, &res);
4357c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
4367c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
4377c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // luma-AC
4387c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  for (y = 0; y < 4; ++y) {
4397c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    for (x = 0; x < 4; ++x) {
4407c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      const int ctx = it->top_nz_[x] + it->left_nz_[y];
4417c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
4427c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      it->top_nz_[x] = it->left_nz_[y] = PutCoeffs(bw, ctx, &res);
4437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
4447c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
4457c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  pos2 = VP8BitWriterPos(bw);
4467c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
4477c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // U/V
4485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  InitResidual(0, 2, enc, &res);
4497c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  for (ch = 0; ch <= 2; ch += 2) {
4507c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    for (y = 0; y < 2; ++y) {
4517c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      for (x = 0; x < 2; ++x) {
4527c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
4537c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
4547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
4557c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora            PutCoeffs(bw, ctx, &res);
4567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      }
4577c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
4587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
4597c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  pos3 = VP8BitWriterPos(bw);
4607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->luma_bits_ = pos2 - pos1;
4617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->uv_bits_ = pos3 - pos2;
4627c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->bit_count_[segment][i16] += it->luma_bits_;
4637c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->bit_count_[segment][2] += it->uv_bits_;
4647c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8IteratorBytesToNz(it);
4657c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
4667c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
4677c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Same as CodeResiduals, but doesn't actually write anything.
4687c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Instead, it just records the event distribution.
4697c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void RecordResiduals(VP8EncIterator* const it,
4707c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora                            const VP8ModeScore* const rd) {
4717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int x, y, ch;
4727c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8Residual res;
4735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  VP8Encoder* const enc = it->enc_;
4747c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
4757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8IteratorNzToBytes(it);
4767c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
4777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (it->mb_->type_ == 1) {   // i16x16
4785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    InitResidual(0, 1, enc, &res);
4797c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    SetResidualCoeffs(rd->y_dc_levels, &res);
4807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    it->top_nz_[8] = it->left_nz_[8] =
4817c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res);
4825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    InitResidual(1, 0, enc, &res);
4837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  } else {
4845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    InitResidual(0, 3, enc, &res);
4857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
4867c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
4877c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // luma-AC
4887c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  for (y = 0; y < 4; ++y) {
4897c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    for (x = 0; x < 4; ++x) {
4907c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      const int ctx = it->top_nz_[x] + it->left_nz_[y];
4917c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
4927c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      it->top_nz_[x] = it->left_nz_[y] = RecordCoeffs(ctx, &res);
4937c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
4947c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
4957c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
4967c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // U/V
4975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  InitResidual(0, 2, enc, &res);
4987c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  for (ch = 0; ch <= 2; ch += 2) {
4997c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    for (y = 0; y < 2; ++y) {
5007c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      for (x = 0; x < 2; ++x) {
5017c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
5027c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
5037c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
5047c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora            RecordCoeffs(ctx, &res);
5057c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      }
5067c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
5077c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
5087c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
5097c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8IteratorBytesToNz(it);
5107c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
5117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
5125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
5135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Token buffer
5145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
5155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#ifdef USE_TOKEN_BUFFER
5165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
5175a50414796e9a458925c7a13a15055d02406bf43Vikas Aroravoid VP8TBufferInit(VP8TBuffer* const b) {
5185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  b->rows_ = NULL;
5195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  b->tokens_ = NULL;
5205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  b->last_ = &b->rows_;
5215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  b->left_ = 0;
5225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  b->error_ = 0;
5235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
5245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
5255a50414796e9a458925c7a13a15055d02406bf43Vikas Aroraint VP8TBufferNewPage(VP8TBuffer* const b) {
5265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  VP8Tokens* const page = b->error_ ? NULL : (VP8Tokens*)malloc(sizeof(*page));
5275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (page == NULL) {
5285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    b->error_ = 1;
5295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    return 0;
5305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
5315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  *b->last_ = page;
5325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  b->last_ = &page->next_;
5335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  b->left_ = MAX_NUM_TOKEN;
5345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  b->tokens_ = page->tokens_;
5355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return 1;
5365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
5375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
5385a50414796e9a458925c7a13a15055d02406bf43Vikas Aroravoid VP8TBufferClear(VP8TBuffer* const b) {
5395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (b != NULL) {
5405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const VP8Tokens* p = b->rows_;
5415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    while (p != NULL) {
5425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      const VP8Tokens* const next = p->next_;
5435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      free((void*)p);
5445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      p = next;
5455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
5465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    VP8TBufferInit(b);
5475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
5485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
5495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
5505a50414796e9a458925c7a13a15055d02406bf43Vikas Aroraint VP8EmitTokens(const VP8TBuffer* const b, VP8BitWriter* const bw,
5515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                  const uint8_t* const probas) {
5525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  VP8Tokens* p = b->rows_;
5535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (b->error_) return 0;
5545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  while (p != NULL) {
5555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int N = (p->next_ == NULL) ? b->left_ : 0;
5565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int n = MAX_NUM_TOKEN;
5575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    while (n-- > N) {
5585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      VP8PutBit(bw, (p->tokens_[n] >> 15) & 1, probas[p->tokens_[n] & 0x7fff]);
5595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
5605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    p = p->next_;
5615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
5625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return 1;
5635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
5645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
5655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#define TOKEN_ID(b, ctx, p) ((p) + NUM_PROBAS * ((ctx) + (b) * NUM_CTX))
5665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
5675a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int RecordCoeffTokens(int ctx, const VP8Residual* const res,
5685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                             VP8TBuffer* tokens) {
5695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int n = res->first;
5705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int b = VP8EncBands[n];
5715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (!VP8AddToken(tokens, res->last >= 0, TOKEN_ID(b, ctx, 0))) {
5725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    return 0;
5735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
5745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
5755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  while (n < 16) {
5765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int c = res->coeffs[n++];
5775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int sign = c < 0;
5785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int v = sign ? -c : c;
5795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int base_id = TOKEN_ID(b, ctx, 0);
5805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if (!VP8AddToken(tokens, v != 0, base_id + 1)) {
5815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      b = VP8EncBands[n];
5825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      ctx = 0;
5835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      continue;
5845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
5855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if (!VP8AddToken(tokens, v > 1, base_id + 2)) {
5865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      b = VP8EncBands[n];
5875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      ctx = 1;
5885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    } else {
5895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (!VP8AddToken(tokens, v > 4, base_id + 3)) {
5905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        if (VP8AddToken(tokens, v != 2, base_id + 4))
5915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          VP8AddToken(tokens, v == 4, base_id + 5);
5925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      } else if (!VP8AddToken(tokens, v > 10, base_id + 6)) {
5935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        if (!VP8AddToken(tokens, v > 6, base_id + 7)) {
5945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//          VP8AddToken(tokens, v == 6, 159);
5955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        } else {
5965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//          VP8AddToken(tokens, v >= 9, 165);
5975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//          VP8AddToken(tokens, !(v & 1), 145);
5985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        }
5995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      } else {
6005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        int mask;
6015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        const uint8_t* tab;
6025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        if (v < 3 + (8 << 1)) {          // kCat3  (3b)
6035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          VP8AddToken(tokens, 0, base_id + 8);
6045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          VP8AddToken(tokens, 0, base_id + 9);
6055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          v -= 3 + (8 << 0);
6065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          mask = 1 << 2;
6075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          tab = kCat3;
6085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        } else if (v < 3 + (8 << 2)) {   // kCat4  (4b)
6095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          VP8AddToken(tokens, 0, base_id + 8);
6105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          VP8AddToken(tokens, 1, base_id + 9);
6115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          v -= 3 + (8 << 1);
6125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          mask = 1 << 3;
6135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          tab = kCat4;
6145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        } else if (v < 3 + (8 << 3)) {   // kCat5  (5b)
6155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          VP8AddToken(tokens, 1, base_id + 8);
6165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          VP8AddToken(tokens, 0, base_id + 10);
6175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          v -= 3 + (8 << 2);
6185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          mask = 1 << 4;
6195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          tab = kCat5;
6205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        } else {                         // kCat6 (11b)
6215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          VP8AddToken(tokens, 1, base_id + 8);
6225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          VP8AddToken(tokens, 1, base_id + 10);
6235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          v -= 3 + (8 << 3);
6245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          mask = 1 << 10;
6255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          tab = kCat6;
6265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        }
6275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        while (mask) {
6285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          // VP8AddToken(tokens, !!(v & mask), *tab++);
6295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          mask >>= 1;
6305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        }
6315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
6325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      ctx = 2;
6335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
6345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    b = VP8EncBands[n];
6355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    // VP8PutBitUniform(bw, sign);
6365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if (n == 16 || !VP8AddToken(tokens, n <= res->last, TOKEN_ID(b, ctx, 0))) {
6375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      return 1;   // EOB
6385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
6395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
6405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return 1;
6415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
6425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
6435a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void RecordTokens(VP8EncIterator* const it,
6445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                         const VP8ModeScore* const rd, VP8TBuffer tokens[2]) {
6455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int x, y, ch;
6465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  VP8Residual res;
6475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  VP8Encoder* const enc = it->enc_;
6485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
6495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  VP8IteratorNzToBytes(it);
6505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (it->mb_->type_ == 1) {   // i16x16
6515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    InitResidual(0, 1, enc, &res);
6525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    SetResidualCoeffs(rd->y_dc_levels, &res);
6535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// TODO(skal): FIX ->    it->top_nz_[8] = it->left_nz_[8] =
6545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      RecordCoeffTokens(it->top_nz_[8] + it->left_nz_[8], &res, &tokens[0]);
6555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    InitResidual(1, 0, enc, &res);
6565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  } else {
6575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    InitResidual(0, 3, enc, &res);
6585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
6595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
6605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  // luma-AC
6615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (y = 0; y < 4; ++y) {
6625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (x = 0; x < 4; ++x) {
6635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      const int ctx = it->top_nz_[x] + it->left_nz_[y];
6645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
6655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      it->top_nz_[x] = it->left_nz_[y] =
6665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          RecordCoeffTokens(ctx, &res, &tokens[0]);
6675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
6685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
6695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
6705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  // U/V
6715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  InitResidual(0, 2, enc, &res);
6725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (ch = 0; ch <= 2; ch += 2) {
6735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (y = 0; y < 2; ++y) {
6745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      for (x = 0; x < 2; ++x) {
6755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
6765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
6775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
6785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora            RecordCoeffTokens(ctx, &res, &tokens[1]);
6795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
6805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
6815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
6825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
6835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
6845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#endif    // USE_TOKEN_BUFFER
6855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
6865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
6877c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// ExtraInfo map / Debug function
6887c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
6897c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#if SEGMENT_VISU
6907c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void SetBlock(uint8_t* p, int value, int size) {
6917c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int y;
6927c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  for (y = 0; y < size; ++y) {
6937c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    memset(p, value, size);
6947c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    p += BPS;
6957c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
6967c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
6977c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#endif
6987c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
6997c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void ResetSSE(VP8Encoder* const enc) {
7007c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  memset(enc->sse_, 0, sizeof(enc->sse_));
7017c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  enc->sse_count_ = 0;
7027c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
7037c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
7047c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void StoreSSE(const VP8EncIterator* const it) {
7057c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8Encoder* const enc = it->enc_;
7067c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const uint8_t* const in = it->yuv_in_;
7077c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const uint8_t* const out = it->yuv_out_;
7087c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // Note: not totally accurate at boundary. And doesn't include in-loop filter.
7097c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  enc->sse_[0] += VP8SSE16x16(in + Y_OFF, out + Y_OFF);
7107c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  enc->sse_[1] += VP8SSE8x8(in + U_OFF, out + U_OFF);
7117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  enc->sse_[2] += VP8SSE8x8(in + V_OFF, out + V_OFF);
7127c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  enc->sse_count_ += 16 * 16;
7137c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
7147c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
7157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void StoreSideInfo(const VP8EncIterator* const it) {
7167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8Encoder* const enc = it->enc_;
7177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const VP8MBInfo* const mb = it->mb_;
7187c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  WebPPicture* const pic = enc->pic_;
7197c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
7205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (pic->stats != NULL) {
7217c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    StoreSSE(it);
7227c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    enc->block_count_[0] += (mb->type_ == 0);
7237c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    enc->block_count_[1] += (mb->type_ == 1);
7247c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    enc->block_count_[2] += (mb->skip_ != 0);
7257c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
7267c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
7275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (pic->extra_info != NULL) {
7287c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    uint8_t* const info = &pic->extra_info[it->x_ + it->y_ * enc->mb_w_];
7295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    switch (pic->extra_info_type) {
7307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      case 1: *info = mb->type_; break;
7317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      case 2: *info = mb->segment_; break;
7327c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      case 3: *info = enc->dqm_[mb->segment_].quant_; break;
7337c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      case 4: *info = (mb->type_ == 1) ? it->preds_[0] : 0xff; break;
7347c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      case 5: *info = mb->uv_mode_; break;
7357c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      case 6: {
7367c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3);
7377c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        *info = (b > 255) ? 255 : b; break;
7387c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      }
7397c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      default: *info = 0; break;
7407c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    };
7417c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
7427c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#if SEGMENT_VISU  // visualize segments and prediction modes
7437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  SetBlock(it->yuv_out_ + Y_OFF, mb->segment_ * 64, 16);
7447c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  SetBlock(it->yuv_out_ + U_OFF, it->preds_[0] * 64, 8);
7457c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  SetBlock(it->yuv_out_ + V_OFF, mb->uv_mode_ * 64, 8);
7467c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#endif
7477c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
7487c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
7495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
7507c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Main loops
7517c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//
7527c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  VP8EncLoop(): does the final bitstream coding.
7537c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
7547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void ResetAfterSkip(VP8EncIterator* const it) {
7557c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (it->mb_->type_ == 1) {
7567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    *it->nz_ = 0;  // reset all predictors
7577c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    it->left_nz_[8] = 0;
7587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  } else {
7597c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    *it->nz_ &= (1 << 24);  // preserve the dc_nz bit
7607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
7617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
7627c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
7637c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroraint VP8EncLoop(VP8Encoder* const enc) {
7647c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int i, s, p;
7655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int ok = 1;
7667c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8EncIterator it;
7677c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8ModeScore info;
7687c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const int dont_use_skip = !enc->proba_.use_skip_proba_;
7697c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const int rd_opt = enc->rd_opt_level_;
7707c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const int kAverageBytesPerMB = 5;     // TODO: have a kTable[quality/10]
7717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const int bytes_per_parts =
7727c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    enc->mb_w_ * enc->mb_h_ * kAverageBytesPerMB / enc->num_parts_;
7737c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
7747c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // Initialize the bit-writers
7757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  for (p = 0; p < enc->num_parts_; ++p) {
7767c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    VP8BitWriterInit(enc->parts_ + p, bytes_per_parts);
7777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
7787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
7795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  ResetStats(enc);
7807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  ResetSSE(enc);
7817c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
7827c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8IteratorInit(enc, &it);
7837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8InitFilter(&it);
7847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  do {
7857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    VP8IteratorImport(&it);
7867c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    // Warning! order is important: first call VP8Decimate() and
7877c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    // *then* decide how to code the skip decision if there's one.
7887c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) {
7897c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      CodeResiduals(it.bw_, &it, &info);
7907c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    } else {   // reset predictors after a skip
7917c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      ResetAfterSkip(&it);
7927c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
793466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#ifdef WEBP_EXPERIMENTAL_FEATURES
794466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    if (enc->use_layer_) {
795466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora      VP8EncCodeLayerBlock(&it);
796466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    }
797466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#endif
7987c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    StoreSideInfo(&it);
7997c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    VP8StoreFilterStats(&it);
8007c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    VP8IteratorExport(&it);
8015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    ok = VP8IteratorProgress(&it, 20);
8025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  } while (ok && VP8IteratorNext(&it, it.yuv_out_));
8037c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
8045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (ok) {      // Finalize the partitions, check for extra errors.
8055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (p = 0; p < enc->num_parts_; ++p) {
8065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      VP8BitWriterFinish(enc->parts_ + p);
8075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      ok &= !enc->parts_[p].error_;
8085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
8097c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
8105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
8115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (ok) {      // All good. Finish up.
8125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if (enc->pic_->stats) {           // finalize byte counters...
8135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      for (i = 0; i <= 2; ++i) {
8145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
8155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          enc->residual_bytes_[i][s] = (int)((it.bit_count_[s][i] + 7) >> 3);
8165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        }
8177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      }
8187c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
8195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    VP8AdjustFilterStrength(&it);     // ...and store filter stats.
8205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  } else {
8215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    // Something bad happened -> need to do some memory cleanup.
8225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    VP8EncFreeBitWriters(enc);
8237c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
8245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
8255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return ok;
8267c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
8277c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
8285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
8297c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  VP8StatLoop(): only collect statistics (number of skips, token usage, ...)
8307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//                 This is used for deciding optimal probabilities. It also
8317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//                 modifies the quantizer value if some target (size, PNSR)
8327c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//                 was specified.
8337c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
8347c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#define kHeaderSizeEstimate (15 + 20 + 10)      // TODO: fix better
8357c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
8367c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic int OneStatPass(VP8Encoder* const enc, float q, int rd_opt, int nb_mbs,
8375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                       float* const PSNR, int percent_delta) {
8387c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8EncIterator it;
8397c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  uint64_t size = 0;
8407c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  uint64_t distortion = 0;
8417c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const uint64_t pixel_count = nb_mbs * 384;
8427c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
8437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // Make sure the quality parameter is inside valid bounds
8447c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (q < 0.) {
8457c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    q = 0;
8467c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  } else if (q > 100.) {
8477c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    q = 100;
8487c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
8497c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
8507c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8SetSegmentParams(enc, q);      // setup segment quantizations and filters
8517c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
8525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  ResetStats(enc);
8537c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  ResetTokenStats(enc);
8547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
8557c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8IteratorInit(enc, &it);
8567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  do {
8577c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    VP8ModeScore info;
8587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    VP8IteratorImport(&it);
8597c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    if (VP8Decimate(&it, &info, rd_opt)) {
8607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      // Just record the number of skips and act like skip_proba is not used.
8617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      enc->proba_.nb_skip_++;
8627c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
8637c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    RecordResiduals(&it, &info);
8647c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    size += info.R;
8657c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    distortion += info.D;
8665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if (percent_delta && !VP8IteratorProgress(&it, percent_delta))
8675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      return 0;
8687c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  } while (VP8IteratorNext(&it, it.yuv_out_) && --nb_mbs > 0);
8697c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  size += FinalizeSkipProba(enc);
8707c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  size += FinalizeTokenProbas(enc);
8717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  size += enc->segment_hdr_.size_;
8727c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  size = ((size + 1024) >> 11) + kHeaderSizeEstimate;
8737c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
8747c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (PSNR) {
8757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    *PSNR = (float)(10.* log10(255. * 255. * pixel_count / distortion));
8767c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
8777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  return (int)size;
8787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
8797c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
8807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// successive refinement increments.
8817c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic const int dqs[] = { 20, 15, 10, 8, 6, 4, 2, 1, 0 };
8827c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
8837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroraint VP8StatLoop(VP8Encoder* const enc) {
8847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const int do_search =
8857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    (enc->config_->target_size > 0 || enc->config_->target_PSNR > 0);
8867c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const int fast_probe = (enc->method_ < 2 && !do_search);
8877c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  float q = enc->config_->quality;
8885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int max_passes = enc->config_->pass;
8895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int task_percent = 20;
8905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int percent_per_pass = (task_percent + max_passes / 2) / max_passes;
8915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int final_percent = enc->percent_ + task_percent;
8927c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int pass;
8937c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int nb_mbs;
8947c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
8957c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // Fast mode: quick analysis pass over few mbs. Better than nothing.
8967c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  nb_mbs = enc->mb_w_ * enc->mb_h_;
8977c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (fast_probe && nb_mbs > 100) nb_mbs = 100;
8987c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
8997c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // No target size: just do several pass without changing 'q'
9007c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (!do_search) {
9015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (pass = 0; pass < max_passes; ++pass) {
9027c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      const int rd_opt = (enc->method_ > 2);
9035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (!OneStatPass(enc, q, rd_opt, nb_mbs, NULL, percent_per_pass)) {
9045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        return 0;
9055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
9067c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
9075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  } else {
9085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    // binary search for a size close to target
9095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (pass = 0; pass < max_passes && (dqs[pass] > 0); ++pass) {
9105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      const int rd_opt = 1;
9115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      float PSNR;
9125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      int criterion;
9135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      const int size = OneStatPass(enc, q, rd_opt, nb_mbs, &PSNR,
9145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                   percent_per_pass);
9157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#if DEBUG_SEARCH
9165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      printf("#%d size=%d PSNR=%.2f q=%.2f\n", pass, size, PSNR, q);
9177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#endif
9185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (!size) return 0;
9195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (enc->config_->target_PSNR > 0) {
9205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        criterion = (PSNR < enc->config_->target_PSNR);
9215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      } else {
9225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        criterion = (size < enc->config_->target_size);
9235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
9245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      // dichotomize
9255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (criterion) {
9265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        q += dqs[pass];
9275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      } else {
9285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        q -= dqs[pass];
9295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
9307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
9317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
9325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return WebPReportProgress(enc->pic_, final_percent, &enc->percent_);
9337c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
9347c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
9355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
9367c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
9377c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#if defined(__cplusplus) || defined(c_plusplus)
9387c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}    // extern "C"
9397c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#endif
940