| /* | |
| * Copyright (c) 2017, Alliance for Open Media. All rights reserved | |
| * | |
| * This source code is subject to the terms of the BSD 2 Clause License and | |
| * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License | |
| * was not distributed with this source code in the LICENSE file, you can | |
| * obtain it at www.aomedia.org/license/software. If the Alliance for Open | |
| * Media Patent License 1.0 was not distributed with this source code in the | |
| * PATENTS file, you can obtain it at www.aomedia.org/license/patent. | |
| */ | |
| #include "./av1_rtcd.h" | |
| #include "./aom_config.h" | |
| #include "./aom_dsp_rtcd.h" | |
| #include "av1/common/daala_tx.h" | |
| #include "av1/common/daala_inv_txfm.h" | |
| #include "av1/common/idct.h" | |
| #if CONFIG_DAALA_TX | |
| // Complete Daala TX map, sans lossless which is special cased | |
| typedef void (*daala_itx)(od_coeff *, int, const od_coeff[]); | |
| static daala_itx tx_map[TX_SIZES][TX_TYPES] = { | |
| // 4-point transforms | |
| { od_bin_idct4, od_bin_idst4, od_bin_idst4, od_bin_iidtx4 }, | |
| // 8-point transforms | |
| { od_bin_idct8, od_bin_idst8, od_bin_idst8, od_bin_iidtx8 }, | |
| // 16-point transforms | |
| { od_bin_idct16, od_bin_idst16, od_bin_idst16, od_bin_iidtx16 }, | |
| // 32-point transforms | |
| { od_bin_idct32, od_bin_idst32, od_bin_idst32, od_bin_iidtx32 }, | |
| #if CONFIG_TX64X64 | |
| // 64-point transforms | |
| { od_bin_idct64, NULL, NULL, od_bin_iidtx64 }, | |
| #endif | |
| }; | |
| static int tx_flip(TX_TYPE_1D t) { return t == FLIPADST_1D; } | |
| // Daala TX toplevel inverse entry point. This same function is | |
| // intended for both low and high bitdepth cases with a tran_low_t of | |
| // 32 bits (matching od_coeff), and a passed-in pixel buffer of either | |
| // bytes (hbd=0) or shorts (hbd=1). | |
| void daala_inv_txfm_add_c(const tran_low_t *input_coeffs, void *output_pixels, | |
| int output_stride, TxfmParam *txfm_param) { | |
| const TX_SIZE tx_size = txfm_param->tx_size; | |
| const TX_TYPE tx_type = txfm_param->tx_type; | |
| const int px_depth = txfm_param->bd; | |
| assert(tx_size <= TX_SIZES_ALL); | |
| assert(tx_type <= TX_TYPES); | |
| if (txfm_param->lossless) { | |
| // Transform function special-cased for lossless | |
| assert(tx_type == DCT_DCT); | |
| assert(tx_size == TX_4X4); | |
| if (txfm_param->is_hbd) | |
| // Note that the output pointer in the prototype is uint8, but the | |
| // function converts to short internally | |
| av1_highbd_iwht4x4_add(input_coeffs, output_pixels, output_stride, | |
| txfm_param->eob, px_depth); | |
| else | |
| av1_iwht4x4_add(input_coeffs, output_pixels, output_stride, txfm_param); | |
| } else { | |
| // General TX case | |
| const int downshift = TX_COEFF_DEPTH - px_depth; | |
| assert(downshift >= 0); | |
| assert(sizeof(tran_low_t) == sizeof(od_coeff)); | |
| assert(sizeof(tran_low_t) >= 4); | |
| // Hook into existing map translation infrastructure to select | |
| // appropriate TX functions | |
| const int cols = tx_size_wide[tx_size]; | |
| const int rows = tx_size_high[tx_size]; | |
| const TX_SIZE col_idx = txsize_vert_map[tx_size]; | |
| const TX_SIZE row_idx = txsize_horz_map[tx_size]; | |
| assert(col_idx <= TX_SIZES); | |
| assert(row_idx <= TX_SIZES); | |
| assert(vtx_tab[tx_type] <= (int)TX_TYPES_1D); | |
| assert(htx_tab[tx_type] <= (int)TX_TYPES_1D); | |
| daala_itx col_tx = tx_map[col_idx][vtx_tab[tx_type]]; | |
| daala_itx row_tx = tx_map[row_idx][htx_tab[tx_type]]; | |
| int col_flip = tx_flip(vtx_tab[tx_type]); | |
| int row_flip = tx_flip(htx_tab[tx_type]); | |
| od_coeff tmpsq[MAX_TX_SQUARE]; | |
| int r; | |
| int c; | |
| assert(col_tx); | |
| assert(row_tx); | |
| // Inverse-transform rows | |
| for (r = 0; r < rows; ++r) { | |
| // The output addressing transposes | |
| if (row_flip) | |
| row_tx(tmpsq + r + (rows * cols) - rows, -rows, | |
| input_coeffs + r * cols); | |
| else | |
| row_tx(tmpsq + r, rows, input_coeffs + r * cols); | |
| } | |
| // Inverse-transform columns | |
| for (c = 0; c < cols; ++c) { | |
| // Above transposed, so our cols are now rows | |
| if (col_flip) | |
| col_tx(tmpsq + c * rows + rows - 1, -1, tmpsq + c * rows); | |
| else | |
| col_tx(tmpsq + c * rows, 1, tmpsq + c * rows); | |
| } | |
| // Sum with destination according to bit depth | |
| // The tmpsq array is currently transposed relative to output | |
| if (txfm_param->is_hbd) { | |
| // Destination array is shorts | |
| uint16_t *out16 = CONVERT_TO_SHORTPTR(output_pixels); | |
| for (r = 0; r < rows; ++r) | |
| for (c = 0; c < cols; ++c) | |
| out16[r * output_stride + c] = highbd_clip_pixel_add( | |
| out16[r * output_stride + c], | |
| (tmpsq[c * rows + r] + (1 << downshift >> 1)) >> downshift, | |
| px_depth); | |
| } else { | |
| // Destination array is bytes | |
| uint8_t *out8 = (uint8_t *)output_pixels; | |
| for (r = 0; r < rows; ++r) | |
| for (c = 0; c < cols; ++c) | |
| out8[r * output_stride + c] = clip_pixel_add( | |
| out8[r * output_stride + c], | |
| (tmpsq[c * rows + r] + (1 << downshift >> 1)) >> downshift); | |
| } | |
| } | |
| } | |
| #endif |