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