1a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Copyright 2011 Google Inc. All Rights Reserved. 27c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 30406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Use of this source code is governed by a BSD-style license 40406ce1417f76f2034833414dcecc9f56253640cVikas Arora// that can be found in the COPYING file in the root of the source 50406ce1417f76f2034833414dcecc9f56253640cVikas Arora// tree. An additional intellectual property rights grant can be found 60406ce1417f76f2034833414dcecc9f56253640cVikas Arora// in the file PATENTS. All contributing project authors may 70406ce1417f76f2034833414dcecc9f56253640cVikas Arora// be found in the AUTHORS file in the root of the source tree. 87c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// ----------------------------------------------------------------------------- 97c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 107c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// frame coding and analysis 117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 127c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Author: Skal (pascal.massimino@gmail.com) 137c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 147c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#include <string.h> 157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#include <math.h> 167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 17a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "./vp8enci.h" 18a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "./cost.h" 198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#include "webp/format_constants.h" // RIFF constants 207c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 217c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#define SEGMENT_VISU 0 227c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#define DEBUG_SEARCH 0 // useful to track search convergence 237c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 24a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// multi-pass convergence 268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#define HEADER_SIZE_ESTIMATE (RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + \ 288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8_FRAME_HEADER_SIZE) 298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#define DQ_LIMIT 0.4 // convergence is considered reached if dq < DQ_LIMIT 308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// we allow 2k of extra head-room in PARTITION0 limit. 318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#define PARTITION0_SIZE_LIMIT ((VP8_MAX_PARTITION0_SIZE - 2048ULL) << 11) 328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 338b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroratypedef struct { // struct for organizing convergence in either size or PSNR 348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int is_first; 358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora float dq; 368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora float q, last_q; 378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora double value, last_value; // PSNR or size 388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora double target; 398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int do_size_search; 408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} PassStats; 418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int InitPassStats(const VP8Encoder* const enc, PassStats* const s) { 438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint64_t target_size = (uint64_t)enc->config_->target_size; 448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int do_size_search = (target_size != 0); 458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const float target_PSNR = enc->config_->target_PSNR; 468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora s->is_first = 1; 488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora s->dq = 10.f; 498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora s->q = s->last_q = enc->config_->quality; 508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora s->target = do_size_search ? (double)target_size 518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora : (target_PSNR > 0.) ? target_PSNR 528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora : 40.; // default, just in case 538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora s->value = s->last_value = 0.; 548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora s->do_size_search = do_size_search; 558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return do_size_search; 568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic float Clamp(float v, float min, float max) { 598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return (v < min) ? min : (v > max) ? max : v; 608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic float ComputeNextQ(PassStats* const s) { 638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora float dq; 648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (s->is_first) { 658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dq = (s->value > s->target) ? -s->dq : s->dq; 668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora s->is_first = 0; 678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else if (s->value != s->last_value) { 688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const double slope = (s->target - s->value) / (s->last_value - s->value); 698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dq = (float)(slope * (s->last_q - s->q)); 708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { 718b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dq = 0.; // we're done?! 728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Limit variable to avoid large swings. 748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora s->dq = Clamp(dq, -30.f, 30.f); 758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora s->last_q = s->q; 768b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora s->last_value = s->value; 778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora s->q = Clamp(s->q + s->dq, 0.f, 100.f); 788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return s->q; 798b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora//------------------------------------------------------------------------------ 827c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Tables for level coding 837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroraconst uint8_t VP8EncBands[16 + 1] = { 857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 867c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 0 // sentinel 877c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}; 887c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 891e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroraconst uint8_t VP8Cat3[] = { 173, 148, 140 }; 901e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroraconst uint8_t VP8Cat4[] = { 176, 155, 140, 135 }; 911e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroraconst uint8_t VP8Cat5[] = { 180, 157, 141, 134, 130 }; 921e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroraconst uint8_t VP8Cat6[] = 937c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 }; 947c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 95a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 967c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Reset the statistics about: number of skips, token proba, level cost,... 977c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 98a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ResetStats(VP8Encoder* const enc) { 997c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8Proba* const proba = &enc->proba_; 100a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8CalculateLevelCosts(proba); 1017c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora proba->nb_skip_ = 0; 1027c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 1037c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 104a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 1057c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Skip decision probability 1067c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 107a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define SKIP_PROBA_THRESHOLD 250 // value below which using skip_proba is OK. 108a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1097c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic int CalcSkipProba(uint64_t nb, uint64_t total) { 1107c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora return (int)(total ? (total - nb) * 255 / total : 255); 1117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 1127c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 1137c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Returns the bit-cost for coding the skip probability. 1147c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic int FinalizeSkipProba(VP8Encoder* const enc) { 1157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8Proba* const proba = &enc->proba_; 1167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int nb_mbs = enc->mb_w_ * enc->mb_h_; 1177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int nb_events = proba->nb_skip_; 1187c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora int size; 1197c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora proba->skip_proba_ = CalcSkipProba(nb_events, nb_mbs); 120a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora proba->use_skip_proba_ = (proba->skip_proba_ < SKIP_PROBA_THRESHOLD); 1217c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora size = 256; // 'use_skip_proba' bit 1227c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora if (proba->use_skip_proba_) { 1237c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora size += nb_events * VP8BitCost(1, proba->skip_proba_) 1247c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora + (nb_mbs - nb_events) * VP8BitCost(0, proba->skip_proba_); 1257c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora size += 8 * 256; // cost of signaling the skip_proba_ itself. 1267c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 1277c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora return size; 1287c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 1297c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 1307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Collect statistics and deduce probabilities for next coding pass. 1317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Return the total bit-cost for coding the probability updates. 132a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int CalcTokenProba(int nb, int total) { 133a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(nb <= total); 134a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return nb ? (255 - nb * 255 / total) : 255; 135a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 136a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 137a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Cost of coding 'nb' 1's and 'total-nb' 0's using 'proba' probability. 138a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int BranchCost(int nb, int total, int proba) { 139a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return nb * VP8BitCost(1, proba) + (total - nb) * VP8BitCost(0, proba); 1407c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 1417c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 142af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arorastatic void ResetTokenStats(VP8Encoder* const enc) { 143af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8Proba* const proba = &enc->proba_; 144af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora memset(proba->stats_, 0, sizeof(proba->stats_)); 145af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora} 146af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora 1471e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic int FinalizeTokenProbas(VP8Proba* const proba) { 148a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int has_changed = 0; 1497c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora int size = 0; 1507c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora int t, b, c, p; 1517c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (t = 0; t < NUM_TYPES; ++t) { 1527c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (b = 0; b < NUM_BANDS; ++b) { 1537c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (c = 0; c < NUM_CTX; ++c) { 1547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (p = 0; p < NUM_PROBAS; ++p) { 155a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const proba_t stats = proba->stats_[t][b][c][p]; 156a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int nb = (stats >> 0) & 0xffff; 157a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int total = (stats >> 16) & 0xffff; 1587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int update_proba = VP8CoeffsUpdateProba[t][b][c][p]; 1597c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int old_p = VP8CoeffsProba0[t][b][c][p]; 160a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int new_p = CalcTokenProba(nb, total); 161a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int old_cost = BranchCost(nb, total, old_p) 162a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora + VP8BitCost(0, update_proba); 163a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int new_cost = BranchCost(nb, total, new_p) 164a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora + VP8BitCost(1, update_proba) 165a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora + 8 * 256; 1667c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int use_new_p = (old_cost > new_cost); 1677c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora size += VP8BitCost(use_new_p, update_proba); 1687c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora if (use_new_p) { // only use proba that seem meaningful enough. 1697c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora proba->coeffs_[t][b][c][p] = new_p; 170a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora has_changed |= (new_p != old_p); 1717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora size += 8 * 256; 1727c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } else { 1737c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora proba->coeffs_[t][b][c][p] = old_p; 1747c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 1757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 1767c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 1777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 1787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 179a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora proba->dirty_ = has_changed; 1807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora return size; 1817c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 1827c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 183a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 1841e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// Finalize Segment probability based on the coding tree 1851e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1861e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic int GetProba(int a, int b) { 1871e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int total = a + b; 1881e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return (total == 0) ? 255 // that's the default probability. 1891e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora : (255 * a + total / 2) / total; // rounded proba 1901e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 1911e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1921e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic void SetSegmentProbas(VP8Encoder* const enc) { 1931e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int p[NUM_MB_SEGMENTS] = { 0 }; 1941e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int n; 1951e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1961e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { 1971e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const VP8MBInfo* const mb = &enc->mb_info_[n]; 1981e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora p[mb->segment_]++; 1991e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 2001e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (enc->pic_->stats != NULL) { 2011e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora for (n = 0; n < NUM_MB_SEGMENTS; ++n) { 2021e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora enc->pic_->stats->segment_size[n] = p[n]; 2031e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 2041e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 2051e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (enc->segment_hdr_.num_segments_ > 1) { 2061e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora uint8_t* const probas = enc->proba_.segments_; 2071e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora probas[0] = GetProba(p[0] + p[1], p[2] + p[3]); 2081e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora probas[1] = GetProba(p[0], p[1]); 2091e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora probas[2] = GetProba(p[2], p[3]); 2101e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2111e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora enc->segment_hdr_.update_map_ = 2121e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255); 2131e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora enc->segment_hdr_.size_ = 2141e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) + 2151e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) + 2161e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) + 2171e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2])); 2181e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } else { 2191e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora enc->segment_hdr_.update_map_ = 0; 2201e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora enc->segment_hdr_.size_ = 0; 2211e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 2221e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 2231e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2241e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//------------------------------------------------------------------------------ 2257c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Coefficient coding 2267c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 2277c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) { 2287c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora int n = res->first; 2291e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 2301e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const uint8_t* p = res->prob[n][ctx]; 2317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora if (!VP8PutBit(bw, res->last >= 0, p[0])) { 2327c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora return 0; 2337c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 2347c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 2357c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora while (n < 16) { 2367c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int c = res->coeffs[n++]; 2377c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int sign = c < 0; 2387c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora int v = sign ? -c : c; 2397c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora if (!VP8PutBit(bw, v != 0, p[1])) { 2407c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora p = res->prob[VP8EncBands[n]][0]; 2417c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora continue; 2427c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 2437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora if (!VP8PutBit(bw, v > 1, p[2])) { 2447c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora p = res->prob[VP8EncBands[n]][1]; 2457c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } else { 2467c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora if (!VP8PutBit(bw, v > 4, p[3])) { 2477c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora if (VP8PutBit(bw, v != 2, p[4])) 2487c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8PutBit(bw, v == 4, p[5]); 2497c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } else if (!VP8PutBit(bw, v > 10, p[6])) { 2507c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora if (!VP8PutBit(bw, v > 6, p[7])) { 2517c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8PutBit(bw, v == 6, 159); 2527c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } else { 2537c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8PutBit(bw, v >= 9, 165); 2547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8PutBit(bw, !(v & 1), 145); 2557c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 2567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } else { 2577c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora int mask; 2587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const uint8_t* tab; 2591e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (v < 3 + (8 << 1)) { // VP8Cat3 (3b) 2607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8PutBit(bw, 0, p[8]); 2617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8PutBit(bw, 0, p[9]); 2627c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora v -= 3 + (8 << 0); 2637c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mask = 1 << 2; 2641e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora tab = VP8Cat3; 2651e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } else if (v < 3 + (8 << 2)) { // VP8Cat4 (4b) 2667c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8PutBit(bw, 0, p[8]); 2677c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8PutBit(bw, 1, p[9]); 2687c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora v -= 3 + (8 << 1); 2697c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mask = 1 << 3; 2701e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora tab = VP8Cat4; 2711e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } else if (v < 3 + (8 << 3)) { // VP8Cat5 (5b) 2727c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8PutBit(bw, 1, p[8]); 2737c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8PutBit(bw, 0, p[10]); 2747c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora v -= 3 + (8 << 2); 2757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mask = 1 << 4; 2761e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora tab = VP8Cat5; 2771e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } else { // VP8Cat6 (11b) 2787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8PutBit(bw, 1, p[8]); 2797c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8PutBit(bw, 1, p[10]); 2807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora v -= 3 + (8 << 3); 2817c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mask = 1 << 10; 2821e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora tab = VP8Cat6; 2837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 2847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora while (mask) { 2857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8PutBit(bw, !!(v & mask), *tab++); 2867c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mask >>= 1; 2877c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 2887c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 2897c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora p = res->prob[VP8EncBands[n]][2]; 2907c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 2917c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8PutBitUniform(bw, sign); 2927c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora if (n == 16 || !VP8PutBit(bw, n <= res->last, p[0])) { 2937c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora return 1; // EOB 2947c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 2957c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 2967c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora return 1; 2977c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 2987c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 2991e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic void CodeResiduals(VP8BitWriter* const bw, VP8EncIterator* const it, 3007c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const VP8ModeScore* const rd) { 3017c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora int x, y, ch; 3027c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8Residual res; 3037c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora uint64_t pos1, pos2, pos3; 3047c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int i16 = (it->mb_->type_ == 1); 3057c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int segment = it->mb_->segment_; 306a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Encoder* const enc = it->enc_; 3077c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 3087c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8IteratorNzToBytes(it); 3097c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 3107c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora pos1 = VP8BitWriterPos(bw); 3117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora if (i16) { 312af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8InitResidual(0, 1, enc, &res); 313af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8SetResidualCoeffs(rd->y_dc_levels, &res); 3147c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora it->top_nz_[8] = it->left_nz_[8] = 3157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora PutCoeffs(bw, it->top_nz_[8] + it->left_nz_[8], &res); 316af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8InitResidual(1, 0, enc, &res); 3177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } else { 318af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8InitResidual(0, 3, enc, &res); 3197c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 3207c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 3217c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora // luma-AC 3227c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (y = 0; y < 4; ++y) { 3237c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (x = 0; x < 4; ++x) { 3247c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int ctx = it->top_nz_[x] + it->left_nz_[y]; 325af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); 3267c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora it->top_nz_[x] = it->left_nz_[y] = PutCoeffs(bw, ctx, &res); 3277c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 3287c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 3297c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora pos2 = VP8BitWriterPos(bw); 3307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 3317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora // U/V 332af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8InitResidual(0, 2, enc, &res); 3337c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (ch = 0; ch <= 2; ch += 2) { 3347c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (y = 0; y < 2; ++y) { 3357c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (x = 0; x < 2; ++x) { 3367c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; 337af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); 3387c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = 3397c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora PutCoeffs(bw, ctx, &res); 3407c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 3417c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 3427c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 3437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora pos3 = VP8BitWriterPos(bw); 3447c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora it->luma_bits_ = pos2 - pos1; 3457c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora it->uv_bits_ = pos3 - pos2; 3467c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora it->bit_count_[segment][i16] += it->luma_bits_; 3477c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora it->bit_count_[segment][2] += it->uv_bits_; 3487c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8IteratorBytesToNz(it); 3497c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 3507c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 3517c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Same as CodeResiduals, but doesn't actually write anything. 3527c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Instead, it just records the event distribution. 3537c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void RecordResiduals(VP8EncIterator* const it, 3547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const VP8ModeScore* const rd) { 3557c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora int x, y, ch; 3567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8Residual res; 357a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Encoder* const enc = it->enc_; 3587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 3597c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8IteratorNzToBytes(it); 3607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 3617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora if (it->mb_->type_ == 1) { // i16x16 362af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8InitResidual(0, 1, enc, &res); 363af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8SetResidualCoeffs(rd->y_dc_levels, &res); 3647c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora it->top_nz_[8] = it->left_nz_[8] = 365af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res); 366af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8InitResidual(1, 0, enc, &res); 3677c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } else { 368af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8InitResidual(0, 3, enc, &res); 3697c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 3707c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 3717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora // luma-AC 3727c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (y = 0; y < 4; ++y) { 3737c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (x = 0; x < 4; ++x) { 3747c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int ctx = it->top_nz_[x] + it->left_nz_[y]; 375af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); 376af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora it->top_nz_[x] = it->left_nz_[y] = VP8RecordCoeffs(ctx, &res); 3777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 3787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 3797c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 3807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora // U/V 381af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8InitResidual(0, 2, enc, &res); 3827c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (ch = 0; ch <= 2; ch += 2) { 3837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (y = 0; y < 2; ++y) { 3847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (x = 0; x < 2; ++x) { 3857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; 386af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); 3877c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = 388af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8RecordCoeffs(ctx, &res); 3897c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 3907c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 3917c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 3927c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 3937c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8IteratorBytesToNz(it); 3947c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 3957c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 396a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 397a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Token buffer 398a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 3991e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#if !defined(DISABLE_TOKEN_BUFFER) 400b6dbce6bfeaabde2a7b581c4c6888d532d32f3acDerek Sollenberger 401af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arorastatic int RecordTokens(VP8EncIterator* const it, const VP8ModeScore* const rd, 402af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8TBuffer* const tokens) { 403a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int x, y, ch; 404a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Residual res; 405a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Encoder* const enc = it->enc_; 406a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 407a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8IteratorNzToBytes(it); 408a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (it->mb_->type_ == 1) { // i16x16 4091e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int ctx = it->top_nz_[8] + it->left_nz_[8]; 410af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8InitResidual(0, 1, enc, &res); 411af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8SetResidualCoeffs(rd->y_dc_levels, &res); 4121e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora it->top_nz_[8] = it->left_nz_[8] = 4131e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8RecordCoeffTokens(ctx, 1, 4141e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora res.first, res.last, res.coeffs, tokens); 415af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8RecordCoeffs(ctx, &res); 416af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8InitResidual(1, 0, enc, &res); 417a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 418af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8InitResidual(0, 3, enc, &res); 419a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 420a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 421a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // luma-AC 422a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (y = 0; y < 4; ++y) { 423a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (x = 0; x < 4; ++x) { 424a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int ctx = it->top_nz_[x] + it->left_nz_[y]; 425af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); 426a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora it->top_nz_[x] = it->left_nz_[y] = 4271e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8RecordCoeffTokens(ctx, res.coeff_type, 4281e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora res.first, res.last, res.coeffs, tokens); 429af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8RecordCoeffs(ctx, &res); 430a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 431a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 432a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 433a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // U/V 434af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8InitResidual(0, 2, enc, &res); 435a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (ch = 0; ch <= 2; ch += 2) { 436a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (y = 0; y < 2; ++y) { 437a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (x = 0; x < 2; ++x) { 438a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; 439af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); 440a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = 4411e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8RecordCoeffTokens(ctx, 2, 4421e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora res.first, res.last, res.coeffs, tokens); 443af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8RecordCoeffs(ctx, &res); 444a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 445a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 446a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 4471e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8IteratorBytesToNz(it); 448af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora return !tokens->error_; 449a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 450a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 4511e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#endif // !DISABLE_TOKEN_BUFFER 452a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 453a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 4547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// ExtraInfo map / Debug function 4557c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 4567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#if SEGMENT_VISU 4577c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void SetBlock(uint8_t* p, int value, int size) { 4587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora int y; 4597c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (y = 0; y < size; ++y) { 4607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora memset(p, value, size); 4617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora p += BPS; 4627c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 4637c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 4647c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#endif 4657c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 4667c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void ResetSSE(VP8Encoder* const enc) { 4671e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora enc->sse_[0] = 0; 4681e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora enc->sse_[1] = 0; 4691e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora enc->sse_[2] = 0; 4701e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora // Note: enc->sse_[3] is managed by alpha.c 4717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->sse_count_ = 0; 4727c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 4737c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 4747c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void StoreSSE(const VP8EncIterator* const it) { 4757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8Encoder* const enc = it->enc_; 4767c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const uint8_t* const in = it->yuv_in_; 4777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const uint8_t* const out = it->yuv_out_; 4787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora // Note: not totally accurate at boundary. And doesn't include in-loop filter. 4797c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->sse_[0] += VP8SSE16x16(in + Y_OFF, out + Y_OFF); 4807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->sse_[1] += VP8SSE8x8(in + U_OFF, out + U_OFF); 4817c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->sse_[2] += VP8SSE8x8(in + V_OFF, out + V_OFF); 4827c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->sse_count_ += 16 * 16; 4837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 4847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 4857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void StoreSideInfo(const VP8EncIterator* const it) { 4867c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8Encoder* const enc = it->enc_; 4877c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const VP8MBInfo* const mb = it->mb_; 4887c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora WebPPicture* const pic = enc->pic_; 4897c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 490a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (pic->stats != NULL) { 4917c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora StoreSSE(it); 4927c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->block_count_[0] += (mb->type_ == 0); 4937c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->block_count_[1] += (mb->type_ == 1); 4947c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->block_count_[2] += (mb->skip_ != 0); 4957c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 4967c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 497a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (pic->extra_info != NULL) { 4987c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora uint8_t* const info = &pic->extra_info[it->x_ + it->y_ * enc->mb_w_]; 499a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora switch (pic->extra_info_type) { 5007c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora case 1: *info = mb->type_; break; 5017c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora case 2: *info = mb->segment_; break; 5027c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora case 3: *info = enc->dqm_[mb->segment_].quant_; break; 5037c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora case 4: *info = (mb->type_ == 1) ? it->preds_[0] : 0xff; break; 5047c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora case 5: *info = mb->uv_mode_; break; 5057c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora case 6: { 5067c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3); 5077c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora *info = (b > 255) ? 255 : b; break; 5087c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 5091e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora case 7: *info = mb->alpha_; break; 5107c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora default: *info = 0; break; 5117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora }; 5127c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 5137c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#if SEGMENT_VISU // visualize segments and prediction modes 5147c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora SetBlock(it->yuv_out_ + Y_OFF, mb->segment_ * 64, 16); 5157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora SetBlock(it->yuv_out_ + U_OFF, it->preds_[0] * 64, 8); 5167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora SetBlock(it->yuv_out_ + V_OFF, mb->uv_mode_ * 64, 8); 5177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#endif 5187c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 5197c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 5208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic double GetPSNR(uint64_t mse, uint64_t size) { 5218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return (mse > 0 && size > 0) ? 10. * log10(255. * 255. * size / mse) : 99; 5228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 5238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 524a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 5251e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// StatLoop(): only collect statistics (number of skips, token usage, ...). 5261e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// This is used for deciding optimal probabilities. It also modifies the 5278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// quantizer value if some target (size, PSNR) was specified. 5287c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 5291e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic void SetLoopParams(VP8Encoder* const enc, float q) { 5307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora // Make sure the quality parameter is inside valid bounds 5318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora q = Clamp(q, 0.f, 100.f); 5327c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 5337c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8SetSegmentParams(enc, q); // setup segment quantizations and filters 5341e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora SetSegmentProbas(enc); // compute segment probabilities 5357c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 536a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ResetStats(enc); 5371e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora ResetSSE(enc); 5381e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 5391e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 5408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic uint64_t OneStatPass(VP8Encoder* const enc, VP8RDLevel rd_opt, 5418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int nb_mbs, int percent_delta, 5428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora PassStats* const s) { 5431e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8EncIterator it; 5441e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora uint64_t size = 0; 5458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint64_t size_p0 = 0; 5461e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora uint64_t distortion = 0; 5471e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const uint64_t pixel_count = nb_mbs * 384; 5481e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 5497c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8IteratorInit(enc, &it); 5508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora SetLoopParams(enc, s->q); 5517c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora do { 5527c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8ModeScore info; 5538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8IteratorImport(&it, NULL); 5547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora if (VP8Decimate(&it, &info, rd_opt)) { 5557c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora // Just record the number of skips and act like skip_proba is not used. 5567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->proba_.nb_skip_++; 5577c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 5587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora RecordResiduals(&it, &info); 5598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora size += info.R + info.H; 5608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora size_p0 += info.H; 5617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora distortion += info.D; 562a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (percent_delta && !VP8IteratorProgress(&it, percent_delta)) 563a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 5648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8IteratorSaveBoundary(&it); 5658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } while (VP8IteratorNext(&it) && --nb_mbs > 0); 5668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 5678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora size_p0 += enc->segment_hdr_.size_; 5688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (s->do_size_search) { 5698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora size += FinalizeSkipProba(enc); 5708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora size += FinalizeTokenProbas(&enc->proba_); 5718b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora size = ((size + size_p0 + 1024) >> 11) + HEADER_SIZE_ESTIMATE; 5728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora s->value = (double)size; 5738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { 5748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora s->value = GetPSNR(distortion, pixel_count); 5757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 5768b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return size_p0; 5777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 5787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 5791e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic int StatLoop(VP8Encoder* const enc) { 5801e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int method = enc->method_; 5811e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int do_search = enc->do_search_; 5821e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int fast_probe = ((method == 0 || method == 3) && !do_search); 5838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int num_pass_left = enc->config_->pass; 584a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int task_percent = 20; 5858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int percent_per_pass = 5868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora (task_percent + num_pass_left / 2) / num_pass_left; 587a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int final_percent = enc->percent_ + task_percent; 5888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const VP8RDLevel rd_opt = 5898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora (method >= 3 || do_search) ? RD_OPT_BASIC : RD_OPT_NONE; 5908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int nb_mbs = enc->mb_w_ * enc->mb_h_; 5918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora PassStats stats; 5928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 5938b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora InitPassStats(enc, &stats); 5948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ResetTokenStats(enc); 5957c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 5967c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora // Fast mode: quick analysis pass over few mbs. Better than nothing. 5971e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (fast_probe) { 5981e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (method == 3) { // we need more stats for method 3 to be reliable. 5991e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora nb_mbs = (nb_mbs > 200) ? nb_mbs >> 1 : 100; 6001e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } else { 6011e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora nb_mbs = (nb_mbs > 200) ? nb_mbs >> 2 : 50; 6021e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 6031e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 6047c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 6058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora while (num_pass_left-- > 0) { 6068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) || 6078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora (num_pass_left == 0) || 6088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora (enc->max_i4_header_bits_ == 0); 6098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint64_t size_p0 = 6108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora OneStatPass(enc, rd_opt, nb_mbs, percent_per_pass, &stats); 6118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (size_p0 == 0) return 0; 6128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#if (DEBUG_SEARCH > 0) 6138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora printf("#%d value:%.1lf -> %.1lf q:%.2f -> %.2f\n", 6148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora num_pass_left, stats.last_value, stats.value, stats.last_q, stats.q); 6157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#endif 6168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (enc->max_i4_header_bits_ > 0 && size_p0 > PARTITION0_SIZE_LIMIT) { 6178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++num_pass_left; 6188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation... 6198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora continue; // ...and start over 6207c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 6218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (is_last_pass) { 6228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora break; 6238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 6248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // If no target size: just do several pass without changing 'q' 6258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (do_search) { 6268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ComputeNextQ(&stats); 6278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (fabs(stats.dq) <= DQ_LIMIT) break; 6288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 6298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 6308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!do_search || !stats.do_size_search) { 6318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Need to finalize probas now, since it wasn't done during the search. 6328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora FinalizeSkipProba(enc); 6338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora FinalizeTokenProbas(&enc->proba_); 6347c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 6351e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8CalculateLevelCosts(&enc->proba_); // finalize costs 636a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return WebPReportProgress(enc->pic_, final_percent, &enc->percent_); 6377c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 6387c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 639a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 6401e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// Main loops 6411e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// 6421e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 6431e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic const int kAverageBytesPerMB[8] = { 50, 24, 16, 9, 7, 5, 3, 2 }; 6441e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 6451e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic int PreLoopInitialize(VP8Encoder* const enc) { 6461e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int p; 6471e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int ok = 1; 6481e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int average_bytes_per_MB = kAverageBytesPerMB[enc->base_quant_ >> 4]; 6491e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int bytes_per_parts = 6501e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora enc->mb_w_ * enc->mb_h_ * average_bytes_per_MB / enc->num_parts_; 6511e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora // Initialize the bit-writers 6521e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora for (p = 0; ok && p < enc->num_parts_; ++p) { 6531e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora ok = VP8BitWriterInit(enc->parts_ + p, bytes_per_parts); 6541e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 655af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora if (!ok) { 656af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8EncFreeBitWriters(enc); // malloc error occurred 657af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); 658af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora } 6591e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return ok; 6601e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 6611e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 6621e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic int PostLoopFinalize(VP8EncIterator* const it, int ok) { 6631e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8Encoder* const enc = it->enc_; 6641e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (ok) { // Finalize the partitions, check for extra errors. 6651e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int p; 6661e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora for (p = 0; p < enc->num_parts_; ++p) { 6671e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8BitWriterFinish(enc->parts_ + p); 6681e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora ok &= !enc->parts_[p].error_; 6691e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 6701e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 6711e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 6721e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (ok) { // All good. Finish up. 6738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (enc->pic_->stats != NULL) { // finalize byte counters... 6741e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int i, s; 6751e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora for (i = 0; i <= 2; ++i) { 6761e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora for (s = 0; s < NUM_MB_SEGMENTS; ++s) { 6771e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora enc->residual_bytes_[i][s] = (int)((it->bit_count_[s][i] + 7) >> 3); 6781e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 6791e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 6801e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 6811e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8AdjustFilterStrength(it); // ...and store filter stats. 6821e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } else { 6831e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora // Something bad happened -> need to do some memory cleanup. 6841e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8EncFreeBitWriters(enc); 6851e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 6861e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return ok; 6871e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 6881e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 6891e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//------------------------------------------------------------------------------ 6901e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// VP8EncLoop(): does the final bitstream coding. 6911e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 6921e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic void ResetAfterSkip(VP8EncIterator* const it) { 6931e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (it->mb_->type_ == 1) { 6941e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora *it->nz_ = 0; // reset all predictors 6951e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora it->left_nz_[8] = 0; 6961e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } else { 6971e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora *it->nz_ &= (1 << 24); // preserve the dc_nz bit 6981e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 6991e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 7001e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 7011e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroraint VP8EncLoop(VP8Encoder* const enc) { 7021e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8EncIterator it; 7031e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int ok = PreLoopInitialize(enc); 7041e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (!ok) return 0; 7051e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 7061e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora StatLoop(enc); // stats-collection loop 7071e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 7081e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8IteratorInit(enc, &it); 7091e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8InitFilter(&it); 7101e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora do { 7111e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8ModeScore info; 7121e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int dont_use_skip = !enc->proba_.use_skip_proba_; 7131e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const VP8RDLevel rd_opt = enc->rd_opt_level_; 7141e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 7158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8IteratorImport(&it, NULL); 7161e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora // Warning! order is important: first call VP8Decimate() and 7171e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora // *then* decide how to code the skip decision if there's one. 7181e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) { 7191e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora CodeResiduals(it.bw_, &it, &info); 7201e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } else { // reset predictors after a skip 7211e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora ResetAfterSkip(&it); 7221e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 7231e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora StoreSideInfo(&it); 7241e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8StoreFilterStats(&it); 7251e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8IteratorExport(&it); 7261e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora ok = VP8IteratorProgress(&it, 20); 7278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8IteratorSaveBoundary(&it); 7288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } while (ok && VP8IteratorNext(&it)); 7291e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 7301e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return PostLoopFinalize(&it, ok); 7311e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 7321e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 7331e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//------------------------------------------------------------------------------ 7341e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// Single pass using Token Buffer. 7351e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 7361e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#if !defined(DISABLE_TOKEN_BUFFER) 7370406ce1417f76f2034833414dcecc9f56253640cVikas Arora 7388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#define MIN_COUNT 96 // minimum number of macroblocks before updating stats 7390406ce1417f76f2034833414dcecc9f56253640cVikas Arora 7401e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroraint VP8EncTokenLoop(VP8Encoder* const enc) { 7418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Roughly refresh the proba eight times per pass 7420406ce1417f76f2034833414dcecc9f56253640cVikas Arora int max_count = (enc->mb_w_ * enc->mb_h_) >> 3; 7438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int num_pass_left = enc->config_->pass; 7448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int do_search = enc->do_search_; 7451e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8EncIterator it; 7461e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8Proba* const proba = &enc->proba_; 7471e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const VP8RDLevel rd_opt = enc->rd_opt_level_; 7488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint64_t pixel_count = enc->mb_w_ * enc->mb_h_ * 384; 7498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora PassStats stats; 7508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int ok; 7518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 7528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora InitPassStats(enc, &stats); 7538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = PreLoopInitialize(enc); 7548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!ok) return 0; 7551e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 7560406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (max_count < MIN_COUNT) max_count = MIN_COUNT; 7570406ce1417f76f2034833414dcecc9f56253640cVikas Arora 7581e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora assert(enc->num_parts_ == 1); 7591e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora assert(enc->use_tokens_); 7601e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora assert(proba->use_skip_proba_ == 0); 7611e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora assert(rd_opt >= RD_OPT_BASIC); // otherwise, token-buffer won't be useful 7628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(num_pass_left > 0); 7638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 7648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora while (ok && num_pass_left-- > 0) { 7658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) || 7668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora (num_pass_left == 0) || 7678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora (enc->max_i4_header_bits_ == 0); 7688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint64_t size_p0 = 0; 7698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint64_t distortion = 0; 7708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int cnt = max_count; 7718b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8IteratorInit(enc, &it); 7728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora SetLoopParams(enc, stats.q); 7738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (is_last_pass) { 7748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ResetTokenStats(enc); 7758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8InitFilter(&it); // don't collect stats until last pass (too costly) 7761e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 7778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8TBufferClear(&enc->tokens_); 7788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora do { 7798b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8ModeScore info; 7808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8IteratorImport(&it, NULL); 7818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (--cnt < 0) { 7828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora FinalizeTokenProbas(proba); 7838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8CalculateLevelCosts(proba); // refresh cost tables for rd-opt 7848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora cnt = max_count; 7858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8Decimate(&it, &info, rd_opt); 787af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora ok = RecordTokens(&it, &info, &enc->tokens_); 788af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora if (!ok) { 789af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); 790af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora break; 791af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora } 7928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora size_p0 += info.H; 7938b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora distortion += info.D; 7948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (is_last_pass) { 7958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora StoreSideInfo(&it); 7968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8StoreFilterStats(&it); 7978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8IteratorExport(&it); 7988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = VP8IteratorProgress(&it, 20); 7998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8IteratorSaveBoundary(&it); 8018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } while (ok && VP8IteratorNext(&it)); 8028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!ok) break; 8038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 8048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora size_p0 += enc->segment_hdr_.size_; 8058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (stats.do_size_search) { 8068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint64_t size = FinalizeTokenProbas(&enc->proba_); 8078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora size += VP8EstimateTokenSize(&enc->tokens_, 8088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora (const uint8_t*)proba->coeffs_); 8098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora size = (size + size_p0 + 1024) >> 11; // -> size in bytes 8108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora size += HEADER_SIZE_ESTIMATE; 8118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora stats.value = (double)size; 8128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { // compute and store PSNR 8138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora stats.value = GetPSNR(distortion, pixel_count); 8148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8151e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 8168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#if (DEBUG_SEARCH > 0) 8178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora printf("#%2d metric:%.1lf -> %.1lf last_q=%.2lf q=%.2lf dq=%.2lf\n", 8188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora num_pass_left, stats.last_value, stats.value, 8198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora stats.last_q, stats.q, stats.dq); 8208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#endif 8218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (size_p0 > PARTITION0_SIZE_LIMIT) { 8228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++num_pass_left; 8238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation... 8248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora continue; // ...and start over 8258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (is_last_pass) { 8278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora break; // done 8288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (do_search) { 8308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ComputeNextQ(&stats); // Adjust q 8318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8331e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (ok) { 8348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!stats.do_size_search) { 8358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora FinalizeTokenProbas(&enc->proba_); 8368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8371e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora ok = VP8EmitTokens(&enc->tokens_, enc->parts_ + 0, 8381e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora (const uint8_t*)proba->coeffs_, 1); 8391e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 8408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = ok && WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); 8411e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return PostLoopFinalize(&it, ok); 8421e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 8431e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 8441e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#else 8451e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 8461e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroraint VP8EncTokenLoop(VP8Encoder* const enc) { 8471e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora (void)enc; 8481e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return 0; // we shouldn't be here. 8491e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 8501e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 8511e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#endif // DISABLE_TOKEN_BUFFER 8521e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 8531e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//------------------------------------------------------------------------------ 8547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 855