Coverage Report

Created: 2026-07-25 07:52

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