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. */
av1_fwht4x4_c(const int16_t * input,tran_low_t * output,int stride)22 void av1_fwht4x4_c(const int16_t *input, tran_low_t *output, int stride) {
23 int i;
24 tran_high_t a1, b1, c1, d1, e1;
25 const int16_t *ip_pass0 = input;
26 const tran_low_t *ip = NULL;
27 tran_low_t *op = output;
28
29 for (i = 0; i < 4; i++) {
30 a1 = ip_pass0[0 * stride];
31 b1 = ip_pass0[1 * stride];
32 c1 = ip_pass0[2 * stride];
33 d1 = ip_pass0[3 * stride];
34
35 a1 += b1;
36 d1 = d1 - c1;
37 e1 = (a1 - d1) >> 1;
38 b1 = e1 - b1;
39 c1 = e1 - c1;
40 a1 -= c1;
41 d1 += b1;
42 op[0] = (tran_low_t)a1;
43 op[4] = (tran_low_t)c1;
44 op[8] = (tran_low_t)d1;
45 op[12] = (tran_low_t)b1;
46
47 ip_pass0++;
48 op++;
49 }
50 ip = output;
51 op = output;
52
53 for (i = 0; i < 4; i++) {
54 a1 = ip[0];
55 b1 = ip[1];
56 c1 = ip[2];
57 d1 = ip[3];
58
59 a1 += b1;
60 d1 -= c1;
61 e1 = (a1 - d1) >> 1;
62 b1 = e1 - b1;
63 c1 = e1 - c1;
64 a1 -= c1;
65 d1 += b1;
66 op[0] = (tran_low_t)(a1 * UNIT_QUANT_FACTOR);
67 op[1] = (tran_low_t)(c1 * UNIT_QUANT_FACTOR);
68 op[2] = (tran_low_t)(d1 * UNIT_QUANT_FACTOR);
69 op[3] = (tran_low_t)(b1 * UNIT_QUANT_FACTOR);
70
71 ip += 4;
72 op += 4;
73 }
74 }
75
av1_highbd_fwht4x4_c(const int16_t * input,tran_low_t * output,int stride)76 void av1_highbd_fwht4x4_c(const int16_t *input, tran_low_t *output,
77 int stride) {
78 av1_fwht4x4_c(input, output, stride);
79 }
80
highbd_fwd_txfm_4x4(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)81 static void highbd_fwd_txfm_4x4(const int16_t *src_diff, tran_low_t *coeff,
82 int diff_stride, TxfmParam *txfm_param) {
83 int32_t *dst_coeff = (int32_t *)coeff;
84 const TX_TYPE tx_type = txfm_param->tx_type;
85 const int bd = txfm_param->bd;
86 if (txfm_param->lossless) {
87 assert(tx_type == DCT_DCT);
88 av1_highbd_fwht4x4(src_diff, coeff, diff_stride);
89 return;
90 }
91 av1_fwd_txfm2d_4x4(src_diff, dst_coeff, diff_stride, tx_type, bd);
92 }
93
highbd_fwd_txfm_4x8(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)94 static void highbd_fwd_txfm_4x8(const int16_t *src_diff, tran_low_t *coeff,
95 int diff_stride, TxfmParam *txfm_param) {
96 int32_t *dst_coeff = (int32_t *)coeff;
97 av1_fwd_txfm2d_4x8(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
98 txfm_param->bd);
99 }
100
highbd_fwd_txfm_8x4(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)101 static void highbd_fwd_txfm_8x4(const int16_t *src_diff, tran_low_t *coeff,
102 int diff_stride, TxfmParam *txfm_param) {
103 int32_t *dst_coeff = (int32_t *)coeff;
104 av1_fwd_txfm2d_8x4(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
105 txfm_param->bd);
106 }
107
highbd_fwd_txfm_8x16(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)108 static void highbd_fwd_txfm_8x16(const int16_t *src_diff, tran_low_t *coeff,
109 int diff_stride, TxfmParam *txfm_param) {
110 int32_t *dst_coeff = (int32_t *)coeff;
111 const TX_TYPE tx_type = txfm_param->tx_type;
112 const int bd = txfm_param->bd;
113 av1_fwd_txfm2d_8x16(src_diff, dst_coeff, diff_stride, tx_type, bd);
114 }
115
highbd_fwd_txfm_16x8(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)116 static void highbd_fwd_txfm_16x8(const int16_t *src_diff, tran_low_t *coeff,
117 int diff_stride, TxfmParam *txfm_param) {
118 int32_t *dst_coeff = (int32_t *)coeff;
119 const TX_TYPE tx_type = txfm_param->tx_type;
120 const int bd = txfm_param->bd;
121 av1_fwd_txfm2d_16x8(src_diff, dst_coeff, diff_stride, tx_type, bd);
122 }
123
highbd_fwd_txfm_16x32(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)124 static void highbd_fwd_txfm_16x32(const int16_t *src_diff, tran_low_t *coeff,
125 int diff_stride, TxfmParam *txfm_param) {
126 int32_t *dst_coeff = (int32_t *)coeff;
127 av1_fwd_txfm2d_16x32(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
128 txfm_param->bd);
129 }
130
highbd_fwd_txfm_32x16(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)131 static void highbd_fwd_txfm_32x16(const int16_t *src_diff, tran_low_t *coeff,
132 int diff_stride, TxfmParam *txfm_param) {
133 int32_t *dst_coeff = (int32_t *)coeff;
134 av1_fwd_txfm2d_32x16(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
135 txfm_param->bd);
136 }
137
138 #if !CONFIG_REALTIME_ONLY
highbd_fwd_txfm_16x4(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)139 static void highbd_fwd_txfm_16x4(const int16_t *src_diff, tran_low_t *coeff,
140 int diff_stride, TxfmParam *txfm_param) {
141 int32_t *dst_coeff = (int32_t *)coeff;
142 av1_fwd_txfm2d_16x4(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
143 txfm_param->bd);
144 }
145
highbd_fwd_txfm_4x16(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)146 static void highbd_fwd_txfm_4x16(const int16_t *src_diff, tran_low_t *coeff,
147 int diff_stride, TxfmParam *txfm_param) {
148 int32_t *dst_coeff = (int32_t *)coeff;
149 av1_fwd_txfm2d_4x16(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
150 txfm_param->bd);
151 }
152
highbd_fwd_txfm_32x8(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)153 static void highbd_fwd_txfm_32x8(const int16_t *src_diff, tran_low_t *coeff,
154 int diff_stride, TxfmParam *txfm_param) {
155 int32_t *dst_coeff = (int32_t *)coeff;
156 av1_fwd_txfm2d_32x8(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
157 txfm_param->bd);
158 }
159
highbd_fwd_txfm_8x32(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)160 static void highbd_fwd_txfm_8x32(const int16_t *src_diff, tran_low_t *coeff,
161 int diff_stride, TxfmParam *txfm_param) {
162 int32_t *dst_coeff = (int32_t *)coeff;
163 av1_fwd_txfm2d_8x32(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
164 txfm_param->bd);
165 }
166 #endif
167
highbd_fwd_txfm_8x8(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)168 static void highbd_fwd_txfm_8x8(const int16_t *src_diff, tran_low_t *coeff,
169 int diff_stride, TxfmParam *txfm_param) {
170 int32_t *dst_coeff = (int32_t *)coeff;
171 const TX_TYPE tx_type = txfm_param->tx_type;
172 const int bd = txfm_param->bd;
173 av1_fwd_txfm2d_8x8(src_diff, dst_coeff, diff_stride, tx_type, bd);
174 }
175
highbd_fwd_txfm_16x16(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)176 static void highbd_fwd_txfm_16x16(const int16_t *src_diff, tran_low_t *coeff,
177 int diff_stride, TxfmParam *txfm_param) {
178 int32_t *dst_coeff = (int32_t *)coeff;
179 const TX_TYPE tx_type = txfm_param->tx_type;
180 const int bd = txfm_param->bd;
181 av1_fwd_txfm2d_16x16(src_diff, dst_coeff, diff_stride, tx_type, bd);
182 }
183
highbd_fwd_txfm_32x32(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)184 static void highbd_fwd_txfm_32x32(const int16_t *src_diff, tran_low_t *coeff,
185 int diff_stride, TxfmParam *txfm_param) {
186 int32_t *dst_coeff = (int32_t *)coeff;
187 const TX_TYPE tx_type = txfm_param->tx_type;
188 const int bd = txfm_param->bd;
189 av1_fwd_txfm2d_32x32(src_diff, dst_coeff, diff_stride, tx_type, bd);
190 }
191
highbd_fwd_txfm_32x64(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)192 static void highbd_fwd_txfm_32x64(const int16_t *src_diff, tran_low_t *coeff,
193 int diff_stride, TxfmParam *txfm_param) {
194 assert(txfm_param->tx_type == DCT_DCT);
195 int32_t *dst_coeff = (int32_t *)coeff;
196 const int bd = txfm_param->bd;
197 av1_fwd_txfm2d_32x64(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
198 bd);
199 }
200
highbd_fwd_txfm_64x32(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)201 static void highbd_fwd_txfm_64x32(const int16_t *src_diff, tran_low_t *coeff,
202 int diff_stride, TxfmParam *txfm_param) {
203 assert(txfm_param->tx_type == DCT_DCT);
204 int32_t *dst_coeff = (int32_t *)coeff;
205 const int bd = txfm_param->bd;
206 av1_fwd_txfm2d_64x32(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
207 bd);
208 }
209
210 #if !CONFIG_REALTIME_ONLY
highbd_fwd_txfm_16x64(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)211 static void highbd_fwd_txfm_16x64(const int16_t *src_diff, tran_low_t *coeff,
212 int diff_stride, TxfmParam *txfm_param) {
213 assert(txfm_param->tx_type == DCT_DCT);
214 int32_t *dst_coeff = (int32_t *)coeff;
215 const int bd = txfm_param->bd;
216 av1_fwd_txfm2d_16x64(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
217 }
218
highbd_fwd_txfm_64x16(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)219 static void highbd_fwd_txfm_64x16(const int16_t *src_diff, tran_low_t *coeff,
220 int diff_stride, TxfmParam *txfm_param) {
221 assert(txfm_param->tx_type == DCT_DCT);
222 int32_t *dst_coeff = (int32_t *)coeff;
223 const int bd = txfm_param->bd;
224 av1_fwd_txfm2d_64x16(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
225 }
226 #endif
227
highbd_fwd_txfm_64x64(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)228 static void highbd_fwd_txfm_64x64(const int16_t *src_diff, tran_low_t *coeff,
229 int diff_stride, TxfmParam *txfm_param) {
230 assert(txfm_param->tx_type == DCT_DCT);
231 int32_t *dst_coeff = (int32_t *)coeff;
232 const int bd = txfm_param->bd;
233 av1_fwd_txfm2d_64x64(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
234 }
235
av1_fwd_txfm(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)236 void av1_fwd_txfm(const int16_t *src_diff, tran_low_t *coeff, int diff_stride,
237 TxfmParam *txfm_param) {
238 if (txfm_param->bd == 8)
239 av1_lowbd_fwd_txfm(src_diff, coeff, diff_stride, txfm_param);
240 else
241 av1_highbd_fwd_txfm(src_diff, coeff, diff_stride, txfm_param);
242 }
243
av1_lowbd_fwd_txfm_c(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)244 void av1_lowbd_fwd_txfm_c(const int16_t *src_diff, tran_low_t *coeff,
245 int diff_stride, TxfmParam *txfm_param) {
246 av1_highbd_fwd_txfm(src_diff, coeff, diff_stride, txfm_param);
247 }
248
av1_highbd_fwd_txfm(const int16_t * src_diff,tran_low_t * coeff,int diff_stride,TxfmParam * txfm_param)249 void av1_highbd_fwd_txfm(const int16_t *src_diff, tran_low_t *coeff,
250 int diff_stride, TxfmParam *txfm_param) {
251 assert(av1_ext_tx_used[txfm_param->tx_set_type][txfm_param->tx_type]);
252 const TX_SIZE tx_size = txfm_param->tx_size;
253 switch (tx_size) {
254 case TX_64X64:
255 highbd_fwd_txfm_64x64(src_diff, coeff, diff_stride, txfm_param);
256 break;
257 case TX_32X64:
258 highbd_fwd_txfm_32x64(src_diff, coeff, diff_stride, txfm_param);
259 break;
260 case TX_64X32:
261 highbd_fwd_txfm_64x32(src_diff, coeff, diff_stride, txfm_param);
262 break;
263
264 case TX_32X32:
265 highbd_fwd_txfm_32x32(src_diff, coeff, diff_stride, txfm_param);
266 break;
267 case TX_16X16:
268 highbd_fwd_txfm_16x16(src_diff, coeff, diff_stride, txfm_param);
269 break;
270 case TX_8X8:
271 highbd_fwd_txfm_8x8(src_diff, coeff, diff_stride, txfm_param);
272 break;
273 case TX_4X8:
274 highbd_fwd_txfm_4x8(src_diff, coeff, diff_stride, txfm_param);
275 break;
276 case TX_8X4:
277 highbd_fwd_txfm_8x4(src_diff, coeff, diff_stride, txfm_param);
278 break;
279 case TX_8X16:
280 highbd_fwd_txfm_8x16(src_diff, coeff, diff_stride, txfm_param);
281 break;
282 case TX_16X8:
283 highbd_fwd_txfm_16x8(src_diff, coeff, diff_stride, txfm_param);
284 break;
285 case TX_16X32:
286 highbd_fwd_txfm_16x32(src_diff, coeff, diff_stride, txfm_param);
287 break;
288 case TX_32X16:
289 highbd_fwd_txfm_32x16(src_diff, coeff, diff_stride, txfm_param);
290 break;
291 case TX_4X4:
292 highbd_fwd_txfm_4x4(src_diff, coeff, diff_stride, txfm_param);
293 break;
294 #if !CONFIG_REALTIME_ONLY
295 case TX_4X16:
296 highbd_fwd_txfm_4x16(src_diff, coeff, diff_stride, txfm_param);
297 break;
298 case TX_16X4:
299 highbd_fwd_txfm_16x4(src_diff, coeff, diff_stride, txfm_param);
300 break;
301 case TX_8X32:
302 highbd_fwd_txfm_8x32(src_diff, coeff, diff_stride, txfm_param);
303 break;
304 case TX_32X8:
305 highbd_fwd_txfm_32x8(src_diff, coeff, diff_stride, txfm_param);
306 break;
307 case TX_16X64:
308 highbd_fwd_txfm_16x64(src_diff, coeff, diff_stride, txfm_param);
309 break;
310 case TX_64X16:
311 highbd_fwd_txfm_64x16(src_diff, coeff, diff_stride, txfm_param);
312 break;
313 #endif
314 default: assert(0); break;
315 }
316 }
317
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)318 void av1_quick_txfm(int use_hadamard, TX_SIZE tx_size, BitDepthInfo bd_info,
319 const int16_t *src_diff, int src_stride,
320 tran_low_t *coeff) {
321 if (use_hadamard) {
322 switch (tx_size) {
323 case TX_4X4: aom_hadamard_4x4(src_diff, src_stride, coeff); break;
324 case TX_8X8: aom_hadamard_8x8(src_diff, src_stride, coeff); break;
325 case TX_16X16: aom_hadamard_16x16(src_diff, src_stride, coeff); break;
326 case TX_32X32: aom_hadamard_32x32(src_diff, src_stride, coeff); break;
327 default: assert(0);
328 }
329 } else {
330 TxfmParam txfm_param;
331 txfm_param.tx_type = DCT_DCT;
332 txfm_param.tx_size = tx_size;
333 txfm_param.lossless = 0;
334 txfm_param.bd = bd_info.bit_depth;
335 txfm_param.is_hbd = bd_info.use_highbitdepth_buf;
336 txfm_param.tx_set_type = EXT_TX_SET_ALL16;
337 av1_fwd_txfm(src_diff, coeff, src_stride, &txfm_param);
338 }
339 }
340