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