blob: caab8e1543ceea614ef123b5663a74592c1d217b [file] [log] [blame]
Yaowu Xuc27fc142016-08-22 16:08:15 -07001/*
Yaowu Xubde4ac82016-11-28 15:26:06 -08002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Yaowu Xuc27fc142016-08-22 16:08:15 -07003 *
Yaowu Xubde4ac82016-11-28 15:26:06 -08004 * 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.
Yaowu Xuc27fc142016-08-22 16:08:15 -070010 */
Yaowu Xubde4ac82016-11-28 15:26:06 -080011
Yaowu Xuf883b422016-08-30 14:01:10 -070012#ifndef AV1_TXFM_H_
13#define AV1_TXFM_H_
Yaowu Xuc27fc142016-08-22 16:08:15 -070014
15#include <assert.h>
16#include <math.h>
17#include <stdio.h>
18
Tom Finegan60e653d2018-05-22 11:34:58 -070019#include "config/aom_config.h"
20
Yaowu Xuc27fc142016-08-22 16:08:15 -070021#include "av1/common/enums.h"
Angie Chiang155bf9a2017-08-06 19:52:57 -070022#include "av1/common/blockd.h"
Yaowu Xuf883b422016-08-30 14:01:10 -070023#include "aom/aom_integer.h"
24#include "aom_dsp/aom_dsp_common.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070025
Angie Chiang9c7089a2017-08-08 16:21:11 -070026#ifdef __cplusplus
27extern "C" {
28#endif
29
Hui Su8d950192018-04-27 15:47:23 -070030#if !defined(DO_RANGE_CHECK_CLAMP)
31#define DO_RANGE_CHECK_CLAMP 0
32#endif
33
Yue Chen5b53ea12018-03-09 11:26:43 -080034extern const int32_t av1_cospi_arr_data[7][64];
35extern const int32_t av1_sinpi_arr_data[7][5];
36
Angie Chiangce3ad282017-08-08 09:51:54 -070037#define MAX_TXFM_STAGE_NUM 12
38
Yaowu Xuc27fc142016-08-22 16:08:15 -070039static const int cos_bit_min = 10;
40static const int cos_bit_max = 16;
41
Angie Chiangc8d6c082018-02-06 14:26:55 -080042static const int NewSqrt2Bits = 12;
43// 2^12 * sqrt(2)
44static const int32_t NewSqrt2 = 5793;
45// 2^12 / sqrt(2)
46static const int32_t NewInvSqrt2 = 2896;
47
Frederic Barbierbbf7bb02017-05-05 09:37:40 +020048static INLINE const int32_t *cospi_arr(int n) {
Yue Chen5b53ea12018-03-09 11:26:43 -080049 return av1_cospi_arr_data[n - cos_bit_min];
Frederic Barbierbbf7bb02017-05-05 09:37:40 +020050}
51
Angie Chiang82517362018-01-17 17:31:54 -080052static INLINE const int32_t *sinpi_arr(int n) {
Yue Chen5b53ea12018-03-09 11:26:43 -080053 return av1_sinpi_arr_data[n - cos_bit_min];
Angie Chiang82517362018-01-17 17:31:54 -080054}
55
James Zerndc857592018-02-01 19:21:48 -080056static INLINE int32_t range_check_value(int32_t value, int8_t bit) {
57#if CONFIG_COEFFICIENT_RANGE_CHECKING
James Zernb785b952018-02-01 19:27:09 -080058 const int64_t max_value = (1LL << (bit - 1)) - 1;
59 const int64_t min_value = -(1LL << (bit - 1));
60 if (value < min_value || value > max_value) {
James Zerndc857592018-02-01 19:21:48 -080061 fprintf(stderr, "coeff out of bit range, value: %d bit %d\n", value, bit);
62 assert(0);
63 }
Hui Su8d950192018-04-27 15:47:23 -070064#endif // CONFIG_COEFFICIENT_RANGE_CHECKING
65#if DO_RANGE_CHECK_CLAMP
66 bit = AOMMIN(bit, 31);
Angie Chiang66b7d7b2018-07-25 14:57:17 -070067 return clamp(value, -(1 << (bit - 1)), (1 << (bit - 1)) - 1);
Hui Su8d950192018-04-27 15:47:23 -070068#endif // DO_RANGE_CHECK_CLAMP
James Zerndc857592018-02-01 19:21:48 -080069 (void)bit;
James Zerndc857592018-02-01 19:21:48 -080070 return value;
71}
72
Hui Su6d0fdad2018-03-12 10:46:40 -070073static INLINE int32_t round_shift(int64_t value, int bit) {
Yaowu Xu637590c2016-11-16 15:15:46 -080074 assert(bit >= 1);
Hui Su6d0fdad2018-03-12 10:46:40 -070075 return (int32_t)((value + (1ll << (bit - 1))) >> bit);
Yaowu Xuc27fc142016-08-22 16:08:15 -070076}
77
Yaowu Xuc27fc142016-08-22 16:08:15 -070078static INLINE int32_t half_btf(int32_t w0, int32_t in0, int32_t w1, int32_t in1,
79 int bit) {
Angie Chiangd1c222d2018-02-28 19:41:01 -080080 int64_t result_64 = (int64_t)(w0 * in0) + (int64_t)(w1 * in1);
81#if CONFIG_COEFFICIENT_RANGE_CHECKING
82 assert(result_64 >= INT32_MIN && result_64 <= INT32_MAX);
83#endif
Hui Su6d0fdad2018-03-12 10:46:40 -070084 return round_shift(result_64, bit);
Yaowu Xuc27fc142016-08-22 16:08:15 -070085}
86
Angie Chiang8c489a82018-05-15 16:07:30 -070087static INLINE uint16_t highbd_clip_pixel_add(uint16_t dest, tran_high_t trans,
88 int bd) {
89 return clip_pixel_highbd(dest + (int)trans, bd);
90}
91
Angie Chiangd4327bc2018-01-22 20:54:04 -080092typedef void (*TxfmFunc)(const int32_t *input, int32_t *output, int8_t cos_bit,
93 const int8_t *stage_range);
Yaowu Xuc27fc142016-08-22 16:08:15 -070094
Peng Bin9f041802018-04-09 13:16:26 +080095typedef void (*FwdTxfm2dFunc)(const int16_t *input, int32_t *output, int stride,
96 TX_TYPE tx_type, int bd);
97
Yaowu Xuc27fc142016-08-22 16:08:15 -070098typedef enum TXFM_TYPE {
99 TXFM_TYPE_DCT4,
100 TXFM_TYPE_DCT8,
101 TXFM_TYPE_DCT16,
102 TXFM_TYPE_DCT32,
103 TXFM_TYPE_DCT64,
104 TXFM_TYPE_ADST4,
105 TXFM_TYPE_ADST8,
106 TXFM_TYPE_ADST16,
Sarah Parker3eed4172017-05-15 20:49:22 -0700107 TXFM_TYPE_IDENTITY4,
108 TXFM_TYPE_IDENTITY8,
109 TXFM_TYPE_IDENTITY16,
110 TXFM_TYPE_IDENTITY32,
Angie Chiang0c7b8d82018-01-23 19:20:44 -0800111 TXFM_TYPES,
112 TXFM_TYPE_INVALID,
Yaowu Xuc27fc142016-08-22 16:08:15 -0700113} TXFM_TYPE;
114
Yaowu Xuc27fc142016-08-22 16:08:15 -0700115typedef struct TXFM_2D_FLIP_CFG {
Angie Chiang0c7b8d82018-01-23 19:20:44 -0800116 TX_SIZE tx_size;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700117 int ud_flip; // flip upside down
118 int lr_flip; // flip left to right
Angie Chiang4a75b5a2018-01-10 17:19:06 -0800119 const int8_t *shift;
Angie Chiangd4327bc2018-01-22 20:54:04 -0800120 int8_t cos_bit_col;
121 int8_t cos_bit_row;
Angie Chiang0c7b8d82018-01-23 19:20:44 -0800122 int8_t stage_range_col[MAX_TXFM_STAGE_NUM];
123 int8_t stage_range_row[MAX_TXFM_STAGE_NUM];
124 TXFM_TYPE txfm_type_col;
125 TXFM_TYPE txfm_type_row;
126 int stage_num_col;
127 int stage_num_row;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700128} TXFM_2D_FLIP_CFG;
129
Angie Chiangeae82082018-02-05 16:49:33 -0800130static INLINE void get_flip_cfg(TX_TYPE tx_type, int *ud_flip, int *lr_flip) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700131 switch (tx_type) {
132 case DCT_DCT:
133 case ADST_DCT:
134 case DCT_ADST:
135 case ADST_ADST:
Angie Chiangeae82082018-02-05 16:49:33 -0800136 *ud_flip = 0;
137 *lr_flip = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700138 break;
Sarah Parker3eed4172017-05-15 20:49:22 -0700139 case IDTX:
140 case V_DCT:
141 case H_DCT:
142 case V_ADST:
143 case H_ADST:
Angie Chiangeae82082018-02-05 16:49:33 -0800144 *ud_flip = 0;
145 *lr_flip = 0;
Sarah Parker3eed4172017-05-15 20:49:22 -0700146 break;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700147 case FLIPADST_DCT:
Sarah Parkereec47e62017-05-15 20:49:22 -0700148 case FLIPADST_ADST:
Sarah Parker3eed4172017-05-15 20:49:22 -0700149 case V_FLIPADST:
Angie Chiangeae82082018-02-05 16:49:33 -0800150 *ud_flip = 1;
151 *lr_flip = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700152 break;
153 case DCT_FLIPADST:
Sarah Parkereec47e62017-05-15 20:49:22 -0700154 case ADST_FLIPADST:
Sarah Parker3eed4172017-05-15 20:49:22 -0700155 case H_FLIPADST:
Angie Chiangeae82082018-02-05 16:49:33 -0800156 *ud_flip = 0;
157 *lr_flip = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700158 break;
159 case FLIPADST_FLIPADST:
Angie Chiangeae82082018-02-05 16:49:33 -0800160 *ud_flip = 1;
161 *lr_flip = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700162 break;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700163 default:
Angie Chiangeae82082018-02-05 16:49:33 -0800164 *ud_flip = 0;
165 *lr_flip = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700166 assert(0);
167 }
168}
169
Angie Chiangeae82082018-02-05 16:49:33 -0800170static INLINE void set_flip_cfg(TX_TYPE tx_type, TXFM_2D_FLIP_CFG *cfg) {
171 get_flip_cfg(tx_type, &cfg->ud_flip, &cfg->lr_flip);
172}
173
Debargha Mukherjee9eabd692017-11-16 12:44:31 -0800174// Utility function that returns the log of the ratio of the col and row
175// sizes.
176static INLINE int get_rect_tx_log_ratio(int col, int row) {
177 if (col == row) return 0;
178 if (col > row) {
179 if (col == row * 2) return 1;
180 if (col == row * 4) return 2;
181 assert(0 && "Unsupported transform size");
182 } else {
183 if (row == col * 2) return -1;
184 if (row == col * 4) return -2;
185 assert(0 && "Unsupported transform size");
186 }
187 return 0; // Invalid
188}
189
Angie Chiangce3ad282017-08-08 09:51:54 -0700190void av1_gen_fwd_stage_range(int8_t *stage_range_col, int8_t *stage_range_row,
191 const TXFM_2D_FLIP_CFG *cfg, int bd);
192
193void av1_gen_inv_stage_range(int8_t *stage_range_col, int8_t *stage_range_row,
Debargha Mukherjee1158bff2018-01-01 18:23:59 -0800194 const TXFM_2D_FLIP_CFG *cfg, TX_SIZE tx_size,
Angie Chiangce3ad282017-08-08 09:51:54 -0700195 int bd);
196
Urvang Joshic5022162017-11-21 15:57:42 -0800197void av1_get_fwd_txfm_cfg(TX_TYPE tx_type, TX_SIZE tx_size,
198 TXFM_2D_FLIP_CFG *cfg);
199void av1_get_inv_txfm_cfg(TX_TYPE tx_type, TX_SIZE tx_size,
200 TXFM_2D_FLIP_CFG *cfg);
Angie Chiang0c7b8d82018-01-23 19:20:44 -0800201extern const TXFM_TYPE av1_txfm_type_ls[5][TX_TYPES_1D];
202extern const int8_t av1_txfm_stage_num_list[TXFM_TYPES];
Angie Chiang29d2f212018-01-24 19:42:57 -0800203static INLINE int get_txw_idx(TX_SIZE tx_size) {
204 return tx_size_wide_log2[tx_size] - tx_size_wide_log2[0];
205}
206static INLINE int get_txh_idx(TX_SIZE tx_size) {
207 return tx_size_high_log2[tx_size] - tx_size_high_log2[0];
208}
209#define MAX_TXWH_IDX 5
Yaowu Xuc27fc142016-08-22 16:08:15 -0700210#ifdef __cplusplus
211}
212#endif // __cplusplus
213
Yaowu Xuf883b422016-08-30 14:01:10 -0700214#endif // AV1_TXFM_H_