hybrid_fwd_txfm.c (13490B)
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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 }