Coverage Report

Created: 2024-09-06 07:53

/src/libvpx/vpx_dsp/quantize.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *  Copyright (c) 2015 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
13
#include "./vpx_dsp_rtcd.h"
14
#include "vpx_dsp/quantize.h"
15
#include "vpx_dsp/vpx_dsp_common.h"
16
#include "vpx_mem/vpx_mem.h"
17
#include "vp9/common/vp9_scan.h"
18
#include "vp9/encoder/vp9_block.h"
19
20
void vpx_quantize_dc(const tran_low_t *coeff_ptr, int n_coeffs,
21
                     const int16_t *round_ptr, const int16_t quant,
22
                     tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
23
299k
                     const int16_t dequant, uint16_t *eob_ptr) {
24
299k
  const int rc = 0;
25
299k
  const int coeff = coeff_ptr[rc];
26
299k
  const int coeff_sign = (coeff >> 31);
27
299k
  const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
28
299k
  int tmp, eob = -1;
29
30
299k
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
31
299k
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
32
33
299k
  tmp = clamp(abs_coeff + round_ptr[rc != 0], INT16_MIN, INT16_MAX);
34
299k
  tmp = (tmp * quant) >> 16;
35
299k
  qcoeff_ptr[rc] = (tmp ^ coeff_sign) - coeff_sign;
36
299k
  dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant;
37
299k
  if (tmp) eob = 0;
38
39
299k
  *eob_ptr = eob + 1;
40
299k
}
41
42
#if CONFIG_VP9_HIGHBITDEPTH
43
void vpx_highbd_quantize_dc(const tran_low_t *coeff_ptr, int n_coeffs,
44
                            const int16_t *round_ptr, const int16_t quant,
45
                            tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
46
0
                            const int16_t dequant, uint16_t *eob_ptr) {
47
0
  int eob = -1;
48
49
0
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
50
0
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
51
52
0
  {
53
0
    const int coeff = coeff_ptr[0];
54
0
    const int coeff_sign = (coeff >> 31);
55
0
    const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
56
0
    const int64_t tmp = abs_coeff + round_ptr[0];
57
0
    const int abs_qcoeff = (int)((tmp * quant) >> 16);
58
0
    qcoeff_ptr[0] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
59
0
    dqcoeff_ptr[0] = qcoeff_ptr[0] * dequant;
60
0
    if (abs_qcoeff) eob = 0;
61
0
  }
62
63
0
  *eob_ptr = eob + 1;
64
0
}
65
#endif
66
67
void vpx_quantize_dc_32x32(const tran_low_t *coeff_ptr,
68
                           const int16_t *round_ptr, const int16_t quant,
69
                           tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
70
2.09k
                           const int16_t dequant, uint16_t *eob_ptr) {
71
2.09k
  const int n_coeffs = 1024;
72
2.09k
  const int rc = 0;
73
2.09k
  const int coeff = coeff_ptr[rc];
74
2.09k
  const int coeff_sign = (coeff >> 31);
75
2.09k
  const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
76
2.09k
  int tmp, eob = -1;
77
78
2.09k
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
79
2.09k
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
80
81
2.09k
  tmp = clamp(abs_coeff + ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1), INT16_MIN,
82
2.09k
              INT16_MAX);
83
2.09k
  tmp = (tmp * quant) >> 15;
84
2.09k
  qcoeff_ptr[rc] = (tmp ^ coeff_sign) - coeff_sign;
85
2.09k
  dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant / 2;
86
2.09k
  if (tmp) eob = 0;
87
88
2.09k
  *eob_ptr = eob + 1;
89
2.09k
}
90
91
#if CONFIG_VP9_HIGHBITDEPTH
92
void vpx_highbd_quantize_dc_32x32(const tran_low_t *coeff_ptr,
93
                                  const int16_t *round_ptr, const int16_t quant,
94
                                  tran_low_t *qcoeff_ptr,
95
                                  tran_low_t *dqcoeff_ptr,
96
0
                                  const int16_t dequant, uint16_t *eob_ptr) {
97
0
  const int n_coeffs = 1024;
98
0
  int eob = -1;
99
100
0
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
101
0
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
102
103
0
  {
104
0
    const int coeff = coeff_ptr[0];
105
0
    const int coeff_sign = (coeff >> 31);
106
0
    const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
107
0
    const int64_t tmp = abs_coeff + ROUND_POWER_OF_TWO(round_ptr[0], 1);
108
0
    const int abs_qcoeff = (int)((tmp * quant) >> 15);
109
0
    qcoeff_ptr[0] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
110
0
    dqcoeff_ptr[0] = qcoeff_ptr[0] * dequant / 2;
111
0
    if (abs_qcoeff) eob = 0;
112
0
  }
113
114
0
  *eob_ptr = eob + 1;
115
0
}
116
#endif
117
118
void vpx_quantize_b_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
119
                      const struct macroblock_plane *const mb_plane,
120
                      tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
121
                      const int16_t *dequant_ptr, uint16_t *eob_ptr,
122
0
                      const struct ScanOrder *const scan_order) {
123
0
  int i, non_zero_count = (int)n_coeffs, eob = -1;
124
0
  const int zbins[2] = { mb_plane->zbin[0], mb_plane->zbin[1] };
125
0
  const int nzbins[2] = { zbins[0] * -1, zbins[1] * -1 };
126
0
  const int16_t *round_ptr = mb_plane->round;
127
0
  const int16_t *quant_ptr = mb_plane->quant;
128
0
  const int16_t *quant_shift_ptr = mb_plane->quant_shift;
129
0
  const int16_t *scan = scan_order->scan;
130
131
0
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
132
0
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
133
134
  // Pre-scan pass
135
0
  for (i = (int)n_coeffs - 1; i >= 0; i--) {
136
0
    const int rc = scan[i];
137
0
    const int coeff = coeff_ptr[rc];
138
139
0
    if (coeff < zbins[rc != 0] && coeff > nzbins[rc != 0])
140
0
      non_zero_count--;
141
0
    else
142
0
      break;
143
0
  }
144
145
  // Quantization pass: All coefficients with index >= zero_flag are
146
  // skippable. Note: zero_flag can be zero.
147
0
  for (i = 0; i < non_zero_count; i++) {
148
0
    const int rc = scan[i];
149
0
    const int coeff = coeff_ptr[rc];
150
0
    const int coeff_sign = (coeff >> 31);
151
0
    const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
152
153
0
    if (abs_coeff >= zbins[rc != 0]) {
154
0
      int tmp = clamp(abs_coeff + round_ptr[rc != 0], INT16_MIN, INT16_MAX);
155
0
      tmp = ((((tmp * quant_ptr[rc != 0]) >> 16) + tmp) *
156
0
             quant_shift_ptr[rc != 0]) >>
157
0
            16;  // quantization
158
0
      qcoeff_ptr[rc] = (tmp ^ coeff_sign) - coeff_sign;
159
0
      dqcoeff_ptr[rc] = (tran_low_t)(qcoeff_ptr[rc] * dequant_ptr[rc != 0]);
160
161
0
      if (tmp) eob = i;
162
0
    }
163
0
  }
164
0
  *eob_ptr = eob + 1;
165
0
}
166
167
#if CONFIG_VP9_HIGHBITDEPTH
168
void vpx_highbd_quantize_b_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
169
                             const struct macroblock_plane *const mb_plane,
170
                             tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
171
                             const int16_t *dequant_ptr, uint16_t *eob_ptr,
172
0
                             const struct ScanOrder *const scan_order) {
173
0
  int i, non_zero_count = (int)n_coeffs, eob = -1;
174
0
  const int zbins[2] = { mb_plane->zbin[0], mb_plane->zbin[1] };
175
0
  const int nzbins[2] = { zbins[0] * -1, zbins[1] * -1 };
176
0
  const int16_t *round_ptr = mb_plane->round;
177
0
  const int16_t *quant_ptr = mb_plane->quant;
178
0
  const int16_t *quant_shift_ptr = mb_plane->quant_shift;
179
0
  const int16_t *scan = scan_order->scan;
180
181
0
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
182
0
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
183
184
  // Pre-scan pass
185
0
  for (i = (int)n_coeffs - 1; i >= 0; i--) {
186
0
    const int rc = scan[i];
187
0
    const int coeff = coeff_ptr[rc];
188
189
0
    if (coeff < zbins[rc != 0] && coeff > nzbins[rc != 0])
190
0
      non_zero_count--;
191
0
    else
192
0
      break;
193
0
  }
194
195
  // Quantization pass: All coefficients with index >= zero_flag are
196
  // skippable. Note: zero_flag can be zero.
197
0
  for (i = 0; i < non_zero_count; i++) {
198
0
    const int rc = scan[i];
199
0
    const int coeff = coeff_ptr[rc];
200
0
    const int coeff_sign = (coeff >> 31);
201
0
    const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
202
203
0
    if (abs_coeff >= zbins[rc != 0]) {
204
0
      const int64_t tmp1 = abs_coeff + round_ptr[rc != 0];
205
0
      const int64_t tmp2 = ((tmp1 * quant_ptr[rc != 0]) >> 16) + tmp1;
206
0
      const int abs_qcoeff = (int)((tmp2 * quant_shift_ptr[rc != 0]) >> 16);
207
0
      qcoeff_ptr[rc] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
208
0
      dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0];
209
0
      if (abs_qcoeff) eob = i;
210
0
    }
211
0
  }
212
0
  *eob_ptr = eob + 1;
213
0
}
214
#endif
215
216
void vpx_quantize_b_32x32_c(const tran_low_t *coeff_ptr,
217
                            const struct macroblock_plane *const mb_plane,
218
                            tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
219
                            const int16_t *dequant_ptr, uint16_t *eob_ptr,
220
0
                            const struct ScanOrder *const scan_order) {
221
0
  const int n_coeffs = 32 * 32;
222
0
  const int zbins[2] = { ROUND_POWER_OF_TWO(mb_plane->zbin[0], 1),
223
0
                         ROUND_POWER_OF_TWO(mb_plane->zbin[1], 1) };
224
0
  const int nzbins[2] = { zbins[0] * -1, zbins[1] * -1 };
225
0
  const int16_t *round_ptr = mb_plane->round;
226
0
  const int16_t *quant_ptr = mb_plane->quant;
227
0
  const int16_t *quant_shift_ptr = mb_plane->quant_shift;
228
0
  const int16_t *scan = scan_order->scan;
229
230
0
  int idx = 0;
231
0
  int idx_arr[32 * 32 /* n_coeffs */];
232
0
  int i, eob = -1;
233
234
0
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
235
0
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
236
237
  // Pre-scan pass
238
0
  for (i = 0; i < n_coeffs; i++) {
239
0
    const int rc = scan[i];
240
0
    const int coeff = coeff_ptr[rc];
241
242
    // If the coefficient is out of the base ZBIN range, keep it for
243
    // quantization.
244
0
    if (coeff >= zbins[rc != 0] || coeff <= nzbins[rc != 0]) idx_arr[idx++] = i;
245
0
  }
246
247
  // Quantization pass: only process the coefficients selected in
248
  // pre-scan pass. Note: idx can be zero.
249
0
  for (i = 0; i < idx; i++) {
250
0
    const int rc = scan[idx_arr[i]];
251
0
    const int coeff = coeff_ptr[rc];
252
0
    const int coeff_sign = (coeff >> 31);
253
0
    int tmp;
254
0
    int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
255
0
    abs_coeff += ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1);
256
0
    abs_coeff = clamp(abs_coeff, INT16_MIN, INT16_MAX);
257
0
    tmp = ((((abs_coeff * quant_ptr[rc != 0]) >> 16) + abs_coeff) *
258
0
           quant_shift_ptr[rc != 0]) >>
259
0
          15;
260
261
0
    qcoeff_ptr[rc] = (tmp ^ coeff_sign) - coeff_sign;
262
#if (VPX_ARCH_X86 || VPX_ARCH_X86_64) && !CONFIG_VP9_HIGHBITDEPTH
263
    // When tran_low_t is only 16 bits dqcoeff can outrange it. Rather than
264
    // truncating with a cast, saturate the value. This is easier to implement
265
    // on x86 and preserves the sign of the value.
266
    dqcoeff_ptr[rc] =
267
        clamp(qcoeff_ptr[rc] * dequant_ptr[rc != 0] / 2, INT16_MIN, INT16_MAX);
268
#else
269
0
    dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0] / 2;
270
0
#endif  // VPX_ARCH_X86 && CONFIG_VP9_HIGHBITDEPTH
271
272
0
    if (tmp) eob = idx_arr[i];
273
0
  }
274
0
  *eob_ptr = eob + 1;
275
0
}
276
277
#if CONFIG_VP9_HIGHBITDEPTH
278
void vpx_highbd_quantize_b_32x32_c(
279
    const tran_low_t *coeff_ptr, const struct macroblock_plane *const mb_plane,
280
    tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr,
281
0
    uint16_t *eob_ptr, const struct ScanOrder *const scan_order) {
282
0
  const intptr_t n_coeffs = 32 * 32;
283
0
  const int zbins[2] = { ROUND_POWER_OF_TWO(mb_plane->zbin[0], 1),
284
0
                         ROUND_POWER_OF_TWO(mb_plane->zbin[1], 1) };
285
0
  const int nzbins[2] = { zbins[0] * -1, zbins[1] * -1 };
286
0
  const int16_t *round_ptr = mb_plane->round;
287
0
  const int16_t *quant_ptr = mb_plane->quant;
288
0
  const int16_t *quant_shift_ptr = mb_plane->quant_shift;
289
0
  const int16_t *scan = scan_order->scan;
290
291
0
  int idx = 0;
292
0
  int idx_arr[1024];
293
0
  int i, eob = -1;
294
295
0
  memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
296
0
  memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
297
298
  // Pre-scan pass
299
0
  for (i = 0; i < n_coeffs; i++) {
300
0
    const int rc = scan[i];
301
0
    const int coeff = coeff_ptr[rc];
302
303
    // If the coefficient is out of the base ZBIN range, keep it for
304
    // quantization.
305
0
    if (coeff >= zbins[rc != 0] || coeff <= nzbins[rc != 0]) idx_arr[idx++] = i;
306
0
  }
307
308
  // Quantization pass: only process the coefficients selected in
309
  // pre-scan pass. Note: idx can be zero.
310
0
  for (i = 0; i < idx; i++) {
311
0
    const int rc = scan[idx_arr[i]];
312
0
    const int coeff = coeff_ptr[rc];
313
0
    const int coeff_sign = (coeff >> 31);
314
0
    const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
315
0
    const int64_t tmp1 = abs_coeff + ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1);
316
0
    const int64_t tmp2 = ((tmp1 * quant_ptr[rc != 0]) >> 16) + tmp1;
317
0
    const int abs_qcoeff = (int)((tmp2 * quant_shift_ptr[rc != 0]) >> 15);
318
0
    qcoeff_ptr[rc] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
319
0
    dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0] / 2;
320
0
    if (abs_qcoeff) eob = idx_arr[i];
321
0
  }
322
0
  *eob_ptr = eob + 1;
323
0
}
324
#endif