vp9_quantize.c 11.7 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
73
        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
74
75
        x  = (y ^ sz) - sz;                         // get the sign back
        qcoeff_ptr[rc]  = x;                        // write to destination
76
        dqcoeff_ptr[rc] = x * dequant_ptr[rc != 0];  // dequantized value
Yunqing Wang's avatar
Yunqing Wang committed
77
78
79
80
81
82
83
84
85
86

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

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

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

  eob = -1;

  // Base ZBIN
107
108
  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);
109
110
  nzbins[0] = zbins[0] * -1;
  nzbins[1] = zbins[1] * -1;
Yunqing Wang's avatar
Yunqing Wang committed
111
112
113
114
115

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

      // If the coefficient is out of the base ZBIN range, keep it for
      // quantization.
120
      if (z >= zbins[rc != 0] || z <= nzbins[rc != 0])
Yunqing Wang's avatar
Yunqing Wang committed
121
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]];

      // Calculate ZBIN
130
      zbin = (zbins[rc != 0]);
Yunqing Wang's avatar
Yunqing Wang committed
131

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

      if (x >= zbin) {
137
        x += ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1);
138
        x  = clamp(x, INT16_MIN, INT16_MAX);
139
        y  = (((int)(((int)(x * quant_ptr[rc != 0]) >> 16) + x)) *
140
              quant_shift_ptr[rc != 0]) >> 15;      // quantize (x)
Yunqing Wang's avatar
Yunqing Wang committed
141
142
143

        x  = (y ^ sz) - sz;                         // get the sign back
        qcoeff_ptr[rc]  = x;                        // write to destination
144
        dqcoeff_ptr[rc] = x * dequant_ptr[rc != 0] / 2;  // dequantized value
Yunqing Wang's avatar
Yunqing Wang committed
145
146
147
148
149
150
151
152
153

        if (y) {
          eob = idx_arr[i];                         // last nonzero coeffs
        }
      }
    }
  }
  *eob_ptr = eob + 1;
}
Daniel Kang's avatar
Daniel Kang committed
154

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
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;
}

181
182
183
184
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);
185
186
  const int16_t *scan = get_scan_4x4(tx_type);
  const int16_t *iscan = get_iscan_4x4(tx_type);
187

188
  vp9_quantize_b(BLOCK_OFFSET(mb->plane[pb_idx.plane].coeff, pb_idx.block),
189
190
191
192
193
           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,
194
195
           BLOCK_OFFSET(xd->plane[pb_idx.plane].qcoeff, pb_idx.block),
           BLOCK_OFFSET(xd->plane[pb_idx.plane].dqcoeff, pb_idx.block),
196
197
198
           xd->plane[pb_idx.plane].dequant,
           mb->plane[pb_idx.plane].zbin_extra,
           &xd->plane[pb_idx.plane].eobs[pb_idx.block],
199
           scan, iscan);
200
201
}

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

213
void vp9_init_quantizer(VP9_COMP *cpi) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
214
215
  int i, q;
  VP9_COMMON *const cm = &cpi->common;
216

217
  for (q = 0; q < QINDEX_RANGE; q++) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
218
219
220
221
222
223
224
225
226
227
228
    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
229
    }
230

Dmitry Kovalev's avatar
Dmitry Kovalev committed
231
232
233
234
235
236
237
238
239
    // 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;
    }
240

241
#if CONFIG_ALPHA
Dmitry Kovalev's avatar
Dmitry Kovalev committed
242
243
244
245
246
247
248
249
250
    // 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;
    }
251
#endif
John Koleszar's avatar
John Koleszar committed
252

253
254
255
256
257
    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
258
      cm->y_dequant[q][i] = cm->y_dequant[q][1];
259

260
261
262
263
      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
264
      cm->uv_dequant[q][i] = cm->uv_dequant[q][1];
265
266

#if CONFIG_ALPHA
267
268
269
270
      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
271
      cm->a_dequant[q][i] = cm->a_dequant[q][1];
272
#endif
273
    }
John Koleszar's avatar
John Koleszar committed
274
275
  }
}
276

277
void vp9_mb_init_quantizer(VP9_COMP *cpi, MACROBLOCK *x) {
John Koleszar's avatar
John Koleszar committed
278
279
280
281
  int i;
  MACROBLOCKD *xd = &x->e_mbd;
  int zbin_extra;
  int segment_id = xd->mode_info_context->mbmi.segment_id;
282
283
  const int qindex = vp9_get_qindex(&cpi->common.seg, segment_id,
                                    cpi->common.base_qindex);
John Koleszar's avatar
John Koleszar committed
284
285

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

289
290
291
292
  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];
293
  x->plane[0].zbin_extra = (int16_t)zbin_extra;
294
  x->e_mbd.plane[0].dequant = cpi->common.y_dequant[qindex];
John Koleszar's avatar
John Koleszar committed
295
296

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

300
  for (i = 1; i < 3; i++) {
301
302
303
304
    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];
305
    x->plane[i].zbin_extra = (int16_t)zbin_extra;
306
    x->e_mbd.plane[i].dequant = cpi->common.uv_dequant[qindex];
307
  }
John Koleszar's avatar
John Koleszar committed
308

309
310
311
312
313
314
315
316
317
#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

318
319
  x->skip_block = vp9_segfeature_active(&cpi->common.seg, segment_id,
                                        SEG_LVL_SKIP);
John Koleszar's avatar
John Koleszar committed
320

321
  /* save this macroblock QIndex for vp9_update_zbin_extra() */
Dmitry Kovalev's avatar
Dmitry Kovalev committed
322
  x->e_mbd.q_index = qindex;
323
324
}

325
void vp9_update_zbin_extra(VP9_COMP *cpi, MACROBLOCK *x) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
326
327
328
329
330
  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;
331

332
333
334
  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;
335
336
}

337
void vp9_frame_init_quantizer(VP9_COMP *cpi) {
John Koleszar's avatar
John Koleszar committed
338
339
  // Clear Zbin mode boost for default case
  cpi->zbin_mode_boost = 0;
340

John Koleszar's avatar
John Koleszar committed
341
  // MB level quantizer setup
342
  vp9_mb_init_quantizer(cpi, &cpi->mb);
343
344
}

345
346
void vp9_set_quantizer(struct VP9_COMP *cpi, int Q) {
  VP9_COMMON *cm = &cpi->common;
347

John Koleszar's avatar
John Koleszar committed
348
  cm->base_qindex = Q;
349

John Koleszar's avatar
John Koleszar committed
350
351
  // if any of the delta_q values are changing update flag will
  // have to be set.
352
353
354
  cm->y_dc_delta_q = 0;
  cm->uv_dc_delta_q = 0;
  cm->uv_ac_delta_q = 0;
355

John Koleszar's avatar
John Koleszar committed
356
357
358
  // quantizer has to be reinitialized if any delta_q changes.
  // As there are not any here for now this is inactive code.
  // if(update)
359
  //    vp9_init_quantizer(cpi);
360
}