Coverage Report

Created: 2026-01-16 07:48

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