blob: 4c983a10648719f49be5376a58cf648022d621b3 [file] [log] [blame]
Yaowu Xuc27fc142016-08-22 16:08:15 -07001/*
Krishna Rapaka7319db52021-09-28 20:35:29 -07002 * Copyright (c) 2021, Alliance for Open Media. All rights reserved
Yaowu Xuc27fc142016-08-22 16:08:15 -07003 *
Vibhoothi41c6dd72021-10-12 18:48:26 +00004 * This source code is subject to the terms of the BSD 3-Clause Clear License
5 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6 * License was not distributed with this source code in the LICENSE file, you
7 * can obtain it at aomedia.org/license/software-license/bsd-3-c-c/. If the
8 * Alliance for Open Media Patent License 1.0 was not distributed with this
9 * source code in the PATENTS file, you can obtain it at
10 * aomedia.org/license/patent-license/.
Yaowu Xuc27fc142016-08-22 16:08:15 -070011 */
Yaowu Xubde4ac82016-11-28 15:26:06 -080012
James Zerne1cbb132018-08-22 14:10:36 -070013#ifndef AOM_AV1_COMMON_AV1_TXFM_H_
14#define AOM_AV1_COMMON_AV1_TXFM_H_
Yaowu Xuc27fc142016-08-22 16:08:15 -070015
16#include <assert.h>
17#include <math.h>
18#include <stdio.h>
19
Tom Finegan60e653d2018-05-22 11:34:58 -070020#include "config/aom_config.h"
21
Yaowu Xuc27fc142016-08-22 16:08:15 -070022#include "av1/common/enums.h"
Angie Chiang155bf9a2017-08-06 19:52:57 -070023#include "av1/common/blockd.h"
Yaowu Xuf883b422016-08-30 14:01:10 -070024#include "aom/aom_integer.h"
25#include "aom_dsp/aom_dsp_common.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070026
Angie Chiang9c7089a2017-08-08 16:21:11 -070027#ifdef __cplusplus
28extern "C" {
29#endif
30
Hui Su8d950192018-04-27 15:47:23 -070031#if !defined(DO_RANGE_CHECK_CLAMP)
32#define DO_RANGE_CHECK_CLAMP 0
33#endif
34
Yue Chen5b53ea12018-03-09 11:26:43 -080035extern const int32_t av1_cospi_arr_data[7][64];
36extern const int32_t av1_sinpi_arr_data[7][5];
37
Lester Lu68b107b2022-12-20 21:24:24 +000038#if CONFIG_CROSS_CHROMA_TX
39#define CCTX_PREC_BITS 8
40extern const int32_t cctx_mtx[CCTX_TYPES - 1][2];
41#endif // CONFIG_CROSS_CHROMA_TX
42
Angie Chiangce3ad282017-08-08 09:51:54 -070043#define MAX_TXFM_STAGE_NUM 12
44
Yaowu Xuc27fc142016-08-22 16:08:15 -070045static const int cos_bit_min = 10;
46static const int cos_bit_max = 16;
47
Martin Storsjo01c165a2018-07-28 22:11:04 +030048#define NewSqrt2Bits ((int32_t)12)
Angie Chiangc8d6c082018-02-06 14:26:55 -080049// 2^12 * sqrt(2)
50static const int32_t NewSqrt2 = 5793;
51// 2^12 / sqrt(2)
52static const int32_t NewInvSqrt2 = 2896;
53
Frederic Barbierbbf7bb02017-05-05 09:37:40 +020054static INLINE const int32_t *cospi_arr(int n) {
Yue Chen5b53ea12018-03-09 11:26:43 -080055 return av1_cospi_arr_data[n - cos_bit_min];
Frederic Barbierbbf7bb02017-05-05 09:37:40 +020056}
57
Angie Chiang82517362018-01-17 17:31:54 -080058static INLINE const int32_t *sinpi_arr(int n) {
Yue Chen5b53ea12018-03-09 11:26:43 -080059 return av1_sinpi_arr_data[n - cos_bit_min];
Angie Chiang82517362018-01-17 17:31:54 -080060}
61
James Zerndc857592018-02-01 19:21:48 -080062static INLINE int32_t range_check_value(int32_t value, int8_t bit) {
63#if CONFIG_COEFFICIENT_RANGE_CHECKING
James Zernb785b952018-02-01 19:27:09 -080064 const int64_t max_value = (1LL << (bit - 1)) - 1;
65 const int64_t min_value = -(1LL << (bit - 1));
66 if (value < min_value || value > max_value) {
James Zerndc857592018-02-01 19:21:48 -080067 fprintf(stderr, "coeff out of bit range, value: %d bit %d\n", value, bit);
Yaowu Xue7261ac2019-03-15 09:21:33 -070068#if !CONFIG_AV1_ENCODER
James Zerndc857592018-02-01 19:21:48 -080069 assert(0);
Yaowu Xue7261ac2019-03-15 09:21:33 -070070#endif
James Zerndc857592018-02-01 19:21:48 -080071 }
Hui Su8d950192018-04-27 15:47:23 -070072#endif // CONFIG_COEFFICIENT_RANGE_CHECKING
73#if DO_RANGE_CHECK_CLAMP
74 bit = AOMMIN(bit, 31);
Angie Chiang66b7d7b2018-07-25 14:57:17 -070075 return clamp(value, -(1 << (bit - 1)), (1 << (bit - 1)) - 1);
Hui Su8d950192018-04-27 15:47:23 -070076#endif // DO_RANGE_CHECK_CLAMP
James Zerndc857592018-02-01 19:21:48 -080077 (void)bit;
James Zerndc857592018-02-01 19:21:48 -080078 return value;
79}
80
Hui Su6d0fdad2018-03-12 10:46:40 -070081static INLINE int32_t round_shift(int64_t value, int bit) {
Yaowu Xu637590c2016-11-16 15:15:46 -080082 assert(bit >= 1);
Hui Su6d0fdad2018-03-12 10:46:40 -070083 return (int32_t)((value + (1ll << (bit - 1))) >> bit);
Yaowu Xuc27fc142016-08-22 16:08:15 -070084}
85
Yaowu Xuc27fc142016-08-22 16:08:15 -070086static INLINE int32_t half_btf(int32_t w0, int32_t in0, int32_t w1, int32_t in1,
87 int bit) {
Angie Chiangd1c222d2018-02-28 19:41:01 -080088 int64_t result_64 = (int64_t)(w0 * in0) + (int64_t)(w1 * in1);
David Barker6f33c682018-09-12 17:18:47 +010089 int64_t intermediate = result_64 + (1LL << (bit - 1));
Rachel Barker8bde1452021-12-16 18:13:47 +000090 // NOTE(rachelbarker): The value 'result_64' may not necessarily fit
David Barker6f33c682018-09-12 17:18:47 +010091 // into 32 bits. However, the result of this function is nominally
92 // ROUND_POWER_OF_TWO_64(result_64, bit)
93 // and that is required to fit into stage_range[stage] many bits
94 // (checked by range_check_buf()).
95 //
96 // Here we've unpacked that rounding operation, and it can be shown
97 // that the value of 'intermediate' here *does* fit into 32 bits
98 // for any conformant bitstream.
99 // The upshot is that, if you do all this calculation using
100 // wrapping 32-bit arithmetic instead of (non-wrapping) 64-bit arithmetic,
101 // then you'll still get the correct result.
102 // To provide a check on this logic, we assert that 'intermediate'
103 // would fit into an int32 if range checking is enabled.
Angie Chiangd1c222d2018-02-28 19:41:01 -0800104#if CONFIG_COEFFICIENT_RANGE_CHECKING
David Barker6f33c682018-09-12 17:18:47 +0100105 assert(intermediate >= INT32_MIN && intermediate <= INT32_MAX);
Angie Chiangd1c222d2018-02-28 19:41:01 -0800106#endif
David Barker6f33c682018-09-12 17:18:47 +0100107 return (int32_t)(intermediate >> bit);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700108}
109
Angie Chiang8c489a82018-05-15 16:07:30 -0700110static INLINE uint16_t highbd_clip_pixel_add(uint16_t dest, tran_high_t trans,
111 int bd) {
112 return clip_pixel_highbd(dest + (int)trans, bd);
113}
114
Angie Chiangd4327bc2018-01-22 20:54:04 -0800115typedef void (*TxfmFunc)(const int32_t *input, int32_t *output, int8_t cos_bit,
116 const int8_t *stage_range);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700117
Peng Bin9f041802018-04-09 13:16:26 +0800118typedef void (*FwdTxfm2dFunc)(const int16_t *input, int32_t *output, int stride,
119 TX_TYPE tx_type, int bd);
120
Satish Kumar Suman4667aa12018-12-14 18:28:19 +0530121enum {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700122 TXFM_TYPE_DCT4,
123 TXFM_TYPE_DCT8,
124 TXFM_TYPE_DCT16,
125 TXFM_TYPE_DCT32,
126 TXFM_TYPE_DCT64,
127 TXFM_TYPE_ADST4,
128 TXFM_TYPE_ADST8,
129 TXFM_TYPE_ADST16,
Sarah Parker3eed4172017-05-15 20:49:22 -0700130 TXFM_TYPE_IDENTITY4,
131 TXFM_TYPE_IDENTITY8,
132 TXFM_TYPE_IDENTITY16,
133 TXFM_TYPE_IDENTITY32,
Angie Chiang0c7b8d82018-01-23 19:20:44 -0800134 TXFM_TYPES,
135 TXFM_TYPE_INVALID,
Satish Kumar Suman4667aa12018-12-14 18:28:19 +0530136} UENUM1BYTE(TXFM_TYPE);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700137
Yaowu Xuc27fc142016-08-22 16:08:15 -0700138typedef struct TXFM_2D_FLIP_CFG {
Angie Chiang0c7b8d82018-01-23 19:20:44 -0800139 TX_SIZE tx_size;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700140 int ud_flip; // flip upside down
141 int lr_flip; // flip left to right
Angie Chiang4a75b5a2018-01-10 17:19:06 -0800142 const int8_t *shift;
Angie Chiangd4327bc2018-01-22 20:54:04 -0800143 int8_t cos_bit_col;
144 int8_t cos_bit_row;
Angie Chiang0c7b8d82018-01-23 19:20:44 -0800145 int8_t stage_range_col[MAX_TXFM_STAGE_NUM];
146 int8_t stage_range_row[MAX_TXFM_STAGE_NUM];
147 TXFM_TYPE txfm_type_col;
148 TXFM_TYPE txfm_type_row;
149 int stage_num_col;
150 int stage_num_row;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700151} TXFM_2D_FLIP_CFG;
152
Angie Chiangeae82082018-02-05 16:49:33 -0800153static INLINE void get_flip_cfg(TX_TYPE tx_type, int *ud_flip, int *lr_flip) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700154 switch (tx_type) {
155 case DCT_DCT:
156 case ADST_DCT:
157 case DCT_ADST:
158 case ADST_ADST:
Angie Chiangeae82082018-02-05 16:49:33 -0800159 *ud_flip = 0;
160 *lr_flip = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700161 break;
Sarah Parker3eed4172017-05-15 20:49:22 -0700162 case IDTX:
163 case V_DCT:
164 case H_DCT:
165 case V_ADST:
166 case H_ADST:
Angie Chiangeae82082018-02-05 16:49:33 -0800167 *ud_flip = 0;
168 *lr_flip = 0;
Sarah Parker3eed4172017-05-15 20:49:22 -0700169 break;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700170 case FLIPADST_DCT:
Sarah Parkereec47e62017-05-15 20:49:22 -0700171 case FLIPADST_ADST:
Sarah Parker3eed4172017-05-15 20:49:22 -0700172 case V_FLIPADST:
Angie Chiangeae82082018-02-05 16:49:33 -0800173 *ud_flip = 1;
174 *lr_flip = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700175 break;
176 case DCT_FLIPADST:
Sarah Parkereec47e62017-05-15 20:49:22 -0700177 case ADST_FLIPADST:
Sarah Parker3eed4172017-05-15 20:49:22 -0700178 case H_FLIPADST:
Angie Chiangeae82082018-02-05 16:49:33 -0800179 *ud_flip = 0;
180 *lr_flip = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700181 break;
182 case FLIPADST_FLIPADST:
Angie Chiangeae82082018-02-05 16:49:33 -0800183 *ud_flip = 1;
184 *lr_flip = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700185 break;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700186 default:
Angie Chiangeae82082018-02-05 16:49:33 -0800187 *ud_flip = 0;
188 *lr_flip = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700189 assert(0);
190 }
191}
192
Angie Chiangeae82082018-02-05 16:49:33 -0800193static INLINE void set_flip_cfg(TX_TYPE tx_type, TXFM_2D_FLIP_CFG *cfg) {
194 get_flip_cfg(tx_type, &cfg->ud_flip, &cfg->lr_flip);
195}
196
Debargha Mukherjee9eabd692017-11-16 12:44:31 -0800197// Utility function that returns the log of the ratio of the col and row
198// sizes.
199static INLINE int get_rect_tx_log_ratio(int col, int row) {
200 if (col == row) return 0;
201 if (col > row) {
202 if (col == row * 2) return 1;
203 if (col == row * 4) return 2;
204 assert(0 && "Unsupported transform size");
205 } else {
206 if (row == col * 2) return -1;
207 if (row == col * 4) return -2;
208 assert(0 && "Unsupported transform size");
209 }
210 return 0; // Invalid
211}
212
Angie Chiangce3ad282017-08-08 09:51:54 -0700213void av1_gen_fwd_stage_range(int8_t *stage_range_col, int8_t *stage_range_row,
214 const TXFM_2D_FLIP_CFG *cfg, int bd);
215
216void av1_gen_inv_stage_range(int8_t *stage_range_col, int8_t *stage_range_row,
Debargha Mukherjee1158bff2018-01-01 18:23:59 -0800217 const TXFM_2D_FLIP_CFG *cfg, TX_SIZE tx_size,
Angie Chiangce3ad282017-08-08 09:51:54 -0700218 int bd);
219
Urvang Joshic5022162017-11-21 15:57:42 -0800220void av1_get_fwd_txfm_cfg(TX_TYPE tx_type, TX_SIZE tx_size,
221 TXFM_2D_FLIP_CFG *cfg);
222void av1_get_inv_txfm_cfg(TX_TYPE tx_type, TX_SIZE tx_size,
223 TXFM_2D_FLIP_CFG *cfg);
Angie Chiang0c7b8d82018-01-23 19:20:44 -0800224extern const TXFM_TYPE av1_txfm_type_ls[5][TX_TYPES_1D];
225extern const int8_t av1_txfm_stage_num_list[TXFM_TYPES];
Angie Chiang29d2f212018-01-24 19:42:57 -0800226static INLINE int get_txw_idx(TX_SIZE tx_size) {
227 return tx_size_wide_log2[tx_size] - tx_size_wide_log2[0];
228}
229static INLINE int get_txh_idx(TX_SIZE tx_size) {
230 return tx_size_high_log2[tx_size] - tx_size_high_log2[0];
231}
Angie Chiangaf311e02018-08-21 16:08:28 -0700232
233void av1_range_check_buf(int32_t stage, const int32_t *input,
234 const int32_t *buf, int32_t size, int8_t bit);
Angie Chiang29d2f212018-01-24 19:42:57 -0800235#define MAX_TXWH_IDX 5
Yaowu Xuc27fc142016-08-22 16:08:15 -0700236#ifdef __cplusplus
237}
238#endif // __cplusplus
239
James Zerne1cbb132018-08-22 14:10:36 -0700240#endif // AOM_AV1_COMMON_AV1_TXFM_H_