blob: b3de273adc6ffcbccab9fe6c8a606bfb9ac55cb5 [file] [log] [blame]
Angie Chiang80b82262017-02-24 11:39:47 -08001/*
2 * Copyright (c) 2017, Alliance for Open Media. All rights reserved
3 *
4 * 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.
10 */
11
Angie Chiang41220ab2018-02-14 17:48:23 -080012#include "av1/encoder/encodetxb.h"
13
Linfeng Zhangae7b2f32017-11-08 15:46:57 -080014#include "aom_ports/mem.h"
Angie Chiang0397eda2017-03-15 16:57:14 -070015#include "av1/common/blockd.h"
Angie Chiange50f3ec2017-04-10 15:50:33 -070016#include "av1/common/idct.h"
Angie Chiang0397eda2017-03-15 16:57:14 -070017#include "av1/common/pred_common.h"
Angie Chiang41220ab2018-02-14 17:48:23 -080018#include "av1/common/scan.h"
Angie Chiang1628fcc2017-04-13 16:30:30 -070019#include "av1/encoder/bitstream.h"
Angie Chiang47c72182017-02-27 14:30:38 -080020#include "av1/encoder/cost.h"
Angie Chiang41220ab2018-02-14 17:48:23 -080021#include "av1/encoder/encodeframe.h"
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -080022#include "av1/encoder/hash.h"
Angie Chiang808d8592017-04-06 18:36:55 -070023#include "av1/encoder/rdopt.h"
Angie Chiang0397eda2017-03-15 16:57:14 -070024#include "av1/encoder/tokenize.h"
Angie Chiang80b82262017-02-24 11:39:47 -080025
Dake Hea47cd6c2017-10-13 18:09:58 -070026typedef struct LevelDownStats {
27 int update;
28 tran_low_t low_qc;
29 tran_low_t low_dqc;
Dake Hea47cd6c2017-10-13 18:09:58 -070030 int64_t dist0;
31 int rate;
32 int rate_low;
33 int64_t dist;
34 int64_t dist_low;
35 int64_t rd;
36 int64_t rd_low;
Dake He4d447692017-12-15 09:10:06 -080037 int64_t nz_rd;
Dake Hea47cd6c2017-10-13 18:09:58 -070038 int64_t rd_diff;
39 int cost_diff;
40 int64_t dist_diff;
41 int new_eob;
42} LevelDownStats;
43
Ryan Leiccc6ea72021-01-06 11:43:56 -080044#if CONFIG_EXTQUANT
45static INLINE int get_dqv(const int32_t *dequant, int coeff_idx,
46#else
Jingning Han37f53542019-06-06 14:22:17 -070047static INLINE int get_dqv(const int16_t *dequant, int coeff_idx,
Ryan Leiccc6ea72021-01-06 11:43:56 -080048#endif
Jingning Han37f53542019-06-06 14:22:17 -070049 const qm_val_t *iqmatrix) {
50 int dqv = dequant[!!coeff_idx];
51 if (iqmatrix != NULL)
52 dqv =
53 ((iqmatrix[coeff_idx] * dqv) + (1 << (AOM_QM_BITS - 1))) >> AOM_QM_BITS;
54 return dqv;
55}
56
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070057void av1_alloc_txb_buf(AV1_COMP *cpi) {
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070058 AV1_COMMON *cm = &cpi->common;
Urvang Joshi9dc909d2020-03-23 16:07:02 -070059 int size = ((cm->mi_params.mi_rows >> cm->seq_params.mib_size_log2) + 1) *
60 ((cm->mi_params.mi_cols >> cm->seq_params.mib_size_log2) + 1);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070061
Angie Chiang9367e3e2017-10-02 16:28:11 -070062 av1_free_txb_buf(cpi);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070063 // TODO(jingning): This should be further reduced.
64 CHECK_MEM_ERROR(cm, cpi->coeff_buffer_base,
Peng Bin27d7ca92018-03-22 22:25:56 +080065 aom_memalign(32, sizeof(*cpi->coeff_buffer_base) * size));
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070066}
67
Angie Chianged9667e2018-03-02 15:10:50 -080068void av1_free_txb_buf(AV1_COMP *cpi) { aom_free(cpi->coeff_buffer_base); }
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070069
Angie Chiang80b82262017-02-24 11:39:47 -080070static void write_golomb(aom_writer *w, int level) {
71 int x = level + 1;
72 int i = x;
73 int length = 0;
74
75 while (i) {
76 i >>= 1;
77 ++length;
78 }
79 assert(length > 0);
80
81 for (i = 0; i < length - 1; ++i) aom_write_bit(w, 0);
82
83 for (i = length - 1; i >= 0; --i) aom_write_bit(w, (x >> i) & 0x01);
84}
85
Dake Hea47cd6c2017-10-13 18:09:58 -070086static INLINE int64_t get_coeff_dist(tran_low_t tcoeff, tran_low_t dqcoeff,
87 int shift) {
88 const int64_t diff = (tcoeff - dqcoeff) * (1 << shift);
89 const int64_t error = diff * diff;
90 return error;
91}
92
Urvang Joshiac97d272018-07-31 15:16:52 -070093static const int8_t eob_to_pos_small[33] = {
94 0, 1, 2, // 0-2
95 3, 3, // 3-4
96 4, 4, 4, 4, // 5-8
97 5, 5, 5, 5, 5, 5, 5, 5, // 9-16
98 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 // 17-32
99};
100
101static const int8_t eob_to_pos_large[17] = {
102 6, // place holder
103 7, // 33-64
104 8, 8, // 65-128
105 9, 9, 9, 9, // 129-256
106 10, 10, 10, 10, 10, 10, 10, 10, // 257-512
107 11 // 513-
108};
109
110static INLINE int get_eob_pos_token(const int eob, int *const extra) {
111 int t;
112
113 if (eob < 33) {
114 t = eob_to_pos_small[eob];
115 } else {
116 const int e = AOMMIN((eob - 1) >> 5, 16);
117 t = eob_to_pos_large[e];
118 }
119
Yaowu Xu3a19b8a2019-05-01 08:40:42 -0700120 *extra = eob - av1_eob_group_start[t];
Urvang Joshiac97d272018-07-31 15:16:52 -0700121
122 return t;
123}
124
Yue Chen198738d2018-03-08 17:26:01 -0800125#if CONFIG_ENTROPY_STATS
Yaowu Xu49abec82018-03-13 16:09:01 -0700126void av1_update_eob_context(int cdf_idx, int eob, TX_SIZE tx_size,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900127 TX_CLASS tx_class, PLANE_TYPE plane,
Yunqing Wang0e141b52017-11-02 15:08:58 -0700128 FRAME_CONTEXT *ec_ctx, FRAME_COUNTS *counts,
129 uint8_t allow_update_cdf) {
Yue Chen198738d2018-03-08 17:26:01 -0800130#else
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900131void av1_update_eob_context(int eob, TX_SIZE tx_size, TX_CLASS tx_class,
Yaowu Xu49abec82018-03-13 16:09:01 -0700132 PLANE_TYPE plane, FRAME_CONTEXT *ec_ctx,
133 uint8_t allow_update_cdf) {
Yue Chen198738d2018-03-08 17:26:01 -0800134#endif
Yaowu Xu49abec82018-03-13 16:09:01 -0700135 int eob_extra;
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800136 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -0800137 TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Dake Hea47cd6c2017-10-13 18:09:58 -0700138
Dake He0db7d0e2017-12-21 15:23:20 -0800139 const int eob_multi_size = txsize_log2_minus4[tx_size];
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900140 const int eob_multi_ctx = (tx_class == TX_CLASS_2D) ? 0 : 1;
Dake He0db7d0e2017-12-21 15:23:20 -0800141
142 switch (eob_multi_size) {
143 case 0:
Yue Chen198738d2018-03-08 17:26:01 -0800144#if CONFIG_ENTROPY_STATS
145 ++counts->eob_multi16[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
146#endif
Dake He0db7d0e2017-12-21 15:23:20 -0800147 if (allow_update_cdf)
148 update_cdf(ec_ctx->eob_flag_cdf16[plane][eob_multi_ctx], eob_pt - 1, 5);
149 break;
150 case 1:
Yue Chen198738d2018-03-08 17:26:01 -0800151#if CONFIG_ENTROPY_STATS
152 ++counts->eob_multi32[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
153#endif
Dake He0db7d0e2017-12-21 15:23:20 -0800154 if (allow_update_cdf)
155 update_cdf(ec_ctx->eob_flag_cdf32[plane][eob_multi_ctx], eob_pt - 1, 6);
156 break;
157 case 2:
Yue Chen198738d2018-03-08 17:26:01 -0800158#if CONFIG_ENTROPY_STATS
159 ++counts->eob_multi64[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
160#endif
Dake He0db7d0e2017-12-21 15:23:20 -0800161 if (allow_update_cdf)
162 update_cdf(ec_ctx->eob_flag_cdf64[plane][eob_multi_ctx], eob_pt - 1, 7);
163 break;
164 case 3:
Yue Chen198738d2018-03-08 17:26:01 -0800165#if CONFIG_ENTROPY_STATS
166 ++counts->eob_multi128[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
167#endif
Hui Su1cb1c002018-02-05 18:21:20 -0800168 if (allow_update_cdf) {
Dake He0db7d0e2017-12-21 15:23:20 -0800169 update_cdf(ec_ctx->eob_flag_cdf128[plane][eob_multi_ctx], eob_pt - 1,
170 8);
Hui Su1cb1c002018-02-05 18:21:20 -0800171 }
Dake He0db7d0e2017-12-21 15:23:20 -0800172 break;
173 case 4:
Yue Chen198738d2018-03-08 17:26:01 -0800174#if CONFIG_ENTROPY_STATS
175 ++counts->eob_multi256[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
176#endif
Hui Su1cb1c002018-02-05 18:21:20 -0800177 if (allow_update_cdf) {
Dake He0db7d0e2017-12-21 15:23:20 -0800178 update_cdf(ec_ctx->eob_flag_cdf256[plane][eob_multi_ctx], eob_pt - 1,
179 9);
Hui Su1cb1c002018-02-05 18:21:20 -0800180 }
Dake He0db7d0e2017-12-21 15:23:20 -0800181 break;
182 case 5:
Yue Chen198738d2018-03-08 17:26:01 -0800183#if CONFIG_ENTROPY_STATS
184 ++counts->eob_multi512[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
185#endif
Hui Su1cb1c002018-02-05 18:21:20 -0800186 if (allow_update_cdf) {
Dake He0db7d0e2017-12-21 15:23:20 -0800187 update_cdf(ec_ctx->eob_flag_cdf512[plane][eob_multi_ctx], eob_pt - 1,
188 10);
Hui Su1cb1c002018-02-05 18:21:20 -0800189 }
Dake He0db7d0e2017-12-21 15:23:20 -0800190 break;
191 case 6:
192 default:
Yue Chen198738d2018-03-08 17:26:01 -0800193#if CONFIG_ENTROPY_STATS
194 ++counts->eob_multi1024[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
195#endif
Hui Su1cb1c002018-02-05 18:21:20 -0800196 if (allow_update_cdf) {
Dake He0db7d0e2017-12-21 15:23:20 -0800197 update_cdf(ec_ctx->eob_flag_cdf1024[plane][eob_multi_ctx], eob_pt - 1,
198 11);
Hui Su1cb1c002018-02-05 18:21:20 -0800199 }
Dake He0db7d0e2017-12-21 15:23:20 -0800200 break;
201 }
Jingning Han00803a72017-10-25 16:04:34 -0700202
Yaowu Xu3a19b8a2019-05-01 08:40:42 -0700203 if (av1_eob_offset_bits[eob_pt] > 0) {
Jingning Hanff4a9f82018-06-08 10:48:45 -0700204 int eob_ctx = eob_pt - 3;
Yaowu Xu3a19b8a2019-05-01 08:40:42 -0700205 int eob_shift = av1_eob_offset_bits[eob_pt] - 1;
Angie Chiang7ab884e2017-10-18 15:57:12 -0700206 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Hui Su1e959892018-01-22 12:14:43 -0800207#if CONFIG_ENTROPY_STATS
Yue Chen198738d2018-03-08 17:26:01 -0800208 counts->eob_extra[cdf_idx][txs_ctx][plane][eob_pt][bit]++;
Hui Su1e959892018-01-22 12:14:43 -0800209#endif // CONFIG_ENTROPY_STATS
Yunqing Wang0e141b52017-11-02 15:08:58 -0700210 if (allow_update_cdf)
Jingning Hanff4a9f82018-06-08 10:48:45 -0700211 update_cdf(ec_ctx->eob_extra_cdf[txs_ctx][plane][eob_ctx], bit, 2);
Angie Chiang7ab884e2017-10-18 15:57:12 -0700212 }
Dake Hea47cd6c2017-10-13 18:09:58 -0700213}
214
Yaowu Xu49abec82018-03-13 16:09:01 -0700215static int get_eob_cost(int eob, const LV_MAP_EOB_COST *txb_eob_costs,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900216 const LV_MAP_COEFF_COST *txb_costs, TX_CLASS tx_class) {
Yaowu Xu49abec82018-03-13 16:09:01 -0700217 int eob_extra;
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800218 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
Dake Hea47cd6c2017-10-13 18:09:58 -0700219 int eob_cost = 0;
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900220 const int eob_multi_ctx = (tx_class == TX_CLASS_2D) ? 0 : 1;
Dake He0db7d0e2017-12-21 15:23:20 -0800221 eob_cost = txb_eob_costs->eob_cost[eob_multi_ctx][eob_pt - 1];
Dake He0db7d0e2017-12-21 15:23:20 -0800222
Yaowu Xu3a19b8a2019-05-01 08:40:42 -0700223 if (av1_eob_offset_bits[eob_pt] > 0) {
Jingning Hanff4a9f82018-06-08 10:48:45 -0700224 const int eob_ctx = eob_pt - 3;
Yaowu Xu3a19b8a2019-05-01 08:40:42 -0700225 const int eob_shift = av1_eob_offset_bits[eob_pt] - 1;
Hui Su751a2332018-01-23 11:35:03 -0800226 const int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Jingning Hanff4a9f82018-06-08 10:48:45 -0700227 eob_cost += txb_costs->eob_extra_cost[eob_ctx][bit];
Yaowu Xu3a19b8a2019-05-01 08:40:42 -0700228 const int offset_bits = av1_eob_offset_bits[eob_pt];
Hui Su751a2332018-01-23 11:35:03 -0800229 if (offset_bits > 1) eob_cost += av1_cost_literal(offset_bits - 1);
Dake Hea47cd6c2017-10-13 18:09:58 -0700230 }
231 return eob_cost;
232}
233
Wenyao Liuf7e53752019-01-22 17:34:44 +0800234static const int golomb_bits_cost[32] = {
235 0, 512, 512 * 3, 512 * 3, 512 * 5, 512 * 5, 512 * 5, 512 * 5,
236 512 * 7, 512 * 7, 512 * 7, 512 * 7, 512 * 7, 512 * 7, 512 * 7, 512 * 7,
237 512 * 9, 512 * 9, 512 * 9, 512 * 9, 512 * 9, 512 * 9, 512 * 9, 512 * 9,
238 512 * 9, 512 * 9, 512 * 9, 512 * 9, 512 * 9, 512 * 9, 512 * 9, 512 * 9
239};
240static const int golomb_cost_diff[32] = {
241 0, 512, 512 * 2, 0, 512 * 2, 0, 0, 0, 512 * 2, 0, 0, 0, 0, 0, 0, 0,
242 512 * 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
243};
244
Angie Chiange4ea7482018-03-15 11:36:41 -0700245static INLINE int get_golomb_cost(int abs_qc) {
246 if (abs_qc >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
247 const int r = abs_qc - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
248 const int length = get_msb(r) + 1;
249 return av1_cost_literal(2 * length - 1);
250 }
251 return 0;
252}
253
Wenyao Liuf7e53752019-01-22 17:34:44 +0800254static INLINE int get_br_cost_with_diff(tran_low_t level, const int *coeff_lps,
255 int *diff) {
256 const int base_range = AOMMIN(level - 1 - NUM_BASE_LEVELS, COEFF_BASE_RANGE);
257 int golomb_bits = 0;
258 if (level <= COEFF_BASE_RANGE + 1 + NUM_BASE_LEVELS)
259 *diff += coeff_lps[base_range + COEFF_BASE_RANGE + 1];
260
261 if (level >= COEFF_BASE_RANGE + 1 + NUM_BASE_LEVELS) {
262 int r = level - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
263 if (r < 32) {
264 golomb_bits = golomb_bits_cost[r];
265 *diff += golomb_cost_diff[r];
266 } else {
267 golomb_bits = get_golomb_cost(level);
268 *diff += (r & (r - 1)) == 0 ? 1024 : 0;
269 }
270 }
271
272 return coeff_lps[base_range] + golomb_bits;
273}
274
Jim Bankoski24b30d72019-01-14 09:07:43 -0800275static INLINE int get_br_cost(tran_low_t level, const int *coeff_lps) {
276 const int base_range = AOMMIN(level - 1 - NUM_BASE_LEVELS, COEFF_BASE_RANGE);
277 return coeff_lps[base_range] + get_golomb_cost(level);
278}
279
Frederic Barbiere8c67522018-03-27 15:09:57 +0200280static INLINE int get_nz_map_ctx(const uint8_t *const levels,
281 const int coeff_idx, const int bwl,
282 const int height, const int scan_idx,
283 const int is_eob, const TX_SIZE tx_size,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900284 const TX_CLASS tx_class) {
Frederic Barbiere8c67522018-03-27 15:09:57 +0200285 if (is_eob) {
286 if (scan_idx == 0) return 0;
287 if (scan_idx <= (height << bwl) / 8) return 1;
288 if (scan_idx <= (height << bwl) / 4) return 2;
289 return 3;
290 }
Frederic Barbiere8c67522018-03-27 15:09:57 +0200291 const int stats =
292 get_nz_mag(levels + get_padded_idx(coeff_idx, bwl), bwl, tx_class);
293 return get_nz_map_ctx_from_stats(stats, coeff_idx, bwl, tx_size, tx_class);
294}
295
Peng Bin27d7ca92018-03-22 22:25:56 +0800296void av1_txb_init_levels_c(const tran_low_t *const coeff, const int width,
297 const int height, uint8_t *const levels) {
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700298 const int stride = width + TX_PAD_HOR;
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700299 uint8_t *ls = levels;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700300
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700301 memset(levels + stride * height, 0,
302 sizeof(*levels) * (TX_PAD_BOTTOM * stride + TX_PAD_END));
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700303
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700304 for (int i = 0; i < height; i++) {
305 for (int j = 0; j < width; j++) {
Jingning Han5cb408e2017-11-17 14:43:39 -0800306 *ls++ = (uint8_t)clamp(abs(coeff[i * width + j]), 0, INT8_MAX);
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700307 }
308 for (int j = 0; j < TX_PAD_HOR; j++) {
309 *ls++ = 0;
310 }
Linfeng Zhang1015a342017-10-24 16:20:41 -0700311 }
312}
313
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800314void av1_get_nz_map_contexts_c(const uint8_t *const levels,
315 const int16_t *const scan, const uint16_t eob,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900316 const TX_SIZE tx_size, const TX_CLASS tx_class,
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800317 int8_t *const coeff_contexts) {
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800318 const int bwl = get_txb_bwl(tx_size);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800319 const int height = get_txb_high(tx_size);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800320 for (int i = 0; i < eob; ++i) {
321 const int pos = scan[i];
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100322 coeff_contexts[pos] = get_nz_map_ctx(levels, pos, bwl, height, i,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900323 i == eob - 1, tx_size, tx_class);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800324 }
325}
326
Hui Su179fbfa2019-10-07 15:13:06 -0700327void av1_write_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCK *const x,
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500328 aom_writer *w, int blk_row, int blk_col, int plane,
Hui Su179fbfa2019-10-07 15:13:06 -0700329 int block, TX_SIZE tx_size) {
330 MACROBLOCKD *xd = &x->e_mbd;
331 const CB_COEFF_BUFFER *cb_coef_buff = x->cb_coef_buff;
liang zhaoc6f775a2020-12-17 11:54:58 -0800332#if CONFIG_SDP
333 const int txb_offset =
334 x->mbmi_ext_frame->cb_offset[plane > 0 && xd->tree_type == CHROMA_PART] /
335 (TX_SIZE_W_MIN * TX_SIZE_H_MIN);
336#else
Hui Su179fbfa2019-10-07 15:13:06 -0700337 const int txb_offset =
338 x->mbmi_ext_frame->cb_offset / (TX_SIZE_W_MIN * TX_SIZE_H_MIN);
liang zhaoc6f775a2020-12-17 11:54:58 -0800339#endif
Hui Su179fbfa2019-10-07 15:13:06 -0700340 const uint16_t *eob_txb = cb_coef_buff->eobs[plane] + txb_offset;
341 const uint16_t eob = eob_txb[block];
342 const uint8_t *entropy_ctx = cb_coef_buff->entropy_ctx[plane] + txb_offset;
343 const int txb_skip_ctx = entropy_ctx[block] & TXB_SKIP_CTX_MASK;
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -0800344 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Peng Bin66205b72018-09-04 15:11:08 +0800345 FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
Hui Su179fbfa2019-10-07 15:13:06 -0700346 aom_write_symbol(w, eob == 0, ec_ctx->txb_skip_cdf[txs_ctx][txb_skip_ctx], 2);
Peng Bin66205b72018-09-04 15:11:08 +0800347 if (eob == 0) return;
Hui Su179fbfa2019-10-07 15:13:06 -0700348
Peng Bin66205b72018-09-04 15:11:08 +0800349 const PLANE_TYPE plane_type = get_plane_type(plane);
Urvang Joshib6409e92020-03-23 11:23:27 -0700350 const TX_TYPE tx_type =
351 av1_get_tx_type(xd, plane_type, blk_row, blk_col, tx_size,
352 cm->features.reduced_tx_set_used);
Hui Su179fbfa2019-10-07 15:13:06 -0700353 // Only y plane's tx_type is transmitted
354 if (plane == 0) {
355 av1_write_tx_type(cm, xd, tx_type, tx_size, w);
356 }
Angie Chiang80b82262017-02-24 11:39:47 -0800357
Ryan Leiccc6ea72021-01-06 11:43:56 -0800358#if DEBUG_EXTQUANT
359 fprintf(cm->fEncCoeffLog, "\nblk_row=%d,blk_col=%d,plane=%d,tx_size=%d",
360 blk_row, blk_col, plane, tx_size);
361#endif
362
Yaowu Xu49abec82018-03-13 16:09:01 -0700363 int eob_extra;
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800364 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
Dake He0db7d0e2017-12-21 15:23:20 -0800365 const int eob_multi_size = txsize_log2_minus4[tx_size];
Hui Su179fbfa2019-10-07 15:13:06 -0700366 const TX_CLASS tx_class = tx_type_to_class[tx_type];
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900367 const int eob_multi_ctx = (tx_class == TX_CLASS_2D) ? 0 : 1;
Dake He0db7d0e2017-12-21 15:23:20 -0800368 switch (eob_multi_size) {
369 case 0:
370 aom_write_symbol(w, eob_pt - 1,
371 ec_ctx->eob_flag_cdf16[plane_type][eob_multi_ctx], 5);
372 break;
373 case 1:
374 aom_write_symbol(w, eob_pt - 1,
375 ec_ctx->eob_flag_cdf32[plane_type][eob_multi_ctx], 6);
376 break;
377 case 2:
378 aom_write_symbol(w, eob_pt - 1,
379 ec_ctx->eob_flag_cdf64[plane_type][eob_multi_ctx], 7);
380 break;
381 case 3:
382 aom_write_symbol(w, eob_pt - 1,
383 ec_ctx->eob_flag_cdf128[plane_type][eob_multi_ctx], 8);
384 break;
385 case 4:
386 aom_write_symbol(w, eob_pt - 1,
387 ec_ctx->eob_flag_cdf256[plane_type][eob_multi_ctx], 9);
388 break;
389 case 5:
390 aom_write_symbol(w, eob_pt - 1,
391 ec_ctx->eob_flag_cdf512[plane_type][eob_multi_ctx], 10);
392 break;
393 default:
394 aom_write_symbol(w, eob_pt - 1,
395 ec_ctx->eob_flag_cdf1024[plane_type][eob_multi_ctx], 11);
396 break;
397 }
398
Yaowu Xu3a19b8a2019-05-01 08:40:42 -0700399 const int eob_offset_bits = av1_eob_offset_bits[eob_pt];
wenyao.liu0be59012018-12-24 10:27:31 +0800400 if (eob_offset_bits > 0) {
Jingning Hanff4a9f82018-06-08 10:48:45 -0700401 const int eob_ctx = eob_pt - 3;
wenyao.liu0be59012018-12-24 10:27:31 +0800402 int eob_shift = eob_offset_bits - 1;
Angie Chiang7ab884e2017-10-18 15:57:12 -0700403 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Jingning Hanff4a9f82018-06-08 10:48:45 -0700404 aom_write_symbol(w, bit,
405 ec_ctx->eob_extra_cdf[txs_ctx][plane_type][eob_ctx], 2);
wenyao.liu0be59012018-12-24 10:27:31 +0800406 for (int i = 1; i < eob_offset_bits; i++) {
407 eob_shift = eob_offset_bits - 1 - i;
Angie Chiang7ab884e2017-10-18 15:57:12 -0700408 bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700409 aom_write_bit(w, bit);
Dake Hea47cd6c2017-10-13 18:09:58 -0700410 }
411 }
Dake He03a32922017-10-31 08:06:45 -0700412
Ryan Leiccc6ea72021-01-06 11:43:56 -0800413#if DEBUG_EXTQUANT
414 fprintf(cm->fEncCoeffLog, "tx_type=%d, eob=%d\n", tx_type, eob);
415#endif
416
Hui Su179fbfa2019-10-07 15:13:06 -0700417 const int width = get_txb_wide(tx_size);
418 const int height = get_txb_high(tx_size);
419 uint8_t levels_buf[TX_PAD_2D];
420 uint8_t *const levels = set_levels(levels_buf, width);
liang zhaoc6f775a2020-12-17 11:54:58 -0800421#if CONFIG_SDP
422 const tran_low_t *tcoeff_txb =
423 cb_coef_buff->tcoeff[plane] +
424 x->mbmi_ext_frame->cb_offset[plane > 0 && xd->tree_type == CHROMA_PART];
425#else
Hui Su179fbfa2019-10-07 15:13:06 -0700426 const tran_low_t *tcoeff_txb =
427 cb_coef_buff->tcoeff[plane] + x->mbmi_ext_frame->cb_offset;
liang zhaoc6f775a2020-12-17 11:54:58 -0800428#endif
Yaowu Xu18a49962019-10-16 12:47:04 -0700429 const tran_low_t *tcoeff = tcoeff_txb + BLOCK_OFFSET(block);
Hui Su179fbfa2019-10-07 15:13:06 -0700430 av1_txb_init_levels(tcoeff, width, height, levels);
431 const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
432 const int16_t *const scan = scan_order->scan;
433 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900434 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_class, coeff_contexts);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800435
Hui Su179fbfa2019-10-07 15:13:06 -0700436 const int bwl = get_txb_bwl(tx_size);
437 for (int c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800438 const int pos = scan[c];
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800439 const int coeff_ctx = coeff_contexts[pos];
440 const tran_low_t v = tcoeff[pos];
Angie Chiang41220ab2018-02-14 17:48:23 -0800441 const tran_low_t level = abs(v);
Dake He03a32922017-10-31 08:06:45 -0700442
Dake He3fe369c2017-11-16 17:56:44 -0800443 if (c == eob - 1) {
444 aom_write_symbol(
Angie Chiang41220ab2018-02-14 17:48:23 -0800445 w, AOMMIN(level, 3) - 1,
Dake He4d447692017-12-15 09:10:06 -0800446 ec_ctx->coeff_base_eob_cdf[txs_ctx][plane_type][coeff_ctx], 3);
Dake He3fe369c2017-11-16 17:56:44 -0800447 } else {
Angie Chiang41220ab2018-02-14 17:48:23 -0800448 aom_write_symbol(w, AOMMIN(level, 3),
Dake He3fe369c2017-11-16 17:56:44 -0800449 ec_ctx->coeff_base_cdf[txs_ctx][plane_type][coeff_ctx],
450 4);
451 }
Angie Chiang41220ab2018-02-14 17:48:23 -0800452 if (level > NUM_BASE_LEVELS) {
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100453 // level is above 1.
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800454 const int base_range = level - 1 - NUM_BASE_LEVELS;
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900455 const int br_ctx = get_br_ctx(levels, pos, bwl, tx_class);
wenyao.liu0be59012018-12-24 10:27:31 +0800456 aom_cdf_prob *cdf =
457 ec_ctx->coeff_br_cdf[AOMMIN(txs_ctx, TX_32X32)][plane_type][br_ctx];
Angie Chiang41220ab2018-02-14 17:48:23 -0800458 for (int idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800459 const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
wenyao.liu0be59012018-12-24 10:27:31 +0800460 aom_write_symbol(w, k, cdf, BR_CDF_SIZE);
Ola Hugossone72a2092017-11-12 09:11:53 +0100461 if (k < BR_CDF_SIZE - 1) break;
462 }
Angie Chiang6d5419c2018-02-20 15:12:15 -0800463 }
464 }
465
Ryan Leiccc6ea72021-01-06 11:43:56 -0800466#if DEBUG_EXTQUANT
467 for (int c = 0; c < eob; ++c) {
468 const tran_low_t v = tcoeff[scan[c]];
469 const tran_low_t level = abs(v);
470 fprintf(cm->fEncCoeffLog, "c=%d,pos=%d,level=%d,dq_coeff=%d\n", c, scan[c],
471 level, v);
472 }
473#endif
474
Angie Chiang6d5419c2018-02-20 15:12:15 -0800475 // Loop to code all signs in the transform block,
476 // starting with the sign of DC (if applicable)
Hui Su179fbfa2019-10-07 15:13:06 -0700477 for (int c = 0; c < eob; ++c) {
Angie Chiang6d5419c2018-02-20 15:12:15 -0800478 const tran_low_t v = tcoeff[scan[c]];
479 const tran_low_t level = abs(v);
480 const int sign = (v < 0) ? 1 : 0;
481 if (level) {
482 if (c == 0) {
Hui Su179fbfa2019-10-07 15:13:06 -0700483 const int dc_sign_ctx =
484 (entropy_ctx[block] >> DC_SIGN_CTX_SHIFT) & DC_SIGN_CTX_MASK;
485 aom_write_symbol(w, sign, ec_ctx->dc_sign_cdf[plane_type][dc_sign_ctx],
486 2);
Angie Chiang6d5419c2018-02-20 15:12:15 -0800487 } else {
488 aom_write_bit(w, sign);
489 }
Yushin Cho73711d52018-05-04 13:59:46 -0700490 if (level > COEFF_BASE_RANGE + NUM_BASE_LEVELS)
491 write_golomb(w, level - COEFF_BASE_RANGE - 1 - NUM_BASE_LEVELS);
Angie Chiang41220ab2018-02-14 17:48:23 -0800492 }
493 }
Angie Chiang80b82262017-02-24 11:39:47 -0800494}
Angie Chiang47c72182017-02-27 14:30:38 -0800495
Angie Chiang140b3332017-12-12 17:29:25 -0800496typedef struct encode_txb_args {
497 const AV1_COMMON *cm;
498 MACROBLOCK *x;
499 aom_writer *w;
500} ENCODE_TXB_ARGS;
501
angiebird320e2282020-06-29 10:34:43 -0700502void av1_write_intra_coeffs_mb(const AV1_COMMON *const cm, MACROBLOCK *x,
503 aom_writer *w, BLOCK_SIZE bsize) {
Angie Chiang140b3332017-12-12 17:29:25 -0800504 MACROBLOCKD *xd = &x->e_mbd;
Jingning Hanad54a982018-01-12 14:40:29 -0800505 const int num_planes = av1_num_planes(cm);
506 int block[MAX_MB_PLANE] = { 0 };
Jingning Han4b48cd12018-01-11 15:56:42 -0800507 int row, col;
Cheng Chen8ab1f442018-04-27 18:01:52 -0700508 assert(bsize == get_plane_block_size(bsize, xd->plane[0].subsampling_x,
509 xd->plane[0].subsampling_y));
Yushin Choca63a8b2018-04-20 16:46:36 -0700510 const int max_blocks_wide = max_block_wide(xd, bsize, 0);
511 const int max_blocks_high = max_block_high(xd, bsize, 0);
512 const BLOCK_SIZE max_unit_bsize = BLOCK_64X64;
Hui Suadda5872019-12-09 10:08:49 -0800513 int mu_blocks_wide = mi_size_wide[max_unit_bsize];
514 int mu_blocks_high = mi_size_high[max_unit_bsize];
Jingning Han4b48cd12018-01-11 15:56:42 -0800515 mu_blocks_wide = AOMMIN(max_blocks_wide, mu_blocks_wide);
516 mu_blocks_high = AOMMIN(max_blocks_high, mu_blocks_high);
517
518 for (row = 0; row < max_blocks_high; row += mu_blocks_high) {
Jingning Han4b48cd12018-01-11 15:56:42 -0800519 for (col = 0; col < max_blocks_wide; col += mu_blocks_wide) {
liang zhaoc6f775a2020-12-17 11:54:58 -0800520#if CONFIG_SDP
leolzhao3db7cca2021-01-26 16:53:07 -0800521 const int plane_start = (xd->tree_type == CHROMA_PART);
522 const int plane_end = (xd->tree_type == LUMA_PART) ? 1 : num_planes;
523 for (int plane = plane_start; plane < plane_end; ++plane) {
liang zhaoc6f775a2020-12-17 11:54:58 -0800524#else
Jingning Hanad54a982018-01-12 14:40:29 -0800525 for (int plane = 0; plane < num_planes; ++plane) {
liang zhaoc6f775a2020-12-17 11:54:58 -0800526#endif
Hui Su474e1e12020-02-27 15:46:36 -0800527 if (plane && !xd->is_chroma_ref) break;
Jingning Hanad54a982018-01-12 14:40:29 -0800528 const TX_SIZE tx_size = av1_get_tx_size(plane, xd);
529 const int stepr = tx_size_high_unit[tx_size];
530 const int stepc = tx_size_wide_unit[tx_size];
531 const int step = stepr * stepc;
Hui Su474e1e12020-02-27 15:46:36 -0800532 const struct macroblockd_plane *const pd = &xd->plane[plane];
Jingning Hanad54a982018-01-12 14:40:29 -0800533 const int unit_height = ROUND_POWER_OF_TWO(
534 AOMMIN(mu_blocks_high + row, max_blocks_high), pd->subsampling_y);
535 const int unit_width = ROUND_POWER_OF_TWO(
536 AOMMIN(mu_blocks_wide + col, max_blocks_wide), pd->subsampling_x);
537 for (int blk_row = row >> pd->subsampling_y; blk_row < unit_height;
538 blk_row += stepr) {
539 for (int blk_col = col >> pd->subsampling_x; blk_col < unit_width;
540 blk_col += stepc) {
Hui Su179fbfa2019-10-07 15:13:06 -0700541 av1_write_coeffs_txb(cm, x, w, blk_row, blk_col, plane,
542 block[plane], tx_size);
Jingning Hanad54a982018-01-12 14:40:29 -0800543 block[plane] += step;
544 }
Jingning Han4b48cd12018-01-11 15:56:42 -0800545 }
546 }
547 }
548 }
Angie Chiangc8af6112017-03-16 16:11:22 -0700549}
550
Urvang Joshi553096a2018-05-10 15:27:14 -0700551// TODO(angiebird): use this function whenever it's possible
Yaowu Xu33fd0a02019-10-15 18:23:29 -0700552static int get_tx_type_cost(const MACROBLOCK *x, const MACROBLOCKD *xd,
553 int plane, TX_SIZE tx_size, TX_TYPE tx_type,
554 int reduced_tx_set_used) {
Urvang Joshi553096a2018-05-10 15:27:14 -0700555 if (plane > 0) return 0;
556
557 const TX_SIZE square_tx_size = txsize_sqr_map[tx_size];
558
559 const MB_MODE_INFO *mbmi = xd->mi[0];
560 const int is_inter = is_inter_block(mbmi);
Yaowu Xu33fd0a02019-10-15 18:23:29 -0700561 if (get_ext_tx_types(tx_size, is_inter, reduced_tx_set_used) > 1 &&
Urvang Joshi553096a2018-05-10 15:27:14 -0700562 !xd->lossless[xd->mi[0]->segment_id]) {
563 const int ext_tx_set =
Yaowu Xu33fd0a02019-10-15 18:23:29 -0700564 get_ext_tx_set(tx_size, is_inter, reduced_tx_set_used);
Urvang Joshi553096a2018-05-10 15:27:14 -0700565 if (is_inter) {
566 if (ext_tx_set > 0)
chiyotsai9a06d182020-05-01 17:12:12 -0700567 return x->mode_costs
568 .inter_tx_type_costs[ext_tx_set][square_tx_size][tx_type];
Urvang Joshi553096a2018-05-10 15:27:14 -0700569 } else {
570 if (ext_tx_set > 0) {
571 PREDICTION_MODE intra_dir;
572 if (mbmi->filter_intra_mode_info.use_filter_intra)
573 intra_dir = fimode_to_intradir[mbmi->filter_intra_mode_info
574 .filter_intra_mode];
575 else
576 intra_dir = mbmi->mode;
chiyotsai9a06d182020-05-01 17:12:12 -0700577 return x->mode_costs.intra_tx_type_costs[ext_tx_set][square_tx_size]
578 [intra_dir][tx_type];
Urvang Joshi553096a2018-05-10 15:27:14 -0700579 }
580 }
581 }
582 return 0;
583}
584
bohanli0bff42b2020-01-09 15:21:11 -0800585static INLINE void update_coeff_eob_fast(int *eob, int shift,
Ryan Leiccc6ea72021-01-06 11:43:56 -0800586#if CONFIG_EXTQUANT
587 const int32_t *dequant_ptr,
588#else
bohanli0bff42b2020-01-09 15:21:11 -0800589 const int16_t *dequant_ptr,
Ryan Leiccc6ea72021-01-06 11:43:56 -0800590#endif
bohanli0bff42b2020-01-09 15:21:11 -0800591 const int16_t *scan,
592 const tran_low_t *coeff_ptr,
593 tran_low_t *qcoeff_ptr,
594 tran_low_t *dqcoeff_ptr) {
595 // TODO(sarahparker) make this work for aomqm
596 int eob_out = *eob;
Ryan Leiccc6ea72021-01-06 11:43:56 -0800597#if CONFIG_EXTQUANT
598 int zbin[2] = { dequant_ptr[0] + ROUND_POWER_OF_TWO(dequant_ptr[0] * 70,
599 7 + QUANT_TABLE_BITS),
600 dequant_ptr[1] + ROUND_POWER_OF_TWO(dequant_ptr[1] * 70,
601 7 + QUANT_TABLE_BITS) };
602#else
bohanli0bff42b2020-01-09 15:21:11 -0800603 int zbin[2] = { dequant_ptr[0] + ROUND_POWER_OF_TWO(dequant_ptr[0] * 70, 7),
604 dequant_ptr[1] + ROUND_POWER_OF_TWO(dequant_ptr[1] * 70, 7) };
Ryan Leiccc6ea72021-01-06 11:43:56 -0800605#endif
bohanli0bff42b2020-01-09 15:21:11 -0800606 for (int i = *eob - 1; i >= 0; i--) {
607 const int rc = scan[i];
608 const int qcoeff = qcoeff_ptr[rc];
609 const int coeff = coeff_ptr[rc];
Yaowu Xu9db5b8d2020-04-10 08:58:15 -0700610 const int coeff_sign = AOMSIGN(coeff);
bohanli0bff42b2020-01-09 15:21:11 -0800611 int64_t abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
612
613 if (((abs_coeff << (1 + shift)) < zbin[rc != 0]) || (qcoeff == 0)) {
614 eob_out--;
615 qcoeff_ptr[rc] = 0;
616 dqcoeff_ptr[rc] = 0;
617 } else {
618 break;
619 }
620 }
621
622 *eob = eob_out;
623}
624
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900625static AOM_FORCE_INLINE int warehouse_efficients_txb(
bohanli3613e5d2019-10-25 13:10:11 -0700626 const MACROBLOCK *x, const int plane, const int block,
627 const TX_SIZE tx_size, const TXB_CTX *const txb_ctx,
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900628 const struct macroblock_plane *p, const int eob,
629 const PLANE_TYPE plane_type, const LV_MAP_COEFF_COST *const coeff_costs,
bohanli3613e5d2019-10-25 13:10:11 -0700630 const MACROBLOCKD *const xd, const TX_TYPE tx_type, const TX_CLASS tx_class,
631 int reduced_tx_set_used) {
Yaowu Xu18a49962019-10-16 12:47:04 -0700632 const tran_low_t *const qcoeff = p->qcoeff + BLOCK_OFFSET(block);
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800633 const int txb_skip_ctx = txb_ctx->txb_skip_ctx;
Angie Chianga9ba58e2017-12-01 19:22:43 -0800634 const int bwl = get_txb_bwl(tx_size);
635 const int width = get_txb_wide(tx_size);
636 const int height = get_txb_high(tx_size);
Yaowu Xuf1e12932018-02-26 15:50:09 -0800637 const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800638 const int16_t *const scan = scan_order->scan;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700639 uint8_t levels_buf[TX_PAD_2D];
640 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800641 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Dake He0db7d0e2017-12-21 15:23:20 -0800642 const int eob_multi_size = txsize_log2_minus4[tx_size];
643 const LV_MAP_EOB_COST *const eob_costs =
chiyotsai9a06d182020-05-01 17:12:12 -0700644 &x->coeff_costs.eob_costs[eob_multi_size][plane_type];
Hui Su18205542018-03-30 11:37:41 -0700645 int cost = coeff_costs->txb_skip_cost[txb_skip_ctx][0];
Angie Chiang47c72182017-02-27 14:30:38 -0800646
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700647 av1_txb_init_levels(qcoeff, width, height, levels);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700648
bohanli3613e5d2019-10-25 13:10:11 -0700649 cost += get_tx_type_cost(x, xd, plane, tx_size, tx_type, reduced_tx_set_used);
Angie Chiang05917872017-04-15 12:28:56 -0700650
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900651 cost += get_eob_cost(eob, eob_costs, coeff_costs, tx_class);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800652
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900653 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_class, coeff_contexts);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800654
Wenyao Liuf7e53752019-01-22 17:34:44 +0800655 const int(*lps_cost)[COEFF_BASE_RANGE + 1 + COEFF_BASE_RANGE + 1] =
656 coeff_costs->lps_cost;
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900657 int c = eob - 1;
658 {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800659 const int pos = scan[c];
660 const tran_low_t v = qcoeff[pos];
Yaowu Xu9db5b8d2020-04-10 08:58:15 -0700661 const int sign = AOMSIGN(v);
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900662 const int level = (v ^ sign) - sign;
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800663 const int coeff_ctx = coeff_contexts[pos];
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900664 cost += coeff_costs->base_eob_cost[coeff_ctx][AOMMIN(level, 3) - 1];
Dake Hea47cd6c2017-10-13 18:09:58 -0700665
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900666 if (v) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700667 // sign bit cost
Dake Hea47cd6c2017-10-13 18:09:58 -0700668 if (level > NUM_BASE_LEVELS) {
Jim Bankoskife171222019-01-14 08:41:57 -0800669 const int ctx = get_br_ctx_eob(pos, bwl, tx_class);
670 cost += get_br_cost(level, lps_cost[ctx]);
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900671 }
672 if (c) {
673 cost += av1_cost_literal(1);
674 } else {
675 const int sign01 = (sign ^ sign) - sign;
676 const int dc_sign_ctx = txb_ctx->dc_sign_ctx;
677 cost += coeff_costs->dc_sign_cost[dc_sign_ctx][sign01];
678 return cost;
679 }
680 }
681 }
Wenyao Liuf7e53752019-01-22 17:34:44 +0800682 const int(*base_cost)[8] = coeff_costs->base_cost;
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900683 for (c = eob - 2; c >= 1; --c) {
684 const int pos = scan[c];
685 const int coeff_ctx = coeff_contexts[pos];
686 const tran_low_t v = qcoeff[pos];
687 const int level = abs(v);
bohanli3613e5d2019-10-25 13:10:11 -0700688 cost += base_cost[coeff_ctx][AOMMIN(level, 3)];
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900689 if (v) {
690 // sign bit cost
691 cost += av1_cost_literal(1);
692 if (level > NUM_BASE_LEVELS) {
693 const int ctx = get_br_ctx(levels, pos, bwl, tx_class);
Jim Bankoskife171222019-01-14 08:41:57 -0800694 cost += get_br_cost(level, lps_cost[ctx]);
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900695 }
696 }
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900697 }
bohanli3613e5d2019-10-25 13:10:11 -0700698 // c == 0 after previous loop
699 {
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900700 const int pos = scan[c];
701 const tran_low_t v = qcoeff[pos];
702 const int coeff_ctx = coeff_contexts[pos];
Yaowu Xu9db5b8d2020-04-10 08:58:15 -0700703 const int sign = AOMSIGN(v);
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900704 const int level = (v ^ sign) - sign;
705 cost += base_cost[coeff_ctx][AOMMIN(level, 3)];
Dake Hea47cd6c2017-10-13 18:09:58 -0700706
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900707 if (v) {
708 // sign bit cost
709 const int sign01 = (sign ^ sign) - sign;
710 const int dc_sign_ctx = txb_ctx->dc_sign_ctx;
711 cost += coeff_costs->dc_sign_cost[dc_sign_ctx][sign01];
712 if (level > NUM_BASE_LEVELS) {
713 const int ctx = get_br_ctx(levels, pos, bwl, tx_class);
Jim Bankoskife171222019-01-14 08:41:57 -0800714 cost += get_br_cost(level, lps_cost[ctx]);
Dake Hea47cd6c2017-10-13 18:09:58 -0700715 }
716 }
717 }
Angie Chiang47c72182017-02-27 14:30:38 -0800718 return cost;
719}
Angie Chiang0397eda2017-03-15 16:57:14 -0700720
bohanli0bff42b2020-01-09 15:21:11 -0800721static AOM_FORCE_INLINE int warehouse_efficients_txb_laplacian(
722 const MACROBLOCK *x, const int plane, const int block,
723 const TX_SIZE tx_size, const TXB_CTX *const txb_ctx, const int eob,
724 const PLANE_TYPE plane_type, const LV_MAP_COEFF_COST *const coeff_costs,
725 const MACROBLOCKD *const xd, const TX_TYPE tx_type, const TX_CLASS tx_class,
726 int reduced_tx_set_used) {
727 const int txb_skip_ctx = txb_ctx->txb_skip_ctx;
728
729 const int eob_multi_size = txsize_log2_minus4[tx_size];
730 const LV_MAP_EOB_COST *const eob_costs =
chiyotsai9a06d182020-05-01 17:12:12 -0700731 &x->coeff_costs.eob_costs[eob_multi_size][plane_type];
bohanli0bff42b2020-01-09 15:21:11 -0800732 int cost = coeff_costs->txb_skip_cost[txb_skip_ctx][0];
733
734 cost += get_tx_type_cost(x, xd, plane, tx_size, tx_type, reduced_tx_set_used);
735
736 cost += get_eob_cost(eob, eob_costs, coeff_costs, tx_class);
737
738 cost += av1_cost_coeffs_txb_estimate(x, plane, block, tx_size, tx_type);
739 return cost;
740}
741
742// Look up table of individual cost of coefficient by its quantization level.
743// determined based on Laplacian distribution conditioned on estimated context
744static const int costLUT[15] = { -1143, 53, 545, 825, 1031,
745 1209, 1393, 1577, 1763, 1947,
746 2132, 2317, 2501, 2686, 2871 };
747static const int const_term = (1 << AV1_PROB_COST_SHIFT);
748static const int loge_par = ((14427 << AV1_PROB_COST_SHIFT) + 5000) / 10000;
749int av1_cost_coeffs_txb_estimate(const MACROBLOCK *x, const int plane,
750 const int block, const TX_SIZE tx_size,
751 const TX_TYPE tx_type) {
752 assert(plane == 0);
753
754 int cost = 0;
755 const struct macroblock_plane *p = &x->plane[plane];
756 const SCAN_ORDER *scan_order = get_scan(tx_size, tx_type);
757 const int16_t *scan = scan_order->scan;
758 tran_low_t *qcoeff = p->qcoeff + BLOCK_OFFSET(block);
759
760 int eob = p->eobs[block];
761
762 // coeffs
763 int c = eob - 1;
764 // eob
765 {
766 const int pos = scan[c];
767 const tran_low_t v = abs(qcoeff[pos]) - 1;
768 cost += (v << (AV1_PROB_COST_SHIFT + 2));
769 }
770 // other coeffs
771 for (c = eob - 2; c >= 0; c--) {
772 const int pos = scan[c];
773 const tran_low_t v = abs(qcoeff[pos]);
774 const int idx = AOMMIN(v, 14);
775
776 cost += costLUT[idx];
777 }
778
779 // const_term does not contain DC, and log(e) does not contain eob, so both
780 // (eob-1)
781 cost += (const_term + loge_par) * (eob - 1);
782
783 return cost;
784}
785
bohanli3613e5d2019-10-25 13:10:11 -0700786int av1_cost_coeffs_txb(const MACROBLOCK *x, const int plane, const int block,
787 const TX_SIZE tx_size, const TX_TYPE tx_type,
788 const TXB_CTX *const txb_ctx, int reduced_tx_set_used) {
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900789 const struct macroblock_plane *p = &x->plane[plane];
790 const int eob = p->eobs[block];
791 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
792 const PLANE_TYPE plane_type = get_plane_type(plane);
793 const LV_MAP_COEFF_COST *const coeff_costs =
chiyotsai9a06d182020-05-01 17:12:12 -0700794 &x->coeff_costs.coeff_costs[txs_ctx][plane_type];
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900795 if (eob == 0) {
796 return coeff_costs->txb_skip_cost[txb_ctx->txb_skip_ctx][1];
797 }
798
799 const MACROBLOCKD *const xd = &x->e_mbd;
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900800 const TX_CLASS tx_class = tx_type_to_class[tx_type];
801
bohanli3613e5d2019-10-25 13:10:11 -0700802 return warehouse_efficients_txb(x, plane, block, tx_size, txb_ctx, p, eob,
Yaowu Xu109ec9b2019-10-15 17:19:24 -0700803 plane_type, coeff_costs, xd, tx_type,
bohanli3613e5d2019-10-25 13:10:11 -0700804 tx_class, reduced_tx_set_used);
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900805}
806
bohanli736644d2020-01-14 09:30:37 -0800807int av1_cost_coeffs_txb_laplacian(const MACROBLOCK *x, const int plane,
808 const int block, const TX_SIZE tx_size,
809 const TX_TYPE tx_type,
810 const TXB_CTX *const txb_ctx,
811 const int reduced_tx_set_used,
812 const int adjust_eob) {
bohanli0bff42b2020-01-09 15:21:11 -0800813 const struct macroblock_plane *p = &x->plane[plane];
814 int eob = p->eobs[block];
815
816 if (adjust_eob) {
817 const SCAN_ORDER *scan_order = get_scan(tx_size, tx_type);
818 const int16_t *scan = scan_order->scan;
819 tran_low_t *tcoeff = p->coeff + BLOCK_OFFSET(block);
820 tran_low_t *qcoeff = p->qcoeff + BLOCK_OFFSET(block);
Urvang Joshi9543ad72020-04-17 16:59:46 -0700821 tran_low_t *dqcoeff = p->dqcoeff + BLOCK_OFFSET(block);
bohanli0bff42b2020-01-09 15:21:11 -0800822 update_coeff_eob_fast(&eob, av1_get_tx_scale(tx_size), p->dequant_QTX, scan,
823 tcoeff, qcoeff, dqcoeff);
824 p->eobs[block] = eob;
825 }
826
827 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
828 const PLANE_TYPE plane_type = get_plane_type(plane);
829 const LV_MAP_COEFF_COST *const coeff_costs =
chiyotsai9a06d182020-05-01 17:12:12 -0700830 &x->coeff_costs.coeff_costs[txs_ctx][plane_type];
bohanli0bff42b2020-01-09 15:21:11 -0800831 if (eob == 0) {
832 return coeff_costs->txb_skip_cost[txb_ctx->txb_skip_ctx][1];
833 }
834
835 const MACROBLOCKD *const xd = &x->e_mbd;
836 const TX_CLASS tx_class = tx_type_to_class[tx_type];
837
838 return warehouse_efficients_txb_laplacian(
839 x, plane, block, tx_size, txb_ctx, eob, plane_type, coeff_costs, xd,
840 tx_type, tx_class, reduced_tx_set_used);
841}
842
Wenyao Liuf7e53752019-01-22 17:34:44 +0800843static AOM_FORCE_INLINE int get_two_coeff_cost_simple(
Katsuhisa Yuasa9f639962018-04-08 18:00:54 +0900844 int ci, tran_low_t abs_qc, int coeff_ctx,
845 const LV_MAP_COEFF_COST *txb_costs, int bwl, TX_CLASS tx_class,
Wenyao Liuf7e53752019-01-22 17:34:44 +0800846 const uint8_t *levels, int *cost_low) {
Angie Chiang40b07312018-03-30 10:42:55 -0700847 // this simple version assumes the coeff's scan_idx is not DC (scan_idx != 0)
Angie Chiange4ea7482018-03-15 11:36:41 -0700848 // and not the last (scan_idx != eob - 1)
849 assert(ci > 0);
850 int cost = txb_costs->base_cost[coeff_ctx][AOMMIN(abs_qc, 3)];
Wenyao Liuf7e53752019-01-22 17:34:44 +0800851 int diff = 0;
852 if (abs_qc <= 3) diff = txb_costs->base_cost[coeff_ctx][abs_qc + 4];
Angie Chiange4ea7482018-03-15 11:36:41 -0700853 if (abs_qc) {
854 cost += av1_cost_literal(1);
855 if (abs_qc > NUM_BASE_LEVELS) {
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900856 const int br_ctx = get_br_ctx(levels, ci, bwl, tx_class);
Wenyao Liuf7e53752019-01-22 17:34:44 +0800857 int brcost_diff = 0;
858 cost += get_br_cost_with_diff(abs_qc, txb_costs->lps_cost[br_ctx],
859 &brcost_diff);
860 diff += brcost_diff;
Jim Bankoskife171222019-01-14 08:41:57 -0800861 }
862 }
Wenyao Liuf7e53752019-01-22 17:34:44 +0800863 *cost_low = cost - diff;
864
Jim Bankoskife171222019-01-14 08:41:57 -0800865 return cost;
866}
867
868static INLINE int get_coeff_cost_eob(int ci, tran_low_t abs_qc, int sign,
869 int coeff_ctx, int dc_sign_ctx,
870 const LV_MAP_COEFF_COST *txb_costs,
871 int bwl, TX_CLASS tx_class) {
872 int cost = 0;
873 cost += txb_costs->base_eob_cost[coeff_ctx][AOMMIN(abs_qc, 3) - 1];
874 if (abs_qc != 0) {
875 if (ci == 0) {
876 cost += txb_costs->dc_sign_cost[dc_sign_ctx][sign];
877 } else {
878 cost += av1_cost_literal(1);
879 }
880 if (abs_qc > NUM_BASE_LEVELS) {
881 int br_ctx;
882 br_ctx = get_br_ctx_eob(ci, bwl, tx_class);
883 cost += get_br_cost(abs_qc, txb_costs->lps_cost[br_ctx]);
Angie Chiange4ea7482018-03-15 11:36:41 -0700884 }
885 }
886 return cost;
887}
888
889static INLINE int get_coeff_cost_general(int is_last, int ci, tran_low_t abs_qc,
Angie Chiang40b07312018-03-30 10:42:55 -0700890 int sign, int coeff_ctx,
Angie Chiange4ea7482018-03-15 11:36:41 -0700891 int dc_sign_ctx,
892 const LV_MAP_COEFF_COST *txb_costs,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900893 int bwl, TX_CLASS tx_class,
Angie Chiange4ea7482018-03-15 11:36:41 -0700894 const uint8_t *levels) {
895 int cost = 0;
896 if (is_last) {
897 cost += txb_costs->base_eob_cost[coeff_ctx][AOMMIN(abs_qc, 3) - 1];
898 } else {
899 cost += txb_costs->base_cost[coeff_ctx][AOMMIN(abs_qc, 3)];
900 }
901 if (abs_qc != 0) {
902 if (ci == 0) {
Angie Chiang40b07312018-03-30 10:42:55 -0700903 cost += txb_costs->dc_sign_cost[dc_sign_ctx][sign];
Angie Chiange4ea7482018-03-15 11:36:41 -0700904 } else {
905 cost += av1_cost_literal(1);
906 }
907 if (abs_qc > NUM_BASE_LEVELS) {
Jim Bankoski95cb0d72019-01-11 15:20:06 -0800908 int br_ctx;
909 if (is_last)
910 br_ctx = get_br_ctx_eob(ci, bwl, tx_class);
911 else
912 br_ctx = get_br_ctx(levels, ci, bwl, tx_class);
Jim Bankoskife171222019-01-14 08:41:57 -0800913 cost += get_br_cost(abs_qc, txb_costs->lps_cost[br_ctx]);
Angie Chiange4ea7482018-03-15 11:36:41 -0700914 }
915 }
916 return cost;
917}
918
Angie Chiang40b07312018-03-30 10:42:55 -0700919static INLINE void get_qc_dqc_low(tran_low_t abs_qc, int sign, int dqv,
Angie Chiange4ea7482018-03-15 11:36:41 -0700920 int shift, tran_low_t *qc_low,
921 tran_low_t *dqc_low) {
922 tran_low_t abs_qc_low = abs_qc - 1;
Angie Chiang40b07312018-03-30 10:42:55 -0700923 *qc_low = (-sign ^ abs_qc_low) + sign;
924 assert((sign ? -abs_qc_low : abs_qc_low) == *qc_low);
Ryan Leiccc6ea72021-01-06 11:43:56 -0800925#if CONFIG_EXTQUANT
926 tran_low_t abs_dqc_low = (tran_low_t)(
927 ROUND_POWER_OF_TWO_64((tran_high_t)abs_qc_low * dqv, QUANT_TABLE_BITS) >>
928 shift);
929#else
Angie Chiange4ea7482018-03-15 11:36:41 -0700930 tran_low_t abs_dqc_low = (abs_qc_low * dqv) >> shift;
Ryan Leiccc6ea72021-01-06 11:43:56 -0800931#endif // CONFIG_EXTQUANT
Angie Chiang40b07312018-03-30 10:42:55 -0700932 *dqc_low = (-sign ^ abs_dqc_low) + sign;
933 assert((sign ? -abs_dqc_low : abs_dqc_low) == *dqc_low);
Angie Chiange4ea7482018-03-15 11:36:41 -0700934}
935
936static INLINE void update_coeff_general(
937 int *accu_rate, int64_t *accu_dist, int si, int eob, TX_SIZE tx_size,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900938 TX_CLASS tx_class, int bwl, int height, int64_t rdmult, int shift,
Ryan Leiccc6ea72021-01-06 11:43:56 -0800939#if CONFIG_EXTQUANT
940 int dc_sign_ctx, const int32_t *dequant, const int16_t *scan,
941#else
Angie Chiange4ea7482018-03-15 11:36:41 -0700942 int dc_sign_ctx, const int16_t *dequant, const int16_t *scan,
Ryan Leiccc6ea72021-01-06 11:43:56 -0800943#endif
Angie Chiange4ea7482018-03-15 11:36:41 -0700944 const LV_MAP_COEFF_COST *txb_costs, const tran_low_t *tcoeff,
Jingning Han37f53542019-06-06 14:22:17 -0700945 tran_low_t *qcoeff, tran_low_t *dqcoeff, uint8_t *levels,
946 const qm_val_t *iqmatrix) {
947 const int dqv = get_dqv(dequant, scan[si], iqmatrix);
Angie Chiange4ea7482018-03-15 11:36:41 -0700948 const int ci = scan[si];
949 const tran_low_t qc = qcoeff[ci];
950 const int is_last = si == (eob - 1);
951 const int coeff_ctx = get_lower_levels_ctx_general(
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900952 is_last, si, bwl, height, levels, ci, tx_size, tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -0700953 if (qc == 0) {
954 *accu_rate += txb_costs->base_cost[coeff_ctx][0];
955 } else {
Angie Chiang40b07312018-03-30 10:42:55 -0700956 const int sign = (qc < 0) ? 1 : 0;
Angie Chiange4ea7482018-03-15 11:36:41 -0700957 const tran_low_t abs_qc = abs(qc);
958 const tran_low_t tqc = tcoeff[ci];
959 const tran_low_t dqc = dqcoeff[ci];
960 const int64_t dist = get_coeff_dist(tqc, dqc, shift);
961 const int64_t dist0 = get_coeff_dist(tqc, 0, shift);
962 const int rate =
Angie Chiang40b07312018-03-30 10:42:55 -0700963 get_coeff_cost_general(is_last, ci, abs_qc, sign, coeff_ctx,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900964 dc_sign_ctx, txb_costs, bwl, tx_class, levels);
Angie Chiange4ea7482018-03-15 11:36:41 -0700965 const int64_t rd = RDCOST(rdmult, rate, dist);
966
967 tran_low_t qc_low, dqc_low;
Wenyao Liuf7e53752019-01-22 17:34:44 +0800968 tran_low_t abs_qc_low;
969 int64_t dist_low, rd_low;
970 int rate_low;
971 if (abs_qc == 1) {
972 abs_qc_low = qc_low = dqc_low = 0;
973 dist_low = dist0;
974 rate_low = txb_costs->base_cost[coeff_ctx][0];
975 } else {
976 get_qc_dqc_low(abs_qc, sign, dqv, shift, &qc_low, &dqc_low);
977 abs_qc_low = abs_qc - 1;
978 dist_low = get_coeff_dist(tqc, dqc_low, shift);
979 rate_low =
980 get_coeff_cost_general(is_last, ci, abs_qc_low, sign, coeff_ctx,
981 dc_sign_ctx, txb_costs, bwl, tx_class, levels);
982 }
983
984 rd_low = RDCOST(rdmult, rate_low, dist_low);
Angie Chiange4ea7482018-03-15 11:36:41 -0700985 if (rd_low < rd) {
986 qcoeff[ci] = qc_low;
987 dqcoeff[ci] = dqc_low;
988 levels[get_padded_idx(ci, bwl)] = AOMMIN(abs_qc_low, INT8_MAX);
989 *accu_rate += rate_low;
990 *accu_dist += dist_low - dist0;
991 } else {
992 *accu_rate += rate;
993 *accu_dist += dist - dist0;
994 }
995 }
996}
997
Katsuhisa Yuasa9f639962018-04-08 18:00:54 +0900998static AOM_FORCE_INLINE void update_coeff_simple(
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900999 int *accu_rate, int si, int eob, TX_SIZE tx_size, TX_CLASS tx_class,
Ryan Leiccc6ea72021-01-06 11:43:56 -08001000#if CONFIG_EXTQUANT
1001 int bwl, int64_t rdmult, int shift, const int32_t *dequant,
1002#else
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001003 int bwl, int64_t rdmult, int shift, const int16_t *dequant,
Ryan Leiccc6ea72021-01-06 11:43:56 -08001004#endif
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001005 const int16_t *scan, const LV_MAP_COEFF_COST *txb_costs,
1006 const tran_low_t *tcoeff, tran_low_t *qcoeff, tran_low_t *dqcoeff,
Jingning Han37f53542019-06-06 14:22:17 -07001007 uint8_t *levels, const qm_val_t *iqmatrix) {
1008 const int dqv = get_dqv(dequant, scan[si], iqmatrix);
Angie Chiange4ea7482018-03-15 11:36:41 -07001009 (void)eob;
Angie Chiang40b07312018-03-30 10:42:55 -07001010 // this simple version assumes the coeff's scan_idx is not DC (scan_idx != 0)
Angie Chiange4ea7482018-03-15 11:36:41 -07001011 // and not the last (scan_idx != eob - 1)
1012 assert(si != eob - 1);
1013 assert(si > 0);
1014 const int ci = scan[si];
1015 const tran_low_t qc = qcoeff[ci];
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001016 const int coeff_ctx =
1017 get_lower_levels_ctx(levels, ci, bwl, tx_size, tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -07001018 if (qc == 0) {
1019 *accu_rate += txb_costs->base_cost[coeff_ctx][0];
1020 } else {
1021 const tran_low_t abs_qc = abs(qc);
Wenyao Liuf7e53752019-01-22 17:34:44 +08001022 const tran_low_t abs_tqc = abs(tcoeff[ci]);
1023 const tran_low_t abs_dqc = abs(dqcoeff[ci]);
1024 int rate_low = 0;
1025 const int rate = get_two_coeff_cost_simple(
1026 ci, abs_qc, coeff_ctx, txb_costs, bwl, tx_class, levels, &rate_low);
1027 if (abs_dqc < abs_tqc) {
Jingning Han87f5c342018-04-10 23:10:12 -07001028 *accu_rate += rate;
1029 return;
1030 }
Wenyao Liuf7e53752019-01-22 17:34:44 +08001031
1032 const int64_t dist = get_coeff_dist(abs_tqc, abs_dqc, shift);
Angie Chiange4ea7482018-03-15 11:36:41 -07001033 const int64_t rd = RDCOST(rdmult, rate, dist);
1034
Angie Chiange4ea7482018-03-15 11:36:41 -07001035 const tran_low_t abs_qc_low = abs_qc - 1;
Ryan Leiccc6ea72021-01-06 11:43:56 -08001036#if CONFIG_EXTQUANT
1037 const tran_low_t abs_dqc_low =
1038 (tran_low_t)ROUND_POWER_OF_TWO_64((tran_high_t)abs_qc_low * dqv,
1039 QUANT_TABLE_BITS) >>
1040 shift;
1041#else
Wenyao Liuf7e53752019-01-22 17:34:44 +08001042 const tran_low_t abs_dqc_low = (abs_qc_low * dqv) >> shift;
Ryan Leiccc6ea72021-01-06 11:43:56 -08001043#endif // CONFIG_EXTQUANT
Wenyao Liuf7e53752019-01-22 17:34:44 +08001044 const int64_t dist_low = get_coeff_dist(abs_tqc, abs_dqc_low, shift);
Angie Chiange4ea7482018-03-15 11:36:41 -07001045 const int64_t rd_low = RDCOST(rdmult, rate_low, dist_low);
Wenyao Liuf7e53752019-01-22 17:34:44 +08001046
Angie Chiange4ea7482018-03-15 11:36:41 -07001047 if (rd_low < rd) {
Wenyao Liuf7e53752019-01-22 17:34:44 +08001048 const int sign = (qc < 0) ? 1 : 0;
1049 qcoeff[ci] = (-sign ^ abs_qc_low) + sign;
1050 dqcoeff[ci] = (-sign ^ abs_dqc_low) + sign;
Angie Chiange4ea7482018-03-15 11:36:41 -07001051 levels[get_padded_idx(ci, bwl)] = AOMMIN(abs_qc_low, INT8_MAX);
1052 *accu_rate += rate_low;
Angie Chiange4ea7482018-03-15 11:36:41 -07001053 } else {
1054 *accu_rate += rate;
Angie Chiange4ea7482018-03-15 11:36:41 -07001055 }
1056 }
1057}
1058
Katsuhisa Yuasa9f639962018-04-08 18:00:54 +09001059static AOM_FORCE_INLINE void update_coeff_eob(
Angie Chiange4ea7482018-03-15 11:36:41 -07001060 int *accu_rate, int64_t *accu_dist, int *eob, int *nz_num, int *nz_ci,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001061 int si, TX_SIZE tx_size, TX_CLASS tx_class, int bwl, int height,
Ryan Leiccc6ea72021-01-06 11:43:56 -08001062#if CONFIG_EXTQUANT
1063 int dc_sign_ctx, int64_t rdmult, int shift, const int32_t *dequant,
1064#else
Angie Chiange4ea7482018-03-15 11:36:41 -07001065 int dc_sign_ctx, int64_t rdmult, int shift, const int16_t *dequant,
Ryan Leiccc6ea72021-01-06 11:43:56 -08001066#endif
Angie Chiange4ea7482018-03-15 11:36:41 -07001067 const int16_t *scan, const LV_MAP_EOB_COST *txb_eob_costs,
1068 const LV_MAP_COEFF_COST *txb_costs, const tran_low_t *tcoeff,
Jingning Han37f53542019-06-06 14:22:17 -07001069 tran_low_t *qcoeff, tran_low_t *dqcoeff, uint8_t *levels, int sharpness,
1070 const qm_val_t *iqmatrix) {
1071 const int dqv = get_dqv(dequant, scan[si], iqmatrix);
Angie Chiange4ea7482018-03-15 11:36:41 -07001072 assert(si != *eob - 1);
1073 const int ci = scan[si];
1074 const tran_low_t qc = qcoeff[ci];
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001075 const int coeff_ctx =
1076 get_lower_levels_ctx(levels, ci, bwl, tx_size, tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -07001077 if (qc == 0) {
1078 *accu_rate += txb_costs->base_cost[coeff_ctx][0];
1079 } else {
1080 int lower_level = 0;
1081 const tran_low_t abs_qc = abs(qc);
1082 const tran_low_t tqc = tcoeff[ci];
1083 const tran_low_t dqc = dqcoeff[ci];
Angie Chiang40b07312018-03-30 10:42:55 -07001084 const int sign = (qc < 0) ? 1 : 0;
Angie Chiange4ea7482018-03-15 11:36:41 -07001085 const int64_t dist0 = get_coeff_dist(tqc, 0, shift);
1086 int64_t dist = get_coeff_dist(tqc, dqc, shift) - dist0;
1087 int rate =
Angie Chiang40b07312018-03-30 10:42:55 -07001088 get_coeff_cost_general(0, ci, abs_qc, sign, coeff_ctx, dc_sign_ctx,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001089 txb_costs, bwl, tx_class, levels);
Angie Chiange4ea7482018-03-15 11:36:41 -07001090 int64_t rd = RDCOST(rdmult, *accu_rate + rate, *accu_dist + dist);
1091
1092 tran_low_t qc_low, dqc_low;
Wenyao Liuf7e53752019-01-22 17:34:44 +08001093 tran_low_t abs_qc_low;
1094 int64_t dist_low, rd_low;
1095 int rate_low;
1096 if (abs_qc == 1) {
1097 abs_qc_low = 0;
1098 dqc_low = qc_low = 0;
1099 dist_low = 0;
1100 rate_low = txb_costs->base_cost[coeff_ctx][0];
1101 rd_low = RDCOST(rdmult, *accu_rate + rate_low, *accu_dist);
1102 } else {
1103 get_qc_dqc_low(abs_qc, sign, dqv, shift, &qc_low, &dqc_low);
1104 abs_qc_low = abs_qc - 1;
1105 dist_low = get_coeff_dist(tqc, dqc_low, shift) - dist0;
1106 rate_low =
1107 get_coeff_cost_general(0, ci, abs_qc_low, sign, coeff_ctx,
1108 dc_sign_ctx, txb_costs, bwl, tx_class, levels);
1109 rd_low = RDCOST(rdmult, *accu_rate + rate_low, *accu_dist + dist_low);
1110 }
Angie Chiange4ea7482018-03-15 11:36:41 -07001111
1112 int lower_level_new_eob = 0;
1113 const int new_eob = si + 1;
wenyao.liu0be59012018-12-24 10:27:31 +08001114 const int coeff_ctx_new_eob = get_lower_levels_ctx_eob(bwl, height, si);
Angie Chiange4ea7482018-03-15 11:36:41 -07001115 const int new_eob_cost =
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001116 get_eob_cost(new_eob, txb_eob_costs, txb_costs, tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -07001117 int rate_coeff_eob =
Jim Bankoskife171222019-01-14 08:41:57 -08001118 new_eob_cost + get_coeff_cost_eob(ci, abs_qc, sign, coeff_ctx_new_eob,
1119 dc_sign_ctx, txb_costs, bwl,
1120 tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -07001121 int64_t dist_new_eob = dist;
1122 int64_t rd_new_eob = RDCOST(rdmult, rate_coeff_eob, dist_new_eob);
1123
1124 if (abs_qc_low > 0) {
1125 const int rate_coeff_eob_low =
Jim Bankoskife171222019-01-14 08:41:57 -08001126 new_eob_cost + get_coeff_cost_eob(ci, abs_qc_low, sign,
1127 coeff_ctx_new_eob, dc_sign_ctx,
1128 txb_costs, bwl, tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -07001129 const int64_t dist_new_eob_low = dist_low;
1130 const int64_t rd_new_eob_low =
1131 RDCOST(rdmult, rate_coeff_eob_low, dist_new_eob_low);
1132 if (rd_new_eob_low < rd_new_eob) {
1133 lower_level_new_eob = 1;
1134 rd_new_eob = rd_new_eob_low;
1135 rate_coeff_eob = rate_coeff_eob_low;
1136 dist_new_eob = dist_new_eob_low;
1137 }
1138 }
1139
1140 if (rd_low < rd) {
1141 lower_level = 1;
1142 rd = rd_low;
1143 rate = rate_low;
1144 dist = dist_low;
1145 }
1146
Jim Bankoski855ac462018-06-07 09:05:00 -07001147 if (sharpness == 0 && rd_new_eob < rd) {
Angie Chiange4ea7482018-03-15 11:36:41 -07001148 for (int ni = 0; ni < *nz_num; ++ni) {
1149 int last_ci = nz_ci[ni];
Jim Bankoski95cb0d72019-01-11 15:20:06 -08001150 levels[get_padded_idx(last_ci, bwl)] = 0;
Angie Chiange4ea7482018-03-15 11:36:41 -07001151 qcoeff[last_ci] = 0;
1152 dqcoeff[last_ci] = 0;
1153 }
1154 *eob = new_eob;
1155 *nz_num = 0;
1156 *accu_rate = rate_coeff_eob;
1157 *accu_dist = dist_new_eob;
1158 lower_level = lower_level_new_eob;
1159 } else {
Angie Chiange4ea7482018-03-15 11:36:41 -07001160 *accu_rate += rate;
1161 *accu_dist += dist;
1162 }
1163
1164 if (lower_level) {
1165 qcoeff[ci] = qc_low;
1166 dqcoeff[ci] = dqc_low;
1167 levels[get_padded_idx(ci, bwl)] = AOMMIN(abs_qc_low, INT8_MAX);
1168 }
1169 if (qcoeff[ci]) {
1170 nz_ci[*nz_num] = ci;
1171 ++*nz_num;
1172 }
1173 }
1174}
1175
Angie Chiangd0397e12018-03-27 19:03:20 -07001176static INLINE void update_skip(int *accu_rate, int64_t accu_dist, int *eob,
1177 int nz_num, int *nz_ci, int64_t rdmult,
1178 int skip_cost, int non_skip_cost,
Jim Bankoski855ac462018-06-07 09:05:00 -07001179 tran_low_t *qcoeff, tran_low_t *dqcoeff,
1180 int sharpness) {
Angie Chiangd0397e12018-03-27 19:03:20 -07001181 const int64_t rd = RDCOST(rdmult, *accu_rate + non_skip_cost, accu_dist);
Angie Chiange4ea7482018-03-15 11:36:41 -07001182 const int64_t rd_new_eob = RDCOST(rdmult, skip_cost, 0);
Jim Bankoski855ac462018-06-07 09:05:00 -07001183 if (sharpness == 0 && rd_new_eob < rd) {
Angie Chiangd0397e12018-03-27 19:03:20 -07001184 for (int i = 0; i < nz_num; ++i) {
1185 const int ci = nz_ci[i];
Angie Chiange4ea7482018-03-15 11:36:41 -07001186 qcoeff[ci] = 0;
1187 dqcoeff[ci] = 0;
Angie Chiangd0397e12018-03-27 19:03:20 -07001188 // no need to set up levels because this is the last step
1189 // levels[get_padded_idx(ci, bwl)] = 0;
Angie Chiange4ea7482018-03-15 11:36:41 -07001190 }
Angie Chiange4ea7482018-03-15 11:36:41 -07001191 *accu_rate = 0;
1192 *eob = 0;
1193 }
1194}
1195
1196int av1_optimize_txb_new(const struct AV1_COMP *cpi, MACROBLOCK *x, int plane,
Xing Jinbd91e942018-06-21 13:43:17 +08001197 int block, TX_SIZE tx_size, TX_TYPE tx_type,
1198 const TXB_CTX *const txb_ctx, int *rate_cost,
chiyotsaifc56df82020-07-09 15:53:46 -07001199 int sharpness) {
Angie Chiange4ea7482018-03-15 11:36:41 -07001200 MACROBLOCKD *xd = &x->e_mbd;
Sarah Parker89df0342019-02-07 22:23:39 -08001201 const struct macroblock_plane *p = &x->plane[plane];
1202 const SCAN_ORDER *scan_order = get_scan(tx_size, tx_type);
1203 const int16_t *scan = scan_order->scan;
1204 const int shift = av1_get_tx_scale(tx_size);
1205 int eob = p->eobs[block];
Ryan Leiccc6ea72021-01-06 11:43:56 -08001206#if CONFIG_EXTQUANT
1207 const int32_t *dequant = p->dequant_QTX;
1208#else
Sarah Parker89df0342019-02-07 22:23:39 -08001209 const int16_t *dequant = p->dequant_QTX;
Ryan Leiccc6ea72021-01-06 11:43:56 -08001210#endif
Jingning Han37f53542019-06-06 14:22:17 -07001211 const qm_val_t *iqmatrix =
Urvang Joshif409a632020-03-28 01:03:50 -07001212 av1_get_iqmatrix(&cpi->common.quant_params, xd, plane, tx_size, tx_type);
Yaowu Xu18a49962019-10-16 12:47:04 -07001213 const int block_offset = BLOCK_OFFSET(block);
1214 tran_low_t *qcoeff = p->qcoeff + block_offset;
Urvang Joshi9543ad72020-04-17 16:59:46 -07001215 tran_low_t *dqcoeff = p->dqcoeff + block_offset;
Yaowu Xu18a49962019-10-16 12:47:04 -07001216 const tran_low_t *tcoeff = p->coeff + block_offset;
chiyotsai9a06d182020-05-01 17:12:12 -07001217 const CoeffCosts *coeff_costs = &x->coeff_costs;
Sarah Parker89df0342019-02-07 22:23:39 -08001218
Jingning Han3e4c9ed2019-06-07 15:03:16 -07001219 // This function is not called if eob = 0.
1220 assert(eob > 0);
1221
Sarah Parker89df0342019-02-07 22:23:39 -08001222 const AV1_COMMON *cm = &cpi->common;
Angie Chiange4ea7482018-03-15 11:36:41 -07001223 const PLANE_TYPE plane_type = get_plane_type(plane);
1224 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001225 const TX_CLASS tx_class = tx_type_to_class[tx_type];
Yue Chen53b53f02018-03-29 14:31:23 -07001226 const MB_MODE_INFO *mbmi = xd->mi[0];
Angie Chiange4ea7482018-03-15 11:36:41 -07001227 const int bwl = get_txb_bwl(tx_size);
1228 const int width = get_txb_wide(tx_size);
1229 const int height = get_txb_high(tx_size);
1230 assert(width == (1 << bwl));
1231 const int is_inter = is_inter_block(mbmi);
chiyotsai9a06d182020-05-01 17:12:12 -07001232 const LV_MAP_COEFF_COST *txb_costs =
1233 &coeff_costs->coeff_costs[txs_ctx][plane_type];
Angie Chiange4ea7482018-03-15 11:36:41 -07001234 const int eob_multi_size = txsize_log2_minus4[tx_size];
1235 const LV_MAP_EOB_COST *txb_eob_costs =
chiyotsai9a06d182020-05-01 17:12:12 -07001236 &coeff_costs->eob_costs[eob_multi_size][plane_type];
Angie Chiange4ea7482018-03-15 11:36:41 -07001237
Debargha Mukherjee7f3ab7f2019-05-30 00:20:50 -07001238 const int rshift =
1239 (sharpness +
Vishesh734eff92020-06-20 21:46:36 +05301240 (cpi->oxcf.q_cfg.aq_mode == VARIANCE_AQ && mbmi->segment_id < 4
Debargha Mukherjee7f3ab7f2019-05-30 00:20:50 -07001241 ? 7 - mbmi->segment_id
1242 : 2) +
Vishesh734eff92020-06-20 21:46:36 +05301243 (cpi->oxcf.q_cfg.aq_mode != VARIANCE_AQ &&
1244 cpi->oxcf.q_cfg.deltaq_mode == DELTA_Q_PERCEPTUAL &&
Debargha Mukherjee7f3ab7f2019-05-30 00:20:50 -07001245 cm->delta_q_info.delta_q_present_flag && x->sb_energy_level < 0
1246 ? (3 - x->sb_energy_level)
1247 : 0));
Debargha Mukherjee53d45d92019-02-11 12:59:50 -08001248 const int64_t rdmult =
1249 (((int64_t)x->rdmult *
1250 (plane_rd_mult[is_inter][plane_type] << (2 * (xd->bd - 8)))) +
1251 2) >>
1252 rshift;
Angie Chiange4ea7482018-03-15 11:36:41 -07001253
1254 uint8_t levels_buf[TX_PAD_2D];
1255 uint8_t *const levels = set_levels(levels_buf, width);
Jim Bankoski855ac462018-06-07 09:05:00 -07001256
Jim Bankoski102f36b2019-01-14 09:37:05 -08001257 if (eob > 1) av1_txb_init_levels(qcoeff, width, height, levels);
Angie Chiange4ea7482018-03-15 11:36:41 -07001258
1259 // TODO(angirbird): check iqmatrix
1260
1261 const int non_skip_cost = txb_costs->txb_skip_cost[txb_ctx->txb_skip_ctx][0];
1262 const int skip_cost = txb_costs->txb_skip_cost[txb_ctx->txb_skip_ctx][1];
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001263 const int eob_cost = get_eob_cost(eob, txb_eob_costs, txb_costs, tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -07001264 int accu_rate = eob_cost;
1265 int64_t accu_dist = 0;
1266 int si = eob - 1;
1267 const int ci = scan[si];
1268 const tran_low_t qc = qcoeff[ci];
1269 const tran_low_t abs_qc = abs(qc);
Angie Chiang40b07312018-03-30 10:42:55 -07001270 const int sign = qc < 0;
Angie Chiange4ea7482018-03-15 11:36:41 -07001271 const int max_nz_num = 2;
1272 int nz_num = 1;
1273 int nz_ci[3] = { ci, 0, 0 };
1274 if (abs_qc >= 2) {
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001275 update_coeff_general(&accu_rate, &accu_dist, si, eob, tx_size, tx_class,
1276 bwl, height, rdmult, shift, txb_ctx->dc_sign_ctx,
1277 dequant, scan, txb_costs, tcoeff, qcoeff, dqcoeff,
Jingning Han37f53542019-06-06 14:22:17 -07001278 levels, iqmatrix);
Angie Chiange4ea7482018-03-15 11:36:41 -07001279 --si;
1280 } else {
1281 assert(abs_qc == 1);
wenyao.liu0be59012018-12-24 10:27:31 +08001282 const int coeff_ctx = get_lower_levels_ctx_eob(bwl, height, si);
Jim Bankoski102f36b2019-01-14 09:37:05 -08001283 accu_rate +=
1284 get_coeff_cost_eob(ci, abs_qc, sign, coeff_ctx, txb_ctx->dc_sign_ctx,
1285 txb_costs, bwl, tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -07001286 const tran_low_t tqc = tcoeff[ci];
1287 const tran_low_t dqc = dqcoeff[ci];
1288 const int64_t dist = get_coeff_dist(tqc, dqc, shift);
1289 const int64_t dist0 = get_coeff_dist(tqc, 0, shift);
1290 accu_dist += dist - dist0;
1291 --si;
1292 }
1293
Katsuhisa Yuasa9f639962018-04-08 18:00:54 +09001294#define UPDATE_COEFF_EOB_CASE(tx_class_literal) \
1295 case tx_class_literal: \
chiyotsaifc56df82020-07-09 15:53:46 -07001296 for (; si >= 0 && nz_num <= max_nz_num; --si) { \
Katsuhisa Yuasa9f639962018-04-08 18:00:54 +09001297 update_coeff_eob(&accu_rate, &accu_dist, &eob, &nz_num, nz_ci, si, \
1298 tx_size, tx_class_literal, bwl, height, \
1299 txb_ctx->dc_sign_ctx, rdmult, shift, dequant, scan, \
1300 txb_eob_costs, txb_costs, tcoeff, qcoeff, dqcoeff, \
Jingning Han37f53542019-06-06 14:22:17 -07001301 levels, sharpness, iqmatrix); \
Katsuhisa Yuasa9f639962018-04-08 18:00:54 +09001302 } \
1303 break;
1304 switch (tx_class) {
1305 UPDATE_COEFF_EOB_CASE(TX_CLASS_2D);
1306 UPDATE_COEFF_EOB_CASE(TX_CLASS_HORIZ);
1307 UPDATE_COEFF_EOB_CASE(TX_CLASS_VERT);
1308#undef UPDATE_COEFF_EOB_CASE
1309 default: assert(false);
Angie Chiange4ea7482018-03-15 11:36:41 -07001310 }
1311
Angie Chiangd0397e12018-03-27 19:03:20 -07001312 if (si == -1 && nz_num <= max_nz_num) {
1313 update_skip(&accu_rate, accu_dist, &eob, nz_num, nz_ci, rdmult, skip_cost,
Jim Bankoski855ac462018-06-07 09:05:00 -07001314 non_skip_cost, qcoeff, dqcoeff, sharpness);
Angie Chiangd0397e12018-03-27 19:03:20 -07001315 }
1316
Katsuhisa Yuasa9f639962018-04-08 18:00:54 +09001317#define UPDATE_COEFF_SIMPLE_CASE(tx_class_literal) \
1318 case tx_class_literal: \
1319 for (; si >= 1; --si) { \
1320 update_coeff_simple(&accu_rate, si, eob, tx_size, tx_class_literal, bwl, \
1321 rdmult, shift, dequant, scan, txb_costs, tcoeff, \
Jingning Han37f53542019-06-06 14:22:17 -07001322 qcoeff, dqcoeff, levels, iqmatrix); \
Katsuhisa Yuasa9f639962018-04-08 18:00:54 +09001323 } \
1324 break;
1325 switch (tx_class) {
1326 UPDATE_COEFF_SIMPLE_CASE(TX_CLASS_2D);
1327 UPDATE_COEFF_SIMPLE_CASE(TX_CLASS_HORIZ);
1328 UPDATE_COEFF_SIMPLE_CASE(TX_CLASS_VERT);
1329#undef UPDATE_COEFF_SIMPLE_CASE
1330 default: assert(false);
Angie Chiange4ea7482018-03-15 11:36:41 -07001331 }
1332
1333 // DC position
1334 if (si == 0) {
Angie Chiangd0397e12018-03-27 19:03:20 -07001335 // no need to update accu_dist because it's not used after this point
1336 int64_t dummy_dist = 0;
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001337 update_coeff_general(&accu_rate, &dummy_dist, si, eob, tx_size, tx_class,
Angie Chiangd0397e12018-03-27 19:03:20 -07001338 bwl, height, rdmult, shift, txb_ctx->dc_sign_ctx,
1339 dequant, scan, txb_costs, tcoeff, qcoeff, dqcoeff,
Jingning Han37f53542019-06-06 14:22:17 -07001340 levels, iqmatrix);
Angie Chiange4ea7482018-03-15 11:36:41 -07001341 }
1342
Urvang Joshib6409e92020-03-23 11:23:27 -07001343 const int tx_type_cost = get_tx_type_cost(x, xd, plane, tx_size, tx_type,
1344 cm->features.reduced_tx_set_used);
Angie Chiange4ea7482018-03-15 11:36:41 -07001345 if (eob == 0)
1346 accu_rate += skip_cost;
1347 else
1348 accu_rate += non_skip_cost + tx_type_cost;
1349
1350 p->eobs[block] = eob;
1351 p->txb_entropy_ctx[block] =
1352 av1_get_txb_entropy_context(qcoeff, scan_order, p->eobs[block]);
1353
1354 *rate_cost = accu_rate;
1355 return eob;
1356}
1357
angiebird173a7562020-06-30 12:22:20 -07001358uint8_t av1_get_txb_entropy_context(const tran_low_t *qcoeff,
1359 const SCAN_ORDER *scan_order, int eob) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001360 const int16_t *const scan = scan_order->scan;
Angie Chiang74e23072017-03-24 14:54:23 -07001361 int cul_level = 0;
1362 int c;
Jingning Han339cf932017-09-18 10:17:02 -07001363
1364 if (eob == 0) return 0;
Angie Chiang74e23072017-03-24 14:54:23 -07001365 for (c = 0; c < eob; ++c) {
1366 cul_level += abs(qcoeff[scan[c]]);
Jingning Hane3137652018-04-02 11:53:47 -07001367 if (cul_level > COEFF_CONTEXT_MASK) break;
Angie Chiang74e23072017-03-24 14:54:23 -07001368 }
1369
1370 cul_level = AOMMIN(COEFF_CONTEXT_MASK, cul_level);
1371 set_dc_sign(&cul_level, qcoeff[0]);
1372
angiebird173a7562020-06-30 12:22:20 -07001373 return (uint8_t)cul_level;
Angie Chiang74e23072017-03-24 14:54:23 -07001374}
1375
Hui Su6f981af2019-05-21 20:49:51 -07001376static void update_tx_type_count(const AV1_COMP *cpi, const AV1_COMMON *cm,
1377 MACROBLOCKD *xd, int blk_row, int blk_col,
1378 int plane, TX_SIZE tx_size,
1379 FRAME_COUNTS *counts,
Urvang Joshi553096a2018-05-10 15:27:14 -07001380 uint8_t allow_update_cdf) {
1381 MB_MODE_INFO *mbmi = xd->mi[0];
1382 int is_inter = is_inter_block(mbmi);
Urvang Joshib6409e92020-03-23 11:23:27 -07001383 const int reduced_tx_set_used = cm->features.reduced_tx_set_used;
Urvang Joshi553096a2018-05-10 15:27:14 -07001384 FRAME_CONTEXT *fc = xd->tile_ctx;
1385#if !CONFIG_ENTROPY_STATS
1386 (void)counts;
1387#endif // !CONFIG_ENTROPY_STATS
1388
1389 // Only y plane's tx_type is updated
1390 if (plane > 0) return;
Hui Su37980cc2019-10-09 10:16:35 -07001391 const TX_TYPE tx_type = av1_get_tx_type(xd, PLANE_TYPE_Y, blk_row, blk_col,
Yaowu Xu33fd0a02019-10-15 18:23:29 -07001392 tx_size, reduced_tx_set_used);
Hui Su6f981af2019-05-21 20:49:51 -07001393 if (is_inter) {
Vishesh28709f22020-06-02 14:46:24 +05301394 if (cpi->oxcf.txfm_cfg.use_inter_dct_only) {
Hui Su6f981af2019-05-21 20:49:51 -07001395 assert(tx_type == DCT_DCT);
1396 }
1397 } else {
Vishesh28709f22020-06-02 14:46:24 +05301398 if (cpi->oxcf.txfm_cfg.use_intra_dct_only) {
Hui Su6f981af2019-05-21 20:49:51 -07001399 assert(tx_type == DCT_DCT);
Vishesh28709f22020-06-02 14:46:24 +05301400 } else if (cpi->oxcf.txfm_cfg.use_intra_default_tx_only) {
Hui Su6f981af2019-05-21 20:49:51 -07001401 const TX_TYPE default_type = get_default_tx_type(
1402 PLANE_TYPE_Y, xd, tx_size, cpi->is_screen_content_type);
1403 (void)default_type;
1404 assert(tx_type == default_type);
1405 }
1406 }
1407
Yaowu Xu33fd0a02019-10-15 18:23:29 -07001408 if (get_ext_tx_types(tx_size, is_inter, reduced_tx_set_used) > 1 &&
liang zhaoc6f775a2020-12-17 11:54:58 -08001409#if CONFIG_SDP
1410 cm->quant_params.base_qindex > 0 &&
1411 !mbmi->skip_txfm[xd->tree_type == CHROMA_PART] &&
1412#else
chiyotsai8c004e12020-04-17 15:52:08 -07001413 cm->quant_params.base_qindex > 0 && !mbmi->skip_txfm &&
liang zhaoc6f775a2020-12-17 11:54:58 -08001414#endif
Urvang Joshi553096a2018-05-10 15:27:14 -07001415 !segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
Yaowu Xu33fd0a02019-10-15 18:23:29 -07001416 const int eset = get_ext_tx_set(tx_size, is_inter, reduced_tx_set_used);
Urvang Joshi553096a2018-05-10 15:27:14 -07001417 if (eset > 0) {
1418 const TxSetType tx_set_type =
Yaowu Xu33fd0a02019-10-15 18:23:29 -07001419 av1_get_ext_tx_set_type(tx_size, is_inter, reduced_tx_set_used);
Urvang Joshi553096a2018-05-10 15:27:14 -07001420 if (is_inter) {
1421 if (allow_update_cdf) {
1422 update_cdf(fc->inter_ext_tx_cdf[eset][txsize_sqr_map[tx_size]],
1423 av1_ext_tx_ind[tx_set_type][tx_type],
1424 av1_num_ext_tx_set[tx_set_type]);
1425 }
1426#if CONFIG_ENTROPY_STATS
1427 ++counts->inter_ext_tx[eset][txsize_sqr_map[tx_size]]
1428 [av1_ext_tx_ind[tx_set_type][tx_type]];
1429#endif // CONFIG_ENTROPY_STATS
1430 } else {
1431 PREDICTION_MODE intra_dir;
1432 if (mbmi->filter_intra_mode_info.use_filter_intra)
1433 intra_dir = fimode_to_intradir[mbmi->filter_intra_mode_info
1434 .filter_intra_mode];
1435 else
1436 intra_dir = mbmi->mode;
1437#if CONFIG_ENTROPY_STATS
1438 ++counts->intra_ext_tx[eset][txsize_sqr_map[tx_size]][intra_dir]
1439 [av1_ext_tx_ind[tx_set_type][tx_type]];
1440#endif // CONFIG_ENTROPY_STATS
1441 if (allow_update_cdf) {
1442 update_cdf(
1443 fc->intra_ext_tx_cdf[eset][txsize_sqr_map[tx_size]][intra_dir],
1444 av1_ext_tx_ind[tx_set_type][tx_type],
1445 av1_num_ext_tx_set[tx_set_type]);
1446 }
1447 }
1448 }
1449 }
1450}
1451
Jingning Han4fe5f672017-05-19 15:46:07 -07001452void av1_update_and_record_txb_context(int plane, int block, int blk_row,
1453 int blk_col, BLOCK_SIZE plane_bsize,
1454 TX_SIZE tx_size, void *arg) {
Jingning Han6171ae72017-05-18 20:15:06 -07001455 struct tokenize_b_args *const args = arg;
Angie Chiang0397eda2017-03-15 16:57:14 -07001456 const AV1_COMP *cpi = args->cpi;
1457 const AV1_COMMON *cm = &cpi->common;
1458 ThreadData *const td = args->td;
1459 MACROBLOCK *const x = &td->mb;
1460 MACROBLOCKD *const xd = &x->e_mbd;
1461 struct macroblock_plane *p = &x->plane[plane];
1462 struct macroblockd_plane *pd = &xd->plane[plane];
Hui Su8763cd32018-04-02 12:29:05 -07001463 const int eob = p->eobs[block];
Yaowu Xu18a49962019-10-16 12:47:04 -07001464 const int block_offset = BLOCK_OFFSET(block);
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001465 tran_low_t *qcoeff = p->qcoeff + block_offset;
Hui Su8763cd32018-04-02 12:29:05 -07001466 const PLANE_TYPE plane_type = pd->plane_type;
Urvang Joshib6409e92020-03-23 11:23:27 -07001467 const TX_TYPE tx_type =
1468 av1_get_tx_type(xd, plane_type, blk_row, blk_col, tx_size,
1469 cm->features.reduced_tx_set_used);
Hui Su8763cd32018-04-02 12:29:05 -07001470 const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001471 tran_low_t *tcoeff;
1472 assert(args->dry_run != DRY_RUN_COSTCOEFFS);
1473 if (args->dry_run == OUTPUT_ENABLED) {
1474 MB_MODE_INFO *mbmi = xd->mi[0];
1475 TXB_CTX txb_ctx;
Urvang Joshi46ff5522020-03-30 15:27:37 -07001476 get_txb_ctx(plane_bsize, tx_size, plane,
1477 pd->above_entropy_context + blk_col,
1478 pd->left_entropy_context + blk_row, &txb_ctx);
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001479 const int bwl = get_txb_bwl(tx_size);
1480 const int width = get_txb_wide(tx_size);
1481 const int height = get_txb_high(tx_size);
1482 const uint8_t allow_update_cdf = args->allow_update_cdf;
1483 const TX_SIZE txsize_ctx = get_txsize_entropy_ctx(tx_size);
1484 FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
1485#if CONFIG_ENTROPY_STATS
1486 int cdf_idx = cm->coef_cdf_category;
1487 ++td->counts->txb_skip[cdf_idx][txsize_ctx][txb_ctx.txb_skip_ctx][eob == 0];
1488#endif // CONFIG_ENTROPY_STATS
1489 if (allow_update_cdf) {
1490 update_cdf(ec_ctx->txb_skip_cdf[txsize_ctx][txb_ctx.txb_skip_ctx],
1491 eob == 0, 2);
1492 }
Yunqing Wangdb70bf42019-08-19 09:28:11 -07001493
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001494 CB_COEFF_BUFFER *cb_coef_buff = x->cb_coef_buff;
liang zhaoc6f775a2020-12-17 11:54:58 -08001495#if CONFIG_SDP
1496 const int txb_offset =
1497 x->mbmi_ext_frame
1498 ->cb_offset[(plane > 0 && xd->tree_type == CHROMA_PART) ? 1 : 0] /
1499 (TX_SIZE_W_MIN * TX_SIZE_H_MIN);
1500#else
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001501 const int txb_offset =
1502 x->mbmi_ext_frame->cb_offset / (TX_SIZE_W_MIN * TX_SIZE_H_MIN);
liang zhaoc6f775a2020-12-17 11:54:58 -08001503#endif
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001504 uint16_t *eob_txb = cb_coef_buff->eobs[plane] + txb_offset;
1505 uint8_t *const entropy_ctx = cb_coef_buff->entropy_ctx[plane] + txb_offset;
1506 entropy_ctx[block] = txb_ctx.txb_skip_ctx;
1507 eob_txb[block] = eob;
1508
1509 if (eob == 0) {
Urvang Joshi46ff5522020-03-30 15:27:37 -07001510 av1_set_entropy_contexts(xd, pd, plane, plane_bsize, tx_size, 0, blk_col,
1511 blk_row);
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001512 return;
1513 }
1514 const int segment_id = mbmi->segment_id;
1515 const int seg_eob = av1_get_tx_eob(&cpi->common.seg, segment_id, tx_size);
liang zhaoc6f775a2020-12-17 11:54:58 -08001516#if CONFIG_SDP
1517 tran_low_t *tcoeff_txb =
1518 cb_coef_buff->tcoeff[plane] +
1519 x->mbmi_ext_frame->cb_offset[plane > 0 && xd->tree_type == CHROMA_PART];
1520#else
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001521 tran_low_t *tcoeff_txb =
1522 cb_coef_buff->tcoeff[plane] + x->mbmi_ext_frame->cb_offset;
liang zhaoc6f775a2020-12-17 11:54:58 -08001523#endif
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001524 tcoeff = tcoeff_txb + block_offset;
1525 memcpy(tcoeff, qcoeff, sizeof(*tcoeff) * seg_eob);
1526
1527 uint8_t levels_buf[TX_PAD_2D];
1528 uint8_t *const levels = set_levels(levels_buf, width);
1529 av1_txb_init_levels(tcoeff, width, height, levels);
1530 update_tx_type_count(cpi, cm, xd, blk_row, blk_col, plane, tx_size,
1531 td->counts, allow_update_cdf);
1532
1533 const TX_CLASS tx_class = tx_type_to_class[tx_type];
1534 const int16_t *const scan = scan_order->scan;
1535
1536 // record tx type usage
1537 td->rd_counts.tx_type_used[tx_size][tx_type]++;
Yunqing Wangdb70bf42019-08-19 09:28:11 -07001538
Yue Chen198738d2018-03-08 17:26:01 -08001539#if CONFIG_ENTROPY_STATS
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001540 av1_update_eob_context(cdf_idx, eob, tx_size, tx_class, plane_type, ec_ctx,
1541 td->counts, allow_update_cdf);
Yue Chen198738d2018-03-08 17:26:01 -08001542#else
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001543 av1_update_eob_context(eob, tx_size, tx_class, plane_type, ec_ctx,
1544 allow_update_cdf);
Yue Chen198738d2018-03-08 17:26:01 -08001545#endif
Hui Su8763cd32018-04-02 12:29:05 -07001546
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001547 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
1548 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_class,
1549 coeff_contexts);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -08001550
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001551 for (int c = eob - 1; c >= 0; --c) {
1552 const int pos = scan[c];
1553 const int coeff_ctx = coeff_contexts[pos];
1554 const tran_low_t v = qcoeff[pos];
1555 const tran_low_t level = abs(v);
Dake He03a32922017-10-31 08:06:45 -07001556
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001557 if (allow_update_cdf) {
1558 if (c == eob - 1) {
1559 assert(coeff_ctx < 4);
1560 update_cdf(
1561 ec_ctx->coeff_base_eob_cdf[txsize_ctx][plane_type][coeff_ctx],
1562 AOMMIN(level, 3) - 1, 3);
1563 } else {
1564 update_cdf(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][coeff_ctx],
1565 AOMMIN(level, 3), 4);
1566 }
Dake He4d447692017-12-15 09:10:06 -08001567 }
Dake He4d447692017-12-15 09:10:06 -08001568 if (c == eob - 1) {
1569 assert(coeff_ctx < 4);
Yue Chen198738d2018-03-08 17:26:01 -08001570#if CONFIG_ENTROPY_STATS
1571 ++td->counts->coeff_base_eob_multi[cdf_idx][txsize_ctx][plane_type]
1572 [coeff_ctx][AOMMIN(level, 3) - 1];
Dake He4d447692017-12-15 09:10:06 -08001573 } else {
Yue Chen198738d2018-03-08 17:26:01 -08001574 ++td->counts->coeff_base_multi[cdf_idx][txsize_ctx][plane_type]
1575 [coeff_ctx][AOMMIN(level, 3)];
1576#endif
Angie Chiang2cc5eb32018-02-14 18:37:22 -08001577 }
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001578 if (level > NUM_BASE_LEVELS) {
1579 const int base_range = level - 1 - NUM_BASE_LEVELS;
1580 const int br_ctx = get_br_ctx(levels, pos, bwl, tx_class);
1581 for (int idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
1582 const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
1583 if (allow_update_cdf) {
1584 update_cdf(ec_ctx->coeff_br_cdf[AOMMIN(txsize_ctx, TX_32X32)]
1585 [plane_type][br_ctx],
1586 k, BR_CDF_SIZE);
1587 }
1588 for (int lps = 0; lps < BR_CDF_SIZE - 1; lps++) {
Angie Chiang2cc5eb32018-02-14 18:37:22 -08001589#if CONFIG_ENTROPY_STATS
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001590 ++td->counts->coeff_lps[AOMMIN(txsize_ctx, TX_32X32)][plane_type]
1591 [lps][br_ctx][lps == k];
Angie Chiang2cc5eb32018-02-14 18:37:22 -08001592#endif // CONFIG_ENTROPY_STATS
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001593 if (lps == k) break;
1594 }
Yue Chen198738d2018-03-08 17:26:01 -08001595#if CONFIG_ENTROPY_STATS
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001596 ++td->counts->coeff_lps_multi[cdf_idx][AOMMIN(txsize_ctx, TX_32X32)]
1597 [plane_type][br_ctx][k];
Yue Chen198738d2018-03-08 17:26:01 -08001598#endif
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001599 if (k < BR_CDF_SIZE - 1) break;
1600 }
Dake He59881772017-11-24 07:00:02 -08001601 }
1602 }
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001603 // Update the context needed to code the DC sign (if applicable)
1604 if (tcoeff[0] != 0) {
1605 const int dc_sign = (tcoeff[0] < 0) ? 1 : 0;
1606 const int dc_sign_ctx = txb_ctx.dc_sign_ctx;
Hui Su1e959892018-01-22 12:14:43 -08001607#if CONFIG_ENTROPY_STATS
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001608 ++td->counts->dc_sign[plane_type][dc_sign_ctx][dc_sign];
Hui Su1e959892018-01-22 12:14:43 -08001609#endif // CONFIG_ENTROPY_STATS
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001610 if (allow_update_cdf)
1611 update_cdf(ec_ctx->dc_sign_cdf[plane_type][dc_sign_ctx], dc_sign, 2);
1612 entropy_ctx[block] |= dc_sign_ctx << DC_SIGN_CTX_SHIFT;
1613 }
1614 } else {
1615 tcoeff = qcoeff;
Dake He43edb762017-10-26 10:29:46 -07001616 }
angiebird173a7562020-06-30 12:22:20 -07001617 const uint8_t cul_level =
1618 av1_get_txb_entropy_context(tcoeff, scan_order, eob);
Urvang Joshi46ff5522020-03-30 15:27:37 -07001619 av1_set_entropy_contexts(xd, pd, plane, plane_bsize, tx_size, cul_level,
1620 blk_col, blk_row);
Angie Chiang0397eda2017-03-15 16:57:14 -07001621}
1622
angiebird0ddbb7e2020-06-30 19:09:40 -07001623void av1_update_intra_mb_txb_context(const AV1_COMP *cpi, ThreadData *td,
1624 RUN_TYPE dry_run, BLOCK_SIZE bsize,
1625 uint8_t allow_update_cdf) {
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +00001626 const AV1_COMMON *const cm = &cpi->common;
1627 const int num_planes = av1_num_planes(cm);
Angie Chiang0397eda2017-03-15 16:57:14 -07001628 MACROBLOCK *const x = &td->mb;
1629 MACROBLOCKD *const xd = &x->e_mbd;
Yue Chen53b53f02018-03-29 14:31:23 -07001630 MB_MODE_INFO *const mbmi = xd->mi[0];
Yaowu Xuf3dba2c2020-01-03 11:03:03 -08001631 struct tokenize_b_args arg = { cpi, td, 0, allow_update_cdf, dry_run };
liang zhaoc6f775a2020-12-17 11:54:58 -08001632#if CONFIG_SDP
1633 if (mbmi->skip_txfm[xd->tree_type == CHROMA_PART]) {
1634#else
chiyotsai8c004e12020-04-17 15:52:08 -07001635 if (mbmi->skip_txfm) {
liang zhaoc6f775a2020-12-17 11:54:58 -08001636#endif
Urvang Joshi46ff5522020-03-30 15:27:37 -07001637 av1_reset_entropy_context(xd, bsize, num_planes);
Angie Chiang0397eda2017-03-15 16:57:14 -07001638 return;
1639 }
liang zhaoc6f775a2020-12-17 11:54:58 -08001640#if CONFIG_SDP
leolzhao3db7cca2021-01-26 16:53:07 -08001641 const int plane_start = (xd->tree_type == CHROMA_PART);
1642 const int plane_end = (xd->tree_type == LUMA_PART) ? 1 : num_planes;
1643 for (int plane = plane_start; plane < plane_end; ++plane) {
liang zhaoc6f775a2020-12-17 11:54:58 -08001644#else
Yaowu Xu88039f02020-01-03 12:09:18 -08001645 for (int plane = 0; plane < num_planes; ++plane) {
liang zhaoc6f775a2020-12-17 11:54:58 -08001646#endif
Hui Su474e1e12020-02-27 15:46:36 -08001647 if (plane && !xd->is_chroma_ref) break;
Yaowu Xu88039f02020-01-03 12:09:18 -08001648 const struct macroblockd_plane *const pd = &xd->plane[plane];
1649 const int ss_x = pd->subsampling_x;
1650 const int ss_y = pd->subsampling_y;
Yaowu Xu88039f02020-01-03 12:09:18 -08001651 const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, ss_x, ss_y);
1652 av1_foreach_transformed_block_in_plane(
1653 xd, plane_bsize, plane, av1_update_and_record_txb_context, &arg);
1654 }
Angie Chiang0397eda2017-03-15 16:57:14 -07001655}
Hui Suf1b11062019-04-17 14:18:26 -07001656
1657CB_COEFF_BUFFER *av1_get_cb_coeff_buffer(const struct AV1_COMP *cpi, int mi_row,
1658 int mi_col) {
1659 const AV1_COMMON *const cm = &cpi->common;
1660 const int mib_size_log2 = cm->seq_params.mib_size_log2;
Urvang Joshi9dc909d2020-03-23 16:07:02 -07001661 const int stride = (cm->mi_params.mi_cols >> mib_size_log2) + 1;
Hui Suf1b11062019-04-17 14:18:26 -07001662 const int offset =
1663 (mi_row >> mib_size_log2) * stride + (mi_col >> mib_size_log2);
1664 return cpi->coeff_buffer_base + offset;
1665}