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 
vpx_quantize_dc(const tran_low_t * coeff_ptr,int n_coeffs,int skip_block,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)18 void vpx_quantize_dc(const tran_low_t *coeff_ptr, int n_coeffs, int skip_block,
19                      const int16_t *round_ptr, const int16_t quant,
20                      tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
21                      const int16_t dequant, uint16_t *eob_ptr) {
22   const int rc = 0;
23   const int coeff = coeff_ptr[rc];
24   const int coeff_sign = (coeff >> 31);
25   const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
26   int tmp, eob = -1;
27 
28   memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
29   memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
30 
31   if (!skip_block) {
32     tmp = clamp(abs_coeff + round_ptr[rc != 0], INT16_MIN, INT16_MAX);
33     tmp = (tmp * quant) >> 16;
34     qcoeff_ptr[rc] = (tmp ^ coeff_sign) - coeff_sign;
35     dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant;
36     if (tmp) eob = 0;
37   }
38   *eob_ptr = eob + 1;
39 }
40 
41 #if CONFIG_VP9_HIGHBITDEPTH
vpx_highbd_quantize_dc(const tran_low_t * coeff_ptr,int n_coeffs,int skip_block,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)42 void vpx_highbd_quantize_dc(const tran_low_t *coeff_ptr, int n_coeffs,
43                             int skip_block, const int16_t *round_ptr,
44                             const int16_t quant, tran_low_t *qcoeff_ptr,
45                             tran_low_t *dqcoeff_ptr, const int16_t dequant,
46                             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   if (!skip_block) {
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   *eob_ptr = eob + 1;
63 }
64 #endif
65 
vpx_quantize_dc_32x32(const tran_low_t * coeff_ptr,int skip_block,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)66 void vpx_quantize_dc_32x32(const tran_low_t *coeff_ptr, int skip_block,
67                            const int16_t *round_ptr, const int16_t quant,
68                            tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
69                            const int16_t dequant, uint16_t *eob_ptr) {
70   const int n_coeffs = 1024;
71   const int rc = 0;
72   const int coeff = coeff_ptr[rc];
73   const int coeff_sign = (coeff >> 31);
74   const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
75   int tmp, eob = -1;
76 
77   memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
78   memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
79 
80   if (!skip_block) {
81     tmp = clamp(abs_coeff + ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1),
82                 INT16_MIN, 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,int skip_block,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, int skip_block,
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   if (!skip_block) {
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   *eob_ptr = eob + 1;
114 }
115 #endif
116 
vpx_quantize_b_c(const tran_low_t * coeff_ptr,intptr_t n_coeffs,int skip_block,const int16_t * zbin_ptr,const int16_t * round_ptr,const int16_t * quant_ptr,const int16_t * quant_shift_ptr,tran_low_t * qcoeff_ptr,tran_low_t * dqcoeff_ptr,const int16_t * dequant_ptr,uint16_t * eob_ptr,const int16_t * scan,const int16_t * iscan)117 void vpx_quantize_b_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
118                       int skip_block, const int16_t *zbin_ptr,
119                       const int16_t *round_ptr, const int16_t *quant_ptr,
120                       const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr,
121                       tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr,
122                       uint16_t *eob_ptr, const int16_t *scan,
123                       const int16_t *iscan) {
124   int i, non_zero_count = (int)n_coeffs, eob = -1;
125   const int zbins[2] = { zbin_ptr[0], zbin_ptr[1] };
126   const int nzbins[2] = { zbins[0] * -1, zbins[1] * -1 };
127   (void)iscan;
128   (void)skip_block;
129   assert(!skip_block);
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,int skip_block,const int16_t * zbin_ptr,const int16_t * round_ptr,const int16_t * quant_ptr,const int16_t * quant_shift_ptr,tran_low_t * qcoeff_ptr,tran_low_t * dqcoeff_ptr,const int16_t * dequant_ptr,uint16_t * eob_ptr,const int16_t * scan,const int16_t * iscan)168 void vpx_highbd_quantize_b_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
169                              int skip_block, const int16_t *zbin_ptr,
170                              const int16_t *round_ptr, const int16_t *quant_ptr,
171                              const int16_t *quant_shift_ptr,
172                              tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
173                              const int16_t *dequant_ptr, uint16_t *eob_ptr,
174                              const int16_t *scan, const int16_t *iscan) {
175   int i, non_zero_count = (int)n_coeffs, eob = -1;
176   const int zbins[2] = { zbin_ptr[0], zbin_ptr[1] };
177   const int nzbins[2] = { zbins[0] * -1, zbins[1] * -1 };
178   (void)iscan;
179   (void)skip_block;
180   assert(!skip_block);
181 
182   memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
183   memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
184 
185   // Pre-scan pass
186   for (i = (int)n_coeffs - 1; i >= 0; i--) {
187     const int rc = scan[i];
188     const int coeff = coeff_ptr[rc];
189 
190     if (coeff < zbins[rc != 0] && coeff > nzbins[rc != 0])
191       non_zero_count--;
192     else
193       break;
194   }
195 
196   // Quantization pass: All coefficients with index >= zero_flag are
197   // skippable. Note: zero_flag can be zero.
198   for (i = 0; i < non_zero_count; i++) {
199     const int rc = scan[i];
200     const int coeff = coeff_ptr[rc];
201     const int coeff_sign = (coeff >> 31);
202     const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
203 
204     if (abs_coeff >= zbins[rc != 0]) {
205       const int64_t tmp1 = abs_coeff + round_ptr[rc != 0];
206       const int64_t tmp2 = ((tmp1 * quant_ptr[rc != 0]) >> 16) + tmp1;
207       const int abs_qcoeff = (int)((tmp2 * quant_shift_ptr[rc != 0]) >> 16);
208       qcoeff_ptr[rc] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
209       dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0];
210       if (abs_qcoeff) eob = i;
211     }
212   }
213   *eob_ptr = eob + 1;
214 }
215 #endif
216 
vpx_quantize_b_32x32_c(const tran_low_t * coeff_ptr,intptr_t n_coeffs,int skip_block,const int16_t * zbin_ptr,const int16_t * round_ptr,const int16_t * quant_ptr,const int16_t * quant_shift_ptr,tran_low_t * qcoeff_ptr,tran_low_t * dqcoeff_ptr,const int16_t * dequant_ptr,uint16_t * eob_ptr,const int16_t * scan,const int16_t * iscan)217 void vpx_quantize_b_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
218                             int skip_block, const int16_t *zbin_ptr,
219                             const int16_t *round_ptr, const int16_t *quant_ptr,
220                             const int16_t *quant_shift_ptr,
221                             tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
222                             const int16_t *dequant_ptr, uint16_t *eob_ptr,
223                             const int16_t *scan, const int16_t *iscan) {
224   const int zbins[2] = { ROUND_POWER_OF_TWO(zbin_ptr[0], 1),
225                          ROUND_POWER_OF_TWO(zbin_ptr[1], 1) };
226   const int nzbins[2] = { zbins[0] * -1, zbins[1] * -1 };
227 
228   int idx = 0;
229   int idx_arr[1024];
230   int i, eob = -1;
231   (void)iscan;
232   (void)skip_block;
233   assert(!skip_block);
234 
235   memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
236   memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
237 
238   // Pre-scan pass
239   for (i = 0; i < n_coeffs; i++) {
240     const int rc = scan[i];
241     const int coeff = coeff_ptr[rc];
242 
243     // If the coefficient is out of the base ZBIN range, keep it for
244     // quantization.
245     if (coeff >= zbins[rc != 0] || coeff <= nzbins[rc != 0]) idx_arr[idx++] = i;
246   }
247 
248   // Quantization pass: only process the coefficients selected in
249   // pre-scan pass. Note: idx can be zero.
250   for (i = 0; i < idx; i++) {
251     const int rc = scan[idx_arr[i]];
252     const int coeff = coeff_ptr[rc];
253     const int coeff_sign = (coeff >> 31);
254     int tmp;
255     int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
256     abs_coeff += ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1);
257     abs_coeff = clamp(abs_coeff, INT16_MIN, INT16_MAX);
258     tmp = ((((abs_coeff * quant_ptr[rc != 0]) >> 16) + abs_coeff) *
259            quant_shift_ptr[rc != 0]) >>
260           15;
261 
262     qcoeff_ptr[rc] = (tmp ^ coeff_sign) - coeff_sign;
263 #if (VPX_ARCH_X86 || VPX_ARCH_X86_64) && !CONFIG_VP9_HIGHBITDEPTH
264     // When tran_low_t is only 16 bits dqcoeff can outrange it. Rather than
265     // truncating with a cast, saturate the value. This is easier to implement
266     // on x86 and preserves the sign of the value.
267     dqcoeff_ptr[rc] =
268         clamp(qcoeff_ptr[rc] * dequant_ptr[rc != 0] / 2, INT16_MIN, INT16_MAX);
269 #else
270     dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0] / 2;
271 #endif  // VPX_ARCH_X86 && CONFIG_VP9_HIGHBITDEPTH
272 
273     if (tmp) eob = idx_arr[i];
274   }
275   *eob_ptr = eob + 1;
276 }
277 
278 #if CONFIG_VP9_HIGHBITDEPTH
vpx_highbd_quantize_b_32x32_c(const tran_low_t * coeff_ptr,intptr_t n_coeffs,int skip_block,const int16_t * zbin_ptr,const int16_t * round_ptr,const int16_t * quant_ptr,const int16_t * quant_shift_ptr,tran_low_t * qcoeff_ptr,tran_low_t * dqcoeff_ptr,const int16_t * dequant_ptr,uint16_t * eob_ptr,const int16_t * scan,const int16_t * iscan)279 void vpx_highbd_quantize_b_32x32_c(
280     const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block,
281     const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr,
282     const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr,
283     tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr,
284     const int16_t *scan, const int16_t *iscan) {
285   const int zbins[2] = { ROUND_POWER_OF_TWO(zbin_ptr[0], 1),
286                          ROUND_POWER_OF_TWO(zbin_ptr[1], 1) };
287   const int nzbins[2] = { zbins[0] * -1, zbins[1] * -1 };
288 
289   int idx = 0;
290   int idx_arr[1024];
291   int i, eob = -1;
292   (void)iscan;
293   (void)skip_block;
294   assert(!skip_block);
295 
296   memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
297   memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
298 
299   // Pre-scan pass
300   for (i = 0; i < n_coeffs; i++) {
301     const int rc = scan[i];
302     const int coeff = coeff_ptr[rc];
303 
304     // If the coefficient is out of the base ZBIN range, keep it for
305     // quantization.
306     if (coeff >= zbins[rc != 0] || coeff <= nzbins[rc != 0]) idx_arr[idx++] = i;
307   }
308 
309   // Quantization pass: only process the coefficients selected in
310   // pre-scan pass. Note: idx can be zero.
311   for (i = 0; i < idx; i++) {
312     const int rc = scan[idx_arr[i]];
313     const int coeff = coeff_ptr[rc];
314     const int coeff_sign = (coeff >> 31);
315     const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
316     const int64_t tmp1 = abs_coeff + ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1);
317     const int64_t tmp2 = ((tmp1 * quant_ptr[rc != 0]) >> 16) + tmp1;
318     const int abs_qcoeff = (int)((tmp2 * quant_shift_ptr[rc != 0]) >> 15);
319     qcoeff_ptr[rc] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
320     dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0] / 2;
321     if (abs_qcoeff) eob = idx_arr[i];
322   }
323   *eob_ptr = eob + 1;
324 }
325 #endif
326