Coverage Report

Created: 2026-10-28 08:13

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
46.9M
static void invert_quant(int16_t *quant, int16_t *shift, int d) {
160
46.9M
  unsigned int t;
161
46.9M
  int l, m;
162
46.9M
  t = (unsigned int)d;
163
46.9M
  l = get_msb(t);
164
46.9M
  m = 1 + (1 << (16 + l)) / d;
165
46.9M
  *quant = (int16_t)(m - (1 << 16));
166
46.9M
  *shift = 1 << (16 - l);
167
46.9M
}
168
169
11.7M
static int get_qzbin_factor(int q, vpx_bit_depth_t bit_depth) {
170
11.7M
  const int quant = vp9_dc_quant(q, 0, bit_depth);
171
11.7M
#if CONFIG_VP9_HIGHBITDEPTH
172
11.7M
  switch (bit_depth) {
173
8.60M
    case VPX_BITS_8: return q == 0 ? 64 : (quant < 148 ? 84 : 80);
174
1.05M
    case VPX_BITS_10: return q == 0 ? 64 : (quant < 592 ? 84 : 80);
175
2.07M
    default:
176
2.07M
      assert(bit_depth == VPX_BITS_12);
177
2.07M
      return q == 0 ? 64 : (quant < 2368 ? 84 : 80);
178
11.7M
  }
179
#else
180
  (void)bit_depth;
181
  return q == 0 ? 64 : (quant < 148 ? 84 : 80);
182
#endif
183
11.7M
}
184
185
45.8k
void vp9_init_quantizer(VP9_COMP *cpi) {
186
45.8k
  VP9_COMMON *const cm = &cpi->common;
187
45.8k
  QUANTS *const quants = &cpi->quants;
188
45.8k
  int i, q, quant;
189
190
11.7M
  for (q = 0; q < QINDEX_RANGE; q++) {
191
11.7M
    int qzbin_factor = get_qzbin_factor(q, cm->bit_depth);
192
11.7M
    int qrounding_factor = q == 0 ? 64 : 48;
193
11.7M
    const int sharpness_adjustment = 16 * (7 - cpi->oxcf.sharpness) / 7;
194
195
11.7M
    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
35.2M
    for (i = 0; i < 2; ++i) {
201
23.4M
      int qrounding_factor_fp = i == 0 ? 48 : 42;
202
23.4M
      if (q == 0) qrounding_factor_fp = 64;
203
23.4M
      if (cpi->oxcf.sharpness > 0)
204
0
        qrounding_factor_fp = 64 - sharpness_adjustment;
205
      // y
206
23.4M
      quant = i == 0 ? vp9_dc_quant(q, cm->y_dc_delta_q, cm->bit_depth)
207
23.4M
                     : vp9_ac_quant(q, 0, cm->bit_depth);
208
23.4M
      invert_quant(&quants->y_quant[q][i], &quants->y_quant_shift[q][i], quant);
209
23.4M
      quants->y_quant_fp[q][i] = (1 << 16) / quant;
210
23.4M
      quants->y_round_fp[q][i] = (qrounding_factor_fp * quant) >> 7;
211
23.4M
      quants->y_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant, 7);
212
23.4M
      quants->y_round[q][i] = (qrounding_factor * quant) >> 7;
213
23.4M
      cpi->y_dequant[q][i] = quant;
214
215
      // uv
216
23.4M
      quant = i == 0 ? vp9_dc_quant(q, cm->uv_dc_delta_q, cm->bit_depth)
217
23.4M
                     : vp9_ac_quant(q, cm->uv_ac_delta_q, cm->bit_depth);
218
23.4M
      invert_quant(&quants->uv_quant[q][i], &quants->uv_quant_shift[q][i],
219
23.4M
                   quant);
220
23.4M
      quants->uv_quant_fp[q][i] = (1 << 16) / quant;
221
23.4M
      quants->uv_round_fp[q][i] = (qrounding_factor_fp * quant) >> 7;
222
23.4M
      quants->uv_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant, 7);
223
23.4M
      quants->uv_round[q][i] = (qrounding_factor * quant) >> 7;
224
23.4M
      cpi->uv_dequant[q][i] = quant;
225
23.4M
    }
226
227
82.1M
    for (i = 2; i < 8; i++) {
228
70.4M
      quants->y_quant[q][i] = quants->y_quant[q][1];
229
70.4M
      quants->y_quant_fp[q][i] = quants->y_quant_fp[q][1];
230
70.4M
      quants->y_round_fp[q][i] = quants->y_round_fp[q][1];
231
70.4M
      quants->y_quant_shift[q][i] = quants->y_quant_shift[q][1];
232
70.4M
      quants->y_zbin[q][i] = quants->y_zbin[q][1];
233
70.4M
      quants->y_round[q][i] = quants->y_round[q][1];
234
70.4M
      cpi->y_dequant[q][i] = cpi->y_dequant[q][1];
235
236
70.4M
      quants->uv_quant[q][i] = quants->uv_quant[q][1];
237
70.4M
      quants->uv_quant_fp[q][i] = quants->uv_quant_fp[q][1];
238
70.4M
      quants->uv_round_fp[q][i] = quants->uv_round_fp[q][1];
239
70.4M
      quants->uv_quant_shift[q][i] = quants->uv_quant_shift[q][1];
240
70.4M
      quants->uv_zbin[q][i] = quants->uv_zbin[q][1];
241
70.4M
      quants->uv_round[q][i] = quants->uv_round[q][1];
242
70.4M
      cpi->uv_dequant[q][i] = cpi->uv_dequant[q][1];
243
70.4M
    }
244
11.7M
  }
245
45.8k
}
246
247
9.17M
void vp9_init_plane_quantizers(VP9_COMP *cpi, MACROBLOCK *x) {
248
9.17M
  const VP9_COMMON *const cm = &cpi->common;
249
9.17M
  MACROBLOCKD *const xd = &x->e_mbd;
250
9.17M
  QUANTS *const quants = &cpi->quants;
251
9.17M
  const int segment_id = xd->mi[0]->segment_id;
252
9.17M
  const int qindex = vp9_get_qindex(&cm->seg, segment_id, cm->base_qindex);
253
9.17M
  const int rdmult = vp9_compute_rd_mult(cpi, qindex + cm->y_dc_delta_q);
254
9.17M
  int i;
255
256
  // Y
257
9.17M
  x->plane[0].quant = quants->y_quant[qindex];
258
9.17M
  x->plane[0].quant_fp = quants->y_quant_fp[qindex];
259
9.17M
  x->plane[0].round_fp = quants->y_round_fp[qindex];
260
9.17M
  x->plane[0].quant_shift = quants->y_quant_shift[qindex];
261
9.17M
  x->plane[0].zbin = quants->y_zbin[qindex];
262
9.17M
  x->plane[0].round = quants->y_round[qindex];
263
9.17M
  xd->plane[0].dequant = cpi->y_dequant[qindex];
264
9.17M
  x->plane[0].quant_thred[0] = x->plane[0].zbin[0] * x->plane[0].zbin[0];
265
9.17M
  x->plane[0].quant_thred[1] = x->plane[0].zbin[1] * x->plane[0].zbin[1];
266
267
  // UV
268
27.5M
  for (i = 1; i < 3; i++) {
269
18.3M
    x->plane[i].quant = quants->uv_quant[qindex];
270
18.3M
    x->plane[i].quant_fp = quants->uv_quant_fp[qindex];
271
18.3M
    x->plane[i].round_fp = quants->uv_round_fp[qindex];
272
18.3M
    x->plane[i].quant_shift = quants->uv_quant_shift[qindex];
273
18.3M
    x->plane[i].zbin = quants->uv_zbin[qindex];
274
18.3M
    x->plane[i].round = quants->uv_round[qindex];
275
18.3M
    xd->plane[i].dequant = cpi->uv_dequant[qindex];
276
18.3M
    x->plane[i].quant_thred[0] = x->plane[i].zbin[0] * x->plane[i].zbin[0];
277
18.3M
    x->plane[i].quant_thred[1] = x->plane[i].zbin[1] * x->plane[i].zbin[1];
278
18.3M
  }
279
280
9.17M
  x->skip_block = segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP);
281
9.17M
  x->q_index = qindex;
282
283
9.17M
  set_error_per_bit(x, rdmult);
284
285
9.17M
  vp9_initialize_me_consts(cpi, x, x->q_index);
286
9.17M
}
287
288
74.0k
void vp9_frame_init_quantizer(VP9_COMP *cpi) {
289
74.0k
  vp9_init_plane_quantizers(cpi, &cpi->td.mb);
290
74.0k
}
291
292
74.0k
void vp9_set_quantizer(VP9_COMP *cpi, int q, int ext_rc_delta_q_uv) {
293
74.0k
  VP9_COMMON *cm = &cpi->common;
294
  // quantizer has to be reinitialized with vp9_init_quantizer() if any
295
  // delta_q changes.
296
74.0k
  cm->base_qindex = q;
297
74.0k
  cm->y_dc_delta_q = 0;
298
74.0k
  cm->uv_dc_delta_q = 0;
299
74.0k
  cm->uv_ac_delta_q = 0;
300
301
74.0k
  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
74.0k
  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
74.0k
}
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
114k
int vp9_quantizer_to_qindex(int quantizer) {
324
114k
  assert(quantizer >= 0 && quantizer <= 63);
325
114k
  return quantizer_to_qindex[quantizer];
326
114k
}
327
328
68.4k
int vp9_qindex_to_quantizer(int qindex) {
329
68.4k
  int quantizer;
330
331
1.48M
  for (quantizer = 0; quantizer < 64; ++quantizer)
332
1.48M
    if (quantizer_to_qindex[quantizer] >= qindex) return quantizer;
333
334
0
  return 63;
335
68.4k
}