xref: /aosp_15_r20/external/libaom/av1/encoder/hybrid_fwd_txfm.c (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1 /*
2  * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 
12 #include "config/aom_config.h"
13 #include "config/av1_rtcd.h"
14 #include "config/aom_dsp_rtcd.h"
15 
16 #include "av1/common/idct.h"
17 #include "av1/common/blockd.h"
18 #include "av1/encoder/hybrid_fwd_txfm.h"
19 
20 /* 4-point reversible, orthonormal Walsh-Hadamard in 3.5 adds, 0.5 shifts per
21    pixel.
22    Shared for both high and low bit depth.
23  */
av1_fwht4x4_c(const int16_t * input,tran_low_t * output,int stride)24 void av1_fwht4x4_c(const int16_t *input, tran_low_t *output, int stride) {
25   int i;
26   tran_high_t a1, b1, c1, d1, e1;
27   const int16_t *ip_pass0 = input;
28   const tran_low_t *ip = NULL;
29   tran_low_t *op = output;
30 
31   for (i = 0; i < 4; i++) {
32     a1 = ip_pass0[0 * stride];
33     b1 = ip_pass0[1 * stride];
34     c1 = ip_pass0[2 * stride];
35     d1 = ip_pass0[3 * stride];
36 
37     a1 += b1;
38     d1 = d1 - c1;
39     e1 = (a1 - d1) >> 1;
40     b1 = e1 - b1;
41     c1 = e1 - c1;
42     a1 -= c1;
43     d1 += b1;
44     op[0] = (tran_low_t)a1;
45     op[1] = (tran_low_t)c1;
46     op[2] = (tran_low_t)d1;
47     op[3] = (tran_low_t)b1;
48 
49     ip_pass0++;
50     op += 4;
51   }
52   ip = output;
53   op = output;
54 
55   for (i = 0; i < 4; i++) {
56     a1 = ip[4 * 0];
57     b1 = ip[4 * 1];
58     c1 = ip[4 * 2];
59     d1 = ip[4 * 3];
60 
61     a1 += b1;
62     d1 -= c1;
63     e1 = (a1 - d1) >> 1;
64     b1 = e1 - b1;
65     c1 = e1 - c1;
66     a1 -= c1;
67     d1 += b1;
68     op[4 * 0] = (tran_low_t)(a1 * UNIT_QUANT_FACTOR);
69     op[4 * 1] = (tran_low_t)(c1 * UNIT_QUANT_FACTOR);
70     op[4 * 2] = (tran_low_t)(d1 * UNIT_QUANT_FACTOR);
71     op[4 * 3] = (tran_low_t)(b1 * UNIT_QUANT_FACTOR);
72 
73     ip++;
74     op++;
75   }
76 }
77 
highbd_fwd_txfm_4x4(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)78 static void highbd_fwd_txfm_4x4(const int16_t *src_diff, tran_low_t *coeff,
79                                 int diff_stride, TxfmParam *txfm_param) {
80   int32_t *dst_coeff = (int32_t *)coeff;
81   const TX_TYPE tx_type = txfm_param->tx_type;
82   const int bd = txfm_param->bd;
83   if (txfm_param->lossless) {
84     assert(tx_type == DCT_DCT);
85     av1_fwht4x4(src_diff, coeff, diff_stride);
86     return;
87   }
88   av1_fwd_txfm2d_4x4(src_diff, dst_coeff, diff_stride, tx_type, bd);
89 }
90 
highbd_fwd_txfm_4x8(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)91 static void highbd_fwd_txfm_4x8(const int16_t *src_diff, tran_low_t *coeff,
92                                 int diff_stride, TxfmParam *txfm_param) {
93   int32_t *dst_coeff = (int32_t *)coeff;
94   av1_fwd_txfm2d_4x8(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
95                      txfm_param->bd);
96 }
97 
highbd_fwd_txfm_8x4(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)98 static void highbd_fwd_txfm_8x4(const int16_t *src_diff, tran_low_t *coeff,
99                                 int diff_stride, TxfmParam *txfm_param) {
100   int32_t *dst_coeff = (int32_t *)coeff;
101   av1_fwd_txfm2d_8x4(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
102                      txfm_param->bd);
103 }
104 
highbd_fwd_txfm_8x16(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)105 static void highbd_fwd_txfm_8x16(const int16_t *src_diff, tran_low_t *coeff,
106                                  int diff_stride, TxfmParam *txfm_param) {
107   int32_t *dst_coeff = (int32_t *)coeff;
108   const TX_TYPE tx_type = txfm_param->tx_type;
109   const int bd = txfm_param->bd;
110   av1_fwd_txfm2d_8x16(src_diff, dst_coeff, diff_stride, tx_type, bd);
111 }
112 
highbd_fwd_txfm_16x8(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)113 static void highbd_fwd_txfm_16x8(const int16_t *src_diff, tran_low_t *coeff,
114                                  int diff_stride, TxfmParam *txfm_param) {
115   int32_t *dst_coeff = (int32_t *)coeff;
116   const TX_TYPE tx_type = txfm_param->tx_type;
117   const int bd = txfm_param->bd;
118   av1_fwd_txfm2d_16x8(src_diff, dst_coeff, diff_stride, tx_type, bd);
119 }
120 
highbd_fwd_txfm_16x32(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)121 static void highbd_fwd_txfm_16x32(const int16_t *src_diff, tran_low_t *coeff,
122                                   int diff_stride, TxfmParam *txfm_param) {
123   int32_t *dst_coeff = (int32_t *)coeff;
124   av1_fwd_txfm2d_16x32(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
125                        txfm_param->bd);
126 }
127 
highbd_fwd_txfm_32x16(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)128 static void highbd_fwd_txfm_32x16(const int16_t *src_diff, tran_low_t *coeff,
129                                   int diff_stride, TxfmParam *txfm_param) {
130   int32_t *dst_coeff = (int32_t *)coeff;
131   av1_fwd_txfm2d_32x16(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
132                        txfm_param->bd);
133 }
134 
135 #if !CONFIG_REALTIME_ONLY
highbd_fwd_txfm_16x4(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)136 static void highbd_fwd_txfm_16x4(const int16_t *src_diff, tran_low_t *coeff,
137                                  int diff_stride, TxfmParam *txfm_param) {
138   int32_t *dst_coeff = (int32_t *)coeff;
139   av1_fwd_txfm2d_16x4(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
140                       txfm_param->bd);
141 }
142 
highbd_fwd_txfm_4x16(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)143 static void highbd_fwd_txfm_4x16(const int16_t *src_diff, tran_low_t *coeff,
144                                  int diff_stride, TxfmParam *txfm_param) {
145   int32_t *dst_coeff = (int32_t *)coeff;
146   av1_fwd_txfm2d_4x16(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
147                       txfm_param->bd);
148 }
149 
highbd_fwd_txfm_32x8(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)150 static void highbd_fwd_txfm_32x8(const int16_t *src_diff, tran_low_t *coeff,
151                                  int diff_stride, TxfmParam *txfm_param) {
152   int32_t *dst_coeff = (int32_t *)coeff;
153   av1_fwd_txfm2d_32x8(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
154                       txfm_param->bd);
155 }
156 
highbd_fwd_txfm_8x32(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)157 static void highbd_fwd_txfm_8x32(const int16_t *src_diff, tran_low_t *coeff,
158                                  int diff_stride, TxfmParam *txfm_param) {
159   int32_t *dst_coeff = (int32_t *)coeff;
160   av1_fwd_txfm2d_8x32(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
161                       txfm_param->bd);
162 }
163 #endif
164 
highbd_fwd_txfm_8x8(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)165 static void highbd_fwd_txfm_8x8(const int16_t *src_diff, tran_low_t *coeff,
166                                 int diff_stride, TxfmParam *txfm_param) {
167   int32_t *dst_coeff = (int32_t *)coeff;
168   const TX_TYPE tx_type = txfm_param->tx_type;
169   const int bd = txfm_param->bd;
170   av1_fwd_txfm2d_8x8(src_diff, dst_coeff, diff_stride, tx_type, bd);
171 }
172 
highbd_fwd_txfm_16x16(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)173 static void highbd_fwd_txfm_16x16(const int16_t *src_diff, tran_low_t *coeff,
174                                   int diff_stride, TxfmParam *txfm_param) {
175   int32_t *dst_coeff = (int32_t *)coeff;
176   const TX_TYPE tx_type = txfm_param->tx_type;
177   const int bd = txfm_param->bd;
178   av1_fwd_txfm2d_16x16(src_diff, dst_coeff, diff_stride, tx_type, bd);
179 }
180 
highbd_fwd_txfm_32x32(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)181 static void highbd_fwd_txfm_32x32(const int16_t *src_diff, tran_low_t *coeff,
182                                   int diff_stride, TxfmParam *txfm_param) {
183   int32_t *dst_coeff = (int32_t *)coeff;
184   const TX_TYPE tx_type = txfm_param->tx_type;
185   const int bd = txfm_param->bd;
186   av1_fwd_txfm2d_32x32(src_diff, dst_coeff, diff_stride, tx_type, bd);
187 }
188 
highbd_fwd_txfm_32x64(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)189 static void highbd_fwd_txfm_32x64(const int16_t *src_diff, tran_low_t *coeff,
190                                   int diff_stride, TxfmParam *txfm_param) {
191   assert(txfm_param->tx_type == DCT_DCT);
192   int32_t *dst_coeff = (int32_t *)coeff;
193   const int bd = txfm_param->bd;
194   av1_fwd_txfm2d_32x64(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
195                        bd);
196 }
197 
highbd_fwd_txfm_64x32(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)198 static void highbd_fwd_txfm_64x32(const int16_t *src_diff, tran_low_t *coeff,
199                                   int diff_stride, TxfmParam *txfm_param) {
200   assert(txfm_param->tx_type == DCT_DCT);
201   int32_t *dst_coeff = (int32_t *)coeff;
202   const int bd = txfm_param->bd;
203   av1_fwd_txfm2d_64x32(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
204                        bd);
205 }
206 
207 #if !CONFIG_REALTIME_ONLY
highbd_fwd_txfm_16x64(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)208 static void highbd_fwd_txfm_16x64(const int16_t *src_diff, tran_low_t *coeff,
209                                   int diff_stride, TxfmParam *txfm_param) {
210   assert(txfm_param->tx_type == DCT_DCT);
211   int32_t *dst_coeff = (int32_t *)coeff;
212   const int bd = txfm_param->bd;
213   av1_fwd_txfm2d_16x64(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
214 }
215 
highbd_fwd_txfm_64x16(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)216 static void highbd_fwd_txfm_64x16(const int16_t *src_diff, tran_low_t *coeff,
217                                   int diff_stride, TxfmParam *txfm_param) {
218   assert(txfm_param->tx_type == DCT_DCT);
219   int32_t *dst_coeff = (int32_t *)coeff;
220   const int bd = txfm_param->bd;
221   av1_fwd_txfm2d_64x16(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
222 }
223 #endif
224 
highbd_fwd_txfm_64x64(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)225 static void highbd_fwd_txfm_64x64(const int16_t *src_diff, tran_low_t *coeff,
226                                   int diff_stride, TxfmParam *txfm_param) {
227   assert(txfm_param->tx_type == DCT_DCT);
228   int32_t *dst_coeff = (int32_t *)coeff;
229   const int bd = txfm_param->bd;
230   av1_fwd_txfm2d_64x64(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
231 }
232 
av1_fwd_txfm(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)233 void av1_fwd_txfm(const int16_t *src_diff, tran_low_t *coeff, int diff_stride,
234                   TxfmParam *txfm_param) {
235   if (txfm_param->bd == 8)
236     av1_lowbd_fwd_txfm(src_diff, coeff, diff_stride, txfm_param);
237   else
238     av1_highbd_fwd_txfm(src_diff, coeff, diff_stride, txfm_param);
239 }
240 
av1_lowbd_fwd_txfm_c(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)241 void av1_lowbd_fwd_txfm_c(const int16_t *src_diff, tran_low_t *coeff,
242                           int diff_stride, TxfmParam *txfm_param) {
243   av1_highbd_fwd_txfm(src_diff, coeff, diff_stride, txfm_param);
244 }
245 
av1_highbd_fwd_txfm(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)246 void av1_highbd_fwd_txfm(const int16_t *src_diff, tran_low_t *coeff,
247                          int diff_stride, TxfmParam *txfm_param) {
248   assert(av1_ext_tx_used[txfm_param->tx_set_type][txfm_param->tx_type]);
249   const TX_SIZE tx_size = txfm_param->tx_size;
250   switch (tx_size) {
251     case TX_64X64:
252       highbd_fwd_txfm_64x64(src_diff, coeff, diff_stride, txfm_param);
253       break;
254     case TX_32X64:
255       highbd_fwd_txfm_32x64(src_diff, coeff, diff_stride, txfm_param);
256       break;
257     case TX_64X32:
258       highbd_fwd_txfm_64x32(src_diff, coeff, diff_stride, txfm_param);
259       break;
260 
261     case TX_32X32:
262       highbd_fwd_txfm_32x32(src_diff, coeff, diff_stride, txfm_param);
263       break;
264     case TX_16X16:
265       highbd_fwd_txfm_16x16(src_diff, coeff, diff_stride, txfm_param);
266       break;
267     case TX_8X8:
268       highbd_fwd_txfm_8x8(src_diff, coeff, diff_stride, txfm_param);
269       break;
270     case TX_4X8:
271       highbd_fwd_txfm_4x8(src_diff, coeff, diff_stride, txfm_param);
272       break;
273     case TX_8X4:
274       highbd_fwd_txfm_8x4(src_diff, coeff, diff_stride, txfm_param);
275       break;
276     case TX_8X16:
277       highbd_fwd_txfm_8x16(src_diff, coeff, diff_stride, txfm_param);
278       break;
279     case TX_16X8:
280       highbd_fwd_txfm_16x8(src_diff, coeff, diff_stride, txfm_param);
281       break;
282     case TX_16X32:
283       highbd_fwd_txfm_16x32(src_diff, coeff, diff_stride, txfm_param);
284       break;
285     case TX_32X16:
286       highbd_fwd_txfm_32x16(src_diff, coeff, diff_stride, txfm_param);
287       break;
288     case TX_4X4:
289       highbd_fwd_txfm_4x4(src_diff, coeff, diff_stride, txfm_param);
290       break;
291 #if !CONFIG_REALTIME_ONLY
292     case TX_4X16:
293       highbd_fwd_txfm_4x16(src_diff, coeff, diff_stride, txfm_param);
294       break;
295     case TX_16X4:
296       highbd_fwd_txfm_16x4(src_diff, coeff, diff_stride, txfm_param);
297       break;
298     case TX_8X32:
299       highbd_fwd_txfm_8x32(src_diff, coeff, diff_stride, txfm_param);
300       break;
301     case TX_32X8:
302       highbd_fwd_txfm_32x8(src_diff, coeff, diff_stride, txfm_param);
303       break;
304     case TX_16X64:
305       highbd_fwd_txfm_16x64(src_diff, coeff, diff_stride, txfm_param);
306       break;
307     case TX_64X16:
308       highbd_fwd_txfm_64x16(src_diff, coeff, diff_stride, txfm_param);
309       break;
310 #endif
311     default: assert(0); break;
312   }
313 }
314 
315 #if CONFIG_AV1_HIGHBITDEPTH
highbd_wht_fwd_txfm(TX_SIZE tx_size,const int16_t * src_diff,ptrdiff_t src_stride,tran_low_t * coeff)316 static inline void highbd_wht_fwd_txfm(TX_SIZE tx_size, const int16_t *src_diff,
317                                        ptrdiff_t src_stride,
318                                        tran_low_t *coeff) {
319   switch (tx_size) {
320     // As the output transform co-efficients of 4x4 Hadamard transform can be
321     // represented using 15 bits (for 12-bit clip) use lowbd variant of
322     // hadamard_4x4.
323     case TX_4X4: aom_hadamard_4x4(src_diff, src_stride, coeff); break;
324     case TX_8X8: aom_highbd_hadamard_8x8(src_diff, src_stride, coeff); break;
325     case TX_16X16:
326       aom_highbd_hadamard_16x16(src_diff, src_stride, coeff);
327       break;
328     case TX_32X32:
329       aom_highbd_hadamard_32x32(src_diff, src_stride, coeff);
330       break;
331     default: assert(0);
332   }
333 }
334 #endif  // CONFIG_AV1_HIGHBITDEPTH
335 
wht_fwd_txfm(TX_SIZE tx_size,const int16_t * src_diff,ptrdiff_t src_stride,tran_low_t * coeff)336 static inline void wht_fwd_txfm(TX_SIZE tx_size, const int16_t *src_diff,
337                                 ptrdiff_t src_stride, tran_low_t *coeff) {
338   switch (tx_size) {
339     case TX_4X4: aom_hadamard_4x4(src_diff, src_stride, coeff); break;
340     case TX_8X8: aom_hadamard_8x8(src_diff, src_stride, coeff); break;
341     case TX_16X16: aom_hadamard_16x16(src_diff, src_stride, coeff); break;
342     case TX_32X32: aom_hadamard_32x32(src_diff, src_stride, coeff); break;
343     default: assert(0);
344   }
345 }
346 
av1_quick_txfm(int use_hadamard,TX_SIZE tx_size,BitDepthInfo bd_info,const int16_t * src_diff,int src_stride,tran_low_t * coeff)347 void av1_quick_txfm(int use_hadamard, TX_SIZE tx_size, BitDepthInfo bd_info,
348                     const int16_t *src_diff, int src_stride,
349                     tran_low_t *coeff) {
350   if (use_hadamard) {
351 #if CONFIG_AV1_HIGHBITDEPTH
352     if (bd_info.use_highbitdepth_buf) {
353       highbd_wht_fwd_txfm(tx_size, src_diff, src_stride, coeff);
354     } else {
355       wht_fwd_txfm(tx_size, src_diff, src_stride, coeff);
356     }
357 #else
358     wht_fwd_txfm(tx_size, src_diff, src_stride, coeff);
359 #endif  // CONFIG_AV1_HIGHBITDEPTH
360   } else {
361     TxfmParam txfm_param;
362     txfm_param.tx_type = DCT_DCT;
363     txfm_param.tx_size = tx_size;
364     txfm_param.lossless = 0;
365     txfm_param.bd = bd_info.bit_depth;
366     txfm_param.is_hbd = bd_info.use_highbitdepth_buf;
367     txfm_param.tx_set_type = EXT_TX_SET_ALL16;
368     av1_fwd_txfm(src_diff, coeff, src_stride, &txfm_param);
369   }
370 }
371