Coverage Report

Created: 2024-09-06 07:53

/src/libvpx/vp9/encoder/vp9_quantize.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5
 *  that can be found in the LICENSE file in the root of the source
6
 *  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.
9
 */
10
11
#include <assert.h>
12
#include <math.h>
13
#include "./vpx_dsp_rtcd.h"
14
#include "vpx_mem/vpx_mem.h"
15
#include "vpx_ports/bitops.h"
16
#include "vpx_ports/mem.h"
17
18
#include "vp9/common/vp9_quant_common.h"
19
#include "vp9/common/vp9_scan.h"
20
#include "vp9/common/vp9_seg_common.h"
21
22
#include "vp9/encoder/vp9_encoder.h"
23
#include "vp9/encoder/vp9_quantize.h"
24
#include "vp9/encoder/vp9_rd.h"
25
26
void vp9_quantize_fp_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
27
                       const struct macroblock_plane *const mb_plane,
28
                       tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
29
                       const int16_t *dequant_ptr, uint16_t *eob_ptr,
30
0
                       const struct ScanOrder *const scan_order) {
31
0
  int i, eob = -1;
32
0
  const int16_t *round_ptr = mb_plane->round_fp;
33
0
  const int16_t *quant_ptr = mb_plane->quant_fp;
34
0
  const int16_t *scan = scan_order->scan;
35
36
0
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
37
0
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
38
39
  // Quantization pass: All coefficients with index >= zero_flag are
40
  // skippable. Note: zero_flag can be zero.
41
0
  for (i = 0; i < n_coeffs; i++) {
42
0
    const int rc = scan[i];
43
0
    const int coeff = coeff_ptr[rc];
44
0
    const int coeff_sign = (coeff >> 31);
45
0
    const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
46
47
0
    int tmp = clamp(abs_coeff + round_ptr[rc != 0], INT16_MIN, INT16_MAX);
48
0
    tmp = (tmp * quant_ptr[rc != 0]) >> 16;
49
50
0
    qcoeff_ptr[rc] = (tmp ^ coeff_sign) - coeff_sign;
51
0
    dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0];
52
53
0
    if (tmp) eob = i;
54
0
  }
55
0
  *eob_ptr = eob + 1;
56
0
}
57
58
#if CONFIG_VP9_HIGHBITDEPTH
59
void vp9_highbd_quantize_fp_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
60
                              const struct macroblock_plane *const mb_plane,
61
                              tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
62
                              const int16_t *dequant_ptr, uint16_t *eob_ptr,
63
0
                              const struct ScanOrder *const scan_order) {
64
0
  int i;
65
0
  int eob = -1;
66
0
  const int16_t *round_ptr = mb_plane->round_fp;
67
0
  const int16_t *quant_ptr = mb_plane->quant_fp;
68
0
  const int16_t *scan = scan_order->scan;
69
70
0
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
71
0
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
72
73
  // Quantization pass: All coefficients with index >= zero_flag are
74
  // skippable. Note: zero_flag can be zero.
75
0
  for (i = 0; i < n_coeffs; i++) {
76
0
    const int rc = scan[i];
77
0
    const int coeff = coeff_ptr[rc];
78
0
    const int coeff_sign = (coeff >> 31);
79
0
    const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
80
0
    const int64_t tmp = abs_coeff + round_ptr[rc != 0];
81
0
    const int abs_qcoeff = (int)((tmp * quant_ptr[rc != 0]) >> 16);
82
0
    qcoeff_ptr[rc] = (tran_low_t)(abs_qcoeff ^ coeff_sign) - coeff_sign;
83
0
    dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0];
84
0
    if (abs_qcoeff) eob = i;
85
0
  }
86
0
  *eob_ptr = eob + 1;
87
0
}
88
#endif
89
90
// TODO(jingning) Refactor this file and combine functions with similar
91
// operations.
92
void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
93
                             const struct macroblock_plane *const mb_plane,
94
                             tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
95
                             const int16_t *dequant_ptr, uint16_t *eob_ptr,
96
0
                             const struct ScanOrder *const scan_order) {
97
0
  int i, eob = -1;
98
0
  const int16_t *round_ptr = mb_plane->round_fp;
99
0
  const int16_t *quant_ptr = mb_plane->quant_fp;
100
0
  const int16_t *scan = scan_order->scan;
101
102
0
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
103
0
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
104
105
0
  for (i = 0; i < n_coeffs; i++) {
106
0
    const int rc = scan[i];
107
0
    const int coeff = coeff_ptr[rc];
108
0
    const int coeff_sign = (coeff >> 31);
109
0
    int tmp = 0;
110
0
    int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
111
112
0
    if (abs_coeff >= (dequant_ptr[rc != 0] >> 2)) {
113
0
      abs_coeff += ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1);
114
0
      abs_coeff = clamp(abs_coeff, INT16_MIN, INT16_MAX);
115
0
      tmp = (abs_coeff * quant_ptr[rc != 0]) >> 15;
116
0
      qcoeff_ptr[rc] = (tmp ^ coeff_sign) - coeff_sign;
117
0
      dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0] / 2;
118
0
    }
119
120
0
    if (tmp) eob = i;
121
0
  }
122
0
  *eob_ptr = eob + 1;
123
0
}
124
125
#if CONFIG_VP9_HIGHBITDEPTH
126
void vp9_highbd_quantize_fp_32x32_c(
127
    const tran_low_t *coeff_ptr, intptr_t n_coeffs,
128
    const struct macroblock_plane *const mb_plane, tran_low_t *qcoeff_ptr,
129
    tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr,
130
0
    const struct ScanOrder *const scan_order) {
131
0
  int i, eob = -1;
132
0
  const int16_t *round_ptr = mb_plane->round_fp;
133
0
  const int16_t *quant_ptr = mb_plane->quant_fp;
134
0
  const int16_t *scan = scan_order->scan;
135
136
0
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
137
0
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
138
139
0
  for (i = 0; i < n_coeffs; i++) {
140
0
    int abs_qcoeff = 0;
141
0
    const int rc = scan[i];
142
0
    const int coeff = coeff_ptr[rc];
143
0
    const int coeff_sign = (coeff >> 31);
144
0
    const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
145
146
0
    if (abs_coeff >= (dequant_ptr[rc != 0] >> 2)) {
147
0
      const int64_t tmp = abs_coeff + ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1);
148
0
      abs_qcoeff = (int)((tmp * quant_ptr[rc != 0]) >> 15);
149
0
      qcoeff_ptr[rc] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
150
0
      dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0] / 2;
151
0
    }
152
153
0
    if (abs_qcoeff) eob = i;
154
0
  }
155
0
  *eob_ptr = eob + 1;
156
0
}
157
#endif
158
159
29.3M
static void invert_quant(int16_t *quant, int16_t *shift, int d) {
160
29.3M
  unsigned int t;
161
29.3M
  int l, m;
162
29.3M
  t = (unsigned int)d;
163
29.3M
  l = get_msb(t);
164
29.3M
  m = 1 + (1 << (16 + l)) / d;
165
29.3M
  *quant = (int16_t)(m - (1 << 16));
166
29.3M
  *shift = 1 << (16 - l);
167
29.3M
}
168
169
7.33M
static int get_qzbin_factor(int q, vpx_bit_depth_t bit_depth) {
170
7.33M
  const int quant = vp9_dc_quant(q, 0, bit_depth);
171
7.33M
#if CONFIG_VP9_HIGHBITDEPTH
172
7.33M
  switch (bit_depth) {
173
7.33M
    case VPX_BITS_8: return q == 0 ? 64 : (quant < 148 ? 84 : 80);
174
0
    case VPX_BITS_10: return q == 0 ? 64 : (quant < 592 ? 84 : 80);
175
0
    default:
176
0
      assert(bit_depth == VPX_BITS_12);
177
0
      return q == 0 ? 64 : (quant < 2368 ? 84 : 80);
178
7.33M
  }
179
#else
180
  (void)bit_depth;
181
  return q == 0 ? 64 : (quant < 148 ? 84 : 80);
182
#endif
183
7.33M
}
184
185
28.6k
void vp9_init_quantizer(VP9_COMP *cpi) {
186
28.6k
  VP9_COMMON *const cm = &cpi->common;
187
28.6k
  QUANTS *const quants = &cpi->quants;
188
28.6k
  int i, q, quant;
189
190
7.36M
  for (q = 0; q < QINDEX_RANGE; q++) {
191
7.33M
    int qzbin_factor = get_qzbin_factor(q, cm->bit_depth);
192
7.33M
    int qrounding_factor = q == 0 ? 64 : 48;
193
7.33M
    const int sharpness_adjustment = 16 * (7 - cpi->oxcf.sharpness) / 7;
194
195
7.33M
    if (cpi->oxcf.sharpness > 0 && q > 0) {
196
0
      qzbin_factor = 64 + sharpness_adjustment;
197
0
      qrounding_factor = 64 - sharpness_adjustment;
198
0
    }
199
200
22.0M
    for (i = 0; i < 2; ++i) {
201
14.6M
      int qrounding_factor_fp = i == 0 ? 48 : 42;
202
14.6M
      if (q == 0) qrounding_factor_fp = 64;
203
14.6M
      if (cpi->oxcf.sharpness > 0)
204
0
        qrounding_factor_fp = 64 - sharpness_adjustment;
205
      // y
206
14.6M
      quant = i == 0 ? vp9_dc_quant(q, cm->y_dc_delta_q, cm->bit_depth)
207
14.6M
                     : vp9_ac_quant(q, 0, cm->bit_depth);
208
14.6M
      invert_quant(&quants->y_quant[q][i], &quants->y_quant_shift[q][i], quant);
209
14.6M
      quants->y_quant_fp[q][i] = (1 << 16) / quant;
210
14.6M
      quants->y_round_fp[q][i] = (qrounding_factor_fp * quant) >> 7;
211
14.6M
      quants->y_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant, 7);
212
14.6M
      quants->y_round[q][i] = (qrounding_factor * quant) >> 7;
213
14.6M
      cpi->y_dequant[q][i] = quant;
214
215
      // uv
216
14.6M
      quant = i == 0 ? vp9_dc_quant(q, cm->uv_dc_delta_q, cm->bit_depth)
217
14.6M
                     : vp9_ac_quant(q, cm->uv_ac_delta_q, cm->bit_depth);
218
14.6M
      invert_quant(&quants->uv_quant[q][i], &quants->uv_quant_shift[q][i],
219
14.6M
                   quant);
220
14.6M
      quants->uv_quant_fp[q][i] = (1 << 16) / quant;
221
14.6M
      quants->uv_round_fp[q][i] = (qrounding_factor_fp * quant) >> 7;
222
14.6M
      quants->uv_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant, 7);
223
14.6M
      quants->uv_round[q][i] = (qrounding_factor * quant) >> 7;
224
14.6M
      cpi->uv_dequant[q][i] = quant;
225
14.6M
    }
226
227
51.3M
    for (i = 2; i < 8; i++) {
228
44.0M
      quants->y_quant[q][i] = quants->y_quant[q][1];
229
44.0M
      quants->y_quant_fp[q][i] = quants->y_quant_fp[q][1];
230
44.0M
      quants->y_round_fp[q][i] = quants->y_round_fp[q][1];
231
44.0M
      quants->y_quant_shift[q][i] = quants->y_quant_shift[q][1];
232
44.0M
      quants->y_zbin[q][i] = quants->y_zbin[q][1];
233
44.0M
      quants->y_round[q][i] = quants->y_round[q][1];
234
44.0M
      cpi->y_dequant[q][i] = cpi->y_dequant[q][1];
235
236
44.0M
      quants->uv_quant[q][i] = quants->uv_quant[q][1];
237
44.0M
      quants->uv_quant_fp[q][i] = quants->uv_quant_fp[q][1];
238
44.0M
      quants->uv_round_fp[q][i] = quants->uv_round_fp[q][1];
239
44.0M
      quants->uv_quant_shift[q][i] = quants->uv_quant_shift[q][1];
240
44.0M
      quants->uv_zbin[q][i] = quants->uv_zbin[q][1];
241
44.0M
      quants->uv_round[q][i] = quants->uv_round[q][1];
242
44.0M
      cpi->uv_dequant[q][i] = cpi->uv_dequant[q][1];
243
44.0M
    }
244
7.33M
  }
245
28.6k
}
246
247
8.89M
void vp9_init_plane_quantizers(VP9_COMP *cpi, MACROBLOCK *x) {
248
8.89M
  const VP9_COMMON *const cm = &cpi->common;
249
8.89M
  MACROBLOCKD *const xd = &x->e_mbd;
250
8.89M
  QUANTS *const quants = &cpi->quants;
251
8.89M
  const int segment_id = xd->mi[0]->segment_id;
252
8.89M
  const int qindex = vp9_get_qindex(&cm->seg, segment_id, cm->base_qindex);
253
8.89M
  const int rdmult = vp9_compute_rd_mult(cpi, qindex + cm->y_dc_delta_q);
254
8.89M
  int i;
255
256
  // Y
257
8.89M
  x->plane[0].quant = quants->y_quant[qindex];
258
8.89M
  x->plane[0].quant_fp = quants->y_quant_fp[qindex];
259
8.89M
  x->plane[0].round_fp = quants->y_round_fp[qindex];
260
8.89M
  x->plane[0].quant_shift = quants->y_quant_shift[qindex];
261
8.89M
  x->plane[0].zbin = quants->y_zbin[qindex];
262
8.89M
  x->plane[0].round = quants->y_round[qindex];
263
8.89M
  xd->plane[0].dequant = cpi->y_dequant[qindex];
264
8.89M
  x->plane[0].quant_thred[0] = x->plane[0].zbin[0] * x->plane[0].zbin[0];
265
8.89M
  x->plane[0].quant_thred[1] = x->plane[0].zbin[1] * x->plane[0].zbin[1];
266
267
  // UV
268
26.6M
  for (i = 1; i < 3; i++) {
269
17.7M
    x->plane[i].quant = quants->uv_quant[qindex];
270
17.7M
    x->plane[i].quant_fp = quants->uv_quant_fp[qindex];
271
17.7M
    x->plane[i].round_fp = quants->uv_round_fp[qindex];
272
17.7M
    x->plane[i].quant_shift = quants->uv_quant_shift[qindex];
273
17.7M
    x->plane[i].zbin = quants->uv_zbin[qindex];
274
17.7M
    x->plane[i].round = quants->uv_round[qindex];
275
17.7M
    xd->plane[i].dequant = cpi->uv_dequant[qindex];
276
17.7M
    x->plane[i].quant_thred[0] = x->plane[i].zbin[0] * x->plane[i].zbin[0];
277
17.7M
    x->plane[i].quant_thred[1] = x->plane[i].zbin[1] * x->plane[i].zbin[1];
278
17.7M
  }
279
280
8.89M
  x->skip_block = segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP);
281
8.89M
  x->q_index = qindex;
282
283
8.89M
  set_error_per_bit(x, rdmult);
284
285
8.89M
  vp9_initialize_me_consts(cpi, x, x->q_index);
286
8.89M
}
287
288
42.2k
void vp9_frame_init_quantizer(VP9_COMP *cpi) {
289
42.2k
  vp9_init_plane_quantizers(cpi, &cpi->td.mb);
290
42.2k
}
291
292
42.2k
void vp9_set_quantizer(VP9_COMP *cpi, int q) {
293
42.2k
  VP9_COMMON *cm = &cpi->common;
294
  // quantizer has to be reinitialized with vp9_init_quantizer() if any
295
  // delta_q changes.
296
42.2k
  cm->base_qindex = q;
297
42.2k
  cm->y_dc_delta_q = 0;
298
42.2k
  cm->uv_dc_delta_q = 0;
299
42.2k
  cm->uv_ac_delta_q = 0;
300
42.2k
  if (cpi->oxcf.delta_q_uv != 0) {
301
0
    cm->uv_dc_delta_q = cm->uv_ac_delta_q = cpi->oxcf.delta_q_uv;
302
0
    vp9_init_quantizer(cpi);
303
0
  }
304
42.2k
}
305
306
// Table that converts 0-63 Q-range values passed in outside to the Qindex
307
// range used internally.
308
static const int quantizer_to_qindex[] = {
309
  0,   4,   8,   12,  16,  20,  24,  28,  32,  36,  40,  44,  48,
310
  52,  56,  60,  64,  68,  72,  76,  80,  84,  88,  92,  96,  100,
311
  104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152,
312
  156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204,
313
  208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 249, 255,
314
};
315
316
71.8k
int vp9_quantizer_to_qindex(int quantizer) {
317
71.8k
  return quantizer_to_qindex[quantizer];
318
71.8k
}
319
320
41.8k
int vp9_qindex_to_quantizer(int qindex) {
321
41.8k
  int quantizer;
322
323
970k
  for (quantizer = 0; quantizer < 64; ++quantizer)
324
970k
    if (quantizer_to_qindex[quantizer] >= qindex) return quantizer;
325
326
0
  return 63;
327
41.8k
}