blob: 37be8cd082a5f2bc89adb0240ab8d3202bac35d8 [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/encoder/daala_fwd_txfm.h"
#if CONFIG_DAALA_TX
// Temporary while we still need av1_get_tx_scale() for testing
#include "av1/common/idct.h"
// Complete Daala TX map, sans lossless which is special cased
typedef void (*daala_ftx)(od_coeff[], const od_coeff *, int);
static daala_ftx tx_map[TX_SIZES][TX_TYPES_1D] = {
// 4-point transforms
{ od_bin_fdct4, od_bin_fdst4, od_bin_fdst4, od_bin_fidtx4 },
// 8-point transforms
{ od_bin_fdct8, od_bin_fdst8, od_bin_fdst8, od_bin_fidtx8 },
// 16-point transforms
{ od_bin_fdct16, od_bin_fdst16, od_bin_fdst16, od_bin_fidtx16 },
// 32-point transforms
{ od_bin_fdct32, od_bin_fdst32, od_bin_fdst32, od_bin_fidtx32 },
#if CONFIG_TX64X64
// 64-point transforms
{ od_bin_fdct64, NULL, NULL, od_bin_fidtx64 },
#endif
};
static int tx_flip(TX_TYPE_1D t) { return t == 2; }
// Daala TX toplevel entry point, same interface as av1 low-bidepth
// and high-bitdepth TX (av1_fwd_txfm and av1_highbd_fwd_txfm). This
// same function is intended for both low and high bitdepth cases with
// a tran_low_t of 32 bits (matching od_coeff).
void daala_fwd_txfm(const int16_t *input_pixels, tran_low_t *output_coeffs,
int input_stride, TxfmParam *txfm_param) {
const TX_SIZE tx_size = txfm_param->tx_size;
const TX_TYPE tx_type = txfm_param->tx_type;
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);
av1_fwht4x4(input_pixels, output_coeffs, input_stride);
} else {
// General TX case
// up 4, down 1 compatability mode with av1_get_tx_scale
const int upshift = 4;
assert(upshift >= 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_ftx col_tx = tx_map[col_idx][vtx_tab[tx_type]];
daala_ftx 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 tmp[MAX_TX_SIZE];
int r;
int c;
assert(col_tx);
assert(row_tx);
// Transform columns
for (c = 0; c < cols; ++c) {
// Cast and shift
for (r = 0; r < rows; ++r)
tmp[r] =
((od_coeff)(input_pixels[r * input_stride + c])) * (1 << upshift);
if (col_flip)
col_tx(tmp, tmp + (rows - 1), -1);
else
col_tx(tmp, tmp, 1);
// No ystride in daala_tx lowlevel functions, store output vector
// into column the long way
for (r = 0; r < rows; ++r) output_coeffs[r * cols + c] = tmp[r];
}
// Transform rows
for (r = 0; r < rows; ++r) {
if (row_flip)
row_tx(output_coeffs + r * cols, output_coeffs + r * cols + cols - 1,
-1);
else
row_tx(output_coeffs + r * cols, output_coeffs + r * cols, 1);
}
// This is temporary while we're testing against existing
// behavior (preshift up 4, then downshift by one plus av1_get_tx_scale)
int downshift = 1 + av1_get_tx_scale(tx_size);
for (r = 0; r < rows; ++r)
for (c = 0; c < cols; ++c)
output_coeffs[r * cols + c] =
ROUND_POWER_OF_TWO_SIGNED(output_coeffs[r * cols + c], downshift);
}
}
#endif