Coverage Report

Created: 2026-04-01 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/aom/av1/encoder/av1_quantize.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
3
 *
4
 * This source code is subject to the terms of the BSD 2 Clause License and
5
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6
 * was not distributed with this source code in the LICENSE file, you can
7
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8
 * Media Patent License 1.0 was not distributed with this source code in the
9
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10
 */
11
12
#include <math.h>
13
14
#include "config/aom_dsp_rtcd.h"
15
16
#include "aom/aomcx.h"
17
#include "aom_dsp/quantize.h"
18
#include "aom_mem/aom_mem.h"
19
#include "aom_ports/bitops.h"
20
#include "aom_ports/mem.h"
21
22
#include "av1/common/idct.h"
23
#include "av1/common/quant_common.h"
24
#include "av1/common/scan.h"
25
#include "av1/common/seg_common.h"
26
27
#include "av1/encoder/av1_quantize.h"
28
#include "av1/encoder/encoder.h"
29
#include "av1/encoder/rd.h"
30
31
void av1_quantize_skip(intptr_t n_coeffs, tran_low_t *qcoeff_ptr,
32
0
                       tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr) {
33
0
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
34
0
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
35
0
  *eob_ptr = 0;
36
0
}
37
38
int av1_quantize_fp_no_qmatrix(const int16_t quant_ptr[2],
39
                               const int16_t dequant_ptr[2],
40
                               const int16_t round_ptr[2], int log_scale,
41
                               const int16_t *scan, int coeff_count,
42
                               const tran_low_t *coeff_ptr,
43
                               tran_low_t *qcoeff_ptr,
44
0
                               tran_low_t *dqcoeff_ptr) {
45
0
  memset(qcoeff_ptr, 0, coeff_count * sizeof(*qcoeff_ptr));
46
0
  memset(dqcoeff_ptr, 0, coeff_count * sizeof(*dqcoeff_ptr));
47
0
  const int rounding[2] = { ROUND_POWER_OF_TWO(round_ptr[0], log_scale),
48
0
                            ROUND_POWER_OF_TWO(round_ptr[1], log_scale) };
49
0
  int eob = 0;
50
0
  for (int i = 0; i < coeff_count; i++) {
51
0
    const int rc = scan[i];
52
0
    const int32_t thresh = (int32_t)(dequant_ptr[rc != 0]);
53
0
    const int coeff = coeff_ptr[rc];
54
0
    const int coeff_sign = AOMSIGN(coeff);
55
0
    int64_t abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
56
0
    int tmp32 = 0;
57
0
    if ((abs_coeff << (1 + log_scale)) >= thresh) {
58
0
      abs_coeff = clamp64(abs_coeff + rounding[rc != 0], INT16_MIN, INT16_MAX);
59
0
      tmp32 = (int)((abs_coeff * quant_ptr[rc != 0]) >> (16 - log_scale));
60
0
      if (tmp32) {
61
0
        qcoeff_ptr[rc] = (tmp32 ^ coeff_sign) - coeff_sign;
62
0
        const tran_low_t abs_dqcoeff =
63
0
            (tmp32 * dequant_ptr[rc != 0]) >> log_scale;
64
0
        dqcoeff_ptr[rc] = (abs_dqcoeff ^ coeff_sign) - coeff_sign;
65
0
      }
66
0
    }
67
0
    if (tmp32) eob = i + 1;
68
0
  }
69
0
  return eob;
70
0
}
71
72
static void quantize_fp_helper_c(
73
    const tran_low_t *coeff_ptr, intptr_t n_coeffs, const int16_t *zbin_ptr,
74
    const int16_t *round_ptr, const int16_t *quant_ptr,
75
    const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr,
76
    tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr,
77
    const int16_t *scan, const int16_t *iscan, const qm_val_t *qm_ptr,
78
0
    const qm_val_t *iqm_ptr, int log_scale) {
79
0
  int i, eob = -1;
80
0
  const int rounding[2] = { ROUND_POWER_OF_TWO(round_ptr[0], log_scale),
81
0
                            ROUND_POWER_OF_TWO(round_ptr[1], log_scale) };
82
  // TODO(jingning) Decide the need of these arguments after the
83
  // quantization process is completed.
84
0
  (void)zbin_ptr;
85
0
  (void)quant_shift_ptr;
86
0
  (void)iscan;
87
88
0
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
89
0
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
90
91
0
  if (qm_ptr == NULL && iqm_ptr == NULL) {
92
0
    *eob_ptr = av1_quantize_fp_no_qmatrix(quant_ptr, dequant_ptr, round_ptr,
93
0
                                          log_scale, scan, (int)n_coeffs,
94
0
                                          coeff_ptr, qcoeff_ptr, dqcoeff_ptr);
95
0
  } else {
96
    // Quantization pass: All coefficients with index >= zero_flag are
97
    // skippable. Note: zero_flag can be zero.
98
0
    for (i = 0; i < n_coeffs; i++) {
99
0
      const int rc = scan[i];
100
0
      const int coeff = coeff_ptr[rc];
101
0
      const qm_val_t wt = qm_ptr ? qm_ptr[rc] : (1 << AOM_QM_BITS);
102
0
      const qm_val_t iwt = iqm_ptr ? iqm_ptr[rc] : (1 << AOM_QM_BITS);
103
0
      const int dequant =
104
0
          (dequant_ptr[rc != 0] * iwt + (1 << (AOM_QM_BITS - 1))) >>
105
0
          AOM_QM_BITS;
106
0
      const int coeff_sign = AOMSIGN(coeff);
107
0
      int64_t abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
108
0
      int tmp32 = 0;
109
0
      if (abs_coeff * wt >=
110
0
          (dequant_ptr[rc != 0] << (AOM_QM_BITS - (1 + log_scale)))) {
111
0
        abs_coeff += rounding[rc != 0];
112
0
        abs_coeff = clamp64(abs_coeff, INT16_MIN, INT16_MAX);
113
0
        tmp32 = (int)((abs_coeff * wt * quant_ptr[rc != 0]) >>
114
0
                      (16 - log_scale + AOM_QM_BITS));
115
0
        qcoeff_ptr[rc] = (tmp32 ^ coeff_sign) - coeff_sign;
116
0
        const tran_low_t abs_dqcoeff = (tmp32 * dequant) >> log_scale;
117
0
        dqcoeff_ptr[rc] = (abs_dqcoeff ^ coeff_sign) - coeff_sign;
118
0
      }
119
120
0
      if (tmp32) eob = i;
121
0
    }
122
0
    *eob_ptr = eob + 1;
123
0
  }
124
0
}
125
126
#if CONFIG_AV1_HIGHBITDEPTH
127
static void highbd_quantize_fp_helper_c(
128
    const tran_low_t *coeff_ptr, intptr_t count, const int16_t *zbin_ptr,
129
    const int16_t *round_ptr, const int16_t *quant_ptr,
130
    const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr,
131
    tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr,
132
    const int16_t *scan, const int16_t *iscan, const qm_val_t *qm_ptr,
133
0
    const qm_val_t *iqm_ptr, int log_scale) {
134
0
  int i;
135
0
  int eob = -1;
136
0
  const int shift = 16 - log_scale;
137
  // TODO(jingning) Decide the need of these arguments after the
138
  // quantization process is completed.
139
0
  (void)zbin_ptr;
140
0
  (void)quant_shift_ptr;
141
0
  (void)iscan;
142
143
0
  if (qm_ptr || iqm_ptr) {
144
    // Quantization pass: All coefficients with index >= zero_flag are
145
    // skippable. Note: zero_flag can be zero.
146
0
    for (i = 0; i < count; i++) {
147
0
      const int rc = scan[i];
148
0
      const int coeff = coeff_ptr[rc];
149
0
      const qm_val_t wt = qm_ptr != NULL ? qm_ptr[rc] : (1 << AOM_QM_BITS);
150
0
      const qm_val_t iwt = iqm_ptr != NULL ? iqm_ptr[rc] : (1 << AOM_QM_BITS);
151
0
      const int dequant =
152
0
          (dequant_ptr[rc != 0] * iwt + (1 << (AOM_QM_BITS - 1))) >>
153
0
          AOM_QM_BITS;
154
0
      const int coeff_sign = AOMSIGN(coeff);
155
0
      const int64_t abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
156
0
      int abs_qcoeff = 0;
157
0
      if (abs_coeff * wt >=
158
0
          (dequant_ptr[rc != 0] << (AOM_QM_BITS - (1 + log_scale)))) {
159
0
        const int64_t tmp =
160
0
            abs_coeff + ROUND_POWER_OF_TWO(round_ptr[rc != 0], log_scale);
161
0
        abs_qcoeff =
162
0
            (int)((tmp * quant_ptr[rc != 0] * wt) >> (shift + AOM_QM_BITS));
163
0
        qcoeff_ptr[rc] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
164
0
        const tran_low_t abs_dqcoeff = (abs_qcoeff * dequant) >> log_scale;
165
0
        dqcoeff_ptr[rc] = (tran_low_t)((abs_dqcoeff ^ coeff_sign) - coeff_sign);
166
0
        if (abs_qcoeff) eob = i;
167
0
      } else {
168
0
        qcoeff_ptr[rc] = 0;
169
0
        dqcoeff_ptr[rc] = 0;
170
0
      }
171
0
    }
172
0
  } else {
173
0
    const int log_scaled_round_arr[2] = {
174
0
      ROUND_POWER_OF_TWO(round_ptr[0], log_scale),
175
0
      ROUND_POWER_OF_TWO(round_ptr[1], log_scale),
176
0
    };
177
0
    for (i = 0; i < count; i++) {
178
0
      const int rc = scan[i];
179
0
      const int coeff = coeff_ptr[rc];
180
0
      const int rc01 = (rc != 0);
181
0
      const int coeff_sign = AOMSIGN(coeff);
182
0
      const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
183
0
      const int log_scaled_round = log_scaled_round_arr[rc01];
184
0
      if ((abs_coeff << (1 + log_scale)) >= dequant_ptr[rc01]) {
185
0
        const int quant = quant_ptr[rc01];
186
0
        const int dequant = dequant_ptr[rc01];
187
0
        const int64_t tmp = (int64_t)abs_coeff + log_scaled_round;
188
0
        const int abs_qcoeff = (int)((tmp * quant) >> shift);
189
0
        qcoeff_ptr[rc] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
190
0
        const tran_low_t abs_dqcoeff = (abs_qcoeff * dequant) >> log_scale;
191
0
        if (abs_qcoeff) eob = i;
192
0
        dqcoeff_ptr[rc] = (tran_low_t)((abs_dqcoeff ^ coeff_sign) - coeff_sign);
193
0
      } else {
194
0
        qcoeff_ptr[rc] = 0;
195
0
        dqcoeff_ptr[rc] = 0;
196
0
      }
197
0
    }
198
0
  }
199
0
  *eob_ptr = eob + 1;
200
0
}
201
#endif  // CONFIG_AV1_HIGHBITDEPTH
202
203
void av1_quantize_fp_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
204
                       const int16_t *zbin_ptr, const int16_t *round_ptr,
205
                       const int16_t *quant_ptr, const int16_t *quant_shift_ptr,
206
                       tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
207
                       const int16_t *dequant_ptr, uint16_t *eob_ptr,
208
0
                       const int16_t *scan, const int16_t *iscan) {
209
0
  quantize_fp_helper_c(coeff_ptr, n_coeffs, zbin_ptr, round_ptr, quant_ptr,
210
0
                       quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, dequant_ptr,
211
0
                       eob_ptr, scan, iscan, NULL, NULL, 0);
212
0
}
213
214
void av1_quantize_lp_c(const int16_t *coeff_ptr, intptr_t n_coeffs,
215
                       const int16_t *round_ptr, const int16_t *quant_ptr,
216
                       int16_t *qcoeff_ptr, int16_t *dqcoeff_ptr,
217
                       const int16_t *dequant_ptr, uint16_t *eob_ptr,
218
0
                       const int16_t *scan, const int16_t *iscan) {
219
0
  (void)iscan;
220
0
  int eob = -1;
221
222
0
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
223
0
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
224
225
  // Quantization pass: All coefficients with index >= zero_flag are
226
  // skippable. Note: zero_flag can be zero.
227
0
  for (int i = 0; i < n_coeffs; i++) {
228
0
    const int rc = scan[i];
229
0
    const int coeff = coeff_ptr[rc];
230
0
    const int coeff_sign = AOMSIGN(coeff);
231
0
    const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
232
233
0
    int tmp = clamp(abs_coeff + round_ptr[rc != 0], INT16_MIN, INT16_MAX);
234
0
    tmp = (tmp * quant_ptr[rc != 0]) >> 16;
235
236
0
    qcoeff_ptr[rc] = (tmp ^ coeff_sign) - coeff_sign;
237
0
    dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0];
238
239
0
    if (tmp) eob = i;
240
0
  }
241
0
  *eob_ptr = eob + 1;
242
0
}
243
244
void av1_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
245
                             const int16_t *zbin_ptr, const int16_t *round_ptr,
246
                             const int16_t *quant_ptr,
247
                             const int16_t *quant_shift_ptr,
248
                             tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
249
                             const int16_t *dequant_ptr, uint16_t *eob_ptr,
250
0
                             const int16_t *scan, const int16_t *iscan) {
251
0
  quantize_fp_helper_c(coeff_ptr, n_coeffs, zbin_ptr, round_ptr, quant_ptr,
252
0
                       quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, dequant_ptr,
253
0
                       eob_ptr, scan, iscan, NULL, NULL, 1);
254
0
}
255
256
void av1_quantize_fp_64x64_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
257
                             const int16_t *zbin_ptr, const int16_t *round_ptr,
258
                             const int16_t *quant_ptr,
259
                             const int16_t *quant_shift_ptr,
260
                             tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
261
                             const int16_t *dequant_ptr, uint16_t *eob_ptr,
262
0
                             const int16_t *scan, const int16_t *iscan) {
263
0
  quantize_fp_helper_c(coeff_ptr, n_coeffs, zbin_ptr, round_ptr, quant_ptr,
264
0
                       quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, dequant_ptr,
265
0
                       eob_ptr, scan, iscan, NULL, NULL, 2);
266
0
}
267
268
void av1_quantize_fp_facade(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
269
                            const MACROBLOCK_PLANE *p, tran_low_t *qcoeff_ptr,
270
                            tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
271
0
                            const SCAN_ORDER *sc, const QUANT_PARAM *qparam) {
272
0
  const qm_val_t *qm_ptr = qparam->qmatrix;
273
0
  const qm_val_t *iqm_ptr = qparam->iqmatrix;
274
0
  if (qm_ptr != NULL && iqm_ptr != NULL) {
275
0
    quantize_fp_helper_c(coeff_ptr, n_coeffs, p->zbin_QTX, p->round_fp_QTX,
276
0
                         p->quant_fp_QTX, p->quant_shift_QTX, qcoeff_ptr,
277
0
                         dqcoeff_ptr, p->dequant_QTX, eob_ptr, sc->scan,
278
0
                         sc->iscan, qm_ptr, iqm_ptr, qparam->log_scale);
279
0
  } else {
280
0
    switch (qparam->log_scale) {
281
0
      case 0:
282
0
        av1_quantize_fp(coeff_ptr, n_coeffs, p->zbin_QTX, p->round_fp_QTX,
283
0
                        p->quant_fp_QTX, p->quant_shift_QTX, qcoeff_ptr,
284
0
                        dqcoeff_ptr, p->dequant_QTX, eob_ptr, sc->scan,
285
0
                        sc->iscan);
286
0
        break;
287
0
      case 1:
288
0
        av1_quantize_fp_32x32(coeff_ptr, n_coeffs, p->zbin_QTX, p->round_fp_QTX,
289
0
                              p->quant_fp_QTX, p->quant_shift_QTX, qcoeff_ptr,
290
0
                              dqcoeff_ptr, p->dequant_QTX, eob_ptr, sc->scan,
291
0
                              sc->iscan);
292
0
        break;
293
0
      case 2:
294
0
        av1_quantize_fp_64x64(coeff_ptr, n_coeffs, p->zbin_QTX, p->round_fp_QTX,
295
0
                              p->quant_fp_QTX, p->quant_shift_QTX, qcoeff_ptr,
296
0
                              dqcoeff_ptr, p->dequant_QTX, eob_ptr, sc->scan,
297
0
                              sc->iscan);
298
0
        break;
299
0
      default: assert(0);
300
0
    }
301
0
  }
302
0
}
303
304
void av1_quantize_b_facade(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
305
                           const MACROBLOCK_PLANE *p, tran_low_t *qcoeff_ptr,
306
                           tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
307
0
                           const SCAN_ORDER *sc, const QUANT_PARAM *qparam) {
308
0
  const qm_val_t *qm_ptr = qparam->qmatrix;
309
0
  const qm_val_t *iqm_ptr = qparam->iqmatrix;
310
0
#if !CONFIG_REALTIME_ONLY
311
0
  if (qparam->use_quant_b_adapt) {
312
    // TODO(sarahparker) These quantize_b optimizations need SIMD
313
    // implementations
314
0
    if (qm_ptr != NULL && iqm_ptr != NULL) {
315
0
      aom_quantize_b_adaptive_helper_c(
316
0
          coeff_ptr, n_coeffs, p->zbin_QTX, p->round_QTX, p->quant_QTX,
317
0
          p->quant_shift_QTX, qcoeff_ptr, dqcoeff_ptr, p->dequant_QTX, eob_ptr,
318
0
          sc->scan, sc->iscan, qm_ptr, iqm_ptr, qparam->log_scale);
319
0
    } else {
320
0
      switch (qparam->log_scale) {
321
0
        case 0:
322
0
          aom_quantize_b_adaptive(coeff_ptr, n_coeffs, p->zbin_QTX,
323
0
                                  p->round_QTX, p->quant_QTX,
324
0
                                  p->quant_shift_QTX, qcoeff_ptr, dqcoeff_ptr,
325
0
                                  p->dequant_QTX, eob_ptr, sc->scan, sc->iscan);
326
0
          break;
327
0
        case 1:
328
0
          aom_quantize_b_32x32_adaptive(
329
0
              coeff_ptr, n_coeffs, p->zbin_QTX, p->round_QTX, p->quant_QTX,
330
0
              p->quant_shift_QTX, qcoeff_ptr, dqcoeff_ptr, p->dequant_QTX,
331
0
              eob_ptr, sc->scan, sc->iscan);
332
0
          break;
333
0
        case 2:
334
0
          aom_quantize_b_64x64_adaptive(
335
0
              coeff_ptr, n_coeffs, p->zbin_QTX, p->round_QTX, p->quant_QTX,
336
0
              p->quant_shift_QTX, qcoeff_ptr, dqcoeff_ptr, p->dequant_QTX,
337
0
              eob_ptr, sc->scan, sc->iscan);
338
0
          break;
339
0
        default: assert(0);
340
0
      }
341
0
    }
342
0
    return;
343
0
  }
344
0
#endif  // !CONFIG_REALTIME_ONLY
345
346
0
  if (qm_ptr != NULL && iqm_ptr != NULL) {
347
0
    aom_quantize_b_helper_c(coeff_ptr, n_coeffs, p->zbin_QTX, p->round_QTX,
348
0
                            p->quant_QTX, p->quant_shift_QTX, qcoeff_ptr,
349
0
                            dqcoeff_ptr, p->dequant_QTX, eob_ptr, sc->scan,
350
0
                            sc->iscan, qm_ptr, iqm_ptr, qparam->log_scale);
351
0
  } else {
352
0
    switch (qparam->log_scale) {
353
0
      case 0:
354
0
        aom_quantize_b(coeff_ptr, n_coeffs, p->zbin_QTX, p->round_QTX,
355
0
                       p->quant_QTX, p->quant_shift_QTX, qcoeff_ptr,
356
0
                       dqcoeff_ptr, p->dequant_QTX, eob_ptr, sc->scan,
357
0
                       sc->iscan);
358
0
        break;
359
0
      case 1:
360
0
        aom_quantize_b_32x32(coeff_ptr, n_coeffs, p->zbin_QTX, p->round_QTX,
361
0
                             p->quant_QTX, p->quant_shift_QTX, qcoeff_ptr,
362
0
                             dqcoeff_ptr, p->dequant_QTX, eob_ptr, sc->scan,
363
0
                             sc->iscan);
364
0
        break;
365
0
      case 2:
366
0
        aom_quantize_b_64x64(coeff_ptr, n_coeffs, p->zbin_QTX, p->round_QTX,
367
0
                             p->quant_QTX, p->quant_shift_QTX, qcoeff_ptr,
368
0
                             dqcoeff_ptr, p->dequant_QTX, eob_ptr, sc->scan,
369
0
                             sc->iscan);
370
0
        break;
371
0
      default: assert(0);
372
0
    }
373
0
  }
374
0
}
375
376
static void quantize_dc(const tran_low_t *coeff_ptr, int n_coeffs,
377
                        int skip_block, const int16_t *round_ptr,
378
                        const int16_t quant, tran_low_t *qcoeff_ptr,
379
                        tran_low_t *dqcoeff_ptr, const int16_t dequant_ptr,
380
                        uint16_t *eob_ptr, const qm_val_t *qm_ptr,
381
0
                        const qm_val_t *iqm_ptr, const int log_scale) {
382
0
  const int rc = 0;
383
0
  const int coeff = coeff_ptr[rc];
384
0
  const int coeff_sign = AOMSIGN(coeff);
385
0
  const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
386
0
  int64_t tmp;
387
0
  int eob = -1;
388
0
  int32_t tmp32;
389
0
  int dequant;
390
391
0
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
392
0
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
393
394
0
  if (!skip_block) {
395
0
    const int wt = qm_ptr != NULL ? qm_ptr[rc] : (1 << AOM_QM_BITS);
396
0
    const int iwt = iqm_ptr != NULL ? iqm_ptr[rc] : (1 << AOM_QM_BITS);
397
0
    tmp = clamp(abs_coeff + ROUND_POWER_OF_TWO(round_ptr[rc != 0], log_scale),
398
0
                INT16_MIN, INT16_MAX);
399
0
    tmp32 = (int32_t)((tmp * wt * quant) >> (16 - log_scale + AOM_QM_BITS));
400
0
    qcoeff_ptr[rc] = (tmp32 ^ coeff_sign) - coeff_sign;
401
0
    dequant = (dequant_ptr * iwt + (1 << (AOM_QM_BITS - 1))) >> AOM_QM_BITS;
402
0
    const tran_low_t abs_dqcoeff = (tmp32 * dequant) >> log_scale;
403
0
    dqcoeff_ptr[rc] = (tran_low_t)((abs_dqcoeff ^ coeff_sign) - coeff_sign);
404
0
    if (tmp32) eob = 0;
405
0
  }
406
0
  *eob_ptr = eob + 1;
407
0
}
408
409
void av1_quantize_dc_facade(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
410
                            const MACROBLOCK_PLANE *p, tran_low_t *qcoeff_ptr,
411
                            tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
412
0
                            const SCAN_ORDER *sc, const QUANT_PARAM *qparam) {
413
  // obsolete skip_block
414
0
  const int skip_block = 0;
415
0
  (void)sc;
416
0
  assert(qparam->log_scale >= 0 && qparam->log_scale < (3));
417
0
  const qm_val_t *qm_ptr = qparam->qmatrix;
418
0
  const qm_val_t *iqm_ptr = qparam->iqmatrix;
419
0
  quantize_dc(coeff_ptr, (int)n_coeffs, skip_block, p->round_QTX,
420
0
              p->quant_fp_QTX[0], qcoeff_ptr, dqcoeff_ptr, p->dequant_QTX[0],
421
0
              eob_ptr, qm_ptr, iqm_ptr, qparam->log_scale);
422
0
}
423
424
#if CONFIG_AV1_HIGHBITDEPTH
425
void av1_highbd_quantize_fp_facade(const tran_low_t *coeff_ptr,
426
                                   intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
427
                                   tran_low_t *qcoeff_ptr,
428
                                   tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
429
                                   const SCAN_ORDER *sc,
430
0
                                   const QUANT_PARAM *qparam) {
431
0
  const qm_val_t *qm_ptr = qparam->qmatrix;
432
0
  const qm_val_t *iqm_ptr = qparam->iqmatrix;
433
0
  if (qm_ptr != NULL && iqm_ptr != NULL) {
434
0
    highbd_quantize_fp_helper_c(
435
0
        coeff_ptr, n_coeffs, p->zbin_QTX, p->round_fp_QTX, p->quant_fp_QTX,
436
0
        p->quant_shift_QTX, qcoeff_ptr, dqcoeff_ptr, p->dequant_QTX, eob_ptr,
437
0
        sc->scan, sc->iscan, qm_ptr, iqm_ptr, qparam->log_scale);
438
0
  } else {
439
0
    av1_highbd_quantize_fp(coeff_ptr, n_coeffs, p->zbin_QTX, p->round_fp_QTX,
440
0
                           p->quant_fp_QTX, p->quant_shift_QTX, qcoeff_ptr,
441
0
                           dqcoeff_ptr, p->dequant_QTX, eob_ptr, sc->scan,
442
0
                           sc->iscan, qparam->log_scale);
443
0
  }
444
0
}
445
446
void av1_highbd_quantize_b_facade(const tran_low_t *coeff_ptr,
447
                                  intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
448
                                  tran_low_t *qcoeff_ptr,
449
                                  tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
450
                                  const SCAN_ORDER *sc,
451
0
                                  const QUANT_PARAM *qparam) {
452
0
  const qm_val_t *qm_ptr = qparam->qmatrix;
453
0
  const qm_val_t *iqm_ptr = qparam->iqmatrix;
454
0
#if !CONFIG_REALTIME_ONLY
455
0
  if (qparam->use_quant_b_adapt) {
456
0
    if (qm_ptr != NULL && iqm_ptr != NULL) {
457
0
      aom_highbd_quantize_b_adaptive_helper_c(
458
0
          coeff_ptr, n_coeffs, p->zbin_QTX, p->round_QTX, p->quant_QTX,
459
0
          p->quant_shift_QTX, qcoeff_ptr, dqcoeff_ptr, p->dequant_QTX, eob_ptr,
460
0
          sc->scan, sc->iscan, qm_ptr, iqm_ptr, qparam->log_scale);
461
0
    } else {
462
0
      switch (qparam->log_scale) {
463
0
        case 0:
464
0
          aom_highbd_quantize_b_adaptive(
465
0
              coeff_ptr, n_coeffs, p->zbin_QTX, p->round_QTX, p->quant_QTX,
466
0
              p->quant_shift_QTX, qcoeff_ptr, dqcoeff_ptr, p->dequant_QTX,
467
0
              eob_ptr, sc->scan, sc->iscan);
468
0
          break;
469
0
        case 1:
470
0
          aom_highbd_quantize_b_32x32_adaptive(
471
0
              coeff_ptr, n_coeffs, p->zbin_QTX, p->round_QTX, p->quant_QTX,
472
0
              p->quant_shift_QTX, qcoeff_ptr, dqcoeff_ptr, p->dequant_QTX,
473
0
              eob_ptr, sc->scan, sc->iscan);
474
0
          break;
475
0
        case 2:
476
0
          aom_highbd_quantize_b_64x64_adaptive(
477
0
              coeff_ptr, n_coeffs, p->zbin_QTX, p->round_QTX, p->quant_QTX,
478
0
              p->quant_shift_QTX, qcoeff_ptr, dqcoeff_ptr, p->dequant_QTX,
479
0
              eob_ptr, sc->scan, sc->iscan);
480
0
          break;
481
0
        default: assert(0);
482
0
      }
483
0
    }
484
0
    return;
485
0
  }
486
0
#endif  // !CONFIG_REALTIME_ONLY
487
488
0
  if (qm_ptr != NULL && iqm_ptr != NULL) {
489
0
    aom_highbd_quantize_b_helper_c(
490
0
        coeff_ptr, n_coeffs, p->zbin_QTX, p->round_QTX, p->quant_QTX,
491
0
        p->quant_shift_QTX, qcoeff_ptr, dqcoeff_ptr, p->dequant_QTX, eob_ptr,
492
0
        sc->scan, sc->iscan, qm_ptr, iqm_ptr, qparam->log_scale);
493
0
  } else {
494
0
    switch (qparam->log_scale) {
495
0
      case 0:
496
0
        aom_highbd_quantize_b(coeff_ptr, n_coeffs, p->zbin_QTX, p->round_QTX,
497
0
                              p->quant_QTX, p->quant_shift_QTX, qcoeff_ptr,
498
0
                              dqcoeff_ptr, p->dequant_QTX, eob_ptr, sc->scan,
499
0
                              sc->iscan);
500
0
        break;
501
0
      case 1:
502
0
        aom_highbd_quantize_b_32x32(
503
0
            coeff_ptr, n_coeffs, p->zbin_QTX, p->round_QTX, p->quant_QTX,
504
0
            p->quant_shift_QTX, qcoeff_ptr, dqcoeff_ptr, p->dequant_QTX,
505
0
            eob_ptr, sc->scan, sc->iscan);
506
0
        break;
507
0
      case 2:
508
0
        aom_highbd_quantize_b_64x64(
509
0
            coeff_ptr, n_coeffs, p->zbin_QTX, p->round_QTX, p->quant_QTX,
510
0
            p->quant_shift_QTX, qcoeff_ptr, dqcoeff_ptr, p->dequant_QTX,
511
0
            eob_ptr, sc->scan, sc->iscan);
512
0
        break;
513
0
      default: assert(0);
514
0
    }
515
0
  }
516
0
}
517
518
static inline void highbd_quantize_dc(
519
    const tran_low_t *coeff_ptr, int n_coeffs, int skip_block,
520
    const int16_t *round_ptr, const int16_t quant, tran_low_t *qcoeff_ptr,
521
    tran_low_t *dqcoeff_ptr, const int16_t dequant_ptr, uint16_t *eob_ptr,
522
0
    const qm_val_t *qm_ptr, const qm_val_t *iqm_ptr, const int log_scale) {
523
0
  int eob = -1;
524
525
0
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
526
0
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
527
528
0
  if (!skip_block) {
529
0
    const qm_val_t wt = qm_ptr != NULL ? qm_ptr[0] : (1 << AOM_QM_BITS);
530
0
    const qm_val_t iwt = iqm_ptr != NULL ? iqm_ptr[0] : (1 << AOM_QM_BITS);
531
0
    const int coeff = coeff_ptr[0];
532
0
    const int coeff_sign = AOMSIGN(coeff);
533
0
    const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
534
0
    const int64_t tmp = abs_coeff + ROUND_POWER_OF_TWO(round_ptr[0], log_scale);
535
0
    const int64_t tmpw = tmp * wt;
536
0
    const int abs_qcoeff =
537
0
        (int)((tmpw * quant) >> (16 - log_scale + AOM_QM_BITS));
538
0
    qcoeff_ptr[0] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
539
0
    const int dequant =
540
0
        (dequant_ptr * iwt + (1 << (AOM_QM_BITS - 1))) >> AOM_QM_BITS;
541
542
0
    const tran_low_t abs_dqcoeff = (abs_qcoeff * dequant) >> log_scale;
543
0
    dqcoeff_ptr[0] = (tran_low_t)((abs_dqcoeff ^ coeff_sign) - coeff_sign);
544
0
    if (abs_qcoeff) eob = 0;
545
0
  }
546
0
  *eob_ptr = eob + 1;
547
0
}
548
549
void av1_highbd_quantize_dc_facade(const tran_low_t *coeff_ptr,
550
                                   intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
551
                                   tran_low_t *qcoeff_ptr,
552
                                   tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
553
                                   const SCAN_ORDER *sc,
554
0
                                   const QUANT_PARAM *qparam) {
555
  // obsolete skip_block
556
0
  const int skip_block = 0;
557
0
  const qm_val_t *qm_ptr = qparam->qmatrix;
558
0
  const qm_val_t *iqm_ptr = qparam->iqmatrix;
559
0
  (void)sc;
560
561
0
  highbd_quantize_dc(coeff_ptr, (int)n_coeffs, skip_block, p->round_QTX,
562
0
                     p->quant_fp_QTX[0], qcoeff_ptr, dqcoeff_ptr,
563
0
                     p->dequant_QTX[0], eob_ptr, qm_ptr, iqm_ptr,
564
0
                     qparam->log_scale);
565
0
}
566
567
void av1_highbd_quantize_fp_c(const tran_low_t *coeff_ptr, intptr_t count,
568
                              const int16_t *zbin_ptr, const int16_t *round_ptr,
569
                              const int16_t *quant_ptr,
570
                              const int16_t *quant_shift_ptr,
571
                              tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
572
                              const int16_t *dequant_ptr, uint16_t *eob_ptr,
573
                              const int16_t *scan, const int16_t *iscan,
574
0
                              int log_scale) {
575
0
  highbd_quantize_fp_helper_c(coeff_ptr, count, zbin_ptr, round_ptr, quant_ptr,
576
0
                              quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr,
577
0
                              dequant_ptr, eob_ptr, scan, iscan, NULL, NULL,
578
0
                              log_scale);
579
0
}
580
#endif  // CONFIG_AV1_HIGHBITDEPTH
581
582
0
static void invert_quant(int16_t *quant, int16_t *shift, int d) {
583
0
  uint32_t t;
584
0
  int l, m;
585
0
  t = d;
586
0
  l = get_msb(t);
587
0
  m = 1 + (1 << (16 + l)) / d;
588
0
  *quant = (int16_t)(m - (1 << 16));
589
0
  *shift = 1 << (16 - l);
590
0
}
591
592
0
static int get_qzbin_factor(int q, aom_bit_depth_t bit_depth) {
593
0
  const int quant = av1_dc_quant_QTX(q, 0, bit_depth);
594
0
  switch (bit_depth) {
595
0
    case AOM_BITS_8: return q == 0 ? 64 : (quant < 148 ? 84 : 80);
596
0
    case AOM_BITS_10: return q == 0 ? 64 : (quant < 592 ? 84 : 80);
597
0
    case AOM_BITS_12: return q == 0 ? 64 : (quant < 2368 ? 84 : 80);
598
0
    default:
599
0
      assert(0 && "bit_depth should be AOM_BITS_8, AOM_BITS_10 or AOM_BITS_12");
600
0
      return -1;
601
0
  }
602
0
}
603
604
void av1_build_quantizer(aom_bit_depth_t bit_depth, int y_dc_delta_q,
605
                         int u_dc_delta_q, int u_ac_delta_q, int v_dc_delta_q,
606
                         int v_ac_delta_q, QUANTS *const quants,
607
0
                         Dequants *const deq, int sharpness) {
608
0
  int i, q, quant_QTX;
609
0
  const int sharpness_adjustment = 16 * (7 - sharpness) / 7;
610
611
0
  for (q = 0; q < QINDEX_RANGE; q++) {
612
0
    const int qzbin_factor = get_qzbin_factor(q, bit_depth);
613
0
    int qrounding_factor = q == 0 ? 64 : 48;
614
615
0
    for (i = 0; i < 2; ++i) {
616
0
      int qrounding_factor_fp = 64;
617
618
0
      if (sharpness != 0 && q != 0) {
619
0
        qrounding_factor = 64 - sharpness_adjustment;
620
0
        qrounding_factor_fp = 64 - sharpness_adjustment;
621
0
      }
622
623
      // y quantizer with TX scale
624
0
      quant_QTX = i == 0 ? av1_dc_quant_QTX(q, y_dc_delta_q, bit_depth)
625
0
                         : av1_ac_quant_QTX(q, 0, bit_depth);
626
0
      invert_quant(&quants->y_quant[q][i], &quants->y_quant_shift[q][i],
627
0
                   quant_QTX);
628
0
      quants->y_quant_fp[q][i] = (1 << 16) / quant_QTX;
629
0
      quants->y_round_fp[q][i] = (qrounding_factor_fp * quant_QTX) >> 7;
630
0
      quants->y_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant_QTX, 7);
631
0
      quants->y_round[q][i] = (qrounding_factor * quant_QTX) >> 7;
632
0
      deq->y_dequant_QTX[q][i] = quant_QTX;
633
634
      // u quantizer with TX scale
635
0
      quant_QTX = i == 0 ? av1_dc_quant_QTX(q, u_dc_delta_q, bit_depth)
636
0
                         : av1_ac_quant_QTX(q, u_ac_delta_q, bit_depth);
637
0
      invert_quant(&quants->u_quant[q][i], &quants->u_quant_shift[q][i],
638
0
                   quant_QTX);
639
0
      quants->u_quant_fp[q][i] = (1 << 16) / quant_QTX;
640
0
      quants->u_round_fp[q][i] = (qrounding_factor_fp * quant_QTX) >> 7;
641
0
      quants->u_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant_QTX, 7);
642
0
      quants->u_round[q][i] = (qrounding_factor * quant_QTX) >> 7;
643
0
      deq->u_dequant_QTX[q][i] = quant_QTX;
644
645
      // v quantizer with TX scale
646
0
      quant_QTX = i == 0 ? av1_dc_quant_QTX(q, v_dc_delta_q, bit_depth)
647
0
                         : av1_ac_quant_QTX(q, v_ac_delta_q, bit_depth);
648
0
      invert_quant(&quants->v_quant[q][i], &quants->v_quant_shift[q][i],
649
0
                   quant_QTX);
650
0
      quants->v_quant_fp[q][i] = (1 << 16) / quant_QTX;
651
0
      quants->v_round_fp[q][i] = (qrounding_factor_fp * quant_QTX) >> 7;
652
0
      quants->v_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant_QTX, 7);
653
0
      quants->v_round[q][i] = (qrounding_factor * quant_QTX) >> 7;
654
0
      deq->v_dequant_QTX[q][i] = quant_QTX;
655
0
    }
656
657
0
    for (i = 2; i < 8; i++) {  // 8: SIMD width
658
0
      quants->y_quant[q][i] = quants->y_quant[q][1];
659
0
      quants->y_quant_fp[q][i] = quants->y_quant_fp[q][1];
660
0
      quants->y_round_fp[q][i] = quants->y_round_fp[q][1];
661
0
      quants->y_quant_shift[q][i] = quants->y_quant_shift[q][1];
662
0
      quants->y_zbin[q][i] = quants->y_zbin[q][1];
663
0
      quants->y_round[q][i] = quants->y_round[q][1];
664
0
      deq->y_dequant_QTX[q][i] = deq->y_dequant_QTX[q][1];
665
666
0
      quants->u_quant[q][i] = quants->u_quant[q][1];
667
0
      quants->u_quant_fp[q][i] = quants->u_quant_fp[q][1];
668
0
      quants->u_round_fp[q][i] = quants->u_round_fp[q][1];
669
0
      quants->u_quant_shift[q][i] = quants->u_quant_shift[q][1];
670
0
      quants->u_zbin[q][i] = quants->u_zbin[q][1];
671
0
      quants->u_round[q][i] = quants->u_round[q][1];
672
0
      deq->u_dequant_QTX[q][i] = deq->u_dequant_QTX[q][1];
673
674
0
      quants->v_quant[q][i] = quants->v_quant[q][1];
675
0
      quants->v_quant_fp[q][i] = quants->v_quant_fp[q][1];
676
0
      quants->v_round_fp[q][i] = quants->v_round_fp[q][1];
677
0
      quants->v_quant_shift[q][i] = quants->v_quant_shift[q][1];
678
0
      quants->v_zbin[q][i] = quants->v_zbin[q][1];
679
0
      quants->v_round[q][i] = quants->v_round[q][1];
680
0
      deq->v_dequant_QTX[q][i] = deq->v_dequant_QTX[q][1];
681
0
    }
682
0
  }
683
0
}
684
685
static inline bool deltaq_params_have_changed(
686
    const DeltaQuantParams *prev_deltaq_params,
687
0
    const CommonQuantParams *quant_params) {
688
0
  return (prev_deltaq_params->y_dc_delta_q != quant_params->y_dc_delta_q ||
689
0
          prev_deltaq_params->u_dc_delta_q != quant_params->u_dc_delta_q ||
690
0
          prev_deltaq_params->v_dc_delta_q != quant_params->v_dc_delta_q ||
691
0
          prev_deltaq_params->u_ac_delta_q != quant_params->u_ac_delta_q ||
692
0
          prev_deltaq_params->v_ac_delta_q != quant_params->v_ac_delta_q ||
693
0
          prev_deltaq_params->sharpness != quant_params->sharpness);
694
0
}
695
696
void av1_init_quantizer(EncQuantDequantParams *const enc_quant_dequant_params,
697
                        CommonQuantParams *quant_params,
698
0
                        aom_bit_depth_t bit_depth, int sharpness) {
699
0
  DeltaQuantParams *const prev_deltaq_params =
700
0
      &enc_quant_dequant_params->prev_deltaq_params;
701
0
  quant_params->sharpness = sharpness;
702
703
  // Re-initialize the quantizer only if any of the dc/ac deltaq parameters
704
  // change.
705
0
  if (!deltaq_params_have_changed(prev_deltaq_params, quant_params)) return;
706
0
  QUANTS *const quants = &enc_quant_dequant_params->quants;
707
0
  Dequants *const dequants = &enc_quant_dequant_params->dequants;
708
0
  av1_build_quantizer(bit_depth, quant_params->y_dc_delta_q,
709
0
                      quant_params->u_dc_delta_q, quant_params->u_ac_delta_q,
710
0
                      quant_params->v_dc_delta_q, quant_params->v_ac_delta_q,
711
0
                      quants, dequants, sharpness);
712
713
  // Record the state of deltaq parameters.
714
0
  prev_deltaq_params->y_dc_delta_q = quant_params->y_dc_delta_q;
715
0
  prev_deltaq_params->u_dc_delta_q = quant_params->u_dc_delta_q;
716
0
  prev_deltaq_params->v_dc_delta_q = quant_params->v_dc_delta_q;
717
0
  prev_deltaq_params->u_ac_delta_q = quant_params->u_ac_delta_q;
718
0
  prev_deltaq_params->v_ac_delta_q = quant_params->v_ac_delta_q;
719
0
  prev_deltaq_params->sharpness = sharpness;
720
0
}
721
722
/*!\brief Update quantize parameters in MACROBLOCK
723
 *
724
 * \param[in]  enc_quant_dequant_params This parameter cached the quantize and
725
 *                                      dequantize parameters for all q
726
 *                                      indices.
727
 * \param[in]  qindex                   Quantize index used for the current
728
 *                                      superblock.
729
 * \param[out] x                        A superblock data structure for
730
 *                                      encoder.
731
 */
732
static void set_q_index(const EncQuantDequantParams *enc_quant_dequant_params,
733
0
                        int qindex, MACROBLOCK *x) {
734
0
  const QUANTS *const quants = &enc_quant_dequant_params->quants;
735
0
  const Dequants *const dequants = &enc_quant_dequant_params->dequants;
736
0
  x->qindex = qindex;
737
0
  x->seg_skip_block =
738
0
      0;  // TODO(angiebird): Find a proper place to init this variable.
739
740
  // Y
741
0
  x->plane[0].quant_QTX = quants->y_quant[qindex];
742
0
  x->plane[0].quant_fp_QTX = quants->y_quant_fp[qindex];
743
0
  x->plane[0].round_fp_QTX = quants->y_round_fp[qindex];
744
0
  x->plane[0].quant_shift_QTX = quants->y_quant_shift[qindex];
745
0
  x->plane[0].zbin_QTX = quants->y_zbin[qindex];
746
0
  x->plane[0].round_QTX = quants->y_round[qindex];
747
0
  x->plane[0].dequant_QTX = dequants->y_dequant_QTX[qindex];
748
749
  // U
750
0
  x->plane[1].quant_QTX = quants->u_quant[qindex];
751
0
  x->plane[1].quant_fp_QTX = quants->u_quant_fp[qindex];
752
0
  x->plane[1].round_fp_QTX = quants->u_round_fp[qindex];
753
0
  x->plane[1].quant_shift_QTX = quants->u_quant_shift[qindex];
754
0
  x->plane[1].zbin_QTX = quants->u_zbin[qindex];
755
0
  x->plane[1].round_QTX = quants->u_round[qindex];
756
0
  x->plane[1].dequant_QTX = dequants->u_dequant_QTX[qindex];
757
758
  // V
759
0
  x->plane[2].quant_QTX = quants->v_quant[qindex];
760
0
  x->plane[2].quant_fp_QTX = quants->v_quant_fp[qindex];
761
0
  x->plane[2].round_fp_QTX = quants->v_round_fp[qindex];
762
0
  x->plane[2].quant_shift_QTX = quants->v_quant_shift[qindex];
763
0
  x->plane[2].zbin_QTX = quants->v_zbin[qindex];
764
0
  x->plane[2].round_QTX = quants->v_round[qindex];
765
0
  x->plane[2].dequant_QTX = dequants->v_dequant_QTX[qindex];
766
0
}
767
768
/*!\brief Update quantize matrix in MACROBLOCKD based on segment id
769
 *
770
 * \param[in]  quant_params  Quantize parameters used by encoder and decoder
771
 * \param[in]  segment_id    Segment id.
772
 * \param[out] xd            A superblock data structure used by encoder and
773
 * decoder.
774
 */
775
static void set_qmatrix(const CommonQuantParams *quant_params, int segment_id,
776
0
                        MACROBLOCKD *xd) {
777
0
  const int use_qmatrix = av1_use_qmatrix(quant_params, xd, segment_id);
778
0
  const int qmlevel_y =
779
0
      use_qmatrix ? quant_params->qmatrix_level_y : NUM_QM_LEVELS - 1;
780
0
  const int qmlevel_u =
781
0
      use_qmatrix ? quant_params->qmatrix_level_u : NUM_QM_LEVELS - 1;
782
0
  const int qmlevel_v =
783
0
      use_qmatrix ? quant_params->qmatrix_level_v : NUM_QM_LEVELS - 1;
784
0
  const int qmlevel_ls[MAX_MB_PLANE] = { qmlevel_y, qmlevel_u, qmlevel_v };
785
0
  for (int i = 0; i < MAX_MB_PLANE; ++i) {
786
0
    const int qmlevel = qmlevel_ls[i];
787
0
    memcpy(&xd->plane[i].seg_qmatrix[segment_id],
788
0
           quant_params->gqmatrix[qmlevel][i],
789
0
           sizeof(quant_params->gqmatrix[qmlevel][i]));
790
0
    memcpy(&xd->plane[i].seg_iqmatrix[segment_id],
791
0
           quant_params->giqmatrix[qmlevel][i],
792
0
           sizeof(quant_params->giqmatrix[qmlevel][i]));
793
0
  }
794
0
}
795
796
void av1_init_plane_quantizers(const AV1_COMP *cpi, MACROBLOCK *x,
797
0
                               int segment_id, const int do_update) {
798
0
  const AV1_COMMON *const cm = &cpi->common;
799
0
  const CommonQuantParams *const quant_params = &cm->quant_params;
800
0
  const GF_GROUP *const gf_group = &cpi->ppi->gf_group;
801
0
  const int boost_index = AOMMIN(15, (cpi->ppi->p_rc.gfu_boost / 100));
802
0
  const int layer_depth = AOMMIN(gf_group->layer_depth[cpi->gf_frame_index], 6);
803
0
  const FRAME_TYPE frame_type = cm->current_frame.frame_type;
804
0
  int qindex_rd;
805
806
0
  const int current_qindex =
807
0
      clamp(cm->delta_q_info.delta_q_present_flag
808
0
                ? quant_params->base_qindex + x->delta_qindex
809
0
                : quant_params->base_qindex,
810
0
            0, QINDEX_RANGE - 1);
811
0
  const int qindex = av1_get_qindex(&cm->seg, segment_id, current_qindex);
812
813
0
  if (cpi->oxcf.sb_qp_sweep) {
814
0
    const int current_rd_qindex =
815
0
        clamp(cm->delta_q_info.delta_q_present_flag
816
0
                  ? quant_params->base_qindex + x->rdmult_delta_qindex
817
0
                  : quant_params->base_qindex,
818
0
              0, QINDEX_RANGE - 1);
819
0
    qindex_rd = av1_get_qindex(&cm->seg, segment_id, current_rd_qindex);
820
0
  } else {
821
0
    qindex_rd = qindex;
822
0
  }
823
824
0
  const int qindex_rdmult = qindex_rd + quant_params->y_dc_delta_q;
825
0
  const int rdmult = av1_compute_rd_mult(
826
0
      qindex_rdmult, cm->seq_params->bit_depth,
827
0
      cpi->ppi->gf_group.update_type[cpi->gf_frame_index], layer_depth,
828
0
      boost_index, frame_type, cpi->oxcf.q_cfg.use_fixed_qp_offsets,
829
0
      is_stat_consumption_stage(cpi), cpi->oxcf.tune_cfg.tuning,
830
0
      cpi->oxcf.mode);
831
832
0
  const int qindex_change = x->qindex != qindex;
833
0
  if (qindex_change || do_update) {
834
0
    set_q_index(&cpi->enc_quant_dequant_params, qindex, x);
835
0
  }
836
837
0
  MACROBLOCKD *const xd = &x->e_mbd;
838
0
  if ((segment_id != x->prev_segment_id) ||
839
0
      av1_use_qmatrix(quant_params, xd, segment_id)) {
840
0
    set_qmatrix(quant_params, segment_id, xd);
841
0
  }
842
843
0
  x->seg_skip_block = segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP);
844
845
0
  av1_set_error_per_bit(&x->errorperbit, rdmult);
846
0
  av1_set_sad_per_bit(cpi, &x->sadperbit, qindex_rd);
847
848
0
  x->prev_segment_id = segment_id;
849
0
}
850
851
0
void av1_frame_init_quantizer(AV1_COMP *cpi) {
852
0
  MACROBLOCK *const x = &cpi->td.mb;
853
0
  MACROBLOCKD *const xd = &x->e_mbd;
854
0
  x->prev_segment_id = -1;
855
0
  av1_init_plane_quantizers(cpi, x, xd->mi[0]->segment_id, 1);
856
0
}
857
858
0
static int adjust_hdr_cb_deltaq(int base_qindex) {
859
0
  double baseQp = base_qindex / QP_SCALE_FACTOR;
860
0
  const double chromaQp = CHROMA_QP_SCALE * baseQp + CHROMA_QP_OFFSET;
861
0
  const double dcbQP = CHROMA_CB_QP_SCALE * chromaQp * QP_SCALE_FACTOR;
862
0
  int dqpCb = (int)(dcbQP + (dcbQP < 0 ? -0.5 : 0.5));
863
0
  dqpCb = AOMMIN(0, dqpCb);
864
0
  dqpCb = (int)CLIP(dqpCb, -12 * QP_SCALE_FACTOR, 12 * QP_SCALE_FACTOR);
865
0
  return dqpCb;
866
0
}
867
868
0
static int adjust_hdr_cr_deltaq(int base_qindex) {
869
0
  double baseQp = base_qindex / QP_SCALE_FACTOR;
870
0
  const double chromaQp = CHROMA_QP_SCALE * baseQp + CHROMA_QP_OFFSET;
871
0
  const double dcrQP = CHROMA_CR_QP_SCALE * chromaQp * QP_SCALE_FACTOR;
872
0
  int dqpCr = (int)(dcrQP + (dcrQP < 0 ? -0.5 : 0.5));
873
0
  dqpCr = AOMMIN(0, dqpCr);
874
0
  dqpCr = (int)CLIP(dqpCr, -12 * QP_SCALE_FACTOR, 12 * QP_SCALE_FACTOR);
875
0
  return dqpCr;
876
0
}
877
878
void av1_set_quantizer(AV1_COMMON *const cm, int min_qmlevel, int max_qmlevel,
879
                       int q, int enable_chroma_deltaq, int enable_hdr_deltaq,
880
0
                       bool is_allintra, aom_tune_metric tuning) {
881
  // quantizer has to be reinitialized with av1_init_quantizer() if any
882
  // delta_q changes.
883
0
  CommonQuantParams *quant_params = &cm->quant_params;
884
0
  quant_params->base_qindex = AOMMAX(cm->delta_q_info.delta_q_present_flag, q);
885
0
  quant_params->y_dc_delta_q = 0;
886
887
  // Disable deltaq in lossless mode.
888
0
  if (enable_chroma_deltaq && q) {
889
0
    if (tuning == AOM_TUNE_IQ || tuning == AOM_TUNE_SSIMULACRA2) {
890
0
      int chroma_dc_delta_q = 0;
891
0
      int chroma_ac_delta_q = 0;
892
893
0
      if (cm->seq_params->subsampling_x == 1 &&
894
0
          cm->seq_params->subsampling_y == 1) {
895
        // 4:2:0 subsampling: Constant chroma delta_q decrease (i.e. improved
896
        // chroma quality relative to luma) with gradual ramp-down for very low
897
        // qindexes.
898
        // Lowering chroma delta_q by 16 was found to improve SSIMULACRA 2
899
        // BD-Rate by 1.5-2% on Daala's subset1, as well as reducing chroma
900
        // artifacts (smudging, discoloration) during subjective quality
901
        // evaluations.
902
        // The ramp-down of chroma increase was determined by generating the
903
        // convex hull of SSIMULACRA 2 scores (for all boosts from 0-16), and
904
        // finding a linear equation that fits the convex hull.
905
        // For the SSIMULACRA 2 tune only: a convex hull of SSIMULACRA 2 scores
906
        // (mean, 10th percentile) was generated by decreasing chroma delta_q
907
        // by 3 different values (16, 20 and 24). 20 was selected as it had the
908
        // best 10th percentile performance.
909
0
        int offset = (tuning == AOM_TUNE_SSIMULACRA2) ? 20 : 16;
910
0
        chroma_dc_delta_q =
911
0
            -clamp((quant_params->base_qindex / 2) - 14, 0, offset);
912
0
        chroma_ac_delta_q = chroma_dc_delta_q;
913
0
      } else if (cm->seq_params->subsampling_x == 1 &&
914
0
                 cm->seq_params->subsampling_y == 0) {
915
        // 4:2:2 subsampling: Constant chroma AC delta_q increase (i.e. improved
916
        // luma quality relative to chroma) with gradual ramp-down for very low
917
        // qindexes.
918
        // SSIMULACRA 2 appears to have some issues correctly scoring 4:2:2
919
        // material. Solely optimizing for maximum scores suggests a chroma AC
920
        // delta_q of 12 is the most efficient. However, visual inspection on
921
        // difficult-to-encode material resulted in chroma quality degrading too
922
        // much relative to luma, and chroma channels ending up being too small
923
        // compared to equivalent 4:4:4 or 4:2:0 encodes.
924
        // A chroma AC delta_q of 6 was selected because encoded chroma channels
925
        // have a much closer size to 4:4:4 and 4:2:0 encodes, and have more
926
        // favorable visual quality characteristics.
927
        // The ramp-down of chroma decrease was put into place to match 4:2:0
928
        // and 4:4:4 behavior. There were no special considerations on
929
        // SSIMULACRA 2 scores.
930
0
        chroma_dc_delta_q = 0;
931
0
        chroma_ac_delta_q = clamp((quant_params->base_qindex / 2), 0, 6);
932
0
      } else if (cm->seq_params->subsampling_x == 0 &&
933
0
                 cm->seq_params->subsampling_y == 0) {
934
        // 4:4:4 subsampling: Constant chroma AC delta_q increase (i.e. improved
935
        // luma quality relative to chroma) with gradual ramp-down for very low
936
        // qindexes.
937
        // Raising chroma AC delta_q by 24 was found to improve SSIMULACRA 2
938
        // BD-Rate by 2.5-3% on Daala's subset1, as well as providing a more
939
        // balanced bit allocation between the (relatively-starved) luma and
940
        // chroma channels.
941
        // Raising chroma DC delta_q appears to be harmful, both for SSIMULACRA
942
        // 2 scores and subjective quality (harshens blocking artifacts).
943
        // The ramp-down of chroma decrease was put into place so (lossy) QP 0
944
        // encodes still score within 0.1 SSIMULACRA 2 points of the equivalent
945
        // with no chroma delta_q (with a small efficiency improvement), while
946
        // encodes in the SSIMULACRA 2 <=90 range yield full benefits from this
947
        // adjustment.
948
0
        chroma_dc_delta_q = 0;
949
0
        chroma_ac_delta_q = clamp((quant_params->base_qindex / 2), 0, 24);
950
0
      }
951
952
      // TODO: bug https://crbug.com/aomedia/375221136 - find chroma_delta_q
953
      // values for 4:2:2 subsampling mode.
954
0
      quant_params->u_dc_delta_q = chroma_dc_delta_q;
955
0
      quant_params->u_ac_delta_q = chroma_ac_delta_q;
956
0
      quant_params->v_dc_delta_q = chroma_dc_delta_q;
957
0
      quant_params->v_ac_delta_q = chroma_ac_delta_q;
958
0
    } else {
959
      // TODO(aomedia:2717): need to design better delta
960
0
      quant_params->u_dc_delta_q = 2;
961
0
      quant_params->u_ac_delta_q = 2;
962
0
      quant_params->v_dc_delta_q = 2;
963
0
      quant_params->v_ac_delta_q = 2;
964
0
    }
965
0
  } else {
966
0
    quant_params->u_dc_delta_q = 0;
967
0
    quant_params->u_ac_delta_q = 0;
968
0
    quant_params->v_dc_delta_q = 0;
969
0
    quant_params->v_ac_delta_q = 0;
970
0
  }
971
972
  // following section 8.3.2 in T-REC-H.Sup15 document
973
  // to apply to AV1 qindex in the range of [0, 255]
974
0
  if (enable_hdr_deltaq && q) {
975
0
    int dqpCb = adjust_hdr_cb_deltaq(quant_params->base_qindex);
976
0
    int dqpCr = adjust_hdr_cr_deltaq(quant_params->base_qindex);
977
0
    quant_params->u_dc_delta_q = quant_params->u_ac_delta_q = dqpCb;
978
0
    quant_params->v_dc_delta_q = quant_params->v_ac_delta_q = dqpCr;
979
0
    if (dqpCb != dqpCr) {
980
0
      cm->seq_params->separate_uv_delta_q = 1;
981
0
    }
982
0
  }
983
984
  // Select the best luma and chroma QM formulas based on encoding mode and
985
  // tuning
986
0
  int (*get_luma_qmlevel)(int, int, int);
987
0
  int (*get_chroma_qmlevel)(int, int, int);
988
989
0
  if (tuning == AOM_TUNE_IQ || tuning == AOM_TUNE_SSIMULACRA2) {
990
0
    if (tuning == AOM_TUNE_SSIMULACRA2) {
991
      // Use luma QM formula specifically tailored for tune SSIMULACRA2
992
0
      get_luma_qmlevel = aom_get_qmlevel_luma_ssimulacra2;
993
0
    } else {
994
0
      get_luma_qmlevel = aom_get_qmlevel_allintra;
995
0
    }
996
997
0
    if (cm->seq_params->subsampling_x == 0 &&
998
0
        cm->seq_params->subsampling_y == 0) {
999
      // 4:4:4 subsampling mode has 4x the number of chroma coefficients
1000
      // compared to 4:2:0 (2x on each dimension). This means the encoder
1001
      // should use lower chroma QM levels that more closely match the scaling
1002
      // of an equivalent 4:2:0 chroma QM.
1003
0
      get_chroma_qmlevel = aom_get_qmlevel_444_chroma;
1004
0
    } else {
1005
      // For all other chroma subsampling modes, use the all intra QM formula
1006
0
      get_chroma_qmlevel = aom_get_qmlevel_allintra;
1007
0
    }
1008
0
  } else if (is_allintra) {
1009
0
    get_luma_qmlevel = aom_get_qmlevel_allintra;
1010
0
    get_chroma_qmlevel = aom_get_qmlevel_allintra;
1011
0
  } else {
1012
0
    get_luma_qmlevel = aom_get_qmlevel;
1013
0
    get_chroma_qmlevel = aom_get_qmlevel;
1014
0
  }
1015
1016
0
  quant_params->qmatrix_level_y =
1017
0
      get_luma_qmlevel(quant_params->base_qindex, min_qmlevel, max_qmlevel);
1018
0
  quant_params->qmatrix_level_u =
1019
0
      get_chroma_qmlevel(quant_params->base_qindex + quant_params->u_ac_delta_q,
1020
0
                         min_qmlevel, max_qmlevel);
1021
1022
0
  if (cm->seq_params->separate_uv_delta_q) {
1023
0
    quant_params->qmatrix_level_v = get_chroma_qmlevel(
1024
0
        quant_params->base_qindex + quant_params->v_ac_delta_q, min_qmlevel,
1025
0
        max_qmlevel);
1026
0
  } else {
1027
0
    quant_params->qmatrix_level_v = quant_params->qmatrix_level_u;
1028
0
  }
1029
0
}
1030
1031
// Table that converts 0-63 Q-range values passed in outside to the Qindex
1032
// range used internally.
1033
static const int quantizer_to_qindex[] = {
1034
  0,   4,   8,   12,  16,  20,  24,  28,  32,  36,  40,  44,  48,
1035
  52,  56,  60,  64,  68,  72,  76,  80,  84,  88,  92,  96,  100,
1036
  104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152,
1037
  156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204,
1038
  208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 249, 255,
1039
};
1040
1041
0
int av1_quantizer_to_qindex(int quantizer) {
1042
0
  return quantizer_to_qindex[quantizer];
1043
0
}
1044
1045
0
int av1_qindex_to_quantizer(int qindex) {
1046
0
  int quantizer;
1047
1048
0
  for (quantizer = 0; quantizer < 64; ++quantizer)
1049
0
    if (quantizer_to_qindex[quantizer] >= qindex) return quantizer;
1050
1051
0
  return 63;
1052
0
}