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