Coverage Report

Created: 2026-05-16 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvpx/vp9/encoder/vp9_quantize.c
Line
Count
Source
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
37.0M
static void invert_quant(int16_t *quant, int16_t *shift, int d) {
160
37.0M
  unsigned int t;
161
37.0M
  int l, m;
162
37.0M
  t = (unsigned int)d;
163
37.0M
  l = get_msb(t);
164
37.0M
  m = 1 + (1 << (16 + l)) / d;
165
37.0M
  *quant = (int16_t)(m - (1 << 16));
166
37.0M
  *shift = 1 << (16 - l);
167
37.0M
}
168
169
9.26M
static int get_qzbin_factor(int q, vpx_bit_depth_t bit_depth) {
170
9.26M
  const int quant = vp9_dc_quant(q, 0, bit_depth);
171
9.26M
#if CONFIG_VP9_HIGHBITDEPTH
172
9.26M
  switch (bit_depth) {
173
9.26M
    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
9.26M
  }
179
#else
180
  (void)bit_depth;
181
  return q == 0 ? 64 : (quant < 148 ? 84 : 80);
182
#endif
183
9.26M
}
184
185
36.1k
void vp9_init_quantizer(VP9_COMP *cpi) {
186
36.1k
  VP9_COMMON *const cm = &cpi->common;
187
36.1k
  QUANTS *const quants = &cpi->quants;
188
36.1k
  int i, q, quant;
189
190
9.29M
  for (q = 0; q < QINDEX_RANGE; q++) {
191
9.26M
    int qzbin_factor = get_qzbin_factor(q, cm->bit_depth);
192
9.26M
    int qrounding_factor = q == 0 ? 64 : 48;
193
9.26M
    const int sharpness_adjustment = 16 * (7 - cpi->oxcf.sharpness) / 7;
194
195
9.26M
    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
27.7M
    for (i = 0; i < 2; ++i) {
201
18.5M
      int qrounding_factor_fp = i == 0 ? 48 : 42;
202
18.5M
      if (q == 0) qrounding_factor_fp = 64;
203
18.5M
      if (cpi->oxcf.sharpness > 0)
204
0
        qrounding_factor_fp = 64 - sharpness_adjustment;
205
      // y
206
18.5M
      quant = i == 0 ? vp9_dc_quant(q, cm->y_dc_delta_q, cm->bit_depth)
207
18.5M
                     : vp9_ac_quant(q, 0, cm->bit_depth);
208
18.5M
      invert_quant(&quants->y_quant[q][i], &quants->y_quant_shift[q][i], quant);
209
18.5M
      quants->y_quant_fp[q][i] = (1 << 16) / quant;
210
18.5M
      quants->y_round_fp[q][i] = (qrounding_factor_fp * quant) >> 7;
211
18.5M
      quants->y_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant, 7);
212
18.5M
      quants->y_round[q][i] = (qrounding_factor * quant) >> 7;
213
18.5M
      cpi->y_dequant[q][i] = quant;
214
215
      // uv
216
18.5M
      quant = i == 0 ? vp9_dc_quant(q, cm->uv_dc_delta_q, cm->bit_depth)
217
18.5M
                     : vp9_ac_quant(q, cm->uv_ac_delta_q, cm->bit_depth);
218
18.5M
      invert_quant(&quants->uv_quant[q][i], &quants->uv_quant_shift[q][i],
219
18.5M
                   quant);
220
18.5M
      quants->uv_quant_fp[q][i] = (1 << 16) / quant;
221
18.5M
      quants->uv_round_fp[q][i] = (qrounding_factor_fp * quant) >> 7;
222
18.5M
      quants->uv_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant, 7);
223
18.5M
      quants->uv_round[q][i] = (qrounding_factor * quant) >> 7;
224
18.5M
      cpi->uv_dequant[q][i] = quant;
225
18.5M
    }
226
227
64.8M
    for (i = 2; i < 8; i++) {
228
55.5M
      quants->y_quant[q][i] = quants->y_quant[q][1];
229
55.5M
      quants->y_quant_fp[q][i] = quants->y_quant_fp[q][1];
230
55.5M
      quants->y_round_fp[q][i] = quants->y_round_fp[q][1];
231
55.5M
      quants->y_quant_shift[q][i] = quants->y_quant_shift[q][1];
232
55.5M
      quants->y_zbin[q][i] = quants->y_zbin[q][1];
233
55.5M
      quants->y_round[q][i] = quants->y_round[q][1];
234
55.5M
      cpi->y_dequant[q][i] = cpi->y_dequant[q][1];
235
236
55.5M
      quants->uv_quant[q][i] = quants->uv_quant[q][1];
237
55.5M
      quants->uv_quant_fp[q][i] = quants->uv_quant_fp[q][1];
238
55.5M
      quants->uv_round_fp[q][i] = quants->uv_round_fp[q][1];
239
55.5M
      quants->uv_quant_shift[q][i] = quants->uv_quant_shift[q][1];
240
55.5M
      quants->uv_zbin[q][i] = quants->uv_zbin[q][1];
241
55.5M
      quants->uv_round[q][i] = quants->uv_round[q][1];
242
55.5M
      cpi->uv_dequant[q][i] = cpi->uv_dequant[q][1];
243
55.5M
    }
244
9.26M
  }
245
36.1k
}
246
247
10.5M
void vp9_init_plane_quantizers(VP9_COMP *cpi, MACROBLOCK *x) {
248
10.5M
  const VP9_COMMON *const cm = &cpi->common;
249
10.5M
  MACROBLOCKD *const xd = &x->e_mbd;
250
10.5M
  QUANTS *const quants = &cpi->quants;
251
10.5M
  const int segment_id = xd->mi[0]->segment_id;
252
10.5M
  const int qindex = vp9_get_qindex(&cm->seg, segment_id, cm->base_qindex);
253
10.5M
  const int rdmult = vp9_compute_rd_mult(cpi, qindex + cm->y_dc_delta_q);
254
10.5M
  int i;
255
256
  // Y
257
10.5M
  x->plane[0].quant = quants->y_quant[qindex];
258
10.5M
  x->plane[0].quant_fp = quants->y_quant_fp[qindex];
259
10.5M
  x->plane[0].round_fp = quants->y_round_fp[qindex];
260
10.5M
  x->plane[0].quant_shift = quants->y_quant_shift[qindex];
261
10.5M
  x->plane[0].zbin = quants->y_zbin[qindex];
262
10.5M
  x->plane[0].round = quants->y_round[qindex];
263
10.5M
  xd->plane[0].dequant = cpi->y_dequant[qindex];
264
10.5M
  x->plane[0].quant_thred[0] = x->plane[0].zbin[0] * x->plane[0].zbin[0];
265
10.5M
  x->plane[0].quant_thred[1] = x->plane[0].zbin[1] * x->plane[0].zbin[1];
266
267
  // UV
268
31.5M
  for (i = 1; i < 3; i++) {
269
21.0M
    x->plane[i].quant = quants->uv_quant[qindex];
270
21.0M
    x->plane[i].quant_fp = quants->uv_quant_fp[qindex];
271
21.0M
    x->plane[i].round_fp = quants->uv_round_fp[qindex];
272
21.0M
    x->plane[i].quant_shift = quants->uv_quant_shift[qindex];
273
21.0M
    x->plane[i].zbin = quants->uv_zbin[qindex];
274
21.0M
    x->plane[i].round = quants->uv_round[qindex];
275
21.0M
    xd->plane[i].dequant = cpi->uv_dequant[qindex];
276
21.0M
    x->plane[i].quant_thred[0] = x->plane[i].zbin[0] * x->plane[i].zbin[0];
277
21.0M
    x->plane[i].quant_thred[1] = x->plane[i].zbin[1] * x->plane[i].zbin[1];
278
21.0M
  }
279
280
10.5M
  x->skip_block = segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP);
281
10.5M
  x->q_index = qindex;
282
283
10.5M
  set_error_per_bit(x, rdmult);
284
285
10.5M
  vp9_initialize_me_consts(cpi, x, x->q_index);
286
10.5M
}
287
288
72.9k
void vp9_frame_init_quantizer(VP9_COMP *cpi) {
289
72.9k
  vp9_init_plane_quantizers(cpi, &cpi->td.mb);
290
72.9k
}
291
292
72.9k
void vp9_set_quantizer(VP9_COMP *cpi, int q, int ext_rc_delta_q_uv) {
293
72.9k
  VP9_COMMON *cm = &cpi->common;
294
  // quantizer has to be reinitialized with vp9_init_quantizer() if any
295
  // delta_q changes.
296
72.9k
  cm->base_qindex = q;
297
72.9k
  cm->y_dc_delta_q = 0;
298
72.9k
  cm->uv_dc_delta_q = 0;
299
72.9k
  cm->uv_ac_delta_q = 0;
300
301
72.9k
  if (ext_rc_delta_q_uv != 0) {
302
0
    cm->uv_dc_delta_q = cm->uv_ac_delta_q = ext_rc_delta_q_uv;
303
0
    vp9_init_quantizer(cpi);
304
0
    return;
305
0
  }
306
307
72.9k
  if (cpi->oxcf.delta_q_uv != 0) {
308
0
    cm->uv_dc_delta_q = cm->uv_ac_delta_q = cpi->oxcf.delta_q_uv;
309
0
    vp9_init_quantizer(cpi);
310
0
  }
311
72.9k
}
312
313
// Table that converts 0-63 Q-range values passed in outside to the Qindex
314
// range used internally.
315
static const int quantizer_to_qindex[] = {
316
  0,   4,   8,   12,  16,  20,  24,  28,  32,  36,  40,  44,  48,
317
  52,  56,  60,  64,  68,  72,  76,  80,  84,  88,  92,  96,  100,
318
  104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152,
319
  156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204,
320
  208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 249, 255,
321
};
322
323
90.6k
int vp9_quantizer_to_qindex(int quantizer) {
324
90.6k
  assert(quantizer >= 0 && quantizer <= 63);
325
90.6k
  return quantizer_to_qindex[quantizer];
326
90.6k
}
327
328
72.5k
int vp9_qindex_to_quantizer(int qindex) {
329
72.5k
  int quantizer;
330
331
1.63M
  for (quantizer = 0; quantizer < 64; ++quantizer)
332
1.63M
    if (quantizer_to_qindex[quantizer] >= qindex) return quantizer;
333
334
0
  return 63;
335
72.5k
}