xref: /aosp_15_r20/external/libvpx/vpx_dsp/avg.c (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2014 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 #include <stdlib.h>
13*fb1b10abSAndroid Build Coastguard Worker 
14*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_dsp_rtcd.h"
15*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/mem.h"
16*fb1b10abSAndroid Build Coastguard Worker 
vpx_avg_8x8_c(const uint8_t * s,int p)17*fb1b10abSAndroid Build Coastguard Worker unsigned int vpx_avg_8x8_c(const uint8_t *s, int p) {
18*fb1b10abSAndroid Build Coastguard Worker   int i, j;
19*fb1b10abSAndroid Build Coastguard Worker   int sum = 0;
20*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 8; ++i, s += p)
21*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 8; sum += s[j], ++j) {
22*fb1b10abSAndroid Build Coastguard Worker     }
23*fb1b10abSAndroid Build Coastguard Worker 
24*fb1b10abSAndroid Build Coastguard Worker   return (sum + 32) >> 6;
25*fb1b10abSAndroid Build Coastguard Worker }
26*fb1b10abSAndroid Build Coastguard Worker 
vpx_avg_4x4_c(const uint8_t * s,int p)27*fb1b10abSAndroid Build Coastguard Worker unsigned int vpx_avg_4x4_c(const uint8_t *s, int p) {
28*fb1b10abSAndroid Build Coastguard Worker   int i, j;
29*fb1b10abSAndroid Build Coastguard Worker   int sum = 0;
30*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 4; ++i, s += p)
31*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 4; sum += s[j], ++j) {
32*fb1b10abSAndroid Build Coastguard Worker     }
33*fb1b10abSAndroid Build Coastguard Worker 
34*fb1b10abSAndroid Build Coastguard Worker   return (sum + 8) >> 4;
35*fb1b10abSAndroid Build Coastguard Worker }
36*fb1b10abSAndroid Build Coastguard Worker 
37*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
38*fb1b10abSAndroid Build Coastguard Worker // src_diff: 13 bit, dynamic range [-4095, 4095]
39*fb1b10abSAndroid Build Coastguard Worker // coeff: 16 bit
hadamard_highbd_col8_first_pass(const int16_t * src_diff,ptrdiff_t src_stride,int16_t * coeff)40*fb1b10abSAndroid Build Coastguard Worker static void hadamard_highbd_col8_first_pass(const int16_t *src_diff,
41*fb1b10abSAndroid Build Coastguard Worker                                             ptrdiff_t src_stride,
42*fb1b10abSAndroid Build Coastguard Worker                                             int16_t *coeff) {
43*fb1b10abSAndroid Build Coastguard Worker   int16_t b0 = src_diff[0 * src_stride] + src_diff[1 * src_stride];
44*fb1b10abSAndroid Build Coastguard Worker   int16_t b1 = src_diff[0 * src_stride] - src_diff[1 * src_stride];
45*fb1b10abSAndroid Build Coastguard Worker   int16_t b2 = src_diff[2 * src_stride] + src_diff[3 * src_stride];
46*fb1b10abSAndroid Build Coastguard Worker   int16_t b3 = src_diff[2 * src_stride] - src_diff[3 * src_stride];
47*fb1b10abSAndroid Build Coastguard Worker   int16_t b4 = src_diff[4 * src_stride] + src_diff[5 * src_stride];
48*fb1b10abSAndroid Build Coastguard Worker   int16_t b5 = src_diff[4 * src_stride] - src_diff[5 * src_stride];
49*fb1b10abSAndroid Build Coastguard Worker   int16_t b6 = src_diff[6 * src_stride] + src_diff[7 * src_stride];
50*fb1b10abSAndroid Build Coastguard Worker   int16_t b7 = src_diff[6 * src_stride] - src_diff[7 * src_stride];
51*fb1b10abSAndroid Build Coastguard Worker 
52*fb1b10abSAndroid Build Coastguard Worker   int16_t c0 = b0 + b2;
53*fb1b10abSAndroid Build Coastguard Worker   int16_t c1 = b1 + b3;
54*fb1b10abSAndroid Build Coastguard Worker   int16_t c2 = b0 - b2;
55*fb1b10abSAndroid Build Coastguard Worker   int16_t c3 = b1 - b3;
56*fb1b10abSAndroid Build Coastguard Worker   int16_t c4 = b4 + b6;
57*fb1b10abSAndroid Build Coastguard Worker   int16_t c5 = b5 + b7;
58*fb1b10abSAndroid Build Coastguard Worker   int16_t c6 = b4 - b6;
59*fb1b10abSAndroid Build Coastguard Worker   int16_t c7 = b5 - b7;
60*fb1b10abSAndroid Build Coastguard Worker 
61*fb1b10abSAndroid Build Coastguard Worker   coeff[0] = c0 + c4;
62*fb1b10abSAndroid Build Coastguard Worker   coeff[7] = c1 + c5;
63*fb1b10abSAndroid Build Coastguard Worker   coeff[3] = c2 + c6;
64*fb1b10abSAndroid Build Coastguard Worker   coeff[4] = c3 + c7;
65*fb1b10abSAndroid Build Coastguard Worker   coeff[2] = c0 - c4;
66*fb1b10abSAndroid Build Coastguard Worker   coeff[6] = c1 - c5;
67*fb1b10abSAndroid Build Coastguard Worker   coeff[1] = c2 - c6;
68*fb1b10abSAndroid Build Coastguard Worker   coeff[5] = c3 - c7;
69*fb1b10abSAndroid Build Coastguard Worker }
70*fb1b10abSAndroid Build Coastguard Worker 
71*fb1b10abSAndroid Build Coastguard Worker // src_diff: 16 bit, dynamic range [-32760, 32760]
72*fb1b10abSAndroid Build Coastguard Worker // coeff: 19 bit
hadamard_highbd_col8_second_pass(const int16_t * src_diff,ptrdiff_t src_stride,int32_t * coeff)73*fb1b10abSAndroid Build Coastguard Worker static void hadamard_highbd_col8_second_pass(const int16_t *src_diff,
74*fb1b10abSAndroid Build Coastguard Worker                                              ptrdiff_t src_stride,
75*fb1b10abSAndroid Build Coastguard Worker                                              int32_t *coeff) {
76*fb1b10abSAndroid Build Coastguard Worker   int32_t b0 = src_diff[0 * src_stride] + src_diff[1 * src_stride];
77*fb1b10abSAndroid Build Coastguard Worker   int32_t b1 = src_diff[0 * src_stride] - src_diff[1 * src_stride];
78*fb1b10abSAndroid Build Coastguard Worker   int32_t b2 = src_diff[2 * src_stride] + src_diff[3 * src_stride];
79*fb1b10abSAndroid Build Coastguard Worker   int32_t b3 = src_diff[2 * src_stride] - src_diff[3 * src_stride];
80*fb1b10abSAndroid Build Coastguard Worker   int32_t b4 = src_diff[4 * src_stride] + src_diff[5 * src_stride];
81*fb1b10abSAndroid Build Coastguard Worker   int32_t b5 = src_diff[4 * src_stride] - src_diff[5 * src_stride];
82*fb1b10abSAndroid Build Coastguard Worker   int32_t b6 = src_diff[6 * src_stride] + src_diff[7 * src_stride];
83*fb1b10abSAndroid Build Coastguard Worker   int32_t b7 = src_diff[6 * src_stride] - src_diff[7 * src_stride];
84*fb1b10abSAndroid Build Coastguard Worker 
85*fb1b10abSAndroid Build Coastguard Worker   int32_t c0 = b0 + b2;
86*fb1b10abSAndroid Build Coastguard Worker   int32_t c1 = b1 + b3;
87*fb1b10abSAndroid Build Coastguard Worker   int32_t c2 = b0 - b2;
88*fb1b10abSAndroid Build Coastguard Worker   int32_t c3 = b1 - b3;
89*fb1b10abSAndroid Build Coastguard Worker   int32_t c4 = b4 + b6;
90*fb1b10abSAndroid Build Coastguard Worker   int32_t c5 = b5 + b7;
91*fb1b10abSAndroid Build Coastguard Worker   int32_t c6 = b4 - b6;
92*fb1b10abSAndroid Build Coastguard Worker   int32_t c7 = b5 - b7;
93*fb1b10abSAndroid Build Coastguard Worker 
94*fb1b10abSAndroid Build Coastguard Worker   coeff[0] = c0 + c4;
95*fb1b10abSAndroid Build Coastguard Worker   coeff[7] = c1 + c5;
96*fb1b10abSAndroid Build Coastguard Worker   coeff[3] = c2 + c6;
97*fb1b10abSAndroid Build Coastguard Worker   coeff[4] = c3 + c7;
98*fb1b10abSAndroid Build Coastguard Worker   coeff[2] = c0 - c4;
99*fb1b10abSAndroid Build Coastguard Worker   coeff[6] = c1 - c5;
100*fb1b10abSAndroid Build Coastguard Worker   coeff[1] = c2 - c6;
101*fb1b10abSAndroid Build Coastguard Worker   coeff[5] = c3 - c7;
102*fb1b10abSAndroid Build Coastguard Worker }
103*fb1b10abSAndroid Build Coastguard Worker 
104*fb1b10abSAndroid Build Coastguard Worker // The order of the output coeff of the hadamard is not important. For
105*fb1b10abSAndroid Build Coastguard Worker // optimization purposes the final transpose may be skipped.
vpx_highbd_hadamard_8x8_c(const int16_t * src_diff,ptrdiff_t src_stride,tran_low_t * coeff)106*fb1b10abSAndroid Build Coastguard Worker void vpx_highbd_hadamard_8x8_c(const int16_t *src_diff, ptrdiff_t src_stride,
107*fb1b10abSAndroid Build Coastguard Worker                                tran_low_t *coeff) {
108*fb1b10abSAndroid Build Coastguard Worker   int idx;
109*fb1b10abSAndroid Build Coastguard Worker   int16_t buffer[64];
110*fb1b10abSAndroid Build Coastguard Worker   int32_t buffer2[64];
111*fb1b10abSAndroid Build Coastguard Worker   int16_t *tmp_buf = &buffer[0];
112*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < 8; ++idx) {
113*fb1b10abSAndroid Build Coastguard Worker     // src_diff: 13 bit
114*fb1b10abSAndroid Build Coastguard Worker     // buffer: 16 bit, dynamic range [-32760, 32760]
115*fb1b10abSAndroid Build Coastguard Worker     hadamard_highbd_col8_first_pass(src_diff, src_stride, tmp_buf);
116*fb1b10abSAndroid Build Coastguard Worker     tmp_buf += 8;
117*fb1b10abSAndroid Build Coastguard Worker     ++src_diff;
118*fb1b10abSAndroid Build Coastguard Worker   }
119*fb1b10abSAndroid Build Coastguard Worker 
120*fb1b10abSAndroid Build Coastguard Worker   tmp_buf = &buffer[0];
121*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < 8; ++idx) {
122*fb1b10abSAndroid Build Coastguard Worker     // buffer: 16 bit
123*fb1b10abSAndroid Build Coastguard Worker     // buffer2: 19 bit, dynamic range [-262080, 262080]
124*fb1b10abSAndroid Build Coastguard Worker     hadamard_highbd_col8_second_pass(tmp_buf, 8, buffer2 + 8 * idx);
125*fb1b10abSAndroid Build Coastguard Worker     ++tmp_buf;
126*fb1b10abSAndroid Build Coastguard Worker   }
127*fb1b10abSAndroid Build Coastguard Worker 
128*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < 64; ++idx) coeff[idx] = (tran_low_t)buffer2[idx];
129*fb1b10abSAndroid Build Coastguard Worker }
130*fb1b10abSAndroid Build Coastguard Worker 
131*fb1b10abSAndroid Build Coastguard Worker // In place 16x16 2D Hadamard transform
vpx_highbd_hadamard_16x16_c(const int16_t * src_diff,ptrdiff_t src_stride,tran_low_t * coeff)132*fb1b10abSAndroid Build Coastguard Worker void vpx_highbd_hadamard_16x16_c(const int16_t *src_diff, ptrdiff_t src_stride,
133*fb1b10abSAndroid Build Coastguard Worker                                  tran_low_t *coeff) {
134*fb1b10abSAndroid Build Coastguard Worker   int idx;
135*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < 4; ++idx) {
136*fb1b10abSAndroid Build Coastguard Worker     // src_diff: 13 bit, dynamic range [-4095, 4095]
137*fb1b10abSAndroid Build Coastguard Worker     const int16_t *src_ptr =
138*fb1b10abSAndroid Build Coastguard Worker         src_diff + (idx >> 1) * 8 * src_stride + (idx & 0x01) * 8;
139*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_hadamard_8x8_c(src_ptr, src_stride, coeff + idx * 64);
140*fb1b10abSAndroid Build Coastguard Worker   }
141*fb1b10abSAndroid Build Coastguard Worker 
142*fb1b10abSAndroid Build Coastguard Worker   // coeff: 19 bit, dynamic range [-262080, 262080]
143*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < 64; ++idx) {
144*fb1b10abSAndroid Build Coastguard Worker     tran_low_t a0 = coeff[0];
145*fb1b10abSAndroid Build Coastguard Worker     tran_low_t a1 = coeff[64];
146*fb1b10abSAndroid Build Coastguard Worker     tran_low_t a2 = coeff[128];
147*fb1b10abSAndroid Build Coastguard Worker     tran_low_t a3 = coeff[192];
148*fb1b10abSAndroid Build Coastguard Worker 
149*fb1b10abSAndroid Build Coastguard Worker     tran_low_t b0 = (a0 + a1) >> 1;
150*fb1b10abSAndroid Build Coastguard Worker     tran_low_t b1 = (a0 - a1) >> 1;
151*fb1b10abSAndroid Build Coastguard Worker     tran_low_t b2 = (a2 + a3) >> 1;
152*fb1b10abSAndroid Build Coastguard Worker     tran_low_t b3 = (a2 - a3) >> 1;
153*fb1b10abSAndroid Build Coastguard Worker 
154*fb1b10abSAndroid Build Coastguard Worker     // new coeff dynamic range: 20 bit
155*fb1b10abSAndroid Build Coastguard Worker     coeff[0] = b0 + b2;
156*fb1b10abSAndroid Build Coastguard Worker     coeff[64] = b1 + b3;
157*fb1b10abSAndroid Build Coastguard Worker     coeff[128] = b0 - b2;
158*fb1b10abSAndroid Build Coastguard Worker     coeff[192] = b1 - b3;
159*fb1b10abSAndroid Build Coastguard Worker 
160*fb1b10abSAndroid Build Coastguard Worker     ++coeff;
161*fb1b10abSAndroid Build Coastguard Worker   }
162*fb1b10abSAndroid Build Coastguard Worker }
163*fb1b10abSAndroid Build Coastguard Worker 
vpx_highbd_hadamard_32x32_c(const int16_t * src_diff,ptrdiff_t src_stride,tran_low_t * coeff)164*fb1b10abSAndroid Build Coastguard Worker void vpx_highbd_hadamard_32x32_c(const int16_t *src_diff, ptrdiff_t src_stride,
165*fb1b10abSAndroid Build Coastguard Worker                                  tran_low_t *coeff) {
166*fb1b10abSAndroid Build Coastguard Worker   int idx;
167*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < 4; ++idx) {
168*fb1b10abSAndroid Build Coastguard Worker     // src_diff: 13 bit, dynamic range [-4095, 4095]
169*fb1b10abSAndroid Build Coastguard Worker     const int16_t *src_ptr =
170*fb1b10abSAndroid Build Coastguard Worker         src_diff + (idx >> 1) * 16 * src_stride + (idx & 0x01) * 16;
171*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_hadamard_16x16_c(src_ptr, src_stride, coeff + idx * 256);
172*fb1b10abSAndroid Build Coastguard Worker   }
173*fb1b10abSAndroid Build Coastguard Worker 
174*fb1b10abSAndroid Build Coastguard Worker   // coeff: 20 bit
175*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < 256; ++idx) {
176*fb1b10abSAndroid Build Coastguard Worker     tran_low_t a0 = coeff[0];
177*fb1b10abSAndroid Build Coastguard Worker     tran_low_t a1 = coeff[256];
178*fb1b10abSAndroid Build Coastguard Worker     tran_low_t a2 = coeff[512];
179*fb1b10abSAndroid Build Coastguard Worker     tran_low_t a3 = coeff[768];
180*fb1b10abSAndroid Build Coastguard Worker 
181*fb1b10abSAndroid Build Coastguard Worker     tran_low_t b0 = (a0 + a1) >> 2;
182*fb1b10abSAndroid Build Coastguard Worker     tran_low_t b1 = (a0 - a1) >> 2;
183*fb1b10abSAndroid Build Coastguard Worker     tran_low_t b2 = (a2 + a3) >> 2;
184*fb1b10abSAndroid Build Coastguard Worker     tran_low_t b3 = (a2 - a3) >> 2;
185*fb1b10abSAndroid Build Coastguard Worker 
186*fb1b10abSAndroid Build Coastguard Worker     // new coeff dynamic range: 20 bit
187*fb1b10abSAndroid Build Coastguard Worker     coeff[0] = b0 + b2;
188*fb1b10abSAndroid Build Coastguard Worker     coeff[256] = b1 + b3;
189*fb1b10abSAndroid Build Coastguard Worker     coeff[512] = b0 - b2;
190*fb1b10abSAndroid Build Coastguard Worker     coeff[768] = b1 - b3;
191*fb1b10abSAndroid Build Coastguard Worker 
192*fb1b10abSAndroid Build Coastguard Worker     ++coeff;
193*fb1b10abSAndroid Build Coastguard Worker   }
194*fb1b10abSAndroid Build Coastguard Worker }
195*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
196*fb1b10abSAndroid Build Coastguard Worker 
197*fb1b10abSAndroid Build Coastguard Worker // src_diff: first pass, 9 bit, dynamic range [-255, 255]
198*fb1b10abSAndroid Build Coastguard Worker //           second pass, 12 bit, dynamic range [-2040, 2040]
hadamard_col8(const int16_t * src_diff,ptrdiff_t src_stride,int16_t * coeff)199*fb1b10abSAndroid Build Coastguard Worker static void hadamard_col8(const int16_t *src_diff, ptrdiff_t src_stride,
200*fb1b10abSAndroid Build Coastguard Worker                           int16_t *coeff) {
201*fb1b10abSAndroid Build Coastguard Worker   int16_t b0 = src_diff[0 * src_stride] + src_diff[1 * src_stride];
202*fb1b10abSAndroid Build Coastguard Worker   int16_t b1 = src_diff[0 * src_stride] - src_diff[1 * src_stride];
203*fb1b10abSAndroid Build Coastguard Worker   int16_t b2 = src_diff[2 * src_stride] + src_diff[3 * src_stride];
204*fb1b10abSAndroid Build Coastguard Worker   int16_t b3 = src_diff[2 * src_stride] - src_diff[3 * src_stride];
205*fb1b10abSAndroid Build Coastguard Worker   int16_t b4 = src_diff[4 * src_stride] + src_diff[5 * src_stride];
206*fb1b10abSAndroid Build Coastguard Worker   int16_t b5 = src_diff[4 * src_stride] - src_diff[5 * src_stride];
207*fb1b10abSAndroid Build Coastguard Worker   int16_t b6 = src_diff[6 * src_stride] + src_diff[7 * src_stride];
208*fb1b10abSAndroid Build Coastguard Worker   int16_t b7 = src_diff[6 * src_stride] - src_diff[7 * src_stride];
209*fb1b10abSAndroid Build Coastguard Worker 
210*fb1b10abSAndroid Build Coastguard Worker   int16_t c0 = b0 + b2;
211*fb1b10abSAndroid Build Coastguard Worker   int16_t c1 = b1 + b3;
212*fb1b10abSAndroid Build Coastguard Worker   int16_t c2 = b0 - b2;
213*fb1b10abSAndroid Build Coastguard Worker   int16_t c3 = b1 - b3;
214*fb1b10abSAndroid Build Coastguard Worker   int16_t c4 = b4 + b6;
215*fb1b10abSAndroid Build Coastguard Worker   int16_t c5 = b5 + b7;
216*fb1b10abSAndroid Build Coastguard Worker   int16_t c6 = b4 - b6;
217*fb1b10abSAndroid Build Coastguard Worker   int16_t c7 = b5 - b7;
218*fb1b10abSAndroid Build Coastguard Worker 
219*fb1b10abSAndroid Build Coastguard Worker   coeff[0] = c0 + c4;
220*fb1b10abSAndroid Build Coastguard Worker   coeff[7] = c1 + c5;
221*fb1b10abSAndroid Build Coastguard Worker   coeff[3] = c2 + c6;
222*fb1b10abSAndroid Build Coastguard Worker   coeff[4] = c3 + c7;
223*fb1b10abSAndroid Build Coastguard Worker   coeff[2] = c0 - c4;
224*fb1b10abSAndroid Build Coastguard Worker   coeff[6] = c1 - c5;
225*fb1b10abSAndroid Build Coastguard Worker   coeff[1] = c2 - c6;
226*fb1b10abSAndroid Build Coastguard Worker   coeff[5] = c3 - c7;
227*fb1b10abSAndroid Build Coastguard Worker }
228*fb1b10abSAndroid Build Coastguard Worker 
229*fb1b10abSAndroid Build Coastguard Worker // The order of the output coeff of the hadamard is not important. For
230*fb1b10abSAndroid Build Coastguard Worker // optimization purposes the final transpose may be skipped.
vpx_hadamard_8x8_c(const int16_t * src_diff,ptrdiff_t src_stride,tran_low_t * coeff)231*fb1b10abSAndroid Build Coastguard Worker void vpx_hadamard_8x8_c(const int16_t *src_diff, ptrdiff_t src_stride,
232*fb1b10abSAndroid Build Coastguard Worker                         tran_low_t *coeff) {
233*fb1b10abSAndroid Build Coastguard Worker   int idx;
234*fb1b10abSAndroid Build Coastguard Worker   int16_t buffer[64];
235*fb1b10abSAndroid Build Coastguard Worker   int16_t buffer2[64];
236*fb1b10abSAndroid Build Coastguard Worker   int16_t *tmp_buf = &buffer[0];
237*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < 8; ++idx) {
238*fb1b10abSAndroid Build Coastguard Worker     hadamard_col8(src_diff, src_stride, tmp_buf);  // src_diff: 9 bit
239*fb1b10abSAndroid Build Coastguard Worker                                                    // dynamic range [-255, 255]
240*fb1b10abSAndroid Build Coastguard Worker     tmp_buf += 8;
241*fb1b10abSAndroid Build Coastguard Worker     ++src_diff;
242*fb1b10abSAndroid Build Coastguard Worker   }
243*fb1b10abSAndroid Build Coastguard Worker 
244*fb1b10abSAndroid Build Coastguard Worker   tmp_buf = &buffer[0];
245*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < 8; ++idx) {
246*fb1b10abSAndroid Build Coastguard Worker     hadamard_col8(tmp_buf, 8, buffer2 + 8 * idx);  // tmp_buf: 12 bit
247*fb1b10abSAndroid Build Coastguard Worker     // dynamic range [-2040, 2040]
248*fb1b10abSAndroid Build Coastguard Worker     // buffer2: 15 bit
249*fb1b10abSAndroid Build Coastguard Worker     // dynamic range [-16320, 16320]
250*fb1b10abSAndroid Build Coastguard Worker     ++tmp_buf;
251*fb1b10abSAndroid Build Coastguard Worker   }
252*fb1b10abSAndroid Build Coastguard Worker 
253*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < 64; ++idx) coeff[idx] = (tran_low_t)buffer2[idx];
254*fb1b10abSAndroid Build Coastguard Worker }
255*fb1b10abSAndroid Build Coastguard Worker 
256*fb1b10abSAndroid Build Coastguard Worker // In place 16x16 2D Hadamard transform
vpx_hadamard_16x16_c(const int16_t * src_diff,ptrdiff_t src_stride,tran_low_t * coeff)257*fb1b10abSAndroid Build Coastguard Worker void vpx_hadamard_16x16_c(const int16_t *src_diff, ptrdiff_t src_stride,
258*fb1b10abSAndroid Build Coastguard Worker                           tran_low_t *coeff) {
259*fb1b10abSAndroid Build Coastguard Worker   int idx;
260*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < 4; ++idx) {
261*fb1b10abSAndroid Build Coastguard Worker     // src_diff: 9 bit, dynamic range [-255, 255]
262*fb1b10abSAndroid Build Coastguard Worker     const int16_t *src_ptr =
263*fb1b10abSAndroid Build Coastguard Worker         src_diff + (idx >> 1) * 8 * src_stride + (idx & 0x01) * 8;
264*fb1b10abSAndroid Build Coastguard Worker     vpx_hadamard_8x8_c(src_ptr, src_stride, coeff + idx * 64);
265*fb1b10abSAndroid Build Coastguard Worker   }
266*fb1b10abSAndroid Build Coastguard Worker 
267*fb1b10abSAndroid Build Coastguard Worker   // coeff: 15 bit, dynamic range [-16320, 16320]
268*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < 64; ++idx) {
269*fb1b10abSAndroid Build Coastguard Worker     tran_low_t a0 = coeff[0];
270*fb1b10abSAndroid Build Coastguard Worker     tran_low_t a1 = coeff[64];
271*fb1b10abSAndroid Build Coastguard Worker     tran_low_t a2 = coeff[128];
272*fb1b10abSAndroid Build Coastguard Worker     tran_low_t a3 = coeff[192];
273*fb1b10abSAndroid Build Coastguard Worker 
274*fb1b10abSAndroid Build Coastguard Worker     tran_low_t b0 = (a0 + a1) >> 1;  // (a0 + a1): 16 bit, [-32640, 32640]
275*fb1b10abSAndroid Build Coastguard Worker     tran_low_t b1 = (a0 - a1) >> 1;  // b0-b3: 15 bit, dynamic range
276*fb1b10abSAndroid Build Coastguard Worker     tran_low_t b2 = (a2 + a3) >> 1;  // [-16320, 16320]
277*fb1b10abSAndroid Build Coastguard Worker     tran_low_t b3 = (a2 - a3) >> 1;
278*fb1b10abSAndroid Build Coastguard Worker 
279*fb1b10abSAndroid Build Coastguard Worker     coeff[0] = b0 + b2;  // 16 bit, [-32640, 32640]
280*fb1b10abSAndroid Build Coastguard Worker     coeff[64] = b1 + b3;
281*fb1b10abSAndroid Build Coastguard Worker     coeff[128] = b0 - b2;
282*fb1b10abSAndroid Build Coastguard Worker     coeff[192] = b1 - b3;
283*fb1b10abSAndroid Build Coastguard Worker 
284*fb1b10abSAndroid Build Coastguard Worker     ++coeff;
285*fb1b10abSAndroid Build Coastguard Worker   }
286*fb1b10abSAndroid Build Coastguard Worker }
287*fb1b10abSAndroid Build Coastguard Worker 
vpx_hadamard_32x32_c(const int16_t * src_diff,ptrdiff_t src_stride,tran_low_t * coeff)288*fb1b10abSAndroid Build Coastguard Worker void vpx_hadamard_32x32_c(const int16_t *src_diff, ptrdiff_t src_stride,
289*fb1b10abSAndroid Build Coastguard Worker                           tran_low_t *coeff) {
290*fb1b10abSAndroid Build Coastguard Worker   int idx;
291*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < 4; ++idx) {
292*fb1b10abSAndroid Build Coastguard Worker     // src_diff: 9 bit, dynamic range [-255, 255]
293*fb1b10abSAndroid Build Coastguard Worker     const int16_t *src_ptr =
294*fb1b10abSAndroid Build Coastguard Worker         src_diff + (idx >> 1) * 16 * src_stride + (idx & 0x01) * 16;
295*fb1b10abSAndroid Build Coastguard Worker     vpx_hadamard_16x16_c(src_ptr, src_stride, coeff + idx * 256);
296*fb1b10abSAndroid Build Coastguard Worker   }
297*fb1b10abSAndroid Build Coastguard Worker 
298*fb1b10abSAndroid Build Coastguard Worker   // coeff: 16 bit, dynamic range [-32768, 32767]
299*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < 256; ++idx) {
300*fb1b10abSAndroid Build Coastguard Worker     tran_low_t a0 = coeff[0];
301*fb1b10abSAndroid Build Coastguard Worker     tran_low_t a1 = coeff[256];
302*fb1b10abSAndroid Build Coastguard Worker     tran_low_t a2 = coeff[512];
303*fb1b10abSAndroid Build Coastguard Worker     tran_low_t a3 = coeff[768];
304*fb1b10abSAndroid Build Coastguard Worker 
305*fb1b10abSAndroid Build Coastguard Worker     tran_low_t b0 = (a0 + a1) >> 2;  // (a0 + a1): 17 bit, [-65536, 65535]
306*fb1b10abSAndroid Build Coastguard Worker     tran_low_t b1 = (a0 - a1) >> 2;  // b0-b3: 15 bit, dynamic range
307*fb1b10abSAndroid Build Coastguard Worker     tran_low_t b2 = (a2 + a3) >> 2;  // [-16384, 16383]
308*fb1b10abSAndroid Build Coastguard Worker     tran_low_t b3 = (a2 - a3) >> 2;
309*fb1b10abSAndroid Build Coastguard Worker 
310*fb1b10abSAndroid Build Coastguard Worker     coeff[0] = b0 + b2;  // 16 bit, [-32768, 32767]
311*fb1b10abSAndroid Build Coastguard Worker     coeff[256] = b1 + b3;
312*fb1b10abSAndroid Build Coastguard Worker     coeff[512] = b0 - b2;
313*fb1b10abSAndroid Build Coastguard Worker     coeff[768] = b1 - b3;
314*fb1b10abSAndroid Build Coastguard Worker 
315*fb1b10abSAndroid Build Coastguard Worker     ++coeff;
316*fb1b10abSAndroid Build Coastguard Worker   }
317*fb1b10abSAndroid Build Coastguard Worker }
318*fb1b10abSAndroid Build Coastguard Worker 
319*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
320*fb1b10abSAndroid Build Coastguard Worker // coeff: dynamic range 20 bit.
321*fb1b10abSAndroid Build Coastguard Worker // length: value range {16, 64, 256, 1024}.
vpx_highbd_satd_c(const tran_low_t * coeff,int length)322*fb1b10abSAndroid Build Coastguard Worker int vpx_highbd_satd_c(const tran_low_t *coeff, int length) {
323*fb1b10abSAndroid Build Coastguard Worker   int i;
324*fb1b10abSAndroid Build Coastguard Worker   int satd = 0;
325*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < length; ++i) satd += abs(coeff[i]);
326*fb1b10abSAndroid Build Coastguard Worker 
327*fb1b10abSAndroid Build Coastguard Worker   // satd: 30 bits
328*fb1b10abSAndroid Build Coastguard Worker   return satd;
329*fb1b10abSAndroid Build Coastguard Worker }
330*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
331*fb1b10abSAndroid Build Coastguard Worker 
332*fb1b10abSAndroid Build Coastguard Worker // coeff: 16 bits, dynamic range [-32640, 32640].
333*fb1b10abSAndroid Build Coastguard Worker // length: value range {16, 64, 256, 1024}.
vpx_satd_c(const tran_low_t * coeff,int length)334*fb1b10abSAndroid Build Coastguard Worker int vpx_satd_c(const tran_low_t *coeff, int length) {
335*fb1b10abSAndroid Build Coastguard Worker   int i;
336*fb1b10abSAndroid Build Coastguard Worker   int satd = 0;
337*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < length; ++i) satd += abs(coeff[i]);
338*fb1b10abSAndroid Build Coastguard Worker 
339*fb1b10abSAndroid Build Coastguard Worker   // satd: 26 bits, dynamic range [-32640 * 1024, 32640 * 1024]
340*fb1b10abSAndroid Build Coastguard Worker   return satd;
341*fb1b10abSAndroid Build Coastguard Worker }
342*fb1b10abSAndroid Build Coastguard Worker 
343*fb1b10abSAndroid Build Coastguard Worker // Integer projection onto row vectors.
344*fb1b10abSAndroid Build Coastguard Worker // height: value range {16, 32, 64}.
vpx_int_pro_row_c(int16_t hbuf[16],const uint8_t * ref,const int ref_stride,const int height)345*fb1b10abSAndroid Build Coastguard Worker void vpx_int_pro_row_c(int16_t hbuf[16], const uint8_t *ref,
346*fb1b10abSAndroid Build Coastguard Worker                        const int ref_stride, const int height) {
347*fb1b10abSAndroid Build Coastguard Worker   int idx;
348*fb1b10abSAndroid Build Coastguard Worker   const int norm_factor = height >> 1;
349*fb1b10abSAndroid Build Coastguard Worker   assert(height >= 2);
350*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < 16; ++idx) {
351*fb1b10abSAndroid Build Coastguard Worker     int i;
352*fb1b10abSAndroid Build Coastguard Worker     hbuf[idx] = 0;
353*fb1b10abSAndroid Build Coastguard Worker     // hbuf[idx]: 14 bit, dynamic range [0, 16320].
354*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < height; ++i) hbuf[idx] += ref[i * ref_stride];
355*fb1b10abSAndroid Build Coastguard Worker     // hbuf[idx]: 9 bit, dynamic range [0, 510].
356*fb1b10abSAndroid Build Coastguard Worker     hbuf[idx] /= norm_factor;
357*fb1b10abSAndroid Build Coastguard Worker     ++ref;
358*fb1b10abSAndroid Build Coastguard Worker   }
359*fb1b10abSAndroid Build Coastguard Worker }
360*fb1b10abSAndroid Build Coastguard Worker 
361*fb1b10abSAndroid Build Coastguard Worker // width: value range {16, 32, 64}.
vpx_int_pro_col_c(const uint8_t * ref,const int width)362*fb1b10abSAndroid Build Coastguard Worker int16_t vpx_int_pro_col_c(const uint8_t *ref, const int width) {
363*fb1b10abSAndroid Build Coastguard Worker   int idx;
364*fb1b10abSAndroid Build Coastguard Worker   int16_t sum = 0;
365*fb1b10abSAndroid Build Coastguard Worker   // sum: 14 bit, dynamic range [0, 16320]
366*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < width; ++idx) sum += ref[idx];
367*fb1b10abSAndroid Build Coastguard Worker   return sum;
368*fb1b10abSAndroid Build Coastguard Worker }
369*fb1b10abSAndroid Build Coastguard Worker 
370*fb1b10abSAndroid Build Coastguard Worker // ref: [0 - 510]
371*fb1b10abSAndroid Build Coastguard Worker // src: [0 - 510]
372*fb1b10abSAndroid Build Coastguard Worker // bwl: {2, 3, 4}
vpx_vector_var_c(const int16_t * ref,const int16_t * src,const int bwl)373*fb1b10abSAndroid Build Coastguard Worker int vpx_vector_var_c(const int16_t *ref, const int16_t *src, const int bwl) {
374*fb1b10abSAndroid Build Coastguard Worker   int i;
375*fb1b10abSAndroid Build Coastguard Worker   int width = 4 << bwl;
376*fb1b10abSAndroid Build Coastguard Worker   int sse = 0, mean = 0, var;
377*fb1b10abSAndroid Build Coastguard Worker 
378*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < width; ++i) {
379*fb1b10abSAndroid Build Coastguard Worker     int diff = ref[i] - src[i];  // diff: dynamic range [-510, 510], 10 bits.
380*fb1b10abSAndroid Build Coastguard Worker     mean += diff;                // mean: dynamic range 16 bits.
381*fb1b10abSAndroid Build Coastguard Worker     sse += diff * diff;          // sse:  dynamic range 26 bits.
382*fb1b10abSAndroid Build Coastguard Worker   }
383*fb1b10abSAndroid Build Coastguard Worker 
384*fb1b10abSAndroid Build Coastguard Worker   // (mean * mean): dynamic range 31 bits.
385*fb1b10abSAndroid Build Coastguard Worker   var = sse - ((mean * mean) >> (bwl + 2));
386*fb1b10abSAndroid Build Coastguard Worker   return var;
387*fb1b10abSAndroid Build Coastguard Worker }
388*fb1b10abSAndroid Build Coastguard Worker 
vpx_minmax_8x8_c(const uint8_t * s,int p,const uint8_t * d,int dp,int * min,int * max)389*fb1b10abSAndroid Build Coastguard Worker void vpx_minmax_8x8_c(const uint8_t *s, int p, const uint8_t *d, int dp,
390*fb1b10abSAndroid Build Coastguard Worker                       int *min, int *max) {
391*fb1b10abSAndroid Build Coastguard Worker   int i, j;
392*fb1b10abSAndroid Build Coastguard Worker   *min = 255;
393*fb1b10abSAndroid Build Coastguard Worker   *max = 0;
394*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 8; ++i, s += p, d += dp) {
395*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 8; ++j) {
396*fb1b10abSAndroid Build Coastguard Worker       int diff = abs(s[j] - d[j]);
397*fb1b10abSAndroid Build Coastguard Worker       *min = diff < *min ? diff : *min;
398*fb1b10abSAndroid Build Coastguard Worker       *max = diff > *max ? diff : *max;
399*fb1b10abSAndroid Build Coastguard Worker     }
400*fb1b10abSAndroid Build Coastguard Worker   }
401*fb1b10abSAndroid Build Coastguard Worker }
402*fb1b10abSAndroid Build Coastguard Worker 
403*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
vpx_highbd_avg_8x8_c(const uint8_t * s8,int p)404*fb1b10abSAndroid Build Coastguard Worker unsigned int vpx_highbd_avg_8x8_c(const uint8_t *s8, int p) {
405*fb1b10abSAndroid Build Coastguard Worker   int i, j;
406*fb1b10abSAndroid Build Coastguard Worker   int sum = 0;
407*fb1b10abSAndroid Build Coastguard Worker   const uint16_t *s = CONVERT_TO_SHORTPTR(s8);
408*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 8; ++i, s += p)
409*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 8; sum += s[j], ++j) {
410*fb1b10abSAndroid Build Coastguard Worker     }
411*fb1b10abSAndroid Build Coastguard Worker 
412*fb1b10abSAndroid Build Coastguard Worker   return (sum + 32) >> 6;
413*fb1b10abSAndroid Build Coastguard Worker }
414*fb1b10abSAndroid Build Coastguard Worker 
vpx_highbd_avg_4x4_c(const uint8_t * s8,int p)415*fb1b10abSAndroid Build Coastguard Worker unsigned int vpx_highbd_avg_4x4_c(const uint8_t *s8, int p) {
416*fb1b10abSAndroid Build Coastguard Worker   int i, j;
417*fb1b10abSAndroid Build Coastguard Worker   int sum = 0;
418*fb1b10abSAndroid Build Coastguard Worker   const uint16_t *s = CONVERT_TO_SHORTPTR(s8);
419*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 4; ++i, s += p)
420*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 4; sum += s[j], ++j) {
421*fb1b10abSAndroid Build Coastguard Worker     }
422*fb1b10abSAndroid Build Coastguard Worker 
423*fb1b10abSAndroid Build Coastguard Worker   return (sum + 8) >> 4;
424*fb1b10abSAndroid Build Coastguard Worker }
425*fb1b10abSAndroid Build Coastguard Worker 
vpx_highbd_minmax_8x8_c(const uint8_t * s8,int p,const uint8_t * d8,int dp,int * min,int * max)426*fb1b10abSAndroid Build Coastguard Worker void vpx_highbd_minmax_8x8_c(const uint8_t *s8, int p, const uint8_t *d8,
427*fb1b10abSAndroid Build Coastguard Worker                              int dp, int *min, int *max) {
428*fb1b10abSAndroid Build Coastguard Worker   int i, j;
429*fb1b10abSAndroid Build Coastguard Worker   const uint16_t *s = CONVERT_TO_SHORTPTR(s8);
430*fb1b10abSAndroid Build Coastguard Worker   const uint16_t *d = CONVERT_TO_SHORTPTR(d8);
431*fb1b10abSAndroid Build Coastguard Worker   *min = 65535;
432*fb1b10abSAndroid Build Coastguard Worker   *max = 0;
433*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 8; ++i, s += p, d += dp) {
434*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 8; ++j) {
435*fb1b10abSAndroid Build Coastguard Worker       int diff = abs(s[j] - d[j]);
436*fb1b10abSAndroid Build Coastguard Worker       *min = diff < *min ? diff : *min;
437*fb1b10abSAndroid Build Coastguard Worker       *max = diff > *max ? diff : *max;
438*fb1b10abSAndroid Build Coastguard Worker     }
439*fb1b10abSAndroid Build Coastguard Worker   }
440*fb1b10abSAndroid Build Coastguard Worker }
441*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
442