blob: 6b75cf6b687d2ab33c76fc11c04ff36707c4f4b3 [file] [log] [blame]
/*
* 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