1// Copyright 2011 Google Inc.
2//
3// This code is licensed under the same terms as WebM:
4//  Software License Agreement:  http://www.webmproject.org/license/software/
5//  Additional IP Rights Grant:  http://www.webmproject.org/license/additional/
6// -----------------------------------------------------------------------------
7//
8//   frame coding and analysis
9//
10// Author: Skal (pascal.massimino@gmail.com)
11
12#include <stdlib.h>
13#include <string.h>
14#include <assert.h>
15#include <math.h>
16
17#include "vp8enci.h"
18#include "cost.h"
19
20#if defined(__cplusplus) || defined(c_plusplus)
21extern "C" {
22#endif
23
24#define SEGMENT_VISU 0
25#define DEBUG_SEARCH 0    // useful to track search convergence
26
27// On-the-fly info about the current set of residuals. Handy to avoid
28// passing zillions of params.
29typedef struct {
30  int first;
31  int last;
32  const int16_t* coeffs;
33
34  int coeff_type;
35  ProbaArray* prob;
36  StatsArray* stats;
37  CostArray*  cost;
38} VP8Residual;
39
40//-----------------------------------------------------------------------------
41// Tables for level coding
42
43const uint8_t VP8EncBands[16 + 1] = {
44  0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7,
45  0  // sentinel
46};
47
48static const uint8_t kCat3[] = { 173, 148, 140 };
49static const uint8_t kCat4[] = { 176, 155, 140, 135 };
50static const uint8_t kCat5[] = { 180, 157, 141, 134, 130 };
51static const uint8_t kCat6[] =
52    { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 };
53
54//-----------------------------------------------------------------------------
55// Reset the statistics about: number of skips, token proba, level cost,...
56
57static void ResetStats(VP8Encoder* const enc, int precalc_cost) {
58  VP8Proba* const proba = &enc->proba_;
59  if (precalc_cost) VP8CalculateLevelCosts(proba);
60  proba->nb_skip_ = 0;
61  proba->nb_i4_ = 0;
62  proba->nb_i16_ = 0;
63}
64
65//-----------------------------------------------------------------------------
66// Skip decision probability
67
68static int CalcSkipProba(uint64_t nb, uint64_t total) {
69  return (int)(total ? (total - nb) * 255 / total : 255);
70}
71
72// Returns the bit-cost for coding the skip probability.
73static int FinalizeSkipProba(VP8Encoder* const enc) {
74  VP8Proba* const proba = &enc->proba_;
75  const int nb_mbs = enc->mb_w_ * enc->mb_h_;
76  const int nb_events = proba->nb_skip_;
77  int size;
78  proba->skip_proba_ = CalcSkipProba(nb_events, nb_mbs);
79  proba->use_skip_proba_ = (proba->skip_proba_ < 250);
80  size = 256;   // 'use_skip_proba' bit
81  if (proba->use_skip_proba_) {
82    size +=  nb_events * VP8BitCost(1, proba->skip_proba_)
83         + (nb_mbs - nb_events) * VP8BitCost(0, proba->skip_proba_);
84    size += 8 * 256;   // cost of signaling the skip_proba_ itself.
85  }
86  return size;
87}
88
89//-----------------------------------------------------------------------------
90// Recording of token probabilities.
91
92static void ResetTokenStats(VP8Encoder* const enc) {
93  VP8Proba* const proba = &enc->proba_;
94  memset(proba->stats_, 0, sizeof(proba->stats_));
95}
96
97// Record proba context used
98static int Record(int bit, uint64_t* const stats) {
99  stats[0] += bit;
100  stats[1] += 1;
101  return bit;
102}
103
104// Simulate block coding, but only record statistics.
105// Note: no need to record the fixed probas.
106static int RecordCoeffs(int ctx, VP8Residual* res) {
107  int n = res->first;
108  uint64_t (*s)[2] = res->stats[VP8EncBands[n]][ctx];
109  if (!Record(res->last >= 0, s[0])) {
110    return 0;
111  }
112
113  while (1) {
114    const int v = abs(res->coeffs[n++]);
115    if (!Record(v != 0, s[1])) {
116      s = res->stats[VP8EncBands[n]][0];
117      continue;
118    }
119    if (!Record(v > 1, s[2])) {
120      s = res->stats[VP8EncBands[n]][1];
121    } else {
122      if (!Record(v > 4, s[3])) {
123        if (Record(v != 2, s[4]))
124          Record(v == 4, s[5]);
125      } else if (!Record(v > 10, s[6])) {
126        Record(v > 6, s[7]);
127      } else if (!Record((v >= 3 + (8 << 2)), s[8])) {
128        Record((v >= 3 + (8 << 1)), s[9]);
129      } else {
130        Record((v >= 3 + (8 << 3)), s[10]);
131      }
132      s = res->stats[VP8EncBands[n]][2];
133    }
134    if (n == 16 || !Record(n <= res->last, s[0])) {
135      return 1;
136    }
137  }
138}
139
140// Collect statistics and deduce probabilities for next coding pass.
141// Return the total bit-cost for coding the probability updates.
142static int CalcTokenProba(uint64_t nb, uint64_t total) {
143  return (int)(nb ? ((total - nb) * 255 + total / 2) / total : 255);
144}
145
146static int FinalizeTokenProbas(VP8Encoder* const enc) {
147  VP8Proba* const proba = &enc->proba_;
148  int size = 0;
149  int t, b, c, p;
150  for (t = 0; t < NUM_TYPES; ++t) {
151    for (b = 0; b < NUM_BANDS; ++b) {
152      for (c = 0; c < NUM_CTX; ++c) {
153        for (p = 0; p < NUM_PROBAS; ++p) {
154          const uint64_t* const cnt = proba->stats_[t][b][c][p];
155          const int update_proba = VP8CoeffsUpdateProba[t][b][c][p];
156          const int old_p = VP8CoeffsProba0[t][b][c][p];
157          const int new_p = CalcTokenProba(cnt[0], cnt[1]);
158          const uint64_t old_cost = VP8BranchCost(cnt[0], cnt[1], old_p)
159                                  + VP8BitCost(0, update_proba);
160          const uint64_t new_cost = VP8BranchCost(cnt[0], cnt[1], new_p)
161                                  + VP8BitCost(1, update_proba) + 8 * 256;
162          const int use_new_p = (old_cost > new_cost);
163          size += VP8BitCost(use_new_p, update_proba);
164          if (use_new_p) {  // only use proba that seem meaningful enough.
165            proba->coeffs_[t][b][c][p] = new_p;
166            size += 8 * 256;
167          } else {
168            proba->coeffs_[t][b][c][p] = old_p;
169          }
170        }
171      }
172    }
173  }
174  return size;
175}
176
177//-----------------------------------------------------------------------------
178// helper functions for residuals struct VP8Residual.
179
180static void InitResidual(int first, int coeff_type,
181                         VP8Encoder* const enc, VP8Residual* const res) {
182  res->coeff_type = coeff_type;
183  res->prob  = enc->proba_.coeffs_[coeff_type];
184  res->stats = enc->proba_.stats_[coeff_type];
185  res->cost  = enc->proba_.level_cost_[coeff_type];
186  res->first = first;
187}
188
189static void SetResidualCoeffs(const int16_t* const coeffs,
190                              VP8Residual* const res) {
191  int n;
192  res->last = -1;
193  for (n = 15; n >= res->first; --n) {
194    if (coeffs[n]) {
195      res->last = n;
196      break;
197    }
198  }
199  res->coeffs = coeffs;
200}
201
202//-----------------------------------------------------------------------------
203// Mode costs
204
205static int GetResidualCost(int ctx, const VP8Residual* const res) {
206  int n = res->first;
207  const uint8_t* p = res->prob[VP8EncBands[n]][ctx];
208  const uint16_t *t = res->cost[VP8EncBands[n]][ctx];
209  int cost;
210
211  cost = VP8BitCost(res->last >= 0, p[0]);
212  if (res->last < 0) {
213    return cost;
214  }
215  while (n <= res->last) {
216    const int v = abs(res->coeffs[n++]);
217    cost += VP8LevelCost(t, v);
218    if (v == 0) {
219      p = res->prob[VP8EncBands[n]][0];
220      t = res->cost[VP8EncBands[n]][0];
221      continue;
222    } else if (v == 1) {
223      p = res->prob[VP8EncBands[n]][1];
224      t = res->cost[VP8EncBands[n]][1];
225    } else {
226      p = res->prob[VP8EncBands[n]][2];
227      t = res->cost[VP8EncBands[n]][2];
228    }
229    if (n < 16) {
230      cost += VP8BitCost(n <= res->last, p[0]);
231    }
232  }
233  return cost;
234}
235
236int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]) {
237  const int x = (it->i4_ & 3), y = (it->i4_ >> 2);
238  VP8Residual res;
239  int R = 0;
240  int ctx;
241
242  InitResidual(0, 3, it->enc_, &res);
243  ctx = it->top_nz_[x] + it->left_nz_[y];
244  SetResidualCoeffs(levels, &res);
245  R += GetResidualCost(ctx, &res);
246  return R;
247}
248
249int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd) {
250  VP8Residual res;
251  int x, y;
252  int R = 0;
253
254  VP8IteratorNzToBytes(it);   // re-import the non-zero context
255
256  // DC
257  InitResidual(0, 1, it->enc_, &res);
258  SetResidualCoeffs(rd->y_dc_levels, &res);
259  R += GetResidualCost(it->top_nz_[8] + it->left_nz_[8], &res);
260
261  // AC
262  InitResidual(1, 0, it->enc_, &res);
263  for (y = 0; y < 4; ++y) {
264    for (x = 0; x < 4; ++x) {
265      const int ctx = it->top_nz_[x] + it->left_nz_[y];
266      SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
267      R += GetResidualCost(ctx, &res);
268      it->top_nz_[x] = it->left_nz_[y] = (res.last >= 0);
269    }
270  }
271  return R;
272}
273
274int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd) {
275  VP8Residual res;
276  int ch, x, y;
277  int R = 0;
278
279  VP8IteratorNzToBytes(it);  // re-import the non-zero context
280
281  InitResidual(0, 2, it->enc_, &res);
282  for (ch = 0; ch <= 2; ch += 2) {
283    for (y = 0; y < 2; ++y) {
284      for (x = 0; x < 2; ++x) {
285        const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
286        SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
287        R += GetResidualCost(ctx, &res);
288        it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = (res.last >= 0);
289      }
290    }
291  }
292  return R;
293}
294
295//-----------------------------------------------------------------------------
296// Coefficient coding
297
298static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) {
299  int n = res->first;
300  const uint8_t* p = res->prob[VP8EncBands[n]][ctx];
301  if (!VP8PutBit(bw, res->last >= 0, p[0])) {
302    return 0;
303  }
304
305  while (n < 16) {
306    const int c = res->coeffs[n++];
307    const int sign = c < 0;
308    int v = sign ? -c : c;
309    if (!VP8PutBit(bw, v != 0, p[1])) {
310      p = res->prob[VP8EncBands[n]][0];
311      continue;
312    }
313    if (!VP8PutBit(bw, v > 1, p[2])) {
314      p = res->prob[VP8EncBands[n]][1];
315    } else {
316      if (!VP8PutBit(bw, v > 4, p[3])) {
317        if (VP8PutBit(bw, v != 2, p[4]))
318          VP8PutBit(bw, v == 4, p[5]);
319      } else if (!VP8PutBit(bw, v > 10, p[6])) {
320        if (!VP8PutBit(bw, v > 6, p[7])) {
321          VP8PutBit(bw, v == 6, 159);
322        } else {
323          VP8PutBit(bw, v >= 9, 165);
324          VP8PutBit(bw, !(v & 1), 145);
325        }
326      } else {
327        int mask;
328        const uint8_t* tab;
329        if (v < 3 + (8 << 1)) {          // kCat3  (3b)
330          VP8PutBit(bw, 0, p[8]);
331          VP8PutBit(bw, 0, p[9]);
332          v -= 3 + (8 << 0);
333          mask = 1 << 2;
334          tab = kCat3;
335        } else if (v < 3 + (8 << 2)) {   // kCat4  (4b)
336          VP8PutBit(bw, 0, p[8]);
337          VP8PutBit(bw, 1, p[9]);
338          v -= 3 + (8 << 1);
339          mask = 1 << 3;
340          tab = kCat4;
341        } else if (v < 3 + (8 << 3)) {   // kCat5  (5b)
342          VP8PutBit(bw, 1, p[8]);
343          VP8PutBit(bw, 0, p[10]);
344          v -= 3 + (8 << 2);
345          mask = 1 << 4;
346          tab = kCat5;
347        } else {                         // kCat6 (11b)
348          VP8PutBit(bw, 1, p[8]);
349          VP8PutBit(bw, 1, p[10]);
350          v -= 3 + (8 << 3);
351          mask = 1 << 10;
352          tab = kCat6;
353        }
354        while (mask) {
355          VP8PutBit(bw, !!(v & mask), *tab++);
356          mask >>= 1;
357        }
358      }
359      p = res->prob[VP8EncBands[n]][2];
360    }
361    VP8PutBitUniform(bw, sign);
362    if (n == 16 || !VP8PutBit(bw, n <= res->last, p[0])) {
363      return 1;   // EOB
364    }
365  }
366  return 1;
367}
368
369static void CodeResiduals(VP8BitWriter* const bw,
370                          VP8EncIterator* const it,
371                          const VP8ModeScore* const rd) {
372  int x, y, ch;
373  VP8Residual res;
374  uint64_t pos1, pos2, pos3;
375  const int i16 = (it->mb_->type_ == 1);
376  const int segment = it->mb_->segment_;
377
378  VP8IteratorNzToBytes(it);
379
380  pos1 = VP8BitWriterPos(bw);
381  if (i16) {
382    InitResidual(0, 1, it->enc_, &res);
383    SetResidualCoeffs(rd->y_dc_levels, &res);
384    it->top_nz_[8] = it->left_nz_[8] =
385      PutCoeffs(bw, it->top_nz_[8] + it->left_nz_[8], &res);
386    InitResidual(1, 0, it->enc_, &res);
387  } else {
388    InitResidual(0, 3, it->enc_, &res);
389  }
390
391  // luma-AC
392  for (y = 0; y < 4; ++y) {
393    for (x = 0; x < 4; ++x) {
394      const int ctx = it->top_nz_[x] + it->left_nz_[y];
395      SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
396      it->top_nz_[x] = it->left_nz_[y] = PutCoeffs(bw, ctx, &res);
397    }
398  }
399  pos2 = VP8BitWriterPos(bw);
400
401  // U/V
402  InitResidual(0, 2, it->enc_, &res);
403  for (ch = 0; ch <= 2; ch += 2) {
404    for (y = 0; y < 2; ++y) {
405      for (x = 0; x < 2; ++x) {
406        const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
407        SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
408        it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
409            PutCoeffs(bw, ctx, &res);
410      }
411    }
412  }
413  pos3 = VP8BitWriterPos(bw);
414  it->luma_bits_ = pos2 - pos1;
415  it->uv_bits_ = pos3 - pos2;
416  it->bit_count_[segment][i16] += it->luma_bits_;
417  it->bit_count_[segment][2] += it->uv_bits_;
418  VP8IteratorBytesToNz(it);
419}
420
421// Same as CodeResiduals, but doesn't actually write anything.
422// Instead, it just records the event distribution.
423static void RecordResiduals(VP8EncIterator* const it,
424                            const VP8ModeScore* const rd) {
425  int x, y, ch;
426  VP8Residual res;
427
428  VP8IteratorNzToBytes(it);
429
430  if (it->mb_->type_ == 1) {   // i16x16
431    InitResidual(0, 1, it->enc_, &res);
432    SetResidualCoeffs(rd->y_dc_levels, &res);
433    it->top_nz_[8] = it->left_nz_[8] =
434      RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res);
435    InitResidual(1, 0, it->enc_, &res);
436  } else {
437    InitResidual(0, 3, it->enc_, &res);
438  }
439
440  // luma-AC
441  for (y = 0; y < 4; ++y) {
442    for (x = 0; x < 4; ++x) {
443      const int ctx = it->top_nz_[x] + it->left_nz_[y];
444      SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
445      it->top_nz_[x] = it->left_nz_[y] = RecordCoeffs(ctx, &res);
446    }
447  }
448
449  // U/V
450  InitResidual(0, 2, it->enc_, &res);
451  for (ch = 0; ch <= 2; ch += 2) {
452    for (y = 0; y < 2; ++y) {
453      for (x = 0; x < 2; ++x) {
454        const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
455        SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
456        it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
457            RecordCoeffs(ctx, &res);
458      }
459    }
460  }
461
462  VP8IteratorBytesToNz(it);
463}
464
465//-----------------------------------------------------------------------------
466// ExtraInfo map / Debug function
467
468#if SEGMENT_VISU
469static void SetBlock(uint8_t* p, int value, int size) {
470  int y;
471  for (y = 0; y < size; ++y) {
472    memset(p, value, size);
473    p += BPS;
474  }
475}
476#endif
477
478static void ResetSSE(VP8Encoder* const enc) {
479  memset(enc->sse_, 0, sizeof(enc->sse_));
480  enc->sse_count_ = 0;
481}
482
483static void StoreSSE(const VP8EncIterator* const it) {
484  VP8Encoder* const enc = it->enc_;
485  const uint8_t* const in = it->yuv_in_;
486  const uint8_t* const out = it->yuv_out_;
487  // Note: not totally accurate at boundary. And doesn't include in-loop filter.
488  enc->sse_[0] += VP8SSE16x16(in + Y_OFF, out + Y_OFF);
489  enc->sse_[1] += VP8SSE8x8(in + U_OFF, out + U_OFF);
490  enc->sse_[2] += VP8SSE8x8(in + V_OFF, out + V_OFF);
491  enc->sse_count_ += 16 * 16;
492}
493
494static void StoreSideInfo(const VP8EncIterator* const it) {
495  VP8Encoder* const enc = it->enc_;
496  const VP8MBInfo* const mb = it->mb_;
497  WebPPicture* const pic = enc->pic_;
498
499  if (pic->stats) {
500    StoreSSE(it);
501    enc->block_count_[0] += (mb->type_ == 0);
502    enc->block_count_[1] += (mb->type_ == 1);
503    enc->block_count_[2] += (mb->skip_ != 0);
504  }
505
506  if (pic->extra_info) {
507    uint8_t* const info = &pic->extra_info[it->x_ + it->y_ * enc->mb_w_];
508    switch(pic->extra_info_type) {
509      case 1: *info = mb->type_; break;
510      case 2: *info = mb->segment_; break;
511      case 3: *info = enc->dqm_[mb->segment_].quant_; break;
512      case 4: *info = (mb->type_ == 1) ? it->preds_[0] : 0xff; break;
513      case 5: *info = mb->uv_mode_; break;
514      case 6: {
515        const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3);
516        *info = (b > 255) ? 255 : b; break;
517      }
518      default: *info = 0; break;
519    };
520  }
521#if SEGMENT_VISU  // visualize segments and prediction modes
522  SetBlock(it->yuv_out_ + Y_OFF, mb->segment_ * 64, 16);
523  SetBlock(it->yuv_out_ + U_OFF, it->preds_[0] * 64, 8);
524  SetBlock(it->yuv_out_ + V_OFF, mb->uv_mode_ * 64, 8);
525#endif
526}
527
528//-----------------------------------------------------------------------------
529// Main loops
530//
531//  VP8EncLoop(): does the final bitstream coding.
532
533static void ResetAfterSkip(VP8EncIterator* const it) {
534  if (it->mb_->type_ == 1) {
535    *it->nz_ = 0;  // reset all predictors
536    it->left_nz_[8] = 0;
537  } else {
538    *it->nz_ &= (1 << 24);  // preserve the dc_nz bit
539  }
540}
541
542int VP8EncLoop(VP8Encoder* const enc) {
543  int i, s, p;
544  VP8EncIterator it;
545  VP8ModeScore info;
546  const int dont_use_skip = !enc->proba_.use_skip_proba_;
547  const int rd_opt = enc->rd_opt_level_;
548  const int kAverageBytesPerMB = 5;     // TODO: have a kTable[quality/10]
549  const int bytes_per_parts =
550    enc->mb_w_ * enc->mb_h_ * kAverageBytesPerMB / enc->num_parts_;
551
552  // Initialize the bit-writers
553  for (p = 0; p < enc->num_parts_; ++p) {
554    VP8BitWriterInit(enc->parts_ + p, bytes_per_parts);
555  }
556
557  ResetStats(enc, rd_opt != 0);
558  ResetSSE(enc);
559
560  VP8IteratorInit(enc, &it);
561  VP8InitFilter(&it);
562  do {
563    VP8IteratorImport(&it);
564    // Warning! order is important: first call VP8Decimate() and
565    // *then* decide how to code the skip decision if there's one.
566    if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) {
567      CodeResiduals(it.bw_, &it, &info);
568    } else {   // reset predictors after a skip
569      ResetAfterSkip(&it);
570    }
571    StoreSideInfo(&it);
572    VP8StoreFilterStats(&it);
573    VP8IteratorExport(&it);
574  } while (VP8IteratorNext(&it, it.yuv_out_));
575  VP8AdjustFilterStrength(&it);
576
577  // Finalize the partitions
578  for (p = 0; p < enc->num_parts_; ++p) {
579    VP8BitWriterFinish(enc->parts_ + p);
580  }
581  // and byte counters
582  if (enc->pic_->stats) {
583    for (i = 0; i <= 2; ++i) {
584      for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
585        enc->residual_bytes_[i][s] = (int)((it.bit_count_[s][i] + 7) >> 3);
586      }
587    }
588  }
589  return 1;
590}
591
592//-----------------------------------------------------------------------------
593//  VP8StatLoop(): only collect statistics (number of skips, token usage, ...)
594//                 This is used for deciding optimal probabilities. It also
595//                 modifies the quantizer value if some target (size, PNSR)
596//                 was specified.
597
598#define kHeaderSizeEstimate (15 + 20 + 10)      // TODO: fix better
599
600static int OneStatPass(VP8Encoder* const enc, float q, int rd_opt, int nb_mbs,
601                       float* const PSNR) {
602  VP8EncIterator it;
603  uint64_t size = 0;
604  uint64_t distortion = 0;
605  const uint64_t pixel_count = nb_mbs * 384;
606
607  // Make sure the quality parameter is inside valid bounds
608  if (q < 0.) {
609    q = 0;
610  } else if (q > 100.) {
611    q = 100;
612  }
613
614  VP8SetSegmentParams(enc, q);      // setup segment quantizations and filters
615
616  ResetStats(enc, rd_opt != 0);
617  ResetTokenStats(enc);
618
619  VP8IteratorInit(enc, &it);
620  do {
621    VP8ModeScore info;
622    VP8IteratorImport(&it);
623    if (VP8Decimate(&it, &info, rd_opt)) {
624      // Just record the number of skips and act like skip_proba is not used.
625      enc->proba_.nb_skip_++;
626    }
627    RecordResiduals(&it, &info);
628    size += info.R;
629    distortion += info.D;
630  } while (VP8IteratorNext(&it, it.yuv_out_) && --nb_mbs > 0);
631  size += FinalizeSkipProba(enc);
632  size += FinalizeTokenProbas(enc);
633  size += enc->segment_hdr_.size_;
634  size = ((size + 1024) >> 11) + kHeaderSizeEstimate;
635
636  if (PSNR) {
637    *PSNR = (float)(10.* log10(255. * 255. * pixel_count / distortion));
638  }
639  return (int)size;
640}
641
642// successive refinement increments.
643static const int dqs[] = { 20, 15, 10, 8, 6, 4, 2, 1, 0 };
644
645int VP8StatLoop(VP8Encoder* const enc) {
646  const int do_search =
647    (enc->config_->target_size > 0 || enc->config_->target_PSNR > 0);
648  const int fast_probe = (enc->method_ < 2 && !do_search);
649  float q = enc->config_->quality;
650  int pass;
651  int nb_mbs;
652
653  // Fast mode: quick analysis pass over few mbs. Better than nothing.
654  nb_mbs = enc->mb_w_ * enc->mb_h_;
655  if (fast_probe && nb_mbs > 100) nb_mbs = 100;
656
657  // No target size: just do several pass without changing 'q'
658  if (!do_search) {
659    for (pass = 0; pass < enc->config_->pass; ++pass) {
660      const int rd_opt = (enc->method_ > 2);
661      OneStatPass(enc, q, rd_opt, nb_mbs, NULL);
662    }
663    return 1;
664  }
665
666  // binary search for a size close to target
667  for (pass = 0; pass < enc->config_->pass || (dqs[pass] > 0); ++pass) {
668    const int rd_opt = 1;
669    float PSNR;
670    int criterion;
671    const int size = OneStatPass(enc, q, rd_opt, nb_mbs, &PSNR);
672#if DEBUG_SEARCH
673    printf("#%d size=%d PSNR=%.2f q=%.2f\n", pass, size, PSNR, q);
674#endif
675
676    if (enc->config_->target_PSNR > 0) {
677      criterion = (PSNR < enc->config_->target_PSNR);
678    } else {
679      criterion = (size < enc->config_->target_size);
680    }
681    // dichotomize
682    if (criterion) {
683      q += dqs[pass];
684    } else {
685      q -= dqs[pass];
686    }
687  }
688  return 1;
689}
690
691//-----------------------------------------------------------------------------
692
693#if defined(__cplusplus) || defined(c_plusplus)
694}    // extern "C"
695#endif
696