xref: /aosp_15_r20/external/libvpx/vp9/common/vp9_idct.c (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2010 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 <math.h>
12*fb1b10abSAndroid Build Coastguard Worker 
13*fb1b10abSAndroid Build Coastguard Worker #include "./vp9_rtcd.h"
14*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_dsp_rtcd.h"
15*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_blockd.h"
16*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_idct.h"
17*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/inv_txfm.h"
18*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/mem.h"
19*fb1b10abSAndroid Build Coastguard Worker 
vp9_iht4x4_16_add_c(const tran_low_t * input,uint8_t * dest,int stride,int tx_type)20*fb1b10abSAndroid Build Coastguard Worker void vp9_iht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride,
21*fb1b10abSAndroid Build Coastguard Worker                          int tx_type) {
22*fb1b10abSAndroid Build Coastguard Worker   const transform_2d IHT_4[] = {
23*fb1b10abSAndroid Build Coastguard Worker     { idct4_c, idct4_c },   // DCT_DCT  = 0
24*fb1b10abSAndroid Build Coastguard Worker     { iadst4_c, idct4_c },  // ADST_DCT = 1
25*fb1b10abSAndroid Build Coastguard Worker     { idct4_c, iadst4_c },  // DCT_ADST = 2
26*fb1b10abSAndroid Build Coastguard Worker     { iadst4_c, iadst4_c }  // ADST_ADST = 3
27*fb1b10abSAndroid Build Coastguard Worker   };
28*fb1b10abSAndroid Build Coastguard Worker 
29*fb1b10abSAndroid Build Coastguard Worker   int i, j;
30*fb1b10abSAndroid Build Coastguard Worker   tran_low_t out[4 * 4];
31*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *outptr = out;
32*fb1b10abSAndroid Build Coastguard Worker   tran_low_t temp_in[4], temp_out[4];
33*fb1b10abSAndroid Build Coastguard Worker 
34*fb1b10abSAndroid Build Coastguard Worker   // inverse transform row vectors
35*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 4; ++i) {
36*fb1b10abSAndroid Build Coastguard Worker     IHT_4[tx_type].rows(input, outptr);
37*fb1b10abSAndroid Build Coastguard Worker     input += 4;
38*fb1b10abSAndroid Build Coastguard Worker     outptr += 4;
39*fb1b10abSAndroid Build Coastguard Worker   }
40*fb1b10abSAndroid Build Coastguard Worker 
41*fb1b10abSAndroid Build Coastguard Worker   // inverse transform column vectors
42*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 4; ++i) {
43*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 4; ++j) temp_in[j] = out[j * 4 + i];
44*fb1b10abSAndroid Build Coastguard Worker     IHT_4[tx_type].cols(temp_in, temp_out);
45*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 4; ++j) {
46*fb1b10abSAndroid Build Coastguard Worker       dest[j * stride + i] = clip_pixel_add(dest[j * stride + i],
47*fb1b10abSAndroid Build Coastguard Worker                                             ROUND_POWER_OF_TWO(temp_out[j], 4));
48*fb1b10abSAndroid Build Coastguard Worker     }
49*fb1b10abSAndroid Build Coastguard Worker   }
50*fb1b10abSAndroid Build Coastguard Worker }
51*fb1b10abSAndroid Build Coastguard Worker 
52*fb1b10abSAndroid Build Coastguard Worker static const transform_2d IHT_8[] = {
53*fb1b10abSAndroid Build Coastguard Worker   { idct8_c, idct8_c },   // DCT_DCT  = 0
54*fb1b10abSAndroid Build Coastguard Worker   { iadst8_c, idct8_c },  // ADST_DCT = 1
55*fb1b10abSAndroid Build Coastguard Worker   { idct8_c, iadst8_c },  // DCT_ADST = 2
56*fb1b10abSAndroid Build Coastguard Worker   { iadst8_c, iadst8_c }  // ADST_ADST = 3
57*fb1b10abSAndroid Build Coastguard Worker };
58*fb1b10abSAndroid Build Coastguard Worker 
vp9_iht8x8_64_add_c(const tran_low_t * input,uint8_t * dest,int stride,int tx_type)59*fb1b10abSAndroid Build Coastguard Worker void vp9_iht8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride,
60*fb1b10abSAndroid Build Coastguard Worker                          int tx_type) {
61*fb1b10abSAndroid Build Coastguard Worker   int i, j;
62*fb1b10abSAndroid Build Coastguard Worker   tran_low_t out[8 * 8];
63*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *outptr = out;
64*fb1b10abSAndroid Build Coastguard Worker   tran_low_t temp_in[8], temp_out[8];
65*fb1b10abSAndroid Build Coastguard Worker   const transform_2d ht = IHT_8[tx_type];
66*fb1b10abSAndroid Build Coastguard Worker 
67*fb1b10abSAndroid Build Coastguard Worker   // inverse transform row vectors
68*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 8; ++i) {
69*fb1b10abSAndroid Build Coastguard Worker     ht.rows(input, outptr);
70*fb1b10abSAndroid Build Coastguard Worker     input += 8;
71*fb1b10abSAndroid Build Coastguard Worker     outptr += 8;
72*fb1b10abSAndroid Build Coastguard Worker   }
73*fb1b10abSAndroid Build Coastguard Worker 
74*fb1b10abSAndroid Build Coastguard Worker   // inverse transform column vectors
75*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 8; ++i) {
76*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 8; ++j) temp_in[j] = out[j * 8 + i];
77*fb1b10abSAndroid Build Coastguard Worker     ht.cols(temp_in, temp_out);
78*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 8; ++j) {
79*fb1b10abSAndroid Build Coastguard Worker       dest[j * stride + i] = clip_pixel_add(dest[j * stride + i],
80*fb1b10abSAndroid Build Coastguard Worker                                             ROUND_POWER_OF_TWO(temp_out[j], 5));
81*fb1b10abSAndroid Build Coastguard Worker     }
82*fb1b10abSAndroid Build Coastguard Worker   }
83*fb1b10abSAndroid Build Coastguard Worker }
84*fb1b10abSAndroid Build Coastguard Worker 
85*fb1b10abSAndroid Build Coastguard Worker static const transform_2d IHT_16[] = {
86*fb1b10abSAndroid Build Coastguard Worker   { idct16_c, idct16_c },   // DCT_DCT  = 0
87*fb1b10abSAndroid Build Coastguard Worker   { iadst16_c, idct16_c },  // ADST_DCT = 1
88*fb1b10abSAndroid Build Coastguard Worker   { idct16_c, iadst16_c },  // DCT_ADST = 2
89*fb1b10abSAndroid Build Coastguard Worker   { iadst16_c, iadst16_c }  // ADST_ADST = 3
90*fb1b10abSAndroid Build Coastguard Worker };
91*fb1b10abSAndroid Build Coastguard Worker 
vp9_iht16x16_256_add_c(const tran_low_t * input,uint8_t * dest,int stride,int tx_type)92*fb1b10abSAndroid Build Coastguard Worker void vp9_iht16x16_256_add_c(const tran_low_t *input, uint8_t *dest, int stride,
93*fb1b10abSAndroid Build Coastguard Worker                             int tx_type) {
94*fb1b10abSAndroid Build Coastguard Worker   int i, j;
95*fb1b10abSAndroid Build Coastguard Worker   tran_low_t out[16 * 16];
96*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *outptr = out;
97*fb1b10abSAndroid Build Coastguard Worker   tran_low_t temp_in[16], temp_out[16];
98*fb1b10abSAndroid Build Coastguard Worker   const transform_2d ht = IHT_16[tx_type];
99*fb1b10abSAndroid Build Coastguard Worker 
100*fb1b10abSAndroid Build Coastguard Worker   // Rows
101*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 16; ++i) {
102*fb1b10abSAndroid Build Coastguard Worker     ht.rows(input, outptr);
103*fb1b10abSAndroid Build Coastguard Worker     input += 16;
104*fb1b10abSAndroid Build Coastguard Worker     outptr += 16;
105*fb1b10abSAndroid Build Coastguard Worker   }
106*fb1b10abSAndroid Build Coastguard Worker 
107*fb1b10abSAndroid Build Coastguard Worker   // Columns
108*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 16; ++i) {
109*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 16; ++j) temp_in[j] = out[j * 16 + i];
110*fb1b10abSAndroid Build Coastguard Worker     ht.cols(temp_in, temp_out);
111*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 16; ++j) {
112*fb1b10abSAndroid Build Coastguard Worker       dest[j * stride + i] = clip_pixel_add(dest[j * stride + i],
113*fb1b10abSAndroid Build Coastguard Worker                                             ROUND_POWER_OF_TWO(temp_out[j], 6));
114*fb1b10abSAndroid Build Coastguard Worker     }
115*fb1b10abSAndroid Build Coastguard Worker   }
116*fb1b10abSAndroid Build Coastguard Worker }
117*fb1b10abSAndroid Build Coastguard Worker 
118*fb1b10abSAndroid Build Coastguard Worker // idct
vp9_idct4x4_add(const tran_low_t * input,uint8_t * dest,int stride,int eob)119*fb1b10abSAndroid Build Coastguard Worker void vp9_idct4x4_add(const tran_low_t *input, uint8_t *dest, int stride,
120*fb1b10abSAndroid Build Coastguard Worker                      int eob) {
121*fb1b10abSAndroid Build Coastguard Worker   if (eob > 1)
122*fb1b10abSAndroid Build Coastguard Worker     vpx_idct4x4_16_add(input, dest, stride);
123*fb1b10abSAndroid Build Coastguard Worker   else
124*fb1b10abSAndroid Build Coastguard Worker     vpx_idct4x4_1_add(input, dest, stride);
125*fb1b10abSAndroid Build Coastguard Worker }
126*fb1b10abSAndroid Build Coastguard Worker 
vp9_iwht4x4_add(const tran_low_t * input,uint8_t * dest,int stride,int eob)127*fb1b10abSAndroid Build Coastguard Worker void vp9_iwht4x4_add(const tran_low_t *input, uint8_t *dest, int stride,
128*fb1b10abSAndroid Build Coastguard Worker                      int eob) {
129*fb1b10abSAndroid Build Coastguard Worker   if (eob > 1)
130*fb1b10abSAndroid Build Coastguard Worker     vpx_iwht4x4_16_add(input, dest, stride);
131*fb1b10abSAndroid Build Coastguard Worker   else
132*fb1b10abSAndroid Build Coastguard Worker     vpx_iwht4x4_1_add(input, dest, stride);
133*fb1b10abSAndroid Build Coastguard Worker }
134*fb1b10abSAndroid Build Coastguard Worker 
vp9_idct8x8_add(const tran_low_t * input,uint8_t * dest,int stride,int eob)135*fb1b10abSAndroid Build Coastguard Worker void vp9_idct8x8_add(const tran_low_t *input, uint8_t *dest, int stride,
136*fb1b10abSAndroid Build Coastguard Worker                      int eob) {
137*fb1b10abSAndroid Build Coastguard Worker   // If dc is 1, then input[0] is the reconstructed value, do not need
138*fb1b10abSAndroid Build Coastguard Worker   // dequantization. Also, when dc is 1, dc is counted in eobs, namely eobs >=1.
139*fb1b10abSAndroid Build Coastguard Worker 
140*fb1b10abSAndroid Build Coastguard Worker   // The calculation can be simplified if there are not many non-zero dct
141*fb1b10abSAndroid Build Coastguard Worker   // coefficients. Use eobs to decide what to do.
142*fb1b10abSAndroid Build Coastguard Worker   if (eob == 1)
143*fb1b10abSAndroid Build Coastguard Worker     // DC only DCT coefficient
144*fb1b10abSAndroid Build Coastguard Worker     vpx_idct8x8_1_add(input, dest, stride);
145*fb1b10abSAndroid Build Coastguard Worker   else if (eob <= 12)
146*fb1b10abSAndroid Build Coastguard Worker     vpx_idct8x8_12_add(input, dest, stride);
147*fb1b10abSAndroid Build Coastguard Worker   else
148*fb1b10abSAndroid Build Coastguard Worker     vpx_idct8x8_64_add(input, dest, stride);
149*fb1b10abSAndroid Build Coastguard Worker }
150*fb1b10abSAndroid Build Coastguard Worker 
vp9_idct16x16_add(const tran_low_t * input,uint8_t * dest,int stride,int eob)151*fb1b10abSAndroid Build Coastguard Worker void vp9_idct16x16_add(const tran_low_t *input, uint8_t *dest, int stride,
152*fb1b10abSAndroid Build Coastguard Worker                        int eob) {
153*fb1b10abSAndroid Build Coastguard Worker   assert(((intptr_t)input) % 32 == 0);
154*fb1b10abSAndroid Build Coastguard Worker   /* The calculation can be simplified if there are not many non-zero dct
155*fb1b10abSAndroid Build Coastguard Worker    * coefficients. Use eobs to separate different cases. */
156*fb1b10abSAndroid Build Coastguard Worker   if (eob == 1) /* DC only DCT coefficient. */
157*fb1b10abSAndroid Build Coastguard Worker     vpx_idct16x16_1_add(input, dest, stride);
158*fb1b10abSAndroid Build Coastguard Worker   else if (eob <= 10)
159*fb1b10abSAndroid Build Coastguard Worker     vpx_idct16x16_10_add(input, dest, stride);
160*fb1b10abSAndroid Build Coastguard Worker   else if (eob <= 38)
161*fb1b10abSAndroid Build Coastguard Worker     vpx_idct16x16_38_add(input, dest, stride);
162*fb1b10abSAndroid Build Coastguard Worker   else
163*fb1b10abSAndroid Build Coastguard Worker     vpx_idct16x16_256_add(input, dest, stride);
164*fb1b10abSAndroid Build Coastguard Worker }
165*fb1b10abSAndroid Build Coastguard Worker 
vp9_idct32x32_add(const tran_low_t * input,uint8_t * dest,int stride,int eob)166*fb1b10abSAndroid Build Coastguard Worker void vp9_idct32x32_add(const tran_low_t *input, uint8_t *dest, int stride,
167*fb1b10abSAndroid Build Coastguard Worker                        int eob) {
168*fb1b10abSAndroid Build Coastguard Worker   assert(((intptr_t)input) % 32 == 0);
169*fb1b10abSAndroid Build Coastguard Worker   if (eob == 1)
170*fb1b10abSAndroid Build Coastguard Worker     vpx_idct32x32_1_add(input, dest, stride);
171*fb1b10abSAndroid Build Coastguard Worker   else if (eob <= 34)
172*fb1b10abSAndroid Build Coastguard Worker     // non-zero coeff only in upper-left 8x8
173*fb1b10abSAndroid Build Coastguard Worker     vpx_idct32x32_34_add(input, dest, stride);
174*fb1b10abSAndroid Build Coastguard Worker   else if (eob <= 135)
175*fb1b10abSAndroid Build Coastguard Worker     // non-zero coeff only in upper-left 16x16
176*fb1b10abSAndroid Build Coastguard Worker     vpx_idct32x32_135_add(input, dest, stride);
177*fb1b10abSAndroid Build Coastguard Worker   else
178*fb1b10abSAndroid Build Coastguard Worker     vpx_idct32x32_1024_add(input, dest, stride);
179*fb1b10abSAndroid Build Coastguard Worker }
180*fb1b10abSAndroid Build Coastguard Worker 
181*fb1b10abSAndroid Build Coastguard Worker // iht
vp9_iht4x4_add(TX_TYPE tx_type,const tran_low_t * input,uint8_t * dest,int stride,int eob)182*fb1b10abSAndroid Build Coastguard Worker void vp9_iht4x4_add(TX_TYPE tx_type, const tran_low_t *input, uint8_t *dest,
183*fb1b10abSAndroid Build Coastguard Worker                     int stride, int eob) {
184*fb1b10abSAndroid Build Coastguard Worker   if (tx_type == DCT_DCT)
185*fb1b10abSAndroid Build Coastguard Worker     vp9_idct4x4_add(input, dest, stride, eob);
186*fb1b10abSAndroid Build Coastguard Worker   else
187*fb1b10abSAndroid Build Coastguard Worker     vp9_iht4x4_16_add(input, dest, stride, tx_type);
188*fb1b10abSAndroid Build Coastguard Worker }
189*fb1b10abSAndroid Build Coastguard Worker 
vp9_iht8x8_add(TX_TYPE tx_type,const tran_low_t * input,uint8_t * dest,int stride,int eob)190*fb1b10abSAndroid Build Coastguard Worker void vp9_iht8x8_add(TX_TYPE tx_type, const tran_low_t *input, uint8_t *dest,
191*fb1b10abSAndroid Build Coastguard Worker                     int stride, int eob) {
192*fb1b10abSAndroid Build Coastguard Worker   if (tx_type == DCT_DCT) {
193*fb1b10abSAndroid Build Coastguard Worker     vp9_idct8x8_add(input, dest, stride, eob);
194*fb1b10abSAndroid Build Coastguard Worker   } else {
195*fb1b10abSAndroid Build Coastguard Worker     vp9_iht8x8_64_add(input, dest, stride, tx_type);
196*fb1b10abSAndroid Build Coastguard Worker   }
197*fb1b10abSAndroid Build Coastguard Worker }
198*fb1b10abSAndroid Build Coastguard Worker 
vp9_iht16x16_add(TX_TYPE tx_type,const tran_low_t * input,uint8_t * dest,int stride,int eob)199*fb1b10abSAndroid Build Coastguard Worker void vp9_iht16x16_add(TX_TYPE tx_type, const tran_low_t *input, uint8_t *dest,
200*fb1b10abSAndroid Build Coastguard Worker                       int stride, int eob) {
201*fb1b10abSAndroid Build Coastguard Worker   if (tx_type == DCT_DCT) {
202*fb1b10abSAndroid Build Coastguard Worker     vp9_idct16x16_add(input, dest, stride, eob);
203*fb1b10abSAndroid Build Coastguard Worker   } else {
204*fb1b10abSAndroid Build Coastguard Worker     vp9_iht16x16_256_add(input, dest, stride, tx_type);
205*fb1b10abSAndroid Build Coastguard Worker   }
206*fb1b10abSAndroid Build Coastguard Worker }
207*fb1b10abSAndroid Build Coastguard Worker 
208*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
209*fb1b10abSAndroid Build Coastguard Worker 
vp9_highbd_iht4x4_16_add_c(const tran_low_t * input,uint16_t * dest,int stride,int tx_type,int bd)210*fb1b10abSAndroid Build Coastguard Worker void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint16_t *dest,
211*fb1b10abSAndroid Build Coastguard Worker                                 int stride, int tx_type, int bd) {
212*fb1b10abSAndroid Build Coastguard Worker   const highbd_transform_2d IHT_4[] = {
213*fb1b10abSAndroid Build Coastguard Worker     { vpx_highbd_idct4_c, vpx_highbd_idct4_c },   // DCT_DCT  = 0
214*fb1b10abSAndroid Build Coastguard Worker     { vpx_highbd_iadst4_c, vpx_highbd_idct4_c },  // ADST_DCT = 1
215*fb1b10abSAndroid Build Coastguard Worker     { vpx_highbd_idct4_c, vpx_highbd_iadst4_c },  // DCT_ADST = 2
216*fb1b10abSAndroid Build Coastguard Worker     { vpx_highbd_iadst4_c, vpx_highbd_iadst4_c }  // ADST_ADST = 3
217*fb1b10abSAndroid Build Coastguard Worker   };
218*fb1b10abSAndroid Build Coastguard Worker 
219*fb1b10abSAndroid Build Coastguard Worker   int i, j;
220*fb1b10abSAndroid Build Coastguard Worker   tran_low_t out[4 * 4];
221*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *outptr = out;
222*fb1b10abSAndroid Build Coastguard Worker   tran_low_t temp_in[4], temp_out[4];
223*fb1b10abSAndroid Build Coastguard Worker 
224*fb1b10abSAndroid Build Coastguard Worker   // Inverse transform row vectors.
225*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 4; ++i) {
226*fb1b10abSAndroid Build Coastguard Worker     IHT_4[tx_type].rows(input, outptr, bd);
227*fb1b10abSAndroid Build Coastguard Worker     input += 4;
228*fb1b10abSAndroid Build Coastguard Worker     outptr += 4;
229*fb1b10abSAndroid Build Coastguard Worker   }
230*fb1b10abSAndroid Build Coastguard Worker 
231*fb1b10abSAndroid Build Coastguard Worker   // Inverse transform column vectors.
232*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 4; ++i) {
233*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 4; ++j) temp_in[j] = out[j * 4 + i];
234*fb1b10abSAndroid Build Coastguard Worker     IHT_4[tx_type].cols(temp_in, temp_out, bd);
235*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 4; ++j) {
236*fb1b10abSAndroid Build Coastguard Worker       dest[j * stride + i] = highbd_clip_pixel_add(
237*fb1b10abSAndroid Build Coastguard Worker           dest[j * stride + i], ROUND_POWER_OF_TWO(temp_out[j], 4), bd);
238*fb1b10abSAndroid Build Coastguard Worker     }
239*fb1b10abSAndroid Build Coastguard Worker   }
240*fb1b10abSAndroid Build Coastguard Worker }
241*fb1b10abSAndroid Build Coastguard Worker 
242*fb1b10abSAndroid Build Coastguard Worker static const highbd_transform_2d HIGH_IHT_8[] = {
243*fb1b10abSAndroid Build Coastguard Worker   { vpx_highbd_idct8_c, vpx_highbd_idct8_c },   // DCT_DCT  = 0
244*fb1b10abSAndroid Build Coastguard Worker   { vpx_highbd_iadst8_c, vpx_highbd_idct8_c },  // ADST_DCT = 1
245*fb1b10abSAndroid Build Coastguard Worker   { vpx_highbd_idct8_c, vpx_highbd_iadst8_c },  // DCT_ADST = 2
246*fb1b10abSAndroid Build Coastguard Worker   { vpx_highbd_iadst8_c, vpx_highbd_iadst8_c }  // ADST_ADST = 3
247*fb1b10abSAndroid Build Coastguard Worker };
248*fb1b10abSAndroid Build Coastguard Worker 
vp9_highbd_iht8x8_64_add_c(const tran_low_t * input,uint16_t * dest,int stride,int tx_type,int bd)249*fb1b10abSAndroid Build Coastguard Worker void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint16_t *dest,
250*fb1b10abSAndroid Build Coastguard Worker                                 int stride, int tx_type, int bd) {
251*fb1b10abSAndroid Build Coastguard Worker   int i, j;
252*fb1b10abSAndroid Build Coastguard Worker   tran_low_t out[8 * 8];
253*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *outptr = out;
254*fb1b10abSAndroid Build Coastguard Worker   tran_low_t temp_in[8], temp_out[8];
255*fb1b10abSAndroid Build Coastguard Worker   const highbd_transform_2d ht = HIGH_IHT_8[tx_type];
256*fb1b10abSAndroid Build Coastguard Worker 
257*fb1b10abSAndroid Build Coastguard Worker   // Inverse transform row vectors.
258*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 8; ++i) {
259*fb1b10abSAndroid Build Coastguard Worker     ht.rows(input, outptr, bd);
260*fb1b10abSAndroid Build Coastguard Worker     input += 8;
261*fb1b10abSAndroid Build Coastguard Worker     outptr += 8;
262*fb1b10abSAndroid Build Coastguard Worker   }
263*fb1b10abSAndroid Build Coastguard Worker 
264*fb1b10abSAndroid Build Coastguard Worker   // Inverse transform column vectors.
265*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 8; ++i) {
266*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 8; ++j) temp_in[j] = out[j * 8 + i];
267*fb1b10abSAndroid Build Coastguard Worker     ht.cols(temp_in, temp_out, bd);
268*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 8; ++j) {
269*fb1b10abSAndroid Build Coastguard Worker       dest[j * stride + i] = highbd_clip_pixel_add(
270*fb1b10abSAndroid Build Coastguard Worker           dest[j * stride + i], ROUND_POWER_OF_TWO(temp_out[j], 5), bd);
271*fb1b10abSAndroid Build Coastguard Worker     }
272*fb1b10abSAndroid Build Coastguard Worker   }
273*fb1b10abSAndroid Build Coastguard Worker }
274*fb1b10abSAndroid Build Coastguard Worker 
275*fb1b10abSAndroid Build Coastguard Worker static const highbd_transform_2d HIGH_IHT_16[] = {
276*fb1b10abSAndroid Build Coastguard Worker   { vpx_highbd_idct16_c, vpx_highbd_idct16_c },   // DCT_DCT  = 0
277*fb1b10abSAndroid Build Coastguard Worker   { vpx_highbd_iadst16_c, vpx_highbd_idct16_c },  // ADST_DCT = 1
278*fb1b10abSAndroid Build Coastguard Worker   { vpx_highbd_idct16_c, vpx_highbd_iadst16_c },  // DCT_ADST = 2
279*fb1b10abSAndroid Build Coastguard Worker   { vpx_highbd_iadst16_c, vpx_highbd_iadst16_c }  // ADST_ADST = 3
280*fb1b10abSAndroid Build Coastguard Worker };
281*fb1b10abSAndroid Build Coastguard Worker 
vp9_highbd_iht16x16_256_add_c(const tran_low_t * input,uint16_t * dest,int stride,int tx_type,int bd)282*fb1b10abSAndroid Build Coastguard Worker void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint16_t *dest,
283*fb1b10abSAndroid Build Coastguard Worker                                    int stride, int tx_type, int bd) {
284*fb1b10abSAndroid Build Coastguard Worker   int i, j;
285*fb1b10abSAndroid Build Coastguard Worker   tran_low_t out[16 * 16];
286*fb1b10abSAndroid Build Coastguard Worker   tran_low_t *outptr = out;
287*fb1b10abSAndroid Build Coastguard Worker   tran_low_t temp_in[16], temp_out[16];
288*fb1b10abSAndroid Build Coastguard Worker   const highbd_transform_2d ht = HIGH_IHT_16[tx_type];
289*fb1b10abSAndroid Build Coastguard Worker 
290*fb1b10abSAndroid Build Coastguard Worker   // Rows
291*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 16; ++i) {
292*fb1b10abSAndroid Build Coastguard Worker     ht.rows(input, outptr, bd);
293*fb1b10abSAndroid Build Coastguard Worker     input += 16;
294*fb1b10abSAndroid Build Coastguard Worker     outptr += 16;
295*fb1b10abSAndroid Build Coastguard Worker   }
296*fb1b10abSAndroid Build Coastguard Worker 
297*fb1b10abSAndroid Build Coastguard Worker   // Columns
298*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 16; ++i) {
299*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 16; ++j) temp_in[j] = out[j * 16 + i];
300*fb1b10abSAndroid Build Coastguard Worker     ht.cols(temp_in, temp_out, bd);
301*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 16; ++j) {
302*fb1b10abSAndroid Build Coastguard Worker       dest[j * stride + i] = highbd_clip_pixel_add(
303*fb1b10abSAndroid Build Coastguard Worker           dest[j * stride + i], ROUND_POWER_OF_TWO(temp_out[j], 6), bd);
304*fb1b10abSAndroid Build Coastguard Worker     }
305*fb1b10abSAndroid Build Coastguard Worker   }
306*fb1b10abSAndroid Build Coastguard Worker }
307*fb1b10abSAndroid Build Coastguard Worker 
308*fb1b10abSAndroid Build Coastguard Worker // idct
vp9_highbd_idct4x4_add(const tran_low_t * input,uint16_t * dest,int stride,int eob,int bd)309*fb1b10abSAndroid Build Coastguard Worker void vp9_highbd_idct4x4_add(const tran_low_t *input, uint16_t *dest, int stride,
310*fb1b10abSAndroid Build Coastguard Worker                             int eob, int bd) {
311*fb1b10abSAndroid Build Coastguard Worker   if (eob > 1)
312*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_idct4x4_16_add(input, dest, stride, bd);
313*fb1b10abSAndroid Build Coastguard Worker   else
314*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_idct4x4_1_add(input, dest, stride, bd);
315*fb1b10abSAndroid Build Coastguard Worker }
316*fb1b10abSAndroid Build Coastguard Worker 
vp9_highbd_iwht4x4_add(const tran_low_t * input,uint16_t * dest,int stride,int eob,int bd)317*fb1b10abSAndroid Build Coastguard Worker void vp9_highbd_iwht4x4_add(const tran_low_t *input, uint16_t *dest, int stride,
318*fb1b10abSAndroid Build Coastguard Worker                             int eob, int bd) {
319*fb1b10abSAndroid Build Coastguard Worker   if (eob > 1)
320*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_iwht4x4_16_add(input, dest, stride, bd);
321*fb1b10abSAndroid Build Coastguard Worker   else
322*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_iwht4x4_1_add(input, dest, stride, bd);
323*fb1b10abSAndroid Build Coastguard Worker }
324*fb1b10abSAndroid Build Coastguard Worker 
vp9_highbd_idct8x8_add(const tran_low_t * input,uint16_t * dest,int stride,int eob,int bd)325*fb1b10abSAndroid Build Coastguard Worker void vp9_highbd_idct8x8_add(const tran_low_t *input, uint16_t *dest, int stride,
326*fb1b10abSAndroid Build Coastguard Worker                             int eob, int bd) {
327*fb1b10abSAndroid Build Coastguard Worker   // If dc is 1, then input[0] is the reconstructed value, do not need
328*fb1b10abSAndroid Build Coastguard Worker   // dequantization. Also, when dc is 1, dc is counted in eobs, namely eobs >=1.
329*fb1b10abSAndroid Build Coastguard Worker 
330*fb1b10abSAndroid Build Coastguard Worker   // The calculation can be simplified if there are not many non-zero dct
331*fb1b10abSAndroid Build Coastguard Worker   // coefficients. Use eobs to decide what to do.
332*fb1b10abSAndroid Build Coastguard Worker   // DC only DCT coefficient
333*fb1b10abSAndroid Build Coastguard Worker   if (eob == 1) {
334*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_idct8x8_1_add(input, dest, stride, bd);
335*fb1b10abSAndroid Build Coastguard Worker   } else if (eob <= 12) {
336*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_idct8x8_12_add(input, dest, stride, bd);
337*fb1b10abSAndroid Build Coastguard Worker   } else {
338*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_idct8x8_64_add(input, dest, stride, bd);
339*fb1b10abSAndroid Build Coastguard Worker   }
340*fb1b10abSAndroid Build Coastguard Worker }
341*fb1b10abSAndroid Build Coastguard Worker 
vp9_highbd_idct16x16_add(const tran_low_t * input,uint16_t * dest,int stride,int eob,int bd)342*fb1b10abSAndroid Build Coastguard Worker void vp9_highbd_idct16x16_add(const tran_low_t *input, uint16_t *dest,
343*fb1b10abSAndroid Build Coastguard Worker                               int stride, int eob, int bd) {
344*fb1b10abSAndroid Build Coastguard Worker   // The calculation can be simplified if there are not many non-zero dct
345*fb1b10abSAndroid Build Coastguard Worker   // coefficients. Use eobs to separate different cases.
346*fb1b10abSAndroid Build Coastguard Worker   // DC only DCT coefficient.
347*fb1b10abSAndroid Build Coastguard Worker   if (eob == 1) {
348*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_idct16x16_1_add(input, dest, stride, bd);
349*fb1b10abSAndroid Build Coastguard Worker   } else if (eob <= 10) {
350*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_idct16x16_10_add(input, dest, stride, bd);
351*fb1b10abSAndroid Build Coastguard Worker   } else if (eob <= 38) {
352*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_idct16x16_38_add(input, dest, stride, bd);
353*fb1b10abSAndroid Build Coastguard Worker   } else {
354*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_idct16x16_256_add(input, dest, stride, bd);
355*fb1b10abSAndroid Build Coastguard Worker   }
356*fb1b10abSAndroid Build Coastguard Worker }
357*fb1b10abSAndroid Build Coastguard Worker 
vp9_highbd_idct32x32_add(const tran_low_t * input,uint16_t * dest,int stride,int eob,int bd)358*fb1b10abSAndroid Build Coastguard Worker void vp9_highbd_idct32x32_add(const tran_low_t *input, uint16_t *dest,
359*fb1b10abSAndroid Build Coastguard Worker                               int stride, int eob, int bd) {
360*fb1b10abSAndroid Build Coastguard Worker   // Non-zero coeff only in upper-left 8x8
361*fb1b10abSAndroid Build Coastguard Worker   if (eob == 1) {
362*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_idct32x32_1_add(input, dest, stride, bd);
363*fb1b10abSAndroid Build Coastguard Worker   } else if (eob <= 34) {
364*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_idct32x32_34_add(input, dest, stride, bd);
365*fb1b10abSAndroid Build Coastguard Worker   } else if (eob <= 135) {
366*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_idct32x32_135_add(input, dest, stride, bd);
367*fb1b10abSAndroid Build Coastguard Worker   } else {
368*fb1b10abSAndroid Build Coastguard Worker     vpx_highbd_idct32x32_1024_add(input, dest, stride, bd);
369*fb1b10abSAndroid Build Coastguard Worker   }
370*fb1b10abSAndroid Build Coastguard Worker }
371*fb1b10abSAndroid Build Coastguard Worker 
372*fb1b10abSAndroid Build Coastguard Worker // iht
vp9_highbd_iht4x4_add(TX_TYPE tx_type,const tran_low_t * input,uint16_t * dest,int stride,int eob,int bd)373*fb1b10abSAndroid Build Coastguard Worker void vp9_highbd_iht4x4_add(TX_TYPE tx_type, const tran_low_t *input,
374*fb1b10abSAndroid Build Coastguard Worker                            uint16_t *dest, int stride, int eob, int bd) {
375*fb1b10abSAndroid Build Coastguard Worker   if (tx_type == DCT_DCT)
376*fb1b10abSAndroid Build Coastguard Worker     vp9_highbd_idct4x4_add(input, dest, stride, eob, bd);
377*fb1b10abSAndroid Build Coastguard Worker   else
378*fb1b10abSAndroid Build Coastguard Worker     vp9_highbd_iht4x4_16_add(input, dest, stride, tx_type, bd);
379*fb1b10abSAndroid Build Coastguard Worker }
380*fb1b10abSAndroid Build Coastguard Worker 
vp9_highbd_iht8x8_add(TX_TYPE tx_type,const tran_low_t * input,uint16_t * dest,int stride,int eob,int bd)381*fb1b10abSAndroid Build Coastguard Worker void vp9_highbd_iht8x8_add(TX_TYPE tx_type, const tran_low_t *input,
382*fb1b10abSAndroid Build Coastguard Worker                            uint16_t *dest, int stride, int eob, int bd) {
383*fb1b10abSAndroid Build Coastguard Worker   if (tx_type == DCT_DCT) {
384*fb1b10abSAndroid Build Coastguard Worker     vp9_highbd_idct8x8_add(input, dest, stride, eob, bd);
385*fb1b10abSAndroid Build Coastguard Worker   } else {
386*fb1b10abSAndroid Build Coastguard Worker     vp9_highbd_iht8x8_64_add(input, dest, stride, tx_type, bd);
387*fb1b10abSAndroid Build Coastguard Worker   }
388*fb1b10abSAndroid Build Coastguard Worker }
389*fb1b10abSAndroid Build Coastguard Worker 
vp9_highbd_iht16x16_add(TX_TYPE tx_type,const tran_low_t * input,uint16_t * dest,int stride,int eob,int bd)390*fb1b10abSAndroid Build Coastguard Worker void vp9_highbd_iht16x16_add(TX_TYPE tx_type, const tran_low_t *input,
391*fb1b10abSAndroid Build Coastguard Worker                              uint16_t *dest, int stride, int eob, int bd) {
392*fb1b10abSAndroid Build Coastguard Worker   if (tx_type == DCT_DCT) {
393*fb1b10abSAndroid Build Coastguard Worker     vp9_highbd_idct16x16_add(input, dest, stride, eob, bd);
394*fb1b10abSAndroid Build Coastguard Worker   } else {
395*fb1b10abSAndroid Build Coastguard Worker     vp9_highbd_iht16x16_256_add(input, dest, stride, tx_type, bd);
396*fb1b10abSAndroid Build Coastguard Worker   }
397*fb1b10abSAndroid Build Coastguard Worker }
398*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
399