vp9_quantize.c 11.6 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5
6
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
7
 *  in the file PATENTS.  All contributing project authors may
8
 *  be found in the AUTHORS file in the root of the source tree.
John Koleszar's avatar
John Koleszar committed
9
10
11
12
13
 */

#include <math.h>
#include "vpx_mem/vpx_mem.h"

14
15
#include "vp9/encoder/vp9_onyx_int.h"
#include "vp9/encoder/vp9_quantize.h"
16
#include "vp9/common/vp9_quant_common.h"
John Koleszar's avatar
John Koleszar committed
17

18
#include "vp9/common/vp9_seg_common.h"
19

20
21
22
23
#ifdef ENC_DEBUG
extern int enc_debug;
#endif

24
25
26
27
28
29
void vp9_quantize_b_c(int16_t *coeff_ptr, intptr_t n_coeffs, int skip_block,
                      int16_t *zbin_ptr, int16_t *round_ptr, int16_t *quant_ptr,
                      int16_t *quant_shift_ptr, int16_t *qcoeff_ptr,
                      int16_t *dqcoeff_ptr, int16_t *dequant_ptr,
                      int zbin_oq_value, uint16_t *eob_ptr, const int16_t *scan,
                      const int16_t *iscan) {
Yunqing Wang's avatar
Yunqing Wang committed
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  int i, rc, eob;
  int zbins[2], nzbins[2], zbin;
  int x, y, z, sz;
  int zero_flag = n_coeffs;

  vpx_memset(qcoeff_ptr, 0, n_coeffs*sizeof(int16_t));
  vpx_memset(dqcoeff_ptr, 0, n_coeffs*sizeof(int16_t));

  eob = -1;

  // Base ZBIN
  zbins[0] = zbin_ptr[0] + zbin_oq_value;
  zbins[1] = zbin_ptr[1] + zbin_oq_value;
  nzbins[0] = zbins[0] * -1;
  nzbins[1] = zbins[1] * -1;

  if (!skip_block) {
    // Pre-scan pass
    for (i = n_coeffs - 1; i >= 0; i--) {
      rc = scan[i];
50
      z = coeff_ptr[rc];
Yunqing Wang's avatar
Yunqing Wang committed
51
52
53
54
55
56
57
58
59
60
61
62

      if (z < zbins[rc != 0] && z > nzbins[rc != 0]) {
        zero_flag--;
      } else {
        break;
      }
    }

    // Quantization pass: All coefficients with index >= zero_flag are
    // skippable. Note: zero_flag can be zero.
    for (i = 0; i < zero_flag; i++) {
      rc = scan[i];
63
      z  = coeff_ptr[rc];
Yunqing Wang's avatar
Yunqing Wang committed
64

65
      zbin = (zbins[rc != 0]);
Yunqing Wang's avatar
Yunqing Wang committed
66
67
68
69
70
71

      sz = (z >> 31);                               // sign of z
      x  = (z ^ sz) - sz;

      if (x >= zbin) {
        x += (round_ptr[rc != 0]);
72
        x  = clamp(x, INT16_MIN, INT16_MAX);
73
74
        y  = (((int)(((int)(x * quant_ptr[rc != 0]) >> 16) + x)) *
              quant_shift_ptr[rc != 0]) >> 16;      // quantize (x)
Yunqing Wang's avatar
Yunqing Wang committed
75
76
        x  = (y ^ sz) - sz;                         // get the sign back
        qcoeff_ptr[rc]  = x;                        // write to destination
77
        dqcoeff_ptr[rc] = x * dequant_ptr[rc != 0];  // dequantized value
Yunqing Wang's avatar
Yunqing Wang committed
78
79
80
81
82
83
84
85
86
87

        if (y) {
          eob = i;                                  // last nonzero coeffs
        }
      }
    }
  }
  *eob_ptr = eob + 1;
}

88
void vp9_quantize_b_32x32_c(int16_t *coeff_ptr, intptr_t n_coeffs,
89
                            int skip_block,
Yunqing Wang's avatar
Yunqing Wang committed
90
                            int16_t *zbin_ptr, int16_t *round_ptr,
91
                            int16_t *quant_ptr, int16_t *quant_shift_ptr,
Yunqing Wang's avatar
Yunqing Wang committed
92
93
                            int16_t *qcoeff_ptr, int16_t *dqcoeff_ptr,
                            int16_t *dequant_ptr, int zbin_oq_value,
94
                            uint16_t *eob_ptr, const int16_t *scan,
95
                            const int16_t *iscan) {
Yunqing Wang's avatar
Yunqing Wang committed
96
  int i, rc, eob;
97
  int zbins[2], nzbins[2];
Yunqing Wang's avatar
Yunqing Wang committed
98
99
  int x, y, z, sz;
  int idx = 0;
100
  int idx_arr[1024];
Yunqing Wang's avatar
Yunqing Wang committed
101
102
103
104
105
106
107

  vpx_memset(qcoeff_ptr, 0, n_coeffs*sizeof(int16_t));
  vpx_memset(dqcoeff_ptr, 0, n_coeffs*sizeof(int16_t));

  eob = -1;

  // Base ZBIN
108
109
  zbins[0] = ROUND_POWER_OF_TWO(zbin_ptr[0] + zbin_oq_value, 1);
  zbins[1] = ROUND_POWER_OF_TWO(zbin_ptr[1] + zbin_oq_value, 1);
110
111
  nzbins[0] = zbins[0] * -1;
  nzbins[1] = zbins[1] * -1;
Yunqing Wang's avatar
Yunqing Wang committed
112
113
114
115
116

  if (!skip_block) {
    // Pre-scan pass
    for (i = 0; i < n_coeffs; i++) {
      rc = scan[i];
117
      z = coeff_ptr[rc];
Yunqing Wang's avatar
Yunqing Wang committed
118
119
120

      // If the coefficient is out of the base ZBIN range, keep it for
      // quantization.
121
      if (z >= zbins[rc != 0] || z <= nzbins[rc != 0])
Yunqing Wang's avatar
Yunqing Wang committed
122
123
124
125
126
127
128
129
        idx_arr[idx++] = i;
    }

    // Quantization pass: only process the coefficients selected in
    // pre-scan pass. Note: idx can be zero.
    for (i = 0; i < idx; i++) {
      rc = scan[idx_arr[i]];

130
      z = coeff_ptr[rc];
Yunqing Wang's avatar
Yunqing Wang committed
131
132
133
      sz = (z >> 31);                               // sign of z
      x  = (z ^ sz) - sz;                           // x = abs(z)

134
135
136
137
      x += ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1);
      x  = clamp(x, INT16_MIN, INT16_MAX);
      y  = ((((x * quant_ptr[rc != 0]) >> 16) + x) *
            quant_shift_ptr[rc != 0]) >> 15;      // quantize (x)
Yunqing Wang's avatar
Yunqing Wang committed
138

139
140
141
      x  = (y ^ sz) - sz;                         // get the sign back
      qcoeff_ptr[rc]  = x;                        // write to destination
      dqcoeff_ptr[rc] = x * dequant_ptr[rc != 0] / 2;  // dequantized value
Yunqing Wang's avatar
Yunqing Wang committed
142

143
144
      if (y)
        eob = idx_arr[i];                         // last nonzero coeffs
Yunqing Wang's avatar
Yunqing Wang committed
145
146
147
148
    }
  }
  *eob_ptr = eob + 1;
}
Daniel Kang's avatar
Daniel Kang committed
149

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
struct plane_block_idx {
  int plane;
  int block;
};

// TODO(jkoleszar): returning a struct so it can be used in a const context,
// expect to refactor this further later.
static INLINE struct plane_block_idx plane_block_idx(int y_blocks,
                                                     int b_idx) {
  const int v_offset = y_blocks * 5 / 4;
  struct plane_block_idx res;

  if (b_idx < y_blocks) {
    res.plane = 0;
    res.block = b_idx;
  } else if (b_idx < v_offset) {
    res.plane = 1;
    res.block = b_idx - y_blocks;
  } else {
    assert(b_idx < y_blocks * 3 / 2);
    res.plane = 2;
    res.block = b_idx - v_offset;
  }
  return res;
}

176
177
178
179
void vp9_regular_quantize_b_4x4(MACROBLOCK *mb, int b_idx, TX_TYPE tx_type,
                                int y_blocks) {
  MACROBLOCKD *const xd = &mb->e_mbd;
  const struct plane_block_idx pb_idx = plane_block_idx(y_blocks, b_idx);
180
181
  const int16_t *scan = get_scan_4x4(tx_type);
  const int16_t *iscan = get_iscan_4x4(tx_type);
182

183
  vp9_quantize_b(BLOCK_OFFSET(mb->plane[pb_idx.plane].coeff, pb_idx.block),
184
185
186
187
188
           16, mb->skip_block,
           mb->plane[pb_idx.plane].zbin,
           mb->plane[pb_idx.plane].round,
           mb->plane[pb_idx.plane].quant,
           mb->plane[pb_idx.plane].quant_shift,
189
190
           BLOCK_OFFSET(xd->plane[pb_idx.plane].qcoeff, pb_idx.block),
           BLOCK_OFFSET(xd->plane[pb_idx.plane].dqcoeff, pb_idx.block),
191
192
193
           xd->plane[pb_idx.plane].dequant,
           mb->plane[pb_idx.plane].zbin_extra,
           &xd->plane[pb_idx.plane].eobs[pb_idx.block],
194
           scan, iscan);
195
196
}

197
static void invert_quant(int16_t *quant, int16_t *shift, int d) {
John Koleszar's avatar
John Koleszar committed
198
199
200
201
202
203
  unsigned t;
  int l;
  t = d;
  for (l = 0; t > 1; l++)
    t >>= 1;
  t = 1 + (1 << (16 + l)) / d;
204
  *quant = (int16_t)(t - (1 << 16));
205
  *shift = 1 << (16 - l);
206
207
}

208
void vp9_init_quantizer(VP9_COMP *cpi) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
209
210
  int i, q;
  VP9_COMMON *const cm = &cpi->common;
211

212
  for (q = 0; q < QINDEX_RANGE; q++) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
213
214
215
216
217
218
219
220
221
222
223
    const int qzbin_factor = q == 0 ? 64 : (vp9_dc_quant(q, 0) < 148 ? 84 : 80);
    const int qrounding_factor = q == 0 ? 64 : 48;

    // y
    for (i = 0; i < 2; ++i) {
      const int quant = i == 0 ? vp9_dc_quant(q, cm->y_dc_delta_q)
                               : vp9_ac_quant(q, 0);
      invert_quant(&cpi->y_quant[q][i], &cpi->y_quant_shift[q][i], quant);
      cpi->y_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant, 7);
      cpi->y_round[q][i] = (qrounding_factor * quant) >> 7;
      cm->y_dequant[q][i] = quant;
John Koleszar's avatar
John Koleszar committed
224
    }
225

Dmitry Kovalev's avatar
Dmitry Kovalev committed
226
227
228
229
230
231
232
233
234
    // uv
    for (i = 0; i < 2; ++i) {
      const int quant = i == 0 ? vp9_dc_quant(q, cm->uv_dc_delta_q)
                               : vp9_ac_quant(q, cm->uv_ac_delta_q);
      invert_quant(&cpi->uv_quant[q][i], &cpi->uv_quant_shift[q][i], quant);
      cpi->uv_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant, 7);
      cpi->uv_round[q][i] = (qrounding_factor * quant) >> 7;
      cm->uv_dequant[q][i] = quant;
    }
235

236
#if CONFIG_ALPHA
Dmitry Kovalev's avatar
Dmitry Kovalev committed
237
238
239
240
241
242
243
244
245
    // alpha
    for (i = 0; i < 2; ++i) {
      const int quant = i == 0 ? vp9_dc_quant(q, cm->a_dc_delta_q)
                               : vp9_ac_quant(q, cm->a_ac_delta_q);
      invert_quant(&cpi->a_quant[q][i], &cpi->a_quant_shift[q][i], quant);
      cpi->a_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant, 7);
      cpi->a_round[q][i] = (qrounding_factor * quant) >> 7;
      cm->a_dequant[q][i] = quant;
    }
246
#endif
John Koleszar's avatar
John Koleszar committed
247

248
249
250
251
252
    for (i = 2; i < 8; i++) {
      cpi->y_quant[q][i] = cpi->y_quant[q][1];
      cpi->y_quant_shift[q][i] = cpi->y_quant_shift[q][1];
      cpi->y_zbin[q][i] = cpi->y_zbin[q][1];
      cpi->y_round[q][i] = cpi->y_round[q][1];
Dmitry Kovalev's avatar
Dmitry Kovalev committed
253
      cm->y_dequant[q][i] = cm->y_dequant[q][1];
254

255
256
257
258
      cpi->uv_quant[q][i] = cpi->uv_quant[q][1];
      cpi->uv_quant_shift[q][i] = cpi->uv_quant_shift[q][1];
      cpi->uv_zbin[q][i] = cpi->uv_zbin[q][1];
      cpi->uv_round[q][i] = cpi->uv_round[q][1];
Dmitry Kovalev's avatar
Dmitry Kovalev committed
259
      cm->uv_dequant[q][i] = cm->uv_dequant[q][1];
260
261

#if CONFIG_ALPHA
262
263
264
265
      cpi->a_quant[q][i] = cpi->a_quant[q][1];
      cpi->a_quant_shift[q][i] = cpi->a_quant_shift[q][1];
      cpi->a_zbin[q][i] = cpi->a_zbin[q][1];
      cpi->a_round[q][i] = cpi->a_round[q][1];
Dmitry Kovalev's avatar
Dmitry Kovalev committed
266
      cm->a_dequant[q][i] = cm->a_dequant[q][1];
267
#endif
268
    }
John Koleszar's avatar
John Koleszar committed
269
270
  }
}
271

272
void vp9_mb_init_quantizer(VP9_COMP *cpi, MACROBLOCK *x) {
John Koleszar's avatar
John Koleszar committed
273
274
275
  int i;
  MACROBLOCKD *xd = &x->e_mbd;
  int zbin_extra;
276
  int segment_id = xd->this_mi->mbmi.segment_id;
277
278
  const int qindex = vp9_get_qindex(&cpi->common.seg, segment_id,
                                    cpi->common.base_qindex);
John Koleszar's avatar
John Koleszar committed
279
280

  // Y
Dmitry Kovalev's avatar
Dmitry Kovalev committed
281
282
  zbin_extra = (cpi->common.y_dequant[qindex][1] *
                 (cpi->zbin_mode_boost + x->act_zbin_adj)) >> 7;
John Koleszar's avatar
John Koleszar committed
283

284
285
286
287
  x->plane[0].quant = cpi->y_quant[qindex];
  x->plane[0].quant_shift = cpi->y_quant_shift[qindex];
  x->plane[0].zbin = cpi->y_zbin[qindex];
  x->plane[0].round = cpi->y_round[qindex];
288
  x->plane[0].zbin_extra = (int16_t)zbin_extra;
289
  x->e_mbd.plane[0].dequant = cpi->common.y_dequant[qindex];
John Koleszar's avatar
John Koleszar committed
290
291

  // UV
Dmitry Kovalev's avatar
Dmitry Kovalev committed
292
293
  zbin_extra = (cpi->common.uv_dequant[qindex][1] *
                (cpi->zbin_mode_boost + x->act_zbin_adj)) >> 7;
John Koleszar's avatar
John Koleszar committed
294

295
  for (i = 1; i < 3; i++) {
296
297
298
299
    x->plane[i].quant = cpi->uv_quant[qindex];
    x->plane[i].quant_shift = cpi->uv_quant_shift[qindex];
    x->plane[i].zbin = cpi->uv_zbin[qindex];
    x->plane[i].round = cpi->uv_round[qindex];
300
    x->plane[i].zbin_extra = (int16_t)zbin_extra;
301
    x->e_mbd.plane[i].dequant = cpi->common.uv_dequant[qindex];
302
  }
John Koleszar's avatar
John Koleszar committed
303

304
305
306
307
308
309
310
311
312
#if CONFIG_ALPHA
  x->plane[3].quant = cpi->a_quant[qindex];
  x->plane[3].quant_shift = cpi->a_quant_shift[qindex];
  x->plane[3].zbin = cpi->a_zbin[qindex];
  x->plane[3].round = cpi->a_round[qindex];
  x->plane[3].zbin_extra = (int16_t)zbin_extra;
  x->e_mbd.plane[3].dequant = cpi->common.a_dequant[qindex];
#endif

313
314
  x->skip_block = vp9_segfeature_active(&cpi->common.seg, segment_id,
                                        SEG_LVL_SKIP);
John Koleszar's avatar
John Koleszar committed
315

316
  /* save this macroblock QIndex for vp9_update_zbin_extra() */
Dmitry Kovalev's avatar
Dmitry Kovalev committed
317
  x->e_mbd.q_index = qindex;
318
319
}

320
void vp9_update_zbin_extra(VP9_COMP *cpi, MACROBLOCK *x) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
321
322
323
324
325
  const int qindex = x->e_mbd.q_index;
  const int y_zbin_extra = (cpi->common.y_dequant[qindex][1] *
                (cpi->zbin_mode_boost + x->act_zbin_adj)) >> 7;
  const int uv_zbin_extra = (cpi->common.uv_dequant[qindex][1] *
                  (cpi->zbin_mode_boost + x->act_zbin_adj)) >> 7;
326

327
328
329
  x->plane[0].zbin_extra = (int16_t)y_zbin_extra;
  x->plane[1].zbin_extra = (int16_t)uv_zbin_extra;
  x->plane[2].zbin_extra = (int16_t)uv_zbin_extra;
330
331
}

332
void vp9_frame_init_quantizer(VP9_COMP *cpi) {
John Koleszar's avatar
John Koleszar committed
333
334
  // Clear Zbin mode boost for default case
  cpi->zbin_mode_boost = 0;
335

John Koleszar's avatar
John Koleszar committed
336
  // MB level quantizer setup
337
  vp9_mb_init_quantizer(cpi, &cpi->mb);
338
339
}

340
void vp9_set_quantizer(struct VP9_COMP *cpi, int q) {
341
  VP9_COMMON *cm = &cpi->common;
342

343
  cm->base_qindex = q;
344

John Koleszar's avatar
John Koleszar committed
345
346
  // if any of the delta_q values are changing update flag will
  // have to be set.
347
348
349
  cm->y_dc_delta_q = 0;
  cm->uv_dc_delta_q = 0;
  cm->uv_ac_delta_q = 0;
350

John Koleszar's avatar
John Koleszar committed
351
352
353
  // quantizer has to be reinitialized if any delta_q changes.
  // As there are not any here for now this is inactive code.
  // if(update)
354
  //    vp9_init_quantizer(cpi);
355
}