• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 Google Inc. All Rights Reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the COPYING file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8 // -----------------------------------------------------------------------------
9 //
10 //   Quantization
11 //
12 // Author: Skal (pascal.massimino@gmail.com)
13 
14 #include <assert.h>
15 #include <math.h>
16 #include <stdlib.h>  // for abs()
17 
18 #include "src/enc/vp8i_enc.h"
19 #include "src/enc/cost_enc.h"
20 
21 #define DO_TRELLIS_I4  1
22 #define DO_TRELLIS_I16 1   // not a huge gain, but ok at low bitrate.
23 #define DO_TRELLIS_UV  0   // disable trellis for UV. Risky. Not worth.
24 #define USE_TDISTO 1
25 
26 #define MID_ALPHA 64      // neutral value for susceptibility
27 #define MIN_ALPHA 30      // lowest usable value for susceptibility
28 #define MAX_ALPHA 100     // higher meaningful value for susceptibility
29 
30 #define SNS_TO_DQ 0.9     // Scaling constant between the sns value and the QP
31                           // power-law modulation. Must be strictly less than 1.
32 
33 // number of non-zero coeffs below which we consider the block very flat
34 // (and apply a penalty to complex predictions)
35 #define FLATNESS_LIMIT_I16 10      // I16 mode
36 #define FLATNESS_LIMIT_I4  3       // I4 mode
37 #define FLATNESS_LIMIT_UV  2       // UV mode
38 #define FLATNESS_PENALTY   140     // roughly ~1bit per block
39 
40 #define MULT_8B(a, b) (((a) * (b) + 128) >> 8)
41 
42 #define RD_DISTO_MULT      256  // distortion multiplier (equivalent of lambda)
43 
44 // #define DEBUG_BLOCK
45 
46 //------------------------------------------------------------------------------
47 
48 #if defined(DEBUG_BLOCK)
49 
50 #include <stdio.h>
51 #include <stdlib.h>
52 
PrintBlockInfo(const VP8EncIterator * const it,const VP8ModeScore * const rd)53 static void PrintBlockInfo(const VP8EncIterator* const it,
54                            const VP8ModeScore* const rd) {
55   int i, j;
56   const int is_i16 = (it->mb_->type_ == 1);
57   const uint8_t* const y_in = it->yuv_in_ + Y_OFF_ENC;
58   const uint8_t* const y_out = it->yuv_out_ + Y_OFF_ENC;
59   const uint8_t* const uv_in = it->yuv_in_ + U_OFF_ENC;
60   const uint8_t* const uv_out = it->yuv_out_ + U_OFF_ENC;
61   printf("SOURCE / OUTPUT / ABS DELTA\n");
62   for (j = 0; j < 16; ++j) {
63     for (i = 0; i < 16; ++i) printf("%3d ", y_in[i + j * BPS]);
64     printf("     ");
65     for (i = 0; i < 16; ++i) printf("%3d ", y_out[i + j * BPS]);
66     printf("     ");
67     for (i = 0; i < 16; ++i) {
68       printf("%1d ", abs(y_in[i + j * BPS] - y_out[i + j * BPS]));
69     }
70     printf("\n");
71   }
72   printf("\n");   // newline before the U/V block
73   for (j = 0; j < 8; ++j) {
74     for (i = 0; i < 8; ++i) printf("%3d ", uv_in[i + j * BPS]);
75     printf(" ");
76     for (i = 8; i < 16; ++i) printf("%3d ", uv_in[i + j * BPS]);
77     printf("    ");
78     for (i = 0; i < 8; ++i) printf("%3d ", uv_out[i + j * BPS]);
79     printf(" ");
80     for (i = 8; i < 16; ++i) printf("%3d ", uv_out[i + j * BPS]);
81     printf("   ");
82     for (i = 0; i < 8; ++i) {
83       printf("%1d ", abs(uv_out[i + j * BPS] - uv_in[i + j * BPS]));
84     }
85     printf(" ");
86     for (i = 8; i < 16; ++i) {
87       printf("%1d ", abs(uv_out[i + j * BPS] - uv_in[i + j * BPS]));
88     }
89     printf("\n");
90   }
91   printf("\nD:%d SD:%d R:%d H:%d nz:0x%x score:%d\n",
92     (int)rd->D, (int)rd->SD, (int)rd->R, (int)rd->H, (int)rd->nz,
93     (int)rd->score);
94   if (is_i16) {
95     printf("Mode: %d\n", rd->mode_i16);
96     printf("y_dc_levels:");
97     for (i = 0; i < 16; ++i) printf("%3d ", rd->y_dc_levels[i]);
98     printf("\n");
99   } else {
100     printf("Modes[16]: ");
101     for (i = 0; i < 16; ++i) printf("%d ", rd->modes_i4[i]);
102     printf("\n");
103   }
104   printf("y_ac_levels:\n");
105   for (j = 0; j < 16; ++j) {
106     for (i = is_i16 ? 1 : 0; i < 16; ++i) {
107       printf("%4d ", rd->y_ac_levels[j][i]);
108     }
109     printf("\n");
110   }
111   printf("\n");
112   printf("uv_levels (mode=%d):\n", rd->mode_uv);
113   for (j = 0; j < 8; ++j) {
114     for (i = 0; i < 16; ++i) {
115       printf("%4d ", rd->uv_levels[j][i]);
116     }
117     printf("\n");
118   }
119 }
120 
121 #endif   // DEBUG_BLOCK
122 
123 //------------------------------------------------------------------------------
124 
clip(int v,int m,int M)125 static WEBP_INLINE int clip(int v, int m, int M) {
126   return v < m ? m : v > M ? M : v;
127 }
128 
129 static const uint8_t kZigzag[16] = {
130   0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
131 };
132 
133 static const uint8_t kDcTable[128] = {
134   4,     5,   6,   7,   8,   9,  10,  10,
135   11,   12,  13,  14,  15,  16,  17,  17,
136   18,   19,  20,  20,  21,  21,  22,  22,
137   23,   23,  24,  25,  25,  26,  27,  28,
138   29,   30,  31,  32,  33,  34,  35,  36,
139   37,   37,  38,  39,  40,  41,  42,  43,
140   44,   45,  46,  46,  47,  48,  49,  50,
141   51,   52,  53,  54,  55,  56,  57,  58,
142   59,   60,  61,  62,  63,  64,  65,  66,
143   67,   68,  69,  70,  71,  72,  73,  74,
144   75,   76,  76,  77,  78,  79,  80,  81,
145   82,   83,  84,  85,  86,  87,  88,  89,
146   91,   93,  95,  96,  98, 100, 101, 102,
147   104, 106, 108, 110, 112, 114, 116, 118,
148   122, 124, 126, 128, 130, 132, 134, 136,
149   138, 140, 143, 145, 148, 151, 154, 157
150 };
151 
152 static const uint16_t kAcTable[128] = {
153   4,     5,   6,   7,   8,   9,  10,  11,
154   12,   13,  14,  15,  16,  17,  18,  19,
155   20,   21,  22,  23,  24,  25,  26,  27,
156   28,   29,  30,  31,  32,  33,  34,  35,
157   36,   37,  38,  39,  40,  41,  42,  43,
158   44,   45,  46,  47,  48,  49,  50,  51,
159   52,   53,  54,  55,  56,  57,  58,  60,
160   62,   64,  66,  68,  70,  72,  74,  76,
161   78,   80,  82,  84,  86,  88,  90,  92,
162   94,   96,  98, 100, 102, 104, 106, 108,
163   110, 112, 114, 116, 119, 122, 125, 128,
164   131, 134, 137, 140, 143, 146, 149, 152,
165   155, 158, 161, 164, 167, 170, 173, 177,
166   181, 185, 189, 193, 197, 201, 205, 209,
167   213, 217, 221, 225, 229, 234, 239, 245,
168   249, 254, 259, 264, 269, 274, 279, 284
169 };
170 
171 static const uint16_t kAcTable2[128] = {
172   8,     8,   9,  10,  12,  13,  15,  17,
173   18,   20,  21,  23,  24,  26,  27,  29,
174   31,   32,  34,  35,  37,  38,  40,  41,
175   43,   44,  46,  48,  49,  51,  52,  54,
176   55,   57,  58,  60,  62,  63,  65,  66,
177   68,   69,  71,  72,  74,  75,  77,  79,
178   80,   82,  83,  85,  86,  88,  89,  93,
179   96,   99, 102, 105, 108, 111, 114, 117,
180   120, 124, 127, 130, 133, 136, 139, 142,
181   145, 148, 151, 155, 158, 161, 164, 167,
182   170, 173, 176, 179, 184, 189, 193, 198,
183   203, 207, 212, 217, 221, 226, 230, 235,
184   240, 244, 249, 254, 258, 263, 268, 274,
185   280, 286, 292, 299, 305, 311, 317, 323,
186   330, 336, 342, 348, 354, 362, 370, 379,
187   385, 393, 401, 409, 416, 424, 432, 440
188 };
189 
190 static const uint8_t kBiasMatrices[3][2] = {  // [luma-ac,luma-dc,chroma][dc,ac]
191   { 96, 110 }, { 96, 108 }, { 110, 115 }
192 };
193 
194 // Sharpening by (slightly) raising the hi-frequency coeffs.
195 // Hack-ish but helpful for mid-bitrate range. Use with care.
196 #define SHARPEN_BITS 11  // number of descaling bits for sharpening bias
197 static const uint8_t kFreqSharpening[16] = {
198   0,  30, 60, 90,
199   30, 60, 90, 90,
200   60, 90, 90, 90,
201   90, 90, 90, 90
202 };
203 
204 //------------------------------------------------------------------------------
205 // Initialize quantization parameters in VP8Matrix
206 
207 // Returns the average quantizer
ExpandMatrix(VP8Matrix * const m,int type)208 static int ExpandMatrix(VP8Matrix* const m, int type) {
209   int i, sum;
210   for (i = 0; i < 2; ++i) {
211     const int is_ac_coeff = (i > 0);
212     const int bias = kBiasMatrices[type][is_ac_coeff];
213     m->iq_[i] = (1 << QFIX) / m->q_[i];
214     m->bias_[i] = BIAS(bias);
215     // zthresh_ is the exact value such that QUANTDIV(coeff, iQ, B) is:
216     //   * zero if coeff <= zthresh
217     //   * non-zero if coeff > zthresh
218     m->zthresh_[i] = ((1 << QFIX) - 1 - m->bias_[i]) / m->iq_[i];
219   }
220   for (i = 2; i < 16; ++i) {
221     m->q_[i] = m->q_[1];
222     m->iq_[i] = m->iq_[1];
223     m->bias_[i] = m->bias_[1];
224     m->zthresh_[i] = m->zthresh_[1];
225   }
226   for (sum = 0, i = 0; i < 16; ++i) {
227     if (type == 0) {  // we only use sharpening for AC luma coeffs
228       m->sharpen_[i] = (kFreqSharpening[i] * m->q_[i]) >> SHARPEN_BITS;
229     } else {
230       m->sharpen_[i] = 0;
231     }
232     sum += m->q_[i];
233   }
234   return (sum + 8) >> 4;
235 }
236 
CheckLambdaValue(int * const v)237 static void CheckLambdaValue(int* const v) { if (*v < 1) *v = 1; }
238 
SetupMatrices(VP8Encoder * enc)239 static void SetupMatrices(VP8Encoder* enc) {
240   int i;
241   const int tlambda_scale =
242     (enc->method_ >= 4) ? enc->config_->sns_strength
243                         : 0;
244   const int num_segments = enc->segment_hdr_.num_segments_;
245   for (i = 0; i < num_segments; ++i) {
246     VP8SegmentInfo* const m = &enc->dqm_[i];
247     const int q = m->quant_;
248     int q_i4, q_i16, q_uv;
249     m->y1_.q_[0] = kDcTable[clip(q + enc->dq_y1_dc_, 0, 127)];
250     m->y1_.q_[1] = kAcTable[clip(q,                  0, 127)];
251 
252     m->y2_.q_[0] = kDcTable[ clip(q + enc->dq_y2_dc_, 0, 127)] * 2;
253     m->y2_.q_[1] = kAcTable2[clip(q + enc->dq_y2_ac_, 0, 127)];
254 
255     m->uv_.q_[0] = kDcTable[clip(q + enc->dq_uv_dc_, 0, 117)];
256     m->uv_.q_[1] = kAcTable[clip(q + enc->dq_uv_ac_, 0, 127)];
257 
258     q_i4  = ExpandMatrix(&m->y1_, 0);
259     q_i16 = ExpandMatrix(&m->y2_, 1);
260     q_uv  = ExpandMatrix(&m->uv_, 2);
261 
262     m->lambda_i4_          = (3 * q_i4 * q_i4) >> 7;
263     m->lambda_i16_         = (3 * q_i16 * q_i16);
264     m->lambda_uv_          = (3 * q_uv * q_uv) >> 6;
265     m->lambda_mode_        = (1 * q_i4 * q_i4) >> 7;
266     m->lambda_trellis_i4_  = (7 * q_i4 * q_i4) >> 3;
267     m->lambda_trellis_i16_ = (q_i16 * q_i16) >> 2;
268     m->lambda_trellis_uv_  = (q_uv * q_uv) << 1;
269     m->tlambda_            = (tlambda_scale * q_i4) >> 5;
270 
271     // none of these constants should be < 1
272     CheckLambdaValue(&m->lambda_i4_);
273     CheckLambdaValue(&m->lambda_i16_);
274     CheckLambdaValue(&m->lambda_uv_);
275     CheckLambdaValue(&m->lambda_mode_);
276     CheckLambdaValue(&m->lambda_trellis_i4_);
277     CheckLambdaValue(&m->lambda_trellis_i16_);
278     CheckLambdaValue(&m->lambda_trellis_uv_);
279     CheckLambdaValue(&m->tlambda_);
280 
281     m->min_disto_ = 20 * m->y1_.q_[0];   // quantization-aware min disto
282     m->max_edge_  = 0;
283 
284     m->i4_penalty_ = 1000 * q_i4 * q_i4;
285   }
286 }
287 
288 //------------------------------------------------------------------------------
289 // Initialize filtering parameters
290 
291 // Very small filter-strength values have close to no visual effect. So we can
292 // save a little decoding-CPU by turning filtering off for these.
293 #define FSTRENGTH_CUTOFF 2
294 
SetupFilterStrength(VP8Encoder * const enc)295 static void SetupFilterStrength(VP8Encoder* const enc) {
296   int i;
297   // level0 is in [0..500]. Using '-f 50' as filter_strength is mid-filtering.
298   const int level0 = 5 * enc->config_->filter_strength;
299   for (i = 0; i < NUM_MB_SEGMENTS; ++i) {
300     VP8SegmentInfo* const m = &enc->dqm_[i];
301     // We focus on the quantization of AC coeffs.
302     const int qstep = kAcTable[clip(m->quant_, 0, 127)] >> 2;
303     const int base_strength =
304         VP8FilterStrengthFromDelta(enc->filter_hdr_.sharpness_, qstep);
305     // Segments with lower complexity ('beta') will be less filtered.
306     const int f = base_strength * level0 / (256 + m->beta_);
307     m->fstrength_ = (f < FSTRENGTH_CUTOFF) ? 0 : (f > 63) ? 63 : f;
308   }
309   // We record the initial strength (mainly for the case of 1-segment only).
310   enc->filter_hdr_.level_ = enc->dqm_[0].fstrength_;
311   enc->filter_hdr_.simple_ = (enc->config_->filter_type == 0);
312   enc->filter_hdr_.sharpness_ = enc->config_->filter_sharpness;
313 }
314 
315 //------------------------------------------------------------------------------
316 
317 // Note: if you change the values below, remember that the max range
318 // allowed by the syntax for DQ_UV is [-16,16].
319 #define MAX_DQ_UV (6)
320 #define MIN_DQ_UV (-4)
321 
322 // We want to emulate jpeg-like behaviour where the expected "good" quality
323 // is around q=75. Internally, our "good" middle is around c=50. So we
324 // map accordingly using linear piece-wise function
QualityToCompression(double c)325 static double QualityToCompression(double c) {
326   const double linear_c = (c < 0.75) ? c * (2. / 3.) : 2. * c - 1.;
327   // The file size roughly scales as pow(quantizer, 3.). Actually, the
328   // exponent is somewhere between 2.8 and 3.2, but we're mostly interested
329   // in the mid-quant range. So we scale the compressibility inversely to
330   // this power-law: quant ~= compression ^ 1/3. This law holds well for
331   // low quant. Finer modeling for high-quant would make use of kAcTable[]
332   // more explicitly.
333   const double v = pow(linear_c, 1 / 3.);
334   return v;
335 }
336 
QualityToJPEGCompression(double c,double alpha)337 static double QualityToJPEGCompression(double c, double alpha) {
338   // We map the complexity 'alpha' and quality setting 'c' to a compression
339   // exponent empirically matched to the compression curve of libjpeg6b.
340   // On average, the WebP output size will be roughly similar to that of a
341   // JPEG file compressed with same quality factor.
342   const double amin = 0.30;
343   const double amax = 0.85;
344   const double exp_min = 0.4;
345   const double exp_max = 0.9;
346   const double slope = (exp_min - exp_max) / (amax - amin);
347   // Linearly interpolate 'expn' from exp_min to exp_max
348   // in the [amin, amax] range.
349   const double expn = (alpha > amax) ? exp_min
350                     : (alpha < amin) ? exp_max
351                     : exp_max + slope * (alpha - amin);
352   const double v = pow(c, expn);
353   return v;
354 }
355 
SegmentsAreEquivalent(const VP8SegmentInfo * const S1,const VP8SegmentInfo * const S2)356 static int SegmentsAreEquivalent(const VP8SegmentInfo* const S1,
357                                  const VP8SegmentInfo* const S2) {
358   return (S1->quant_ == S2->quant_) && (S1->fstrength_ == S2->fstrength_);
359 }
360 
SimplifySegments(VP8Encoder * const enc)361 static void SimplifySegments(VP8Encoder* const enc) {
362   int map[NUM_MB_SEGMENTS] = { 0, 1, 2, 3 };
363   // 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an
364   // explicit check is needed to avoid a spurious warning about 'i' exceeding
365   // array bounds of 'dqm_' with some compilers (noticed with gcc-4.9).
366   const int num_segments = (enc->segment_hdr_.num_segments_ < NUM_MB_SEGMENTS)
367                                ? enc->segment_hdr_.num_segments_
368                                : NUM_MB_SEGMENTS;
369   int num_final_segments = 1;
370   int s1, s2;
371   for (s1 = 1; s1 < num_segments; ++s1) {    // find similar segments
372     const VP8SegmentInfo* const S1 = &enc->dqm_[s1];
373     int found = 0;
374     // check if we already have similar segment
375     for (s2 = 0; s2 < num_final_segments; ++s2) {
376       const VP8SegmentInfo* const S2 = &enc->dqm_[s2];
377       if (SegmentsAreEquivalent(S1, S2)) {
378         found = 1;
379         break;
380       }
381     }
382     map[s1] = s2;
383     if (!found) {
384       if (num_final_segments != s1) {
385         enc->dqm_[num_final_segments] = enc->dqm_[s1];
386       }
387       ++num_final_segments;
388     }
389   }
390   if (num_final_segments < num_segments) {  // Remap
391     int i = enc->mb_w_ * enc->mb_h_;
392     while (i-- > 0) enc->mb_info_[i].segment_ = map[enc->mb_info_[i].segment_];
393     enc->segment_hdr_.num_segments_ = num_final_segments;
394     // Replicate the trailing segment infos (it's mostly cosmetics)
395     for (i = num_final_segments; i < num_segments; ++i) {
396       enc->dqm_[i] = enc->dqm_[num_final_segments - 1];
397     }
398   }
399 }
400 
VP8SetSegmentParams(VP8Encoder * const enc,float quality)401 void VP8SetSegmentParams(VP8Encoder* const enc, float quality) {
402   int i;
403   int dq_uv_ac, dq_uv_dc;
404   const int num_segments = enc->segment_hdr_.num_segments_;
405   const double amp = SNS_TO_DQ * enc->config_->sns_strength / 100. / 128.;
406   const double Q = quality / 100.;
407   const double c_base = enc->config_->emulate_jpeg_size ?
408       QualityToJPEGCompression(Q, enc->alpha_ / 255.) :
409       QualityToCompression(Q);
410   for (i = 0; i < num_segments; ++i) {
411     // We modulate the base coefficient to accommodate for the quantization
412     // susceptibility and allow denser segments to be quantized more.
413     const double expn = 1. - amp * enc->dqm_[i].alpha_;
414     const double c = pow(c_base, expn);
415     const int q = (int)(127. * (1. - c));
416     assert(expn > 0.);
417     enc->dqm_[i].quant_ = clip(q, 0, 127);
418   }
419 
420   // purely indicative in the bitstream (except for the 1-segment case)
421   enc->base_quant_ = enc->dqm_[0].quant_;
422 
423   // fill-in values for the unused segments (required by the syntax)
424   for (i = num_segments; i < NUM_MB_SEGMENTS; ++i) {
425     enc->dqm_[i].quant_ = enc->base_quant_;
426   }
427 
428   // uv_alpha_ is normally spread around ~60. The useful range is
429   // typically ~30 (quite bad) to ~100 (ok to decimate UV more).
430   // We map it to the safe maximal range of MAX/MIN_DQ_UV for dq_uv.
431   dq_uv_ac = (enc->uv_alpha_ - MID_ALPHA) * (MAX_DQ_UV - MIN_DQ_UV)
432                                           / (MAX_ALPHA - MIN_ALPHA);
433   // we rescale by the user-defined strength of adaptation
434   dq_uv_ac = dq_uv_ac * enc->config_->sns_strength / 100;
435   // and make it safe.
436   dq_uv_ac = clip(dq_uv_ac, MIN_DQ_UV, MAX_DQ_UV);
437   // We also boost the dc-uv-quant a little, based on sns-strength, since
438   // U/V channels are quite more reactive to high quants (flat DC-blocks
439   // tend to appear, and are unpleasant).
440   dq_uv_dc = -4 * enc->config_->sns_strength / 100;
441   dq_uv_dc = clip(dq_uv_dc, -15, 15);   // 4bit-signed max allowed
442 
443   enc->dq_y1_dc_ = 0;       // TODO(skal): dq-lum
444   enc->dq_y2_dc_ = 0;
445   enc->dq_y2_ac_ = 0;
446   enc->dq_uv_dc_ = dq_uv_dc;
447   enc->dq_uv_ac_ = dq_uv_ac;
448 
449   SetupFilterStrength(enc);   // initialize segments' filtering, eventually
450 
451   if (num_segments > 1) SimplifySegments(enc);
452 
453   SetupMatrices(enc);         // finalize quantization matrices
454 }
455 
456 //------------------------------------------------------------------------------
457 // Form the predictions in cache
458 
459 // Must be ordered using {DC_PRED, TM_PRED, V_PRED, H_PRED} as index
460 const uint16_t VP8I16ModeOffsets[4] = { I16DC16, I16TM16, I16VE16, I16HE16 };
461 const uint16_t VP8UVModeOffsets[4] = { C8DC8, C8TM8, C8VE8, C8HE8 };
462 
463 // Must be indexed using {B_DC_PRED -> B_HU_PRED} as index
464 const uint16_t VP8I4ModeOffsets[NUM_BMODES] = {
465   I4DC4, I4TM4, I4VE4, I4HE4, I4RD4, I4VR4, I4LD4, I4VL4, I4HD4, I4HU4
466 };
467 
VP8MakeLuma16Preds(const VP8EncIterator * const it)468 void VP8MakeLuma16Preds(const VP8EncIterator* const it) {
469   const uint8_t* const left = it->x_ ? it->y_left_ : NULL;
470   const uint8_t* const top = it->y_ ? it->y_top_ : NULL;
471   VP8EncPredLuma16(it->yuv_p_, left, top);
472 }
473 
VP8MakeChroma8Preds(const VP8EncIterator * const it)474 void VP8MakeChroma8Preds(const VP8EncIterator* const it) {
475   const uint8_t* const left = it->x_ ? it->u_left_ : NULL;
476   const uint8_t* const top = it->y_ ? it->uv_top_ : NULL;
477   VP8EncPredChroma8(it->yuv_p_, left, top);
478 }
479 
VP8MakeIntra4Preds(const VP8EncIterator * const it)480 void VP8MakeIntra4Preds(const VP8EncIterator* const it) {
481   VP8EncPredLuma4(it->yuv_p_, it->i4_top_);
482 }
483 
484 //------------------------------------------------------------------------------
485 // Quantize
486 
487 // Layout:
488 // +----+----+
489 // |YYYY|UUVV| 0
490 // |YYYY|UUVV| 4
491 // |YYYY|....| 8
492 // |YYYY|....| 12
493 // +----+----+
494 
495 const uint16_t VP8Scan[16] = {  // Luma
496   0 +  0 * BPS,  4 +  0 * BPS, 8 +  0 * BPS, 12 +  0 * BPS,
497   0 +  4 * BPS,  4 +  4 * BPS, 8 +  4 * BPS, 12 +  4 * BPS,
498   0 +  8 * BPS,  4 +  8 * BPS, 8 +  8 * BPS, 12 +  8 * BPS,
499   0 + 12 * BPS,  4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS,
500 };
501 
502 static const uint16_t VP8ScanUV[4 + 4] = {
503   0 + 0 * BPS,   4 + 0 * BPS, 0 + 4 * BPS,  4 + 4 * BPS,    // U
504   8 + 0 * BPS,  12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS     // V
505 };
506 
507 //------------------------------------------------------------------------------
508 // Distortion measurement
509 
510 static const uint16_t kWeightY[16] = {
511   38, 32, 20, 9, 32, 28, 17, 7, 20, 17, 10, 4, 9, 7, 4, 2
512 };
513 
514 static const uint16_t kWeightTrellis[16] = {
515 #if USE_TDISTO == 0
516   16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
517 #else
518   30, 27, 19, 11,
519   27, 24, 17, 10,
520   19, 17, 12,  8,
521   11, 10,  8,  6
522 #endif
523 };
524 
525 // Init/Copy the common fields in score.
InitScore(VP8ModeScore * const rd)526 static void InitScore(VP8ModeScore* const rd) {
527   rd->D  = 0;
528   rd->SD = 0;
529   rd->R  = 0;
530   rd->H  = 0;
531   rd->nz = 0;
532   rd->score = MAX_COST;
533 }
534 
CopyScore(VP8ModeScore * const dst,const VP8ModeScore * const src)535 static void CopyScore(VP8ModeScore* const dst, const VP8ModeScore* const src) {
536   dst->D  = src->D;
537   dst->SD = src->SD;
538   dst->R  = src->R;
539   dst->H  = src->H;
540   dst->nz = src->nz;      // note that nz is not accumulated, but just copied.
541   dst->score = src->score;
542 }
543 
AddScore(VP8ModeScore * const dst,const VP8ModeScore * const src)544 static void AddScore(VP8ModeScore* const dst, const VP8ModeScore* const src) {
545   dst->D  += src->D;
546   dst->SD += src->SD;
547   dst->R  += src->R;
548   dst->H  += src->H;
549   dst->nz |= src->nz;     // here, new nz bits are accumulated.
550   dst->score += src->score;
551 }
552 
553 //------------------------------------------------------------------------------
554 // Performs trellis-optimized quantization.
555 
556 // Trellis node
557 typedef struct {
558   int8_t prev;            // best previous node
559   int8_t sign;            // sign of coeff_i
560   int16_t level;          // level
561 } Node;
562 
563 // Score state
564 typedef struct {
565   score_t score;          // partial RD score
566   const uint16_t* costs;  // shortcut to cost tables
567 } ScoreState;
568 
569 // If a coefficient was quantized to a value Q (using a neutral bias),
570 // we test all alternate possibilities between [Q-MIN_DELTA, Q+MAX_DELTA]
571 // We don't test negative values though.
572 #define MIN_DELTA 0   // how much lower level to try
573 #define MAX_DELTA 1   // how much higher
574 #define NUM_NODES (MIN_DELTA + 1 + MAX_DELTA)
575 #define NODE(n, l) (nodes[(n)][(l) + MIN_DELTA])
576 #define SCORE_STATE(n, l) (score_states[n][(l) + MIN_DELTA])
577 
SetRDScore(int lambda,VP8ModeScore * const rd)578 static WEBP_INLINE void SetRDScore(int lambda, VP8ModeScore* const rd) {
579   rd->score = (rd->R + rd->H) * lambda + RD_DISTO_MULT * (rd->D + rd->SD);
580 }
581 
RDScoreTrellis(int lambda,score_t rate,score_t distortion)582 static WEBP_INLINE score_t RDScoreTrellis(int lambda, score_t rate,
583                                           score_t distortion) {
584   return rate * lambda + RD_DISTO_MULT * distortion;
585 }
586 
TrellisQuantizeBlock(const VP8Encoder * const enc,int16_t in[16],int16_t out[16],int ctx0,int coeff_type,const VP8Matrix * const mtx,int lambda)587 static int TrellisQuantizeBlock(const VP8Encoder* const enc,
588                                 int16_t in[16], int16_t out[16],
589                                 int ctx0, int coeff_type,
590                                 const VP8Matrix* const mtx,
591                                 int lambda) {
592   const ProbaArray* const probas = enc->proba_.coeffs_[coeff_type];
593   CostArrayPtr const costs =
594       (CostArrayPtr)enc->proba_.remapped_costs_[coeff_type];
595   const int first = (coeff_type == 0) ? 1 : 0;
596   Node nodes[16][NUM_NODES];
597   ScoreState score_states[2][NUM_NODES];
598   ScoreState* ss_cur = &SCORE_STATE(0, MIN_DELTA);
599   ScoreState* ss_prev = &SCORE_STATE(1, MIN_DELTA);
600   int best_path[3] = {-1, -1, -1};   // store best-last/best-level/best-previous
601   score_t best_score;
602   int n, m, p, last;
603 
604   {
605     score_t cost;
606     const int thresh = mtx->q_[1] * mtx->q_[1] / 4;
607     const int last_proba = probas[VP8EncBands[first]][ctx0][0];
608 
609     // compute the position of the last interesting coefficient
610     last = first - 1;
611     for (n = 15; n >= first; --n) {
612       const int j = kZigzag[n];
613       const int err = in[j] * in[j];
614       if (err > thresh) {
615         last = n;
616         break;
617       }
618     }
619     // we don't need to go inspect up to n = 16 coeffs. We can just go up
620     // to last + 1 (inclusive) without losing much.
621     if (last < 15) ++last;
622 
623     // compute 'skip' score. This is the max score one can do.
624     cost = VP8BitCost(0, last_proba);
625     best_score = RDScoreTrellis(lambda, cost, 0);
626 
627     // initialize source node.
628     for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) {
629       const score_t rate = (ctx0 == 0) ? VP8BitCost(1, last_proba) : 0;
630       ss_cur[m].score = RDScoreTrellis(lambda, rate, 0);
631       ss_cur[m].costs = costs[first][ctx0];
632     }
633   }
634 
635   // traverse trellis.
636   for (n = first; n <= last; ++n) {
637     const int j = kZigzag[n];
638     const uint32_t Q  = mtx->q_[j];
639     const uint32_t iQ = mtx->iq_[j];
640     const uint32_t B = BIAS(0x00);     // neutral bias
641     // note: it's important to take sign of the _original_ coeff,
642     // so we don't have to consider level < 0 afterward.
643     const int sign = (in[j] < 0);
644     const uint32_t coeff0 = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
645     int level0 = QUANTDIV(coeff0, iQ, B);
646     int thresh_level = QUANTDIV(coeff0, iQ, BIAS(0x80));
647     if (thresh_level > MAX_LEVEL) thresh_level = MAX_LEVEL;
648     if (level0 > MAX_LEVEL) level0 = MAX_LEVEL;
649 
650     {   // Swap current and previous score states
651       ScoreState* const tmp = ss_cur;
652       ss_cur = ss_prev;
653       ss_prev = tmp;
654     }
655 
656     // test all alternate level values around level0.
657     for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) {
658       Node* const cur = &NODE(n, m);
659       int level = level0 + m;
660       const int ctx = (level > 2) ? 2 : level;
661       const int band = VP8EncBands[n + 1];
662       score_t base_score;
663       score_t best_cur_score = MAX_COST;
664       int best_prev = 0;   // default, in case
665 
666       ss_cur[m].score = MAX_COST;
667       ss_cur[m].costs = costs[n + 1][ctx];
668       if (level < 0 || level > thresh_level) {
669         // Node is dead.
670         continue;
671       }
672 
673       {
674         // Compute delta_error = how much coding this level will
675         // subtract to max_error as distortion.
676         // Here, distortion = sum of (|coeff_i| - level_i * Q_i)^2
677         const int new_error = coeff0 - level * Q;
678         const int delta_error =
679             kWeightTrellis[j] * (new_error * new_error - coeff0 * coeff0);
680         base_score = RDScoreTrellis(lambda, 0, delta_error);
681       }
682 
683       // Inspect all possible non-dead predecessors. Retain only the best one.
684       for (p = -MIN_DELTA; p <= MAX_DELTA; ++p) {
685         // Dead nodes (with ss_prev[p].score >= MAX_COST) are automatically
686         // eliminated since their score can't be better than the current best.
687         const score_t cost = VP8LevelCost(ss_prev[p].costs, level);
688         // Examine node assuming it's a non-terminal one.
689         const score_t score =
690             base_score + ss_prev[p].score + RDScoreTrellis(lambda, cost, 0);
691         if (score < best_cur_score) {
692           best_cur_score = score;
693           best_prev = p;
694         }
695       }
696       // Store best finding in current node.
697       cur->sign = sign;
698       cur->level = level;
699       cur->prev = best_prev;
700       ss_cur[m].score = best_cur_score;
701 
702       // Now, record best terminal node (and thus best entry in the graph).
703       if (level != 0) {
704         const score_t last_pos_cost =
705             (n < 15) ? VP8BitCost(0, probas[band][ctx][0]) : 0;
706         const score_t last_pos_score = RDScoreTrellis(lambda, last_pos_cost, 0);
707         const score_t score = best_cur_score + last_pos_score;
708         if (score < best_score) {
709           best_score = score;
710           best_path[0] = n;                     // best eob position
711           best_path[1] = m;                     // best node index
712           best_path[2] = best_prev;             // best predecessor
713         }
714       }
715     }
716   }
717 
718   // Fresh start
719   memset(in + first, 0, (16 - first) * sizeof(*in));
720   memset(out + first, 0, (16 - first) * sizeof(*out));
721   if (best_path[0] == -1) {
722     return 0;   // skip!
723   }
724 
725   {
726     // Unwind the best path.
727     // Note: best-prev on terminal node is not necessarily equal to the
728     // best_prev for non-terminal. So we patch best_path[2] in.
729     int nz = 0;
730     int best_node = best_path[1];
731     n = best_path[0];
732     NODE(n, best_node).prev = best_path[2];   // force best-prev for terminal
733 
734     for (; n >= first; --n) {
735       const Node* const node = &NODE(n, best_node);
736       const int j = kZigzag[n];
737       out[n] = node->sign ? -node->level : node->level;
738       nz |= node->level;
739       in[j] = out[n] * mtx->q_[j];
740       best_node = node->prev;
741     }
742     return (nz != 0);
743   }
744 }
745 
746 #undef NODE
747 
748 //------------------------------------------------------------------------------
749 // Performs: difference, transform, quantize, back-transform, add
750 // all at once. Output is the reconstructed block in *yuv_out, and the
751 // quantized levels in *levels.
752 
ReconstructIntra16(VP8EncIterator * const it,VP8ModeScore * const rd,uint8_t * const yuv_out,int mode)753 static int ReconstructIntra16(VP8EncIterator* const it,
754                               VP8ModeScore* const rd,
755                               uint8_t* const yuv_out,
756                               int mode) {
757   const VP8Encoder* const enc = it->enc_;
758   const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode];
759   const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC;
760   const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
761   int nz = 0;
762   int n;
763   int16_t tmp[16][16], dc_tmp[16];
764 
765   for (n = 0; n < 16; n += 2) {
766     VP8FTransform2(src + VP8Scan[n], ref + VP8Scan[n], tmp[n]);
767   }
768   VP8FTransformWHT(tmp[0], dc_tmp);
769   nz |= VP8EncQuantizeBlockWHT(dc_tmp, rd->y_dc_levels, &dqm->y2_) << 24;
770 
771   if (DO_TRELLIS_I16 && it->do_trellis_) {
772     int x, y;
773     VP8IteratorNzToBytes(it);
774     for (y = 0, n = 0; y < 4; ++y) {
775       for (x = 0; x < 4; ++x, ++n) {
776         const int ctx = it->top_nz_[x] + it->left_nz_[y];
777         const int non_zero =
778             TrellisQuantizeBlock(enc, tmp[n], rd->y_ac_levels[n], ctx, 0,
779                                  &dqm->y1_, dqm->lambda_trellis_i16_);
780         it->top_nz_[x] = it->left_nz_[y] = non_zero;
781         rd->y_ac_levels[n][0] = 0;
782         nz |= non_zero << n;
783       }
784     }
785   } else {
786     for (n = 0; n < 16; n += 2) {
787       // Zero-out the first coeff, so that: a) nz is correct below, and
788       // b) finding 'last' non-zero coeffs in SetResidualCoeffs() is simplified.
789       tmp[n][0] = tmp[n + 1][0] = 0;
790       nz |= VP8EncQuantize2Blocks(tmp[n], rd->y_ac_levels[n], &dqm->y1_) << n;
791       assert(rd->y_ac_levels[n + 0][0] == 0);
792       assert(rd->y_ac_levels[n + 1][0] == 0);
793     }
794   }
795 
796   // Transform back
797   VP8TransformWHT(dc_tmp, tmp[0]);
798   for (n = 0; n < 16; n += 2) {
799     VP8ITransform(ref + VP8Scan[n], tmp[n], yuv_out + VP8Scan[n], 1);
800   }
801 
802   return nz;
803 }
804 
ReconstructIntra4(VP8EncIterator * const it,int16_t levels[16],const uint8_t * const src,uint8_t * const yuv_out,int mode)805 static int ReconstructIntra4(VP8EncIterator* const it,
806                              int16_t levels[16],
807                              const uint8_t* const src,
808                              uint8_t* const yuv_out,
809                              int mode) {
810   const VP8Encoder* const enc = it->enc_;
811   const uint8_t* const ref = it->yuv_p_ + VP8I4ModeOffsets[mode];
812   const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
813   int nz = 0;
814   int16_t tmp[16];
815 
816   VP8FTransform(src, ref, tmp);
817   if (DO_TRELLIS_I4 && it->do_trellis_) {
818     const int x = it->i4_ & 3, y = it->i4_ >> 2;
819     const int ctx = it->top_nz_[x] + it->left_nz_[y];
820     nz = TrellisQuantizeBlock(enc, tmp, levels, ctx, 3, &dqm->y1_,
821                               dqm->lambda_trellis_i4_);
822   } else {
823     nz = VP8EncQuantizeBlock(tmp, levels, &dqm->y1_);
824   }
825   VP8ITransform(ref, tmp, yuv_out, 0);
826   return nz;
827 }
828 
ReconstructUV(VP8EncIterator * const it,VP8ModeScore * const rd,uint8_t * const yuv_out,int mode)829 static int ReconstructUV(VP8EncIterator* const it, VP8ModeScore* const rd,
830                          uint8_t* const yuv_out, int mode) {
831   const VP8Encoder* const enc = it->enc_;
832   const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode];
833   const uint8_t* const src = it->yuv_in_ + U_OFF_ENC;
834   const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
835   int nz = 0;
836   int n;
837   int16_t tmp[8][16];
838 
839   for (n = 0; n < 8; n += 2) {
840     VP8FTransform2(src + VP8ScanUV[n], ref + VP8ScanUV[n], tmp[n]);
841   }
842   if (DO_TRELLIS_UV && it->do_trellis_) {
843     int ch, x, y;
844     for (ch = 0, n = 0; ch <= 2; ch += 2) {
845       for (y = 0; y < 2; ++y) {
846         for (x = 0; x < 2; ++x, ++n) {
847           const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
848           const int non_zero =
849               TrellisQuantizeBlock(enc, tmp[n], rd->uv_levels[n], ctx, 2,
850                                    &dqm->uv_, dqm->lambda_trellis_uv_);
851           it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = non_zero;
852           nz |= non_zero << n;
853         }
854       }
855     }
856   } else {
857     for (n = 0; n < 8; n += 2) {
858       nz |= VP8EncQuantize2Blocks(tmp[n], rd->uv_levels[n], &dqm->uv_) << n;
859     }
860   }
861 
862   for (n = 0; n < 8; n += 2) {
863     VP8ITransform(ref + VP8ScanUV[n], tmp[n], yuv_out + VP8ScanUV[n], 1);
864   }
865   return (nz << 16);
866 }
867 
868 //------------------------------------------------------------------------------
869 // RD-opt decision. Reconstruct each modes, evalue distortion and bit-cost.
870 // Pick the mode is lower RD-cost = Rate + lambda * Distortion.
871 
StoreMaxDelta(VP8SegmentInfo * const dqm,const int16_t DCs[16])872 static void StoreMaxDelta(VP8SegmentInfo* const dqm, const int16_t DCs[16]) {
873   // We look at the first three AC coefficients to determine what is the average
874   // delta between each sub-4x4 block.
875   const int v0 = abs(DCs[1]);
876   const int v1 = abs(DCs[2]);
877   const int v2 = abs(DCs[4]);
878   int max_v = (v1 > v0) ? v1 : v0;
879   max_v = (v2 > max_v) ? v2 : max_v;
880   if (max_v > dqm->max_edge_) dqm->max_edge_ = max_v;
881 }
882 
SwapModeScore(VP8ModeScore ** a,VP8ModeScore ** b)883 static void SwapModeScore(VP8ModeScore** a, VP8ModeScore** b) {
884   VP8ModeScore* const tmp = *a;
885   *a = *b;
886   *b = tmp;
887 }
888 
SwapPtr(uint8_t ** a,uint8_t ** b)889 static void SwapPtr(uint8_t** a, uint8_t** b) {
890   uint8_t* const tmp = *a;
891   *a = *b;
892   *b = tmp;
893 }
894 
SwapOut(VP8EncIterator * const it)895 static void SwapOut(VP8EncIterator* const it) {
896   SwapPtr(&it->yuv_out_, &it->yuv_out2_);
897 }
898 
IsFlat(const int16_t * levels,int num_blocks,score_t thresh)899 static score_t IsFlat(const int16_t* levels, int num_blocks, score_t thresh) {
900   score_t score = 0;
901   while (num_blocks-- > 0) {      // TODO(skal): refine positional scoring?
902     int i;
903     for (i = 1; i < 16; ++i) {    // omit DC, we're only interested in AC
904       score += (levels[i] != 0);
905       if (score > thresh) return 0;
906     }
907     levels += 16;
908   }
909   return 1;
910 }
911 
PickBestIntra16(VP8EncIterator * const it,VP8ModeScore * rd)912 static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* rd) {
913   const int kNumBlocks = 16;
914   VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_];
915   const int lambda = dqm->lambda_i16_;
916   const int tlambda = dqm->tlambda_;
917   const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC;
918   VP8ModeScore rd_tmp;
919   VP8ModeScore* rd_cur = &rd_tmp;
920   VP8ModeScore* rd_best = rd;
921   int mode;
922 
923   rd->mode_i16 = -1;
924   for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
925     uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF_ENC;  // scratch buffer
926     rd_cur->mode_i16 = mode;
927 
928     // Reconstruct
929     rd_cur->nz = ReconstructIntra16(it, rd_cur, tmp_dst, mode);
930 
931     // Measure RD-score
932     rd_cur->D = VP8SSE16x16(src, tmp_dst);
933     rd_cur->SD =
934         tlambda ? MULT_8B(tlambda, VP8TDisto16x16(src, tmp_dst, kWeightY)) : 0;
935     rd_cur->H = VP8FixedCostsI16[mode];
936     rd_cur->R = VP8GetCostLuma16(it, rd_cur);
937     if (mode > 0 &&
938         IsFlat(rd_cur->y_ac_levels[0], kNumBlocks, FLATNESS_LIMIT_I16)) {
939       // penalty to avoid flat area to be mispredicted by complex mode
940       rd_cur->R += FLATNESS_PENALTY * kNumBlocks;
941     }
942 
943     // Since we always examine Intra16 first, we can overwrite *rd directly.
944     SetRDScore(lambda, rd_cur);
945     if (mode == 0 || rd_cur->score < rd_best->score) {
946       SwapModeScore(&rd_cur, &rd_best);
947       SwapOut(it);
948     }
949   }
950   if (rd_best != rd) {
951     memcpy(rd, rd_best, sizeof(*rd));
952   }
953   SetRDScore(dqm->lambda_mode_, rd);   // finalize score for mode decision.
954   VP8SetIntra16Mode(it, rd->mode_i16);
955 
956   // we have a blocky macroblock (only DCs are non-zero) with fairly high
957   // distortion, record max delta so we can later adjust the minimal filtering
958   // strength needed to smooth these blocks out.
959   if ((rd->nz & 0x100ffff) == 0x1000000 && rd->D > dqm->min_disto_) {
960     StoreMaxDelta(dqm, rd->y_dc_levels);
961   }
962 }
963 
964 //------------------------------------------------------------------------------
965 
966 // return the cost array corresponding to the surrounding prediction modes.
GetCostModeI4(VP8EncIterator * const it,const uint8_t modes[16])967 static const uint16_t* GetCostModeI4(VP8EncIterator* const it,
968                                      const uint8_t modes[16]) {
969   const int preds_w = it->enc_->preds_w_;
970   const int x = (it->i4_ & 3), y = it->i4_ >> 2;
971   const int left = (x == 0) ? it->preds_[y * preds_w - 1] : modes[it->i4_ - 1];
972   const int top = (y == 0) ? it->preds_[-preds_w + x] : modes[it->i4_ - 4];
973   return VP8FixedCostsI4[top][left];
974 }
975 
PickBestIntra4(VP8EncIterator * const it,VP8ModeScore * const rd)976 static int PickBestIntra4(VP8EncIterator* const it, VP8ModeScore* const rd) {
977   const VP8Encoder* const enc = it->enc_;
978   const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
979   const int lambda = dqm->lambda_i4_;
980   const int tlambda = dqm->tlambda_;
981   const uint8_t* const src0 = it->yuv_in_ + Y_OFF_ENC;
982   uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF_ENC;
983   int total_header_bits = 0;
984   VP8ModeScore rd_best;
985 
986   if (enc->max_i4_header_bits_ == 0) {
987     return 0;
988   }
989 
990   InitScore(&rd_best);
991   rd_best.H = 211;  // '211' is the value of VP8BitCost(0, 145)
992   SetRDScore(dqm->lambda_mode_, &rd_best);
993   VP8IteratorStartI4(it);
994   do {
995     const int kNumBlocks = 1;
996     VP8ModeScore rd_i4;
997     int mode;
998     int best_mode = -1;
999     const uint8_t* const src = src0 + VP8Scan[it->i4_];
1000     const uint16_t* const mode_costs = GetCostModeI4(it, rd->modes_i4);
1001     uint8_t* best_block = best_blocks + VP8Scan[it->i4_];
1002     uint8_t* tmp_dst = it->yuv_p_ + I4TMP;    // scratch buffer.
1003 
1004     InitScore(&rd_i4);
1005     VP8MakeIntra4Preds(it);
1006     for (mode = 0; mode < NUM_BMODES; ++mode) {
1007       VP8ModeScore rd_tmp;
1008       int16_t tmp_levels[16];
1009 
1010       // Reconstruct
1011       rd_tmp.nz =
1012           ReconstructIntra4(it, tmp_levels, src, tmp_dst, mode) << it->i4_;
1013 
1014       // Compute RD-score
1015       rd_tmp.D = VP8SSE4x4(src, tmp_dst);
1016       rd_tmp.SD =
1017           tlambda ? MULT_8B(tlambda, VP8TDisto4x4(src, tmp_dst, kWeightY))
1018                   : 0;
1019       rd_tmp.H = mode_costs[mode];
1020 
1021       // Add flatness penalty
1022       if (mode > 0 && IsFlat(tmp_levels, kNumBlocks, FLATNESS_LIMIT_I4)) {
1023         rd_tmp.R = FLATNESS_PENALTY * kNumBlocks;
1024       } else {
1025         rd_tmp.R = 0;
1026       }
1027 
1028       // early-out check
1029       SetRDScore(lambda, &rd_tmp);
1030       if (best_mode >= 0 && rd_tmp.score >= rd_i4.score) continue;
1031 
1032       // finish computing score
1033       rd_tmp.R += VP8GetCostLuma4(it, tmp_levels);
1034       SetRDScore(lambda, &rd_tmp);
1035 
1036       if (best_mode < 0 || rd_tmp.score < rd_i4.score) {
1037         CopyScore(&rd_i4, &rd_tmp);
1038         best_mode = mode;
1039         SwapPtr(&tmp_dst, &best_block);
1040         memcpy(rd_best.y_ac_levels[it->i4_], tmp_levels,
1041                sizeof(rd_best.y_ac_levels[it->i4_]));
1042       }
1043     }
1044     SetRDScore(dqm->lambda_mode_, &rd_i4);
1045     AddScore(&rd_best, &rd_i4);
1046     if (rd_best.score >= rd->score) {
1047       return 0;
1048     }
1049     total_header_bits += (int)rd_i4.H;   // <- equal to mode_costs[best_mode];
1050     if (total_header_bits > enc->max_i4_header_bits_) {
1051       return 0;
1052     }
1053     // Copy selected samples if not in the right place already.
1054     if (best_block != best_blocks + VP8Scan[it->i4_]) {
1055       VP8Copy4x4(best_block, best_blocks + VP8Scan[it->i4_]);
1056     }
1057     rd->modes_i4[it->i4_] = best_mode;
1058     it->top_nz_[it->i4_ & 3] = it->left_nz_[it->i4_ >> 2] = (rd_i4.nz ? 1 : 0);
1059   } while (VP8IteratorRotateI4(it, best_blocks));
1060 
1061   // finalize state
1062   CopyScore(rd, &rd_best);
1063   VP8SetIntra4Mode(it, rd->modes_i4);
1064   SwapOut(it);
1065   memcpy(rd->y_ac_levels, rd_best.y_ac_levels, sizeof(rd->y_ac_levels));
1066   return 1;   // select intra4x4 over intra16x16
1067 }
1068 
1069 //------------------------------------------------------------------------------
1070 
PickBestUV(VP8EncIterator * const it,VP8ModeScore * const rd)1071 static void PickBestUV(VP8EncIterator* const it, VP8ModeScore* const rd) {
1072   const int kNumBlocks = 8;
1073   const VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_];
1074   const int lambda = dqm->lambda_uv_;
1075   const uint8_t* const src = it->yuv_in_ + U_OFF_ENC;
1076   uint8_t* tmp_dst = it->yuv_out2_ + U_OFF_ENC;  // scratch buffer
1077   uint8_t* dst0 = it->yuv_out_ + U_OFF_ENC;
1078   uint8_t* dst = dst0;
1079   VP8ModeScore rd_best;
1080   int mode;
1081 
1082   rd->mode_uv = -1;
1083   InitScore(&rd_best);
1084   for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
1085     VP8ModeScore rd_uv;
1086 
1087     // Reconstruct
1088     rd_uv.nz = ReconstructUV(it, &rd_uv, tmp_dst, mode);
1089 
1090     // Compute RD-score
1091     rd_uv.D  = VP8SSE16x8(src, tmp_dst);
1092     rd_uv.SD = 0;    // not calling TDisto here: it tends to flatten areas.
1093     rd_uv.H  = VP8FixedCostsUV[mode];
1094     rd_uv.R  = VP8GetCostUV(it, &rd_uv);
1095     if (mode > 0 && IsFlat(rd_uv.uv_levels[0], kNumBlocks, FLATNESS_LIMIT_UV)) {
1096       rd_uv.R += FLATNESS_PENALTY * kNumBlocks;
1097     }
1098 
1099     SetRDScore(lambda, &rd_uv);
1100     if (mode == 0 || rd_uv.score < rd_best.score) {
1101       CopyScore(&rd_best, &rd_uv);
1102       rd->mode_uv = mode;
1103       memcpy(rd->uv_levels, rd_uv.uv_levels, sizeof(rd->uv_levels));
1104       SwapPtr(&dst, &tmp_dst);
1105     }
1106   }
1107   VP8SetIntraUVMode(it, rd->mode_uv);
1108   AddScore(rd, &rd_best);
1109   if (dst != dst0) {   // copy 16x8 block if needed
1110     VP8Copy16x8(dst, dst0);
1111   }
1112 }
1113 
1114 //------------------------------------------------------------------------------
1115 // Final reconstruction and quantization.
1116 
SimpleQuantize(VP8EncIterator * const it,VP8ModeScore * const rd)1117 static void SimpleQuantize(VP8EncIterator* const it, VP8ModeScore* const rd) {
1118   const VP8Encoder* const enc = it->enc_;
1119   const int is_i16 = (it->mb_->type_ == 1);
1120   int nz = 0;
1121 
1122   if (is_i16) {
1123     nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF_ENC, it->preds_[0]);
1124   } else {
1125     VP8IteratorStartI4(it);
1126     do {
1127       const int mode =
1128           it->preds_[(it->i4_ & 3) + (it->i4_ >> 2) * enc->preds_w_];
1129       const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_];
1130       uint8_t* const dst = it->yuv_out_ + Y_OFF_ENC + VP8Scan[it->i4_];
1131       VP8MakeIntra4Preds(it);
1132       nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_],
1133                               src, dst, mode) << it->i4_;
1134     } while (VP8IteratorRotateI4(it, it->yuv_out_ + Y_OFF_ENC));
1135   }
1136 
1137   nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF_ENC, it->mb_->uv_mode_);
1138   rd->nz = nz;
1139 }
1140 
1141 // Refine intra16/intra4 sub-modes based on distortion only (not rate).
RefineUsingDistortion(VP8EncIterator * const it,int try_both_modes,int refine_uv_mode,VP8ModeScore * const rd)1142 static void RefineUsingDistortion(VP8EncIterator* const it,
1143                                   int try_both_modes, int refine_uv_mode,
1144                                   VP8ModeScore* const rd) {
1145   score_t best_score = MAX_COST;
1146   int nz = 0;
1147   int mode;
1148   int is_i16 = try_both_modes || (it->mb_->type_ == 1);
1149 
1150   const VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_];
1151   // Some empiric constants, of approximate order of magnitude.
1152   const int lambda_d_i16 = 106;
1153   const int lambda_d_i4 = 11;
1154   const int lambda_d_uv = 120;
1155   score_t score_i4 = dqm->i4_penalty_;
1156   score_t i4_bit_sum = 0;
1157   const score_t bit_limit = try_both_modes ? it->enc_->mb_header_limit_
1158                                            : MAX_COST;  // no early-out allowed
1159 
1160   if (is_i16) {   // First, evaluate Intra16 distortion
1161     int best_mode = -1;
1162     const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC;
1163     for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
1164       const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode];
1165       const score_t score = (score_t)VP8SSE16x16(src, ref) * RD_DISTO_MULT
1166                           + VP8FixedCostsI16[mode] * lambda_d_i16;
1167       if (mode > 0 && VP8FixedCostsI16[mode] > bit_limit) {
1168         continue;
1169       }
1170       if (score < best_score) {
1171         best_mode = mode;
1172         best_score = score;
1173       }
1174     }
1175     VP8SetIntra16Mode(it, best_mode);
1176     // we'll reconstruct later, if i16 mode actually gets selected
1177   }
1178 
1179   // Next, evaluate Intra4
1180   if (try_both_modes || !is_i16) {
1181     // We don't evaluate the rate here, but just account for it through a
1182     // constant penalty (i4 mode usually needs more bits compared to i16).
1183     is_i16 = 0;
1184     VP8IteratorStartI4(it);
1185     do {
1186       int best_i4_mode = -1;
1187       score_t best_i4_score = MAX_COST;
1188       const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_];
1189       const uint16_t* const mode_costs = GetCostModeI4(it, rd->modes_i4);
1190 
1191       VP8MakeIntra4Preds(it);
1192       for (mode = 0; mode < NUM_BMODES; ++mode) {
1193         const uint8_t* const ref = it->yuv_p_ + VP8I4ModeOffsets[mode];
1194         const score_t score = VP8SSE4x4(src, ref) * RD_DISTO_MULT
1195                             + mode_costs[mode] * lambda_d_i4;
1196         if (score < best_i4_score) {
1197           best_i4_mode = mode;
1198           best_i4_score = score;
1199         }
1200       }
1201       i4_bit_sum += mode_costs[best_i4_mode];
1202       rd->modes_i4[it->i4_] = best_i4_mode;
1203       score_i4 += best_i4_score;
1204       if (score_i4 >= best_score || i4_bit_sum > bit_limit) {
1205         // Intra4 won't be better than Intra16. Bail out and pick Intra16.
1206         is_i16 = 1;
1207         break;
1208       } else {  // reconstruct partial block inside yuv_out2_ buffer
1209         uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF_ENC + VP8Scan[it->i4_];
1210         nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_],
1211                                 src, tmp_dst, best_i4_mode) << it->i4_;
1212       }
1213     } while (VP8IteratorRotateI4(it, it->yuv_out2_ + Y_OFF_ENC));
1214   }
1215 
1216   // Final reconstruction, depending on which mode is selected.
1217   if (!is_i16) {
1218     VP8SetIntra4Mode(it, rd->modes_i4);
1219     SwapOut(it);
1220     best_score = score_i4;
1221   } else {
1222     nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF_ENC, it->preds_[0]);
1223   }
1224 
1225   // ... and UV!
1226   if (refine_uv_mode) {
1227     int best_mode = -1;
1228     score_t best_uv_score = MAX_COST;
1229     const uint8_t* const src = it->yuv_in_ + U_OFF_ENC;
1230     for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
1231       const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode];
1232       const score_t score = VP8SSE16x8(src, ref) * RD_DISTO_MULT
1233                           + VP8FixedCostsUV[mode] * lambda_d_uv;
1234       if (score < best_uv_score) {
1235         best_mode = mode;
1236         best_uv_score = score;
1237       }
1238     }
1239     VP8SetIntraUVMode(it, best_mode);
1240   }
1241   nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF_ENC, it->mb_->uv_mode_);
1242 
1243   rd->nz = nz;
1244   rd->score = best_score;
1245 }
1246 
1247 //------------------------------------------------------------------------------
1248 // Entry point
1249 
VP8Decimate(VP8EncIterator * const it,VP8ModeScore * const rd,VP8RDLevel rd_opt)1250 int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd,
1251                 VP8RDLevel rd_opt) {
1252   int is_skipped;
1253   const int method = it->enc_->method_;
1254 
1255   InitScore(rd);
1256 
1257   // We can perform predictions for Luma16x16 and Chroma8x8 already.
1258   // Luma4x4 predictions needs to be done as-we-go.
1259   VP8MakeLuma16Preds(it);
1260   VP8MakeChroma8Preds(it);
1261 
1262   if (rd_opt > RD_OPT_NONE) {
1263     it->do_trellis_ = (rd_opt >= RD_OPT_TRELLIS_ALL);
1264     PickBestIntra16(it, rd);
1265     if (method >= 2) {
1266       PickBestIntra4(it, rd);
1267     }
1268     PickBestUV(it, rd);
1269     if (rd_opt == RD_OPT_TRELLIS) {   // finish off with trellis-optim now
1270       it->do_trellis_ = 1;
1271       SimpleQuantize(it, rd);
1272     }
1273   } else {
1274     // At this point we have heuristically decided intra16 / intra4.
1275     // For method >= 2, pick the best intra4/intra16 based on SSE (~tad slower).
1276     // For method <= 1, we don't re-examine the decision but just go ahead with
1277     // quantization/reconstruction.
1278     RefineUsingDistortion(it, (method >= 2), (method >= 1), rd);
1279   }
1280   is_skipped = (rd->nz == 0);
1281   VP8SetSkip(it, is_skipped);
1282   return is_skipped;
1283 }
1284