2016-04-20 04:23:17 +03:00
|
|
|
/*
|
2016-11-29 02:26:06 +03:00
|
|
|
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
2016-04-20 04:23:17 +03:00
|
|
|
*
|
2016-11-29 02:26:06 +03:00
|
|
|
* 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.
|
2016-04-20 04:23:17 +03:00
|
|
|
*/
|
|
|
|
|
2016-08-31 00:01:10 +03:00
|
|
|
#include "./av1_rtcd.h"
|
2016-08-23 02:08:15 +03:00
|
|
|
#include "av1/common/enums.h"
|
2016-08-31 00:01:10 +03:00
|
|
|
#include "av1/common/av1_txfm.h"
|
|
|
|
#include "av1/common/x86/av1_txfm1d_sse4.h"
|
2016-03-23 05:14:12 +03:00
|
|
|
|
2016-05-06 04:28:04 +03:00
|
|
|
static INLINE void int16_array_with_stride_to_int32_array_without_stride(
|
2016-03-23 05:14:12 +03:00
|
|
|
const int16_t *input, int stride, int32_t *output, int txfm1d_size) {
|
|
|
|
int r, c;
|
|
|
|
for (r = 0; r < txfm1d_size; r++) {
|
|
|
|
for (c = 0; c < txfm1d_size; c++) {
|
|
|
|
output[r * txfm1d_size + c] = (int32_t)input[r * stride + c];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef void (*TxfmFuncSSE2)(const __m128i *input, __m128i *output,
|
|
|
|
const int8_t *cos_bit, const int8_t *stage_range);
|
|
|
|
|
2016-05-06 04:28:04 +03:00
|
|
|
static INLINE TxfmFuncSSE2 fwd_txfm_type_to_func(TXFM_TYPE txfm_type) {
|
2016-03-23 05:14:12 +03:00
|
|
|
switch (txfm_type) {
|
2016-08-31 00:01:10 +03:00
|
|
|
case TXFM_TYPE_DCT32: return av1_fdct32_new_sse4_1; break;
|
|
|
|
case TXFM_TYPE_ADST32: return av1_fadst32_new_sse4_1; break;
|
2016-08-12 04:55:00 +03:00
|
|
|
default: assert(0);
|
2016-03-23 05:14:12 +03:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-05-06 04:28:04 +03:00
|
|
|
static INLINE void fwd_txfm2d_sse4_1(const int16_t *input, int32_t *output,
|
2017-05-16 06:49:22 +03:00
|
|
|
const int stride,
|
|
|
|
const TXFM_2D_FLIP_CFG *cfg,
|
2016-04-20 04:23:17 +03:00
|
|
|
int32_t *txfm_buf) {
|
2017-05-20 02:51:07 +03:00
|
|
|
// TODO(sarahparker) This does not currently support rectangular transforms
|
|
|
|
// and will break without splitting txfm_size out into row and col size.
|
|
|
|
// Rectangular transforms use c code only, so it should be ok for now.
|
|
|
|
// It will be corrected when there are sse implementations for rectangular
|
|
|
|
// transforms.
|
2017-06-13 00:02:33 +03:00
|
|
|
assert(cfg->row_cfg->txfm_size == cfg->col_cfg->txfm_size);
|
2017-05-16 06:49:22 +03:00
|
|
|
const int txfm_size = cfg->row_cfg->txfm_size;
|
|
|
|
const int8_t *shift = cfg->row_cfg->shift;
|
|
|
|
const int8_t *stage_range_col = cfg->col_cfg->stage_range;
|
|
|
|
const int8_t *stage_range_row = cfg->row_cfg->stage_range;
|
|
|
|
const int8_t *cos_bit_col = cfg->col_cfg->cos_bit;
|
|
|
|
const int8_t *cos_bit_row = cfg->row_cfg->cos_bit;
|
|
|
|
const TxfmFuncSSE2 txfm_func_col =
|
|
|
|
fwd_txfm_type_to_func(cfg->col_cfg->txfm_type);
|
|
|
|
const TxfmFuncSSE2 txfm_func_row =
|
|
|
|
fwd_txfm_type_to_func(cfg->row_cfg->txfm_type);
|
2016-03-23 05:14:12 +03:00
|
|
|
|
|
|
|
__m128i *buf_128 = (__m128i *)txfm_buf;
|
|
|
|
__m128i *out_128 = (__m128i *)output;
|
|
|
|
int num_per_128 = 4;
|
|
|
|
int txfm2d_size_128 = txfm_size * txfm_size / num_per_128;
|
|
|
|
|
|
|
|
int16_array_with_stride_to_int32_array_without_stride(input, stride, txfm_buf,
|
|
|
|
txfm_size);
|
2016-03-25 01:34:27 +03:00
|
|
|
round_shift_array_32_sse4_1(buf_128, out_128, txfm2d_size_128, -shift[0]);
|
2016-03-23 05:14:12 +03:00
|
|
|
txfm_func_col(out_128, buf_128, cos_bit_col, stage_range_col);
|
2016-03-25 01:34:27 +03:00
|
|
|
round_shift_array_32_sse4_1(buf_128, out_128, txfm2d_size_128, -shift[1]);
|
2016-03-23 05:14:12 +03:00
|
|
|
transpose_32(txfm_size, out_128, buf_128);
|
|
|
|
txfm_func_row(buf_128, out_128, cos_bit_row, stage_range_row);
|
2016-03-25 01:34:27 +03:00
|
|
|
round_shift_array_32_sse4_1(out_128, buf_128, txfm2d_size_128, -shift[2]);
|
2016-03-23 05:14:12 +03:00
|
|
|
transpose_32(txfm_size, buf_128, out_128);
|
|
|
|
}
|
|
|
|
|
2016-08-31 00:01:10 +03:00
|
|
|
void av1_fwd_txfm2d_32x32_sse4_1(const int16_t *input, int32_t *output,
|
|
|
|
int stride, int tx_type, int bd) {
|
2016-12-14 22:50:56 +03:00
|
|
|
DECLARE_ALIGNED(16, int32_t, txfm_buf[1024]);
|
2016-08-31 00:01:10 +03:00
|
|
|
TXFM_2D_FLIP_CFG cfg = av1_get_fwd_txfm_cfg(tx_type, TX_32X32);
|
2016-03-23 05:14:12 +03:00
|
|
|
(void)bd;
|
2017-05-16 06:49:22 +03:00
|
|
|
fwd_txfm2d_sse4_1(input, output, stride, &cfg, txfm_buf);
|
2016-03-23 05:14:12 +03:00
|
|
|
}
|
|
|
|
|
2016-08-31 00:01:10 +03:00
|
|
|
void av1_fwd_txfm2d_64x64_sse4_1(const int16_t *input, int32_t *output,
|
|
|
|
int stride, int tx_type, int bd) {
|
2016-12-14 22:50:56 +03:00
|
|
|
DECLARE_ALIGNED(16, int32_t, txfm_buf[4096]);
|
2016-08-31 00:01:10 +03:00
|
|
|
TXFM_2D_FLIP_CFG cfg = av1_get_fwd_txfm_64x64_cfg(tx_type);
|
2016-03-23 05:14:12 +03:00
|
|
|
(void)bd;
|
2017-05-16 06:49:22 +03:00
|
|
|
fwd_txfm2d_sse4_1(input, output, stride, &cfg, txfm_buf);
|
2016-03-23 05:14:12 +03:00
|
|
|
}
|