xref: /aosp_15_r20/external/libvpx/vpx_dsp/quantize.c (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
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 
vpx_quantize_dc(const tran_low_t * coeff_ptr,int n_coeffs,const int16_t * round_ptr,const int16_t quant,tran_low_t * qcoeff_ptr,tran_low_t * dqcoeff_ptr,const int16_t dequant,uint16_t * eob_ptr)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                      const int16_t dequant, uint16_t *eob_ptr) {
24   const int rc = 0;
25   const int coeff = coeff_ptr[rc];
26   const int coeff_sign = (coeff >> 31);
27   const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
28   int tmp, eob = -1;
29 
30   memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
31   memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
32 
33   tmp = clamp(abs_coeff + round_ptr[rc != 0], INT16_MIN, INT16_MAX);
34   tmp = (tmp * quant) >> 16;
35   qcoeff_ptr[rc] = (tmp ^ coeff_sign) - coeff_sign;
36   dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant;
37   if (tmp) eob = 0;
38 
39   *eob_ptr = eob + 1;
40 }
41 
42 #if CONFIG_VP9_HIGHBITDEPTH
vpx_highbd_quantize_dc(const tran_low_t * coeff_ptr,int n_coeffs,const int16_t * round_ptr,const int16_t quant,tran_low_t * qcoeff_ptr,tran_low_t * dqcoeff_ptr,const int16_t dequant,uint16_t * eob_ptr)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                             const int16_t dequant, uint16_t *eob_ptr) {
47   int eob = -1;
48 
49   memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
50   memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
51 
52   {
53     const int coeff = coeff_ptr[0];
54     const int coeff_sign = (coeff >> 31);
55     const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
56     const int64_t tmp = abs_coeff + round_ptr[0];
57     const int abs_qcoeff = (int)((tmp * quant) >> 16);
58     qcoeff_ptr[0] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
59     dqcoeff_ptr[0] = qcoeff_ptr[0] * dequant;
60     if (abs_qcoeff) eob = 0;
61   }
62 
63   *eob_ptr = eob + 1;
64 }
65 #endif
66 
vpx_quantize_dc_32x32(const tran_low_t * coeff_ptr,const int16_t * round_ptr,const int16_t quant,tran_low_t * qcoeff_ptr,tran_low_t * dqcoeff_ptr,const int16_t dequant,uint16_t * eob_ptr)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                            const int16_t dequant, uint16_t *eob_ptr) {
71   const int n_coeffs = 1024;
72   const int rc = 0;
73   const int coeff = coeff_ptr[rc];
74   const int coeff_sign = (coeff >> 31);
75   const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
76   int tmp, eob = -1;
77 
78   memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
79   memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
80 
81   tmp = clamp(abs_coeff + ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1), INT16_MIN,
82               INT16_MAX);
83   tmp = (tmp * quant) >> 15;
84   qcoeff_ptr[rc] = (tmp ^ coeff_sign) - coeff_sign;
85   dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant / 2;
86   if (tmp) eob = 0;
87 
88   *eob_ptr = eob + 1;
89 }
90 
91 #if CONFIG_VP9_HIGHBITDEPTH
vpx_highbd_quantize_dc_32x32(const tran_low_t * coeff_ptr,const int16_t * round_ptr,const int16_t quant,tran_low_t * qcoeff_ptr,tran_low_t * dqcoeff_ptr,const int16_t dequant,uint16_t * eob_ptr)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                                   const int16_t dequant, uint16_t *eob_ptr) {
97   const int n_coeffs = 1024;
98   int eob = -1;
99 
100   memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
101   memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
102 
103   {
104     const int coeff = coeff_ptr[0];
105     const int coeff_sign = (coeff >> 31);
106     const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
107     const int64_t tmp = abs_coeff + ROUND_POWER_OF_TWO(round_ptr[0], 1);
108     const int abs_qcoeff = (int)((tmp * quant) >> 15);
109     qcoeff_ptr[0] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
110     dqcoeff_ptr[0] = qcoeff_ptr[0] * dequant / 2;
111     if (abs_qcoeff) eob = 0;
112   }
113 
114   *eob_ptr = eob + 1;
115 }
116 #endif
117 
vpx_quantize_b_c(const tran_low_t * coeff_ptr,intptr_t n_coeffs,const struct macroblock_plane * const mb_plane,tran_low_t * qcoeff_ptr,tran_low_t * dqcoeff_ptr,const int16_t * dequant_ptr,uint16_t * eob_ptr,const struct ScanOrder * const scan_order)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                       const struct ScanOrder *const scan_order) {
123   int i, non_zero_count = (int)n_coeffs, eob = -1;
124   const int zbins[2] = { mb_plane->zbin[0], mb_plane->zbin[1] };
125   const int nzbins[2] = { zbins[0] * -1, zbins[1] * -1 };
126   const int16_t *round_ptr = mb_plane->round;
127   const int16_t *quant_ptr = mb_plane->quant;
128   const int16_t *quant_shift_ptr = mb_plane->quant_shift;
129   const int16_t *scan = scan_order->scan;
130 
131   memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
132   memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
133 
134   // Pre-scan pass
135   for (i = (int)n_coeffs - 1; i >= 0; i--) {
136     const int rc = scan[i];
137     const int coeff = coeff_ptr[rc];
138 
139     if (coeff < zbins[rc != 0] && coeff > nzbins[rc != 0])
140       non_zero_count--;
141     else
142       break;
143   }
144 
145   // Quantization pass: All coefficients with index >= zero_flag are
146   // skippable. Note: zero_flag can be zero.
147   for (i = 0; i < non_zero_count; i++) {
148     const int rc = scan[i];
149     const int coeff = coeff_ptr[rc];
150     const int coeff_sign = (coeff >> 31);
151     const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
152 
153     if (abs_coeff >= zbins[rc != 0]) {
154       int tmp = clamp(abs_coeff + round_ptr[rc != 0], INT16_MIN, INT16_MAX);
155       tmp = ((((tmp * quant_ptr[rc != 0]) >> 16) + tmp) *
156              quant_shift_ptr[rc != 0]) >>
157             16;  // quantization
158       qcoeff_ptr[rc] = (tmp ^ coeff_sign) - coeff_sign;
159       dqcoeff_ptr[rc] = (tran_low_t)(qcoeff_ptr[rc] * dequant_ptr[rc != 0]);
160 
161       if (tmp) eob = i;
162     }
163   }
164   *eob_ptr = eob + 1;
165 }
166 
167 #if CONFIG_VP9_HIGHBITDEPTH
vpx_highbd_quantize_b_c(const tran_low_t * coeff_ptr,intptr_t n_coeffs,const struct macroblock_plane * const mb_plane,tran_low_t * qcoeff_ptr,tran_low_t * dqcoeff_ptr,const int16_t * dequant_ptr,uint16_t * eob_ptr,const struct ScanOrder * const scan_order)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                              const struct ScanOrder *const scan_order) {
173   int i, non_zero_count = (int)n_coeffs, eob = -1;
174   const int zbins[2] = { mb_plane->zbin[0], mb_plane->zbin[1] };
175   const int nzbins[2] = { zbins[0] * -1, zbins[1] * -1 };
176   const int16_t *round_ptr = mb_plane->round;
177   const int16_t *quant_ptr = mb_plane->quant;
178   const int16_t *quant_shift_ptr = mb_plane->quant_shift;
179   const int16_t *scan = scan_order->scan;
180 
181   memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
182   memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
183 
184   // Pre-scan pass
185   for (i = (int)n_coeffs - 1; i >= 0; i--) {
186     const int rc = scan[i];
187     const int coeff = coeff_ptr[rc];
188 
189     if (coeff < zbins[rc != 0] && coeff > nzbins[rc != 0])
190       non_zero_count--;
191     else
192       break;
193   }
194 
195   // Quantization pass: All coefficients with index >= zero_flag are
196   // skippable. Note: zero_flag can be zero.
197   for (i = 0; i < non_zero_count; i++) {
198     const int rc = scan[i];
199     const int coeff = coeff_ptr[rc];
200     const int coeff_sign = (coeff >> 31);
201     const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
202 
203     if (abs_coeff >= zbins[rc != 0]) {
204       const int64_t tmp1 = abs_coeff + round_ptr[rc != 0];
205       const int64_t tmp2 = ((tmp1 * quant_ptr[rc != 0]) >> 16) + tmp1;
206       const int abs_qcoeff = (int)((tmp2 * quant_shift_ptr[rc != 0]) >> 16);
207       qcoeff_ptr[rc] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
208       dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0];
209       if (abs_qcoeff) eob = i;
210     }
211   }
212   *eob_ptr = eob + 1;
213 }
214 #endif
215 
vpx_quantize_b_32x32_c(const tran_low_t * coeff_ptr,const struct macroblock_plane * const mb_plane,tran_low_t * qcoeff_ptr,tran_low_t * dqcoeff_ptr,const int16_t * dequant_ptr,uint16_t * eob_ptr,const struct ScanOrder * const scan_order)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                             const struct ScanOrder *const scan_order) {
221   const int n_coeffs = 32 * 32;
222   const int zbins[2] = { ROUND_POWER_OF_TWO(mb_plane->zbin[0], 1),
223                          ROUND_POWER_OF_TWO(mb_plane->zbin[1], 1) };
224   const int nzbins[2] = { zbins[0] * -1, zbins[1] * -1 };
225   const int16_t *round_ptr = mb_plane->round;
226   const int16_t *quant_ptr = mb_plane->quant;
227   const int16_t *quant_shift_ptr = mb_plane->quant_shift;
228   const int16_t *scan = scan_order->scan;
229 
230   int idx = 0;
231   int idx_arr[32 * 32 /* n_coeffs */];
232   int i, eob = -1;
233 
234   memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
235   memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
236 
237   // Pre-scan pass
238   for (i = 0; i < n_coeffs; i++) {
239     const int rc = scan[i];
240     const int coeff = coeff_ptr[rc];
241 
242     // If the coefficient is out of the base ZBIN range, keep it for
243     // quantization.
244     if (coeff >= zbins[rc != 0] || coeff <= nzbins[rc != 0]) idx_arr[idx++] = i;
245   }
246 
247   // Quantization pass: only process the coefficients selected in
248   // pre-scan pass. Note: idx can be zero.
249   for (i = 0; i < idx; i++) {
250     const int rc = scan[idx_arr[i]];
251     const int coeff = coeff_ptr[rc];
252     const int coeff_sign = (coeff >> 31);
253     int tmp;
254     int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
255     abs_coeff += ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1);
256     abs_coeff = clamp(abs_coeff, INT16_MIN, INT16_MAX);
257     tmp = ((((abs_coeff * quant_ptr[rc != 0]) >> 16) + abs_coeff) *
258            quant_shift_ptr[rc != 0]) >>
259           15;
260 
261     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     dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0] / 2;
270 #endif  // VPX_ARCH_X86 && CONFIG_VP9_HIGHBITDEPTH
271 
272     if (tmp) eob = idx_arr[i];
273   }
274   *eob_ptr = eob + 1;
275 }
276 
277 #if CONFIG_VP9_HIGHBITDEPTH
vpx_highbd_quantize_b_32x32_c(const tran_low_t * coeff_ptr,const struct macroblock_plane * const mb_plane,tran_low_t * qcoeff_ptr,tran_low_t * dqcoeff_ptr,const int16_t * dequant_ptr,uint16_t * eob_ptr,const struct ScanOrder * const scan_order)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     uint16_t *eob_ptr, const struct ScanOrder *const scan_order) {
282   const intptr_t n_coeffs = 32 * 32;
283   const int zbins[2] = { ROUND_POWER_OF_TWO(mb_plane->zbin[0], 1),
284                          ROUND_POWER_OF_TWO(mb_plane->zbin[1], 1) };
285   const int nzbins[2] = { zbins[0] * -1, zbins[1] * -1 };
286   const int16_t *round_ptr = mb_plane->round;
287   const int16_t *quant_ptr = mb_plane->quant;
288   const int16_t *quant_shift_ptr = mb_plane->quant_shift;
289   const int16_t *scan = scan_order->scan;
290 
291   int idx = 0;
292   int idx_arr[1024];
293   int i, eob = -1;
294 
295   memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
296   memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
297 
298   // Pre-scan pass
299   for (i = 0; i < n_coeffs; i++) {
300     const int rc = scan[i];
301     const int coeff = coeff_ptr[rc];
302 
303     // If the coefficient is out of the base ZBIN range, keep it for
304     // quantization.
305     if (coeff >= zbins[rc != 0] || coeff <= nzbins[rc != 0]) idx_arr[idx++] = i;
306   }
307 
308   // Quantization pass: only process the coefficients selected in
309   // pre-scan pass. Note: idx can be zero.
310   for (i = 0; i < idx; i++) {
311     const int rc = scan[idx_arr[i]];
312     const int coeff = coeff_ptr[rc];
313     const int coeff_sign = (coeff >> 31);
314     const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
315     const int64_t tmp1 = abs_coeff + ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1);
316     const int64_t tmp2 = ((tmp1 * quant_ptr[rc != 0]) >> 16) + tmp1;
317     const int abs_qcoeff = (int)((tmp2 * quant_shift_ptr[rc != 0]) >> 15);
318     qcoeff_ptr[rc] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
319     dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0] / 2;
320     if (abs_qcoeff) eob = idx_arr[i];
321   }
322   *eob_ptr = eob + 1;
323 }
324 #endif
325