Coverage Report

Created: 2026-02-14 06:59

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