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