blob: 9b8535f8eafbb4b0d9288b0743c8d731f867791f [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
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -080026static int hbt_needs_init = 1;
Peng Bin8a204cd2018-04-08 13:07:35 +080027static CRC32C crc_calculator;
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -080028static const int HBT_EOB = 16; // also the length in opt_qcoeff
29static const int HBT_TABLE_SIZE = 65536; // 16 bit: holds 65536 'arrays'
30static const int HBT_ARRAY_LENGTH = 256; // 8 bit: 256 entries
31// If removed in hbt_create_hashes or increased beyond int8_t, widen deltas type
32static const int HBT_KICKOUT = 3;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -080033
34typedef struct OptTxbQcoeff {
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -080035 // Use larger type if larger/no kickout value is used in hbt_create_hashes
36 int8_t deltas[16];
37 uint32_t hbt_qc_hash;
38 uint32_t hbt_ctx_hash;
39 int init;
40 int rate_cost;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -080041} OptTxbQcoeff;
42
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -080043OptTxbQcoeff *hbt_hash_table;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -080044
Dake Hea47cd6c2017-10-13 18:09:58 -070045typedef struct LevelDownStats {
46 int update;
47 tran_low_t low_qc;
48 tran_low_t low_dqc;
Dake Hea47cd6c2017-10-13 18:09:58 -070049 int64_t dist0;
50 int rate;
51 int rate_low;
52 int64_t dist;
53 int64_t dist_low;
54 int64_t rd;
55 int64_t rd_low;
Dake He4d447692017-12-15 09:10:06 -080056 int64_t nz_rd;
Dake Hea47cd6c2017-10-13 18:09:58 -070057 int64_t rd_diff;
58 int cost_diff;
59 int64_t dist_diff;
60 int new_eob;
61} LevelDownStats;
62
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070063void av1_alloc_txb_buf(AV1_COMP *cpi) {
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070064 AV1_COMMON *cm = &cpi->common;
Imdad Sardharwalla4ec84ab2018-02-06 12:20:18 +000065 int size = ((cm->mi_rows >> cm->seq_params.mib_size_log2) + 1) *
66 ((cm->mi_cols >> cm->seq_params.mib_size_log2) + 1);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070067
Angie Chiang9367e3e2017-10-02 16:28:11 -070068 av1_free_txb_buf(cpi);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070069 // TODO(jingning): This should be further reduced.
70 CHECK_MEM_ERROR(cm, cpi->coeff_buffer_base,
Peng Bin27d7ca92018-03-22 22:25:56 +080071 aom_memalign(32, sizeof(*cpi->coeff_buffer_base) * size));
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070072}
73
Angie Chianged9667e2018-03-02 15:10:50 -080074void av1_free_txb_buf(AV1_COMP *cpi) { aom_free(cpi->coeff_buffer_base); }
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070075
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070076void av1_set_coeff_buffer(const AV1_COMP *const cpi, MACROBLOCK *const x,
77 int mi_row, int mi_col) {
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +000078 const AV1_COMMON *const cm = &cpi->common;
79 const int num_planes = av1_num_planes(cm);
Imdad Sardharwalla4ec84ab2018-02-06 12:20:18 +000080 int mib_size_log2 = cm->seq_params.mib_size_log2;
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +000081 int stride = (cm->mi_cols >> mib_size_log2) + 1;
Dominic Symes917d6c02017-10-11 18:00:52 +020082 int offset = (mi_row >> mib_size_log2) * stride + (mi_col >> mib_size_log2);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070083 CB_COEFF_BUFFER *coeff_buf = &cpi->coeff_buffer_base[offset];
84 const int txb_offset = x->cb_offset / (TX_SIZE_W_MIN * TX_SIZE_H_MIN);
Hui Suad01a472018-03-01 10:46:34 -080085 assert(x->cb_offset < (1 << num_pels_log2_lookup[cm->seq_params.sb_size]));
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +000086 for (int plane = 0; plane < num_planes; ++plane) {
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070087 x->mbmi_ext->tcoeff[plane] = coeff_buf->tcoeff[plane] + x->cb_offset;
88 x->mbmi_ext->eobs[plane] = coeff_buf->eobs[plane] + txb_offset;
89 x->mbmi_ext->txb_skip_ctx[plane] =
90 coeff_buf->txb_skip_ctx[plane] + txb_offset;
91 x->mbmi_ext->dc_sign_ctx[plane] =
92 coeff_buf->dc_sign_ctx[plane] + txb_offset;
93 }
94}
95
Angie Chiang80b82262017-02-24 11:39:47 -080096static void write_golomb(aom_writer *w, int level) {
97 int x = level + 1;
98 int i = x;
99 int length = 0;
100
101 while (i) {
102 i >>= 1;
103 ++length;
104 }
105 assert(length > 0);
106
107 for (i = 0; i < length - 1; ++i) aom_write_bit(w, 0);
108
109 for (i = length - 1; i >= 0; --i) aom_write_bit(w, (x >> i) & 0x01);
110}
111
Dake Hea47cd6c2017-10-13 18:09:58 -0700112static INLINE tran_low_t get_lower_coeff(tran_low_t qc) {
113 if (qc == 0) {
114 return 0;
115 }
116 return qc > 0 ? qc - 1 : qc + 1;
117}
118
Angie Chiangb3167a62018-01-30 19:37:57 -0800119static INLINE tran_low_t qcoeff_to_dqcoeff(tran_low_t qc, int coeff_idx,
Angie Chiangb3167a62018-01-30 19:37:57 -0800120 int dqv, int shift,
121 const qm_val_t *iqmatrix) {
Angie Chiang40b07312018-03-30 10:42:55 -0700122 int sign = qc < 0 ? -1 : 1;
Angie Chiangb3167a62018-01-30 19:37:57 -0800123 if (iqmatrix != NULL)
124 dqv =
125 ((iqmatrix[coeff_idx] * dqv) + (1 << (AOM_QM_BITS - 1))) >> AOM_QM_BITS;
Angie Chiang40b07312018-03-30 10:42:55 -0700126 return sign * ((abs(qc) * dqv) >> shift);
Dake Hea47cd6c2017-10-13 18:09:58 -0700127}
128
129static INLINE int64_t get_coeff_dist(tran_low_t tcoeff, tran_low_t dqcoeff,
130 int shift) {
131 const int64_t diff = (tcoeff - dqcoeff) * (1 << shift);
132 const int64_t error = diff * diff;
133 return error;
134}
135
Urvang Joshiac97d272018-07-31 15:16:52 -0700136static const int8_t eob_to_pos_small[33] = {
137 0, 1, 2, // 0-2
138 3, 3, // 3-4
139 4, 4, 4, 4, // 5-8
140 5, 5, 5, 5, 5, 5, 5, 5, // 9-16
141 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 // 17-32
142};
143
144static const int8_t eob_to_pos_large[17] = {
145 6, // place holder
146 7, // 33-64
147 8, 8, // 65-128
148 9, 9, 9, 9, // 129-256
149 10, 10, 10, 10, 10, 10, 10, 10, // 257-512
150 11 // 513-
151};
152
153static INLINE int get_eob_pos_token(const int eob, int *const extra) {
154 int t;
155
156 if (eob < 33) {
157 t = eob_to_pos_small[eob];
158 } else {
159 const int e = AOMMIN((eob - 1) >> 5, 16);
160 t = eob_to_pos_large[e];
161 }
162
163 *extra = eob - k_eob_group_start[t];
164
165 return t;
166}
167
Yue Chen198738d2018-03-08 17:26:01 -0800168#if CONFIG_ENTROPY_STATS
Yaowu Xu49abec82018-03-13 16:09:01 -0700169void av1_update_eob_context(int cdf_idx, int eob, TX_SIZE tx_size,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900170 TX_CLASS tx_class, PLANE_TYPE plane,
Yunqing Wang0e141b52017-11-02 15:08:58 -0700171 FRAME_CONTEXT *ec_ctx, FRAME_COUNTS *counts,
172 uint8_t allow_update_cdf) {
Yue Chen198738d2018-03-08 17:26:01 -0800173#else
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900174void av1_update_eob_context(int eob, TX_SIZE tx_size, TX_CLASS tx_class,
Yaowu Xu49abec82018-03-13 16:09:01 -0700175 PLANE_TYPE plane, FRAME_CONTEXT *ec_ctx,
176 uint8_t allow_update_cdf) {
Yue Chen198738d2018-03-08 17:26:01 -0800177#endif
Yaowu Xu49abec82018-03-13 16:09:01 -0700178 int eob_extra;
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800179 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -0800180 TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Dake Hea47cd6c2017-10-13 18:09:58 -0700181
Dake He0db7d0e2017-12-21 15:23:20 -0800182 const int eob_multi_size = txsize_log2_minus4[tx_size];
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900183 const int eob_multi_ctx = (tx_class == TX_CLASS_2D) ? 0 : 1;
Dake He0db7d0e2017-12-21 15:23:20 -0800184
185 switch (eob_multi_size) {
186 case 0:
Yue Chen198738d2018-03-08 17:26:01 -0800187#if CONFIG_ENTROPY_STATS
188 ++counts->eob_multi16[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
189#endif
Dake He0db7d0e2017-12-21 15:23:20 -0800190 if (allow_update_cdf)
191 update_cdf(ec_ctx->eob_flag_cdf16[plane][eob_multi_ctx], eob_pt - 1, 5);
192 break;
193 case 1:
Yue Chen198738d2018-03-08 17:26:01 -0800194#if CONFIG_ENTROPY_STATS
195 ++counts->eob_multi32[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
196#endif
Dake He0db7d0e2017-12-21 15:23:20 -0800197 if (allow_update_cdf)
198 update_cdf(ec_ctx->eob_flag_cdf32[plane][eob_multi_ctx], eob_pt - 1, 6);
199 break;
200 case 2:
Yue Chen198738d2018-03-08 17:26:01 -0800201#if CONFIG_ENTROPY_STATS
202 ++counts->eob_multi64[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
203#endif
Dake He0db7d0e2017-12-21 15:23:20 -0800204 if (allow_update_cdf)
205 update_cdf(ec_ctx->eob_flag_cdf64[plane][eob_multi_ctx], eob_pt - 1, 7);
206 break;
207 case 3:
Yue Chen198738d2018-03-08 17:26:01 -0800208#if CONFIG_ENTROPY_STATS
209 ++counts->eob_multi128[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
210#endif
Hui Su1cb1c002018-02-05 18:21:20 -0800211 if (allow_update_cdf) {
Dake He0db7d0e2017-12-21 15:23:20 -0800212 update_cdf(ec_ctx->eob_flag_cdf128[plane][eob_multi_ctx], eob_pt - 1,
213 8);
Hui Su1cb1c002018-02-05 18:21:20 -0800214 }
Dake He0db7d0e2017-12-21 15:23:20 -0800215 break;
216 case 4:
Yue Chen198738d2018-03-08 17:26:01 -0800217#if CONFIG_ENTROPY_STATS
218 ++counts->eob_multi256[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
219#endif
Hui Su1cb1c002018-02-05 18:21:20 -0800220 if (allow_update_cdf) {
Dake He0db7d0e2017-12-21 15:23:20 -0800221 update_cdf(ec_ctx->eob_flag_cdf256[plane][eob_multi_ctx], eob_pt - 1,
222 9);
Hui Su1cb1c002018-02-05 18:21:20 -0800223 }
Dake He0db7d0e2017-12-21 15:23:20 -0800224 break;
225 case 5:
Yue Chen198738d2018-03-08 17:26:01 -0800226#if CONFIG_ENTROPY_STATS
227 ++counts->eob_multi512[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
228#endif
Hui Su1cb1c002018-02-05 18:21:20 -0800229 if (allow_update_cdf) {
Dake He0db7d0e2017-12-21 15:23:20 -0800230 update_cdf(ec_ctx->eob_flag_cdf512[plane][eob_multi_ctx], eob_pt - 1,
231 10);
Hui Su1cb1c002018-02-05 18:21:20 -0800232 }
Dake He0db7d0e2017-12-21 15:23:20 -0800233 break;
234 case 6:
235 default:
Yue Chen198738d2018-03-08 17:26:01 -0800236#if CONFIG_ENTROPY_STATS
237 ++counts->eob_multi1024[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
238#endif
Hui Su1cb1c002018-02-05 18:21:20 -0800239 if (allow_update_cdf) {
Dake He0db7d0e2017-12-21 15:23:20 -0800240 update_cdf(ec_ctx->eob_flag_cdf1024[plane][eob_multi_ctx], eob_pt - 1,
241 11);
Hui Su1cb1c002018-02-05 18:21:20 -0800242 }
Dake He0db7d0e2017-12-21 15:23:20 -0800243 break;
244 }
Jingning Han00803a72017-10-25 16:04:34 -0700245
Angie Chiang7ab884e2017-10-18 15:57:12 -0700246 if (k_eob_offset_bits[eob_pt] > 0) {
Jingning Hanff4a9f82018-06-08 10:48:45 -0700247 int eob_ctx = eob_pt - 3;
Angie Chiang7ab884e2017-10-18 15:57:12 -0700248 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
249 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Hui Su1e959892018-01-22 12:14:43 -0800250#if CONFIG_ENTROPY_STATS
Yue Chen198738d2018-03-08 17:26:01 -0800251 counts->eob_extra[cdf_idx][txs_ctx][plane][eob_pt][bit]++;
Hui Su1e959892018-01-22 12:14:43 -0800252#endif // CONFIG_ENTROPY_STATS
Yunqing Wang0e141b52017-11-02 15:08:58 -0700253 if (allow_update_cdf)
Jingning Hanff4a9f82018-06-08 10:48:45 -0700254 update_cdf(ec_ctx->eob_extra_cdf[txs_ctx][plane][eob_ctx], bit, 2);
Angie Chiang7ab884e2017-10-18 15:57:12 -0700255 }
Dake Hea47cd6c2017-10-13 18:09:58 -0700256}
257
Yaowu Xu49abec82018-03-13 16:09:01 -0700258static int get_eob_cost(int eob, const LV_MAP_EOB_COST *txb_eob_costs,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900259 const LV_MAP_COEFF_COST *txb_costs, TX_CLASS tx_class) {
Yaowu Xu49abec82018-03-13 16:09:01 -0700260 int eob_extra;
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800261 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
Dake Hea47cd6c2017-10-13 18:09:58 -0700262 int eob_cost = 0;
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900263 const int eob_multi_ctx = (tx_class == TX_CLASS_2D) ? 0 : 1;
Dake He0db7d0e2017-12-21 15:23:20 -0800264 eob_cost = txb_eob_costs->eob_cost[eob_multi_ctx][eob_pt - 1];
Dake He0db7d0e2017-12-21 15:23:20 -0800265
Dake Hea47cd6c2017-10-13 18:09:58 -0700266 if (k_eob_offset_bits[eob_pt] > 0) {
Jingning Hanff4a9f82018-06-08 10:48:45 -0700267 const int eob_ctx = eob_pt - 3;
Hui Su751a2332018-01-23 11:35:03 -0800268 const int eob_shift = k_eob_offset_bits[eob_pt] - 1;
269 const int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Jingning Hanff4a9f82018-06-08 10:48:45 -0700270 eob_cost += txb_costs->eob_extra_cost[eob_ctx][bit];
Hui Su751a2332018-01-23 11:35:03 -0800271 const int offset_bits = k_eob_offset_bits[eob_pt];
272 if (offset_bits > 1) eob_cost += av1_cost_literal(offset_bits - 1);
Dake Hea47cd6c2017-10-13 18:09:58 -0700273 }
274 return eob_cost;
275}
276
Angie Chiange4ea7482018-03-15 11:36:41 -0700277static INLINE int get_sign_bit_cost(tran_low_t qc, int coeff_idx,
278 const int (*dc_sign_cost)[2],
279 int dc_sign_ctx) {
Angie Chiange4ea7482018-03-15 11:36:41 -0700280 if (coeff_idx == 0) {
Angie Chiang2f94a452018-04-03 20:21:06 -0700281 const int sign = (qc < 0) ? 1 : 0;
Angie Chiange4ea7482018-03-15 11:36:41 -0700282 return dc_sign_cost[dc_sign_ctx][sign];
Angie Chiange4ea7482018-03-15 11:36:41 -0700283 }
Angie Chiang40b07312018-03-30 10:42:55 -0700284 return av1_cost_literal(1);
Angie Chiange4ea7482018-03-15 11:36:41 -0700285}
286
287static INLINE int get_br_cost(tran_low_t abs_qc, int ctx,
288 const int *coeff_lps) {
289 const tran_low_t min_level = 1 + NUM_BASE_LEVELS;
290 const tran_low_t max_level = 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE;
291 (void)ctx;
292 if (abs_qc >= min_level) {
Angie Chiang40b07312018-03-30 10:42:55 -0700293 if (abs_qc >= max_level) {
Angie Chiange4ea7482018-03-15 11:36:41 -0700294 return coeff_lps[COEFF_BASE_RANGE]; // COEFF_BASE_RANGE * cost0;
Angie Chiang40b07312018-03-30 10:42:55 -0700295 } else {
Angie Chiange4ea7482018-03-15 11:36:41 -0700296 return coeff_lps[(abs_qc - min_level)]; // * cost0 + cost1;
Angie Chiang40b07312018-03-30 10:42:55 -0700297 }
Angie Chiange4ea7482018-03-15 11:36:41 -0700298 }
Angie Chiang40b07312018-03-30 10:42:55 -0700299 return 0;
Angie Chiange4ea7482018-03-15 11:36:41 -0700300}
301
302static INLINE int get_golomb_cost(int abs_qc) {
303 if (abs_qc >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
304 const int r = abs_qc - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
305 const int length = get_msb(r) + 1;
306 return av1_cost_literal(2 * length - 1);
307 }
308 return 0;
309}
310
Linfeng Zhang1015a342017-10-24 16:20:41 -0700311static int get_coeff_cost(const tran_low_t qc, const int scan_idx,
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100312 const int is_eob, const TxbInfo *const txb_info,
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -0800313 const LV_MAP_COEFF_COST *const txb_costs,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900314 const int coeff_ctx, const TX_CLASS tx_class) {
Xing Jinbd91e942018-06-21 13:43:17 +0800315 const TXB_CTX *const txb_ctx = txb_info->txb_ctx;
Angie Chiange4ea7482018-03-15 11:36:41 -0700316 const int is_nz = (qc != 0);
317 const tran_low_t abs_qc = abs(qc);
318 int cost = 0;
319 const int16_t *const scan = txb_info->scan_order->scan;
320 const int pos = scan[scan_idx];
321
322 if (is_eob) {
323 cost += txb_costs->base_eob_cost[coeff_ctx][AOMMIN(abs_qc, 3) - 1];
324 } else {
325 cost += txb_costs->base_cost[coeff_ctx][AOMMIN(abs_qc, 3)];
326 }
327 if (is_nz) {
328 cost += get_sign_bit_cost(qc, scan_idx, txb_costs->dc_sign_cost,
329 txb_ctx->dc_sign_ctx);
330
331 if (abs_qc > NUM_BASE_LEVELS) {
332 const int ctx =
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900333 get_br_ctx(txb_info->levels, pos, txb_info->bwl, tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -0700334 cost += get_br_cost(abs_qc, ctx, txb_costs->lps_cost[ctx]);
335 cost += get_golomb_cost(abs_qc);
336 }
337 }
338 return cost;
339}
Dake Hea47cd6c2017-10-13 18:09:58 -0700340
Frederic Barbiere8c67522018-03-27 15:09:57 +0200341static INLINE int get_nz_map_ctx(const uint8_t *const levels,
342 const int coeff_idx, const int bwl,
343 const int height, const int scan_idx,
344 const int is_eob, const TX_SIZE tx_size,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900345 const TX_CLASS tx_class) {
Frederic Barbiere8c67522018-03-27 15:09:57 +0200346 if (is_eob) {
347 if (scan_idx == 0) return 0;
348 if (scan_idx <= (height << bwl) / 8) return 1;
349 if (scan_idx <= (height << bwl) / 4) return 2;
350 return 3;
351 }
Frederic Barbiere8c67522018-03-27 15:09:57 +0200352 const int stats =
353 get_nz_mag(levels + get_padded_idx(coeff_idx, bwl), bwl, tx_class);
354 return get_nz_map_ctx_from_stats(stats, coeff_idx, bwl, tx_size, tx_class);
355}
356
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800357static void get_dist_cost_stats(LevelDownStats *const stats, const int scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +0100358 const int is_eob,
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800359 const LV_MAP_COEFF_COST *const txb_costs,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900360 const TxbInfo *const txb_info,
361 const TX_CLASS tx_class) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800362 const int16_t *const scan = txb_info->scan_order->scan;
Dake Hea47cd6c2017-10-13 18:09:58 -0700363 const int coeff_idx = scan[scan_idx];
364 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
Linfeng Zhang1015a342017-10-24 16:20:41 -0700365 const uint8_t *const levels = txb_info->levels;
Dake Hea47cd6c2017-10-13 18:09:58 -0700366 stats->new_eob = -1;
367 stats->update = 0;
Debargha Mukherjeee2f6b162018-01-04 17:23:05 -0800368 stats->rd_low = 0;
369 stats->rd = 0;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -0800370 stats->nz_rd = 0;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -0800371 stats->dist_low = 0;
372 stats->rate_low = 0;
373 stats->low_qc = 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700374
375 const tran_low_t tqc = txb_info->tcoeff[coeff_idx];
376 const int dqv = txb_info->dequant[coeff_idx != 0];
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100377 const int coeff_ctx =
378 get_nz_map_ctx(levels, coeff_idx, txb_info->bwl, txb_info->height,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900379 scan_idx, is_eob, txb_info->tx_size, tx_class);
380 const int qc_cost = get_coeff_cost(qc, scan_idx, is_eob, txb_info, txb_costs,
381 coeff_ctx, tx_class);
Angie Chiang99b12422018-03-02 17:15:00 -0800382 assert(qc != 0);
383 const tran_low_t dqc = qcoeff_to_dqcoeff(qc, coeff_idx, dqv, txb_info->shift,
384 txb_info->iqmatrix);
385 const int64_t dqc_dist = get_coeff_dist(tqc, dqc, txb_info->shift);
Cheng Chen79641202018-01-04 18:52:52 -0800386
Angie Chiang99b12422018-03-02 17:15:00 -0800387 // distortion difference when coefficient is quantized to 0
388 const tran_low_t dqc0 =
389 qcoeff_to_dqcoeff(0, coeff_idx, dqv, txb_info->shift, txb_info->iqmatrix);
Cheng Chen79641202018-01-04 18:52:52 -0800390
Angie Chiang99b12422018-03-02 17:15:00 -0800391 stats->dist0 = get_coeff_dist(tqc, dqc0, txb_info->shift);
392 stats->dist = dqc_dist - stats->dist0;
393 stats->rate = qc_cost;
Cheng Chen79641202018-01-04 18:52:52 -0800394
Dake Hea47cd6c2017-10-13 18:09:58 -0700395 stats->rd = RDCOST(txb_info->rdmult, stats->rate, stats->dist);
396
397 stats->low_qc = get_lower_coeff(qc);
Dake Hea47cd6c2017-10-13 18:09:58 -0700398
Dake He4d447692017-12-15 09:10:06 -0800399 if (is_eob && stats->low_qc == 0) {
Dake He4d447692017-12-15 09:10:06 -0800400 stats->rd_low = stats->rd; // disable selection of low_qc in this case.
Ola Hugosson13892102017-11-06 08:01:44 +0100401 } else {
Cheng Chen37d88732018-01-09 14:02:41 -0800402 if (stats->low_qc == 0) {
403 stats->dist_low = 0;
404 } else {
Frederic Barbiere111cba2018-02-20 16:11:28 +0100405 stats->low_dqc = qcoeff_to_dqcoeff(stats->low_qc, coeff_idx, dqv,
406 txb_info->shift, txb_info->iqmatrix);
Cheng Chen37d88732018-01-09 14:02:41 -0800407 const int64_t low_dqc_dist =
408 get_coeff_dist(tqc, stats->low_dqc, txb_info->shift);
409 stats->dist_low = low_dqc_dist - stats->dist0;
410 }
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900411 const int low_qc_cost =
412 get_coeff_cost(stats->low_qc, scan_idx, is_eob, txb_info, txb_costs,
413 coeff_ctx, tx_class);
Dake He4d447692017-12-15 09:10:06 -0800414 stats->rate_low = low_qc_cost;
415 stats->rd_low = RDCOST(txb_info->rdmult, stats->rate_low, stats->dist_low);
Ola Hugosson13892102017-11-06 08:01:44 +0100416 }
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800417}
Cheng Chen37d88732018-01-09 14:02:41 -0800418
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800419static void get_dist_cost_stats_with_eob(
420 LevelDownStats *const stats, const int scan_idx,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900421 const LV_MAP_COEFF_COST *const txb_costs, const TxbInfo *const txb_info,
422 const TX_CLASS tx_class) {
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800423 const int is_eob = 0;
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900424 get_dist_cost_stats(stats, scan_idx, is_eob, txb_costs, txb_info, tx_class);
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800425
426 const int16_t *const scan = txb_info->scan_order->scan;
427 const int coeff_idx = scan[scan_idx];
428 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
429 const int coeff_ctx_temp = get_nz_map_ctx(
430 txb_info->levels, coeff_idx, txb_info->bwl, txb_info->height, scan_idx, 1,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900431 txb_info->tx_size, tx_class);
432 const int qc_eob_cost = get_coeff_cost(qc, scan_idx, 1, txb_info, txb_costs,
433 coeff_ctx_temp, tx_class);
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800434 int64_t rd_eob = RDCOST(txb_info->rdmult, qc_eob_cost, stats->dist);
435 if (stats->low_qc != 0) {
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900436 const int low_qc_eob_cost =
437 get_coeff_cost(stats->low_qc, scan_idx, 1, txb_info, txb_costs,
438 coeff_ctx_temp, tx_class);
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800439 int64_t rd_eob_low =
440 RDCOST(txb_info->rdmult, low_qc_eob_cost, stats->dist_low);
441 rd_eob = (rd_eob > rd_eob_low) ? rd_eob_low : rd_eob;
Cheng Chen37d88732018-01-09 14:02:41 -0800442 }
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800443
444 stats->nz_rd = AOMMIN(stats->rd_low, stats->rd) - rd_eob;
Dake Hea47cd6c2017-10-13 18:09:58 -0700445}
446
Linfeng Zhang1015a342017-10-24 16:20:41 -0700447static INLINE void update_qcoeff(const int coeff_idx, const tran_low_t qc,
448 const TxbInfo *const txb_info) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700449 txb_info->qcoeff[coeff_idx] = qc;
Linfeng Zhangd5647372017-12-05 17:06:07 -0800450 txb_info->levels[get_padded_idx(coeff_idx, txb_info->bwl)] =
Jingning Han5cb408e2017-11-17 14:43:39 -0800451 (uint8_t)clamp(abs(qc), 0, INT8_MAX);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700452}
453
454static INLINE void update_coeff(const int coeff_idx, const tran_low_t qc,
455 const TxbInfo *const txb_info) {
456 update_qcoeff(coeff_idx, qc, txb_info);
Dake Hea47cd6c2017-10-13 18:09:58 -0700457 const int dqv = txb_info->dequant[coeff_idx != 0];
Frederic Barbiere111cba2018-02-20 16:11:28 +0100458 txb_info->dqcoeff[coeff_idx] = qcoeff_to_dqcoeff(
459 qc, coeff_idx, dqv, txb_info->shift, txb_info->iqmatrix);
Dake Hea47cd6c2017-10-13 18:09:58 -0700460}
461
Peng Bin27d7ca92018-03-22 22:25:56 +0800462void av1_txb_init_levels_c(const tran_low_t *const coeff, const int width,
463 const int height, uint8_t *const levels) {
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700464 const int stride = width + TX_PAD_HOR;
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700465 uint8_t *ls = levels;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700466
467 memset(levels - TX_PAD_TOP * stride, 0,
468 sizeof(*levels) * TX_PAD_TOP * stride);
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700469 memset(levels + stride * height, 0,
470 sizeof(*levels) * (TX_PAD_BOTTOM * stride + TX_PAD_END));
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700471
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700472 for (int i = 0; i < height; i++) {
473 for (int j = 0; j < width; j++) {
Jingning Han5cb408e2017-11-17 14:43:39 -0800474 *ls++ = (uint8_t)clamp(abs(coeff[i * width + j]), 0, INT8_MAX);
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700475 }
476 for (int j = 0; j < TX_PAD_HOR; j++) {
477 *ls++ = 0;
478 }
Linfeng Zhang1015a342017-10-24 16:20:41 -0700479 }
480}
481
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800482void av1_get_nz_map_contexts_c(const uint8_t *const levels,
483 const int16_t *const scan, const uint16_t eob,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900484 const TX_SIZE tx_size, const TX_CLASS tx_class,
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800485 int8_t *const coeff_contexts) {
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800486 const int bwl = get_txb_bwl(tx_size);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800487 const int height = get_txb_high(tx_size);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800488 for (int i = 0; i < eob; ++i) {
489 const int pos = scan[i];
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100490 coeff_contexts[pos] = get_nz_map_ctx(levels, pos, bwl, height, i,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900491 i == eob - 1, tx_size, tx_class);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800492 }
493}
494
Angie Chiang80b82262017-02-24 11:39:47 -0800495void av1_write_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCKD *xd,
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500496 aom_writer *w, int blk_row, int blk_col, int plane,
497 TX_SIZE tx_size, const tran_low_t *tcoeff,
Jingning Han7eab9ff2017-07-06 10:12:54 -0700498 uint16_t eob, TXB_CTX *txb_ctx) {
Angie Chiangcea11f22017-02-24 12:30:40 -0800499 const PLANE_TYPE plane_type = get_plane_type(plane);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -0800500 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Sarah Parker7c71cc02018-01-29 12:27:58 -0800501 const TX_TYPE tx_type = av1_get_tx_type(plane_type, xd, blk_row, blk_col,
502 tx_size, cm->reduced_tx_set_used);
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900503 const TX_CLASS tx_class = tx_type_to_class[tx_type];
Yaowu Xuf1e12932018-02-26 15:50:09 -0800504 const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800505 const int16_t *const scan = scan_order->scan;
Angie Chiang80b82262017-02-24 11:39:47 -0800506 int c;
Angie Chianga9ba58e2017-12-01 19:22:43 -0800507 const int bwl = get_txb_bwl(tx_size);
508 const int width = get_txb_wide(tx_size);
509 const int height = get_txb_high(tx_size);
Jingning Han41c7f442017-09-05 14:54:00 -0700510 FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700511 uint8_t levels_buf[TX_PAD_2D];
512 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800513 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Angie Chiang80b82262017-02-24 11:39:47 -0800514
Hui Su41d61522018-01-23 10:47:55 -0800515 aom_write_symbol(w, eob == 0,
516 ec_ctx->txb_skip_cdf[txs_ctx][txb_ctx->txb_skip_ctx], 2);
Angie Chianga3f7d2e2017-12-07 19:51:14 -0800517 if (plane == 0 && eob == 0) {
518 assert(tx_type == DCT_DCT);
519 }
Angie Chiang80b82262017-02-24 11:39:47 -0800520 if (eob == 0) return;
Linfeng Zhangce065ca2017-10-17 16:49:30 -0700521
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700522 av1_txb_init_levels(tcoeff, width, height, levels);
Linfeng Zhangce065ca2017-10-17 16:49:30 -0700523
Debargha Mukherjee3ebb0d02017-12-14 05:05:18 -0800524 av1_write_tx_type(cm, xd, blk_row, blk_col, plane, tx_size, w);
Angie Chiang80b82262017-02-24 11:39:47 -0800525
Yaowu Xu49abec82018-03-13 16:09:01 -0700526 int eob_extra;
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800527 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
Dake He0db7d0e2017-12-21 15:23:20 -0800528 const int eob_multi_size = txsize_log2_minus4[tx_size];
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900529 const int eob_multi_ctx = (tx_class == TX_CLASS_2D) ? 0 : 1;
Dake He0db7d0e2017-12-21 15:23:20 -0800530 switch (eob_multi_size) {
531 case 0:
532 aom_write_symbol(w, eob_pt - 1,
533 ec_ctx->eob_flag_cdf16[plane_type][eob_multi_ctx], 5);
534 break;
535 case 1:
536 aom_write_symbol(w, eob_pt - 1,
537 ec_ctx->eob_flag_cdf32[plane_type][eob_multi_ctx], 6);
538 break;
539 case 2:
540 aom_write_symbol(w, eob_pt - 1,
541 ec_ctx->eob_flag_cdf64[plane_type][eob_multi_ctx], 7);
542 break;
543 case 3:
544 aom_write_symbol(w, eob_pt - 1,
545 ec_ctx->eob_flag_cdf128[plane_type][eob_multi_ctx], 8);
546 break;
547 case 4:
548 aom_write_symbol(w, eob_pt - 1,
549 ec_ctx->eob_flag_cdf256[plane_type][eob_multi_ctx], 9);
550 break;
551 case 5:
552 aom_write_symbol(w, eob_pt - 1,
553 ec_ctx->eob_flag_cdf512[plane_type][eob_multi_ctx], 10);
554 break;
555 default:
556 aom_write_symbol(w, eob_pt - 1,
557 ec_ctx->eob_flag_cdf1024[plane_type][eob_multi_ctx], 11);
558 break;
559 }
560
Dake Hea47cd6c2017-10-13 18:09:58 -0700561 if (k_eob_offset_bits[eob_pt] > 0) {
Jingning Hanff4a9f82018-06-08 10:48:45 -0700562 const int eob_ctx = eob_pt - 3;
Angie Chiang7ab884e2017-10-18 15:57:12 -0700563 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
564 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Jingning Hanff4a9f82018-06-08 10:48:45 -0700565 aom_write_symbol(w, bit,
566 ec_ctx->eob_extra_cdf[txs_ctx][plane_type][eob_ctx], 2);
Angie Chiang7ab884e2017-10-18 15:57:12 -0700567 for (int i = 1; i < k_eob_offset_bits[eob_pt]; i++) {
568 eob_shift = k_eob_offset_bits[eob_pt] - 1 - i;
569 bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700570 aom_write_bit(w, bit);
Dake Hea47cd6c2017-10-13 18:09:58 -0700571 }
572 }
Dake He03a32922017-10-31 08:06:45 -0700573
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900574 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_class, coeff_contexts);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800575
576 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800577 const int pos = scan[c];
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800578 const int coeff_ctx = coeff_contexts[pos];
579 const tran_low_t v = tcoeff[pos];
Angie Chiang41220ab2018-02-14 17:48:23 -0800580 const tran_low_t level = abs(v);
Dake He03a32922017-10-31 08:06:45 -0700581
Dake He3fe369c2017-11-16 17:56:44 -0800582 if (c == eob - 1) {
583 aom_write_symbol(
Angie Chiang41220ab2018-02-14 17:48:23 -0800584 w, AOMMIN(level, 3) - 1,
Dake He4d447692017-12-15 09:10:06 -0800585 ec_ctx->coeff_base_eob_cdf[txs_ctx][plane_type][coeff_ctx], 3);
Dake He3fe369c2017-11-16 17:56:44 -0800586 } else {
Angie Chiang41220ab2018-02-14 17:48:23 -0800587 aom_write_symbol(w, AOMMIN(level, 3),
Dake He3fe369c2017-11-16 17:56:44 -0800588 ec_ctx->coeff_base_cdf[txs_ctx][plane_type][coeff_ctx],
589 4);
590 }
Angie Chiang41220ab2018-02-14 17:48:23 -0800591 if (level > NUM_BASE_LEVELS) {
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100592 // level is above 1.
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800593 const int base_range = level - 1 - NUM_BASE_LEVELS;
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900594 const int br_ctx = get_br_ctx(levels, pos, bwl, tx_class);
Angie Chiang41220ab2018-02-14 17:48:23 -0800595 for (int idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800596 const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
Angie Chiang6d5419c2018-02-20 15:12:15 -0800597 aom_write_symbol(
598 w, k,
599 ec_ctx->coeff_br_cdf[AOMMIN(txs_ctx, TX_32X32)][plane_type][br_ctx],
600 BR_CDF_SIZE);
Ola Hugossone72a2092017-11-12 09:11:53 +0100601 if (k < BR_CDF_SIZE - 1) break;
602 }
Angie Chiang6d5419c2018-02-20 15:12:15 -0800603 }
604 }
605
606 // Loop to code all signs in the transform block,
607 // starting with the sign of DC (if applicable)
608 for (c = 0; c < eob; ++c) {
609 const tran_low_t v = tcoeff[scan[c]];
610 const tran_low_t level = abs(v);
611 const int sign = (v < 0) ? 1 : 0;
612 if (level) {
613 if (c == 0) {
614 aom_write_symbol(
615 w, sign, ec_ctx->dc_sign_cdf[plane_type][txb_ctx->dc_sign_ctx], 2);
616 } else {
617 aom_write_bit(w, sign);
618 }
Yushin Cho73711d52018-05-04 13:59:46 -0700619 if (level > COEFF_BASE_RANGE + NUM_BASE_LEVELS)
620 write_golomb(w, level - COEFF_BASE_RANGE - 1 - NUM_BASE_LEVELS);
Angie Chiang41220ab2018-02-14 17:48:23 -0800621 }
622 }
Angie Chiang80b82262017-02-24 11:39:47 -0800623}
Angie Chiang47c72182017-02-27 14:30:38 -0800624
Angie Chiang140b3332017-12-12 17:29:25 -0800625typedef struct encode_txb_args {
626 const AV1_COMMON *cm;
627 MACROBLOCK *x;
628 aom_writer *w;
629} ENCODE_TXB_ARGS;
630
Jingning Han3a32e102018-01-11 16:00:35 -0800631static void write_coeffs_txb_wrap(const AV1_COMMON *cm, MACROBLOCK *x,
632 aom_writer *w, int plane, int block,
633 int blk_row, int blk_col, TX_SIZE tx_size) {
Angie Chiangc8af6112017-03-16 16:11:22 -0700634 MACROBLOCKD *xd = &x->e_mbd;
Angie Chiang140b3332017-12-12 17:29:25 -0800635 tran_low_t *tcoeff = BLOCK_OFFSET(x->mbmi_ext->tcoeff[plane], block);
636 uint16_t eob = x->mbmi_ext->eobs[plane][block];
637 TXB_CTX txb_ctx = { x->mbmi_ext->txb_skip_ctx[plane][block],
638 x->mbmi_ext->dc_sign_ctx[plane][block] };
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500639 av1_write_coeffs_txb(cm, xd, w, blk_row, blk_col, plane, tx_size, tcoeff, eob,
640 &txb_ctx);
Angie Chiang140b3332017-12-12 17:29:25 -0800641}
642
Jingning Han4b48cd12018-01-11 15:56:42 -0800643void av1_write_coeffs_mb(const AV1_COMMON *const cm, MACROBLOCK *x, int mi_row,
Jingning Hanad54a982018-01-12 14:40:29 -0800644 int mi_col, aom_writer *w, BLOCK_SIZE bsize) {
Angie Chiang140b3332017-12-12 17:29:25 -0800645 MACROBLOCKD *xd = &x->e_mbd;
Jingning Hanad54a982018-01-12 14:40:29 -0800646 const int num_planes = av1_num_planes(cm);
647 int block[MAX_MB_PLANE] = { 0 };
Jingning Han4b48cd12018-01-11 15:56:42 -0800648 int row, col;
Cheng Chen8ab1f442018-04-27 18:01:52 -0700649 assert(bsize == get_plane_block_size(bsize, xd->plane[0].subsampling_x,
650 xd->plane[0].subsampling_y));
Yushin Choca63a8b2018-04-20 16:46:36 -0700651 const int max_blocks_wide = max_block_wide(xd, bsize, 0);
652 const int max_blocks_high = max_block_high(xd, bsize, 0);
653 const BLOCK_SIZE max_unit_bsize = BLOCK_64X64;
Jingning Han4b48cd12018-01-11 15:56:42 -0800654 int mu_blocks_wide = block_size_wide[max_unit_bsize] >> tx_size_wide_log2[0];
655 int mu_blocks_high = block_size_high[max_unit_bsize] >> tx_size_high_log2[0];
656 mu_blocks_wide = AOMMIN(max_blocks_wide, mu_blocks_wide);
657 mu_blocks_high = AOMMIN(max_blocks_high, mu_blocks_high);
658
659 for (row = 0; row < max_blocks_high; row += mu_blocks_high) {
Jingning Han4b48cd12018-01-11 15:56:42 -0800660 for (col = 0; col < max_blocks_wide; col += mu_blocks_wide) {
Jingning Hanad54a982018-01-12 14:40:29 -0800661 for (int plane = 0; plane < num_planes; ++plane) {
662 const struct macroblockd_plane *const pd = &xd->plane[plane];
663 if (!is_chroma_reference(mi_row, mi_col, bsize, pd->subsampling_x,
664 pd->subsampling_y))
665 continue;
666 const TX_SIZE tx_size = av1_get_tx_size(plane, xd);
667 const int stepr = tx_size_high_unit[tx_size];
668 const int stepc = tx_size_wide_unit[tx_size];
669 const int step = stepr * stepc;
Jingning Han4b48cd12018-01-11 15:56:42 -0800670
Jingning Hanad54a982018-01-12 14:40:29 -0800671 const int unit_height = ROUND_POWER_OF_TWO(
672 AOMMIN(mu_blocks_high + row, max_blocks_high), pd->subsampling_y);
673 const int unit_width = ROUND_POWER_OF_TWO(
674 AOMMIN(mu_blocks_wide + col, max_blocks_wide), pd->subsampling_x);
675 for (int blk_row = row >> pd->subsampling_y; blk_row < unit_height;
676 blk_row += stepr) {
677 for (int blk_col = col >> pd->subsampling_x; blk_col < unit_width;
678 blk_col += stepc) {
679 write_coeffs_txb_wrap(cm, x, w, plane, block[plane], blk_row,
680 blk_col, tx_size);
681 block[plane] += step;
682 }
Jingning Han4b48cd12018-01-11 15:56:42 -0800683 }
684 }
685 }
686 }
Angie Chiangc8af6112017-03-16 16:11:22 -0700687}
688
Urvang Joshi553096a2018-05-10 15:27:14 -0700689// TODO(angiebird): use this function whenever it's possible
690static int get_tx_type_cost(const AV1_COMMON *cm, const MACROBLOCK *x,
691 const MACROBLOCKD *xd, int plane, TX_SIZE tx_size,
692 TX_TYPE tx_type) {
693 if (plane > 0) return 0;
694
695 const TX_SIZE square_tx_size = txsize_sqr_map[tx_size];
696
697 const MB_MODE_INFO *mbmi = xd->mi[0];
698 const int is_inter = is_inter_block(mbmi);
699 if (get_ext_tx_types(tx_size, is_inter, cm->reduced_tx_set_used) > 1 &&
700 !xd->lossless[xd->mi[0]->segment_id]) {
701 const int ext_tx_set =
702 get_ext_tx_set(tx_size, is_inter, cm->reduced_tx_set_used);
703 if (is_inter) {
704 if (ext_tx_set > 0)
705 return x->inter_tx_type_costs[ext_tx_set][square_tx_size][tx_type];
706 } else {
707 if (ext_tx_set > 0) {
708 PREDICTION_MODE intra_dir;
709 if (mbmi->filter_intra_mode_info.use_filter_intra)
710 intra_dir = fimode_to_intradir[mbmi->filter_intra_mode_info
711 .filter_intra_mode];
712 else
713 intra_dir = mbmi->mode;
714 return x->intra_tx_type_costs[ext_tx_set][square_tx_size][intra_dir]
715 [tx_type];
716 }
717 }
718 }
719 return 0;
720}
721
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900722static AOM_FORCE_INLINE int warehouse_efficients_txb(
723 const AV1_COMMON *const cm, const MACROBLOCK *x, const int plane,
724 const int block, const TX_SIZE tx_size, const TXB_CTX *const txb_ctx,
725 const struct macroblock_plane *p, const int eob,
726 const PLANE_TYPE plane_type, const LV_MAP_COEFF_COST *const coeff_costs,
727 const MACROBLOCKD *const xd, const TX_TYPE tx_type,
728 const TX_CLASS tx_class) {
Angie Chiang47c72182017-02-27 14:30:38 -0800729 const tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800730 const int txb_skip_ctx = txb_ctx->txb_skip_ctx;
Angie Chianga9ba58e2017-12-01 19:22:43 -0800731 const int bwl = get_txb_bwl(tx_size);
732 const int width = get_txb_wide(tx_size);
733 const int height = get_txb_high(tx_size);
Yaowu Xuf1e12932018-02-26 15:50:09 -0800734 const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800735 const int16_t *const scan = scan_order->scan;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700736 uint8_t levels_buf[TX_PAD_2D];
737 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800738 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Dake He0db7d0e2017-12-21 15:23:20 -0800739 const int eob_multi_size = txsize_log2_minus4[tx_size];
740 const LV_MAP_EOB_COST *const eob_costs =
741 &x->eob_costs[eob_multi_size][plane_type];
Hui Su18205542018-03-30 11:37:41 -0700742 int cost = coeff_costs->txb_skip_cost[txb_skip_ctx][0];
Angie Chiang47c72182017-02-27 14:30:38 -0800743
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700744 av1_txb_init_levels(qcoeff, width, height, levels);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700745
Urvang Joshi553096a2018-05-10 15:27:14 -0700746 cost += get_tx_type_cost(cm, x, xd, plane, tx_size, tx_type);
Angie Chiang05917872017-04-15 12:28:56 -0700747
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900748 cost += get_eob_cost(eob, eob_costs, coeff_costs, tx_class);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800749
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900750 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_class, coeff_contexts);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800751
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900752 const int(*lps_cost)[COEFF_BASE_RANGE + 1] = coeff_costs->lps_cost;
753 int c = eob - 1;
754 {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800755 const int pos = scan[c];
756 const tran_low_t v = qcoeff[pos];
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900757 const int sign = v >> 31;
758 const int level = (v ^ sign) - sign;
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800759 const int coeff_ctx = coeff_contexts[pos];
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900760 cost += coeff_costs->base_eob_cost[coeff_ctx][AOMMIN(level, 3) - 1];
Dake Hea47cd6c2017-10-13 18:09:58 -0700761
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900762 if (v) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700763 // sign bit cost
Dake Hea47cd6c2017-10-13 18:09:58 -0700764 if (level > NUM_BASE_LEVELS) {
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900765 const int ctx = get_br_ctx(levels, pos, bwl, tx_class);
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900766 const int base_range =
767 AOMMIN(level - 1 - NUM_BASE_LEVELS, COEFF_BASE_RANGE);
768 cost += lps_cost[ctx][base_range];
769 cost += get_golomb_cost(level);
770 }
771 if (c) {
772 cost += av1_cost_literal(1);
773 } else {
774 const int sign01 = (sign ^ sign) - sign;
775 const int dc_sign_ctx = txb_ctx->dc_sign_ctx;
776 cost += coeff_costs->dc_sign_cost[dc_sign_ctx][sign01];
777 return cost;
778 }
779 }
780 }
781 const int(*base_cost)[4] = coeff_costs->base_cost;
782 for (c = eob - 2; c >= 1; --c) {
783 const int pos = scan[c];
784 const int coeff_ctx = coeff_contexts[pos];
785 const tran_low_t v = qcoeff[pos];
786 const int level = abs(v);
787 const int cost0 = base_cost[coeff_ctx][AOMMIN(level, 3)];
788 if (v) {
789 // sign bit cost
790 cost += av1_cost_literal(1);
791 if (level > NUM_BASE_LEVELS) {
792 const int ctx = get_br_ctx(levels, pos, bwl, tx_class);
793 const int base_range =
794 AOMMIN(level - 1 - NUM_BASE_LEVELS, COEFF_BASE_RANGE);
795 cost += lps_cost[ctx][base_range];
796 cost += get_golomb_cost(level);
797 }
798 }
799 cost += cost0;
800 }
801 if (c == 0) {
802 const int pos = scan[c];
803 const tran_low_t v = qcoeff[pos];
804 const int coeff_ctx = coeff_contexts[pos];
805 const int sign = v >> 31;
806 const int level = (v ^ sign) - sign;
807 cost += base_cost[coeff_ctx][AOMMIN(level, 3)];
Dake Hea47cd6c2017-10-13 18:09:58 -0700808
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900809 if (v) {
810 // sign bit cost
811 const int sign01 = (sign ^ sign) - sign;
812 const int dc_sign_ctx = txb_ctx->dc_sign_ctx;
813 cost += coeff_costs->dc_sign_cost[dc_sign_ctx][sign01];
814 if (level > NUM_BASE_LEVELS) {
815 const int ctx = get_br_ctx(levels, pos, bwl, tx_class);
816 const int base_range =
817 AOMMIN(level - 1 - NUM_BASE_LEVELS, COEFF_BASE_RANGE);
818 cost += lps_cost[ctx][base_range];
819 cost += get_golomb_cost(level);
Dake Hea47cd6c2017-10-13 18:09:58 -0700820 }
821 }
822 }
Angie Chiang47c72182017-02-27 14:30:38 -0800823 return cost;
824}
Angie Chiang0397eda2017-03-15 16:57:14 -0700825
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900826int av1_cost_coeffs_txb(const AV1_COMMON *const cm, const MACROBLOCK *x,
Xing Jin3a43b3b2018-06-25 15:41:38 +0800827 const int plane, const int block, const TX_SIZE tx_size,
828 const TX_TYPE tx_type, const TXB_CTX *const txb_ctx) {
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900829 const struct macroblock_plane *p = &x->plane[plane];
830 const int eob = p->eobs[block];
831 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
832 const PLANE_TYPE plane_type = get_plane_type(plane);
833 const LV_MAP_COEFF_COST *const coeff_costs =
834 &x->coeff_costs[txs_ctx][plane_type];
835 if (eob == 0) {
836 return coeff_costs->txb_skip_cost[txb_ctx->txb_skip_ctx][1];
837 }
838
839 const MACROBLOCKD *const xd = &x->e_mbd;
Katsuhisa Yuasa51467032018-04-08 16:16:10 +0900840 const TX_CLASS tx_class = tx_type_to_class[tx_type];
841
842#define WAREHOUSE_EFFICIENTS_TXB_CASE(tx_class_literal) \
843 case tx_class_literal: \
844 return warehouse_efficients_txb(cm, x, plane, block, tx_size, txb_ctx, p, \
845 eob, plane_type, coeff_costs, xd, tx_type, \
846 tx_class_literal);
847 switch (tx_class) {
848 WAREHOUSE_EFFICIENTS_TXB_CASE(TX_CLASS_2D);
849 WAREHOUSE_EFFICIENTS_TXB_CASE(TX_CLASS_HORIZ);
850 WAREHOUSE_EFFICIENTS_TXB_CASE(TX_CLASS_VERT);
851#undef WAREHOUSE_EFFICIENTS_TXB_CASE
852 default: assert(false); return 0;
853 }
854}
855
Dake Hea47cd6c2017-10-13 18:09:58 -0700856static int optimize_txb(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang45385b82018-03-02 15:25:58 -0800857 const LV_MAP_EOB_COST *txb_eob_costs, int *rate_cost) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700858 int update = 0;
859 if (txb_info->eob == 0) return update;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800860 const int16_t *const scan = txb_info->scan_order->scan;
Dake Hea47cd6c2017-10-13 18:09:58 -0700861 // forward optimize the nz_map`
862 const int init_eob = txb_info->eob;
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900863 const TX_CLASS tx_class = tx_type_to_class[txb_info->tx_type];
Yaowu Xu49abec82018-03-13 16:09:01 -0700864 const int eob_cost =
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900865 get_eob_cost(init_eob, txb_eob_costs, txb_costs, tx_class);
Dake Hea47cd6c2017-10-13 18:09:58 -0700866
867 // backward optimize the level-k map
Cheng Chen82775f62018-01-18 12:09:54 -0800868 int accu_rate = eob_cost;
Dake Hea47cd6c2017-10-13 18:09:58 -0700869 int64_t accu_dist = 0;
870 int64_t prev_eob_rd_cost = INT64_MAX;
871 int64_t cur_eob_rd_cost = 0;
872
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800873 {
874 const int si = init_eob - 1;
875 const int coeff_idx = scan[si];
876 LevelDownStats stats;
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900877 get_dist_cost_stats(&stats, si, si == init_eob - 1, txb_costs, txb_info,
878 tx_class);
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800879 if ((stats.rd_low < stats.rd) && (stats.low_qc != 0)) {
880 update = 1;
881 update_coeff(coeff_idx, stats.low_qc, txb_info);
882 accu_rate += stats.rate_low;
883 accu_dist += stats.dist_low;
884 } else {
885 accu_rate += stats.rate;
886 accu_dist += stats.dist;
887 }
888 }
889
890 int si = init_eob - 2;
891 int8_t has_nz_tail = 0;
892 // eob is not fixed
893 for (; si >= 0 && has_nz_tail < 2; --si) {
894 assert(si != init_eob - 1);
Dake Hea47cd6c2017-10-13 18:09:58 -0700895 const int coeff_idx = scan[si];
896 tran_low_t qc = txb_info->qcoeff[coeff_idx];
897
Dake Hea47cd6c2017-10-13 18:09:58 -0700898 if (qc == 0) {
Angie Chiang99b12422018-03-02 17:15:00 -0800899 const int coeff_ctx =
900 get_lower_levels_ctx(txb_info->levels, coeff_idx, txb_info->bwl,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900901 txb_info->tx_size, tx_class);
Angie Chiang99b12422018-03-02 17:15:00 -0800902 accu_rate += txb_costs->base_cost[coeff_ctx][0];
Dake Hea47cd6c2017-10-13 18:09:58 -0700903 } else {
Angie Chiang99b12422018-03-02 17:15:00 -0800904 LevelDownStats stats;
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900905 get_dist_cost_stats_with_eob(&stats, si, txb_costs, txb_info, tx_class);
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800906 // check if it is better to make this the last significant coefficient
Yaowu Xu49abec82018-03-13 16:09:01 -0700907 int cur_eob_rate =
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900908 get_eob_cost(si + 1, txb_eob_costs, txb_costs, tx_class);
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800909 cur_eob_rd_cost = RDCOST(txb_info->rdmult, cur_eob_rate, 0);
910 prev_eob_rd_cost =
911 RDCOST(txb_info->rdmult, accu_rate, accu_dist) + stats.nz_rd;
912 if (cur_eob_rd_cost <= prev_eob_rd_cost) {
913 update = 1;
914 for (int j = si + 1; j < txb_info->eob; j++) {
915 const int coeff_pos_j = scan[j];
916 update_coeff(coeff_pos_j, 0, txb_info);
917 }
918 txb_info->eob = si + 1;
Angie Chiang99b12422018-03-02 17:15:00 -0800919
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800920 // rerun cost calculation due to change of eob
921 accu_rate = cur_eob_rate;
922 accu_dist = 0;
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900923 get_dist_cost_stats(&stats, si, 1, txb_costs, txb_info, tx_class);
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800924 if ((stats.rd_low < stats.rd) && (stats.low_qc != 0)) {
925 update = 1;
926 update_coeff(coeff_idx, stats.low_qc, txb_info);
927 accu_rate += stats.rate_low;
928 accu_dist += stats.dist_low;
Cheng Chenec32a742018-01-12 19:09:39 -0800929 } else {
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800930 accu_rate += stats.rate;
931 accu_dist += stats.dist;
932 }
933
934 // reset non zero tail when new eob is found
935 has_nz_tail = 0;
936 } else {
937 int bUpdCoeff = 0;
938 if (stats.rd_low < stats.rd) {
939 if ((si < txb_info->eob - 1)) {
940 bUpdCoeff = 1;
Cheng Chenec32a742018-01-12 19:09:39 -0800941 update = 1;
Cheng Chenec32a742018-01-12 19:09:39 -0800942 }
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800943 } else {
944 ++has_nz_tail;
945 }
946
947 if (bUpdCoeff) {
948 update_coeff(coeff_idx, stats.low_qc, txb_info);
949 accu_rate += stats.rate_low;
950 accu_dist += stats.dist_low;
951 } else {
952 accu_rate += stats.rate;
953 accu_dist += stats.dist;
Jingning Han8be58fa2017-12-18 09:46:13 -0800954 }
Dake Hea47cd6c2017-10-13 18:09:58 -0700955 }
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800956 }
957 } // for (si)
958
959 // eob is fixed
960 for (; si >= 0; --si) {
961 assert(si != init_eob - 1);
962 const int coeff_idx = scan[si];
963 tran_low_t qc = txb_info->qcoeff[coeff_idx];
964
965 if (qc == 0) {
966 const int coeff_ctx =
967 get_lower_levels_ctx(txb_info->levels, coeff_idx, txb_info->bwl,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900968 txb_info->tx_size, tx_class);
Angie Chiangcbbf4f02018-03-02 18:34:38 -0800969 accu_rate += txb_costs->base_cost[coeff_ctx][0];
970 } else {
971 LevelDownStats stats;
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +0900972 get_dist_cost_stats(&stats, si, 0, txb_costs, txb_info, tx_class);
Dake Hea47cd6c2017-10-13 18:09:58 -0700973
974 int bUpdCoeff = 0;
975 if (stats.rd_low < stats.rd) {
Dake He4d447692017-12-15 09:10:06 -0800976 if ((si < txb_info->eob - 1)) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700977 bUpdCoeff = 1;
978 update = 1;
979 }
980 }
Dake Hea47cd6c2017-10-13 18:09:58 -0700981 if (bUpdCoeff) {
982 update_coeff(coeff_idx, stats.low_qc, txb_info);
983 accu_rate += stats.rate_low;
984 accu_dist += stats.dist_low;
985 } else {
986 accu_rate += stats.rate;
987 accu_dist += stats.dist;
988 }
989 }
990 } // for (si)
Jingning Hana7a6f4e2017-12-13 14:44:08 -0800991
Dake Hea47cd6c2017-10-13 18:09:58 -0700992 int non_zero_blk_rate =
993 txb_costs->txb_skip_cost[txb_info->txb_ctx->txb_skip_ctx][0];
994 prev_eob_rd_cost =
995 RDCOST(txb_info->rdmult, accu_rate + non_zero_blk_rate, accu_dist);
996
997 int zero_blk_rate =
998 txb_costs->txb_skip_cost[txb_info->txb_ctx->txb_skip_ctx][1];
999 int64_t zero_blk_rd_cost = RDCOST(txb_info->rdmult, zero_blk_rate, 0);
1000 if (zero_blk_rd_cost <= prev_eob_rd_cost) {
1001 update = 1;
1002 for (int j = 0; j < txb_info->eob; j++) {
1003 const int coeff_pos_j = scan[j];
1004 update_coeff(coeff_pos_j, 0, txb_info);
1005 }
1006 txb_info->eob = 0;
1007 }
1008
Cheng Chen82775f62018-01-18 12:09:54 -08001009 // record total rate cost
1010 *rate_cost = zero_blk_rd_cost <= prev_eob_rd_cost
1011 ? zero_blk_rate
1012 : accu_rate + non_zero_blk_rate;
Angie Chiang0ed53352018-03-08 12:53:43 -08001013
1014 if (txb_info->eob > 0) {
1015 *rate_cost += txb_info->tx_type_cost;
1016 }
1017
Dake Hea47cd6c2017-10-13 18:09:58 -07001018 return update;
1019}
1020
Angie Chiang07c57f32017-05-30 18:18:33 -07001021// These numbers are empirically obtained.
1022static const int plane_rd_mult[REF_TYPES][PLANE_TYPES] = {
Johannb0ef6ff2018-02-08 14:32:21 -08001023 { 17, 13 },
1024 { 16, 10 },
Angie Chiang07c57f32017-05-30 18:18:33 -07001025};
1026
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001027void hbt_init() {
1028 hbt_hash_table =
1029 aom_malloc(sizeof(OptTxbQcoeff) * HBT_TABLE_SIZE * HBT_ARRAY_LENGTH);
1030 memset(hbt_hash_table, 0,
1031 sizeof(OptTxbQcoeff) * HBT_TABLE_SIZE * HBT_ARRAY_LENGTH);
Peng Bin8a204cd2018-04-08 13:07:35 +08001032 av1_crc32c_calculator_init(&crc_calculator); // 31 bit: qc & ctx
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001033
1034 hbt_needs_init = 0;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001035}
1036
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001037void hbt_destroy() { aom_free(hbt_hash_table); }
1038
1039int hbt_hash_miss(uint32_t hbt_ctx_hash, uint32_t hbt_qc_hash,
1040 TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001041 const LV_MAP_EOB_COST *txb_eob_costs,
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001042 const struct macroblock_plane *p, int block, int fast_mode,
1043 int *rate_cost) {
Angie Chiang45385b82018-03-02 15:25:58 -08001044 (void)fast_mode;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001045 const int16_t *scan = txb_info->scan_order->scan;
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001046 int prev_eob = txb_info->eob;
1047 assert(HBT_EOB <= 16); // Lengthen array if allowing longer eob.
1048 int32_t prev_coeff[16];
1049 for (int i = 0; i < prev_eob; i++) {
1050 prev_coeff[i] = txb_info->qcoeff[scan[i]];
1051 }
1052 for (int i = prev_eob; i < HBT_EOB; i++) {
1053 prev_coeff[i] = 0; // For compiler piece of mind.
1054 }
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001055
1056 av1_txb_init_levels(txb_info->qcoeff, txb_info->width, txb_info->height,
1057 txb_info->levels);
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001058
Angie Chiang45385b82018-03-02 15:25:58 -08001059 const int update =
1060 optimize_txb(txb_info, txb_costs, txb_eob_costs, rate_cost);
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001061
1062 // Overwrite old entry
1063 uint16_t hbt_table_index = hbt_ctx_hash % HBT_TABLE_SIZE;
1064 uint16_t hbt_array_index = hbt_qc_hash % HBT_ARRAY_LENGTH;
1065 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1066 .rate_cost = *rate_cost;
1067 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index].init = 1;
1068 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1069 .hbt_qc_hash = hbt_qc_hash;
1070 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1071 .hbt_ctx_hash = hbt_ctx_hash;
1072 assert(prev_eob >= txb_info->eob); // eob can't get longer
1073 for (int i = 0; i < txb_info->eob; i++) {
1074 // Record how coeff changed. Convention: towards zero is negative.
1075 if (txb_info->qcoeff[scan[i]] > 0)
1076 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1077 .deltas[i] = txb_info->qcoeff[scan[i]] - prev_coeff[i];
1078 else
1079 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1080 .deltas[i] = prev_coeff[i] - txb_info->qcoeff[scan[i]];
1081 }
1082 for (int i = txb_info->eob; i < prev_eob; i++) {
1083 // If eob got shorter, record that all after it changed to zero.
1084 if (prev_coeff[i] > 0)
1085 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1086 .deltas[i] = -prev_coeff[i];
1087 else
1088 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1089 .deltas[i] = prev_coeff[i];
1090 }
1091 for (int i = prev_eob; i < HBT_EOB; i++) {
1092 // Record 'no change' after optimized coefficients run out.
1093 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1094 .deltas[i] = 0;
1095 }
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001096
1097 if (update) {
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001098 p->eobs[block] = txb_info->eob;
1099 p->txb_entropy_ctx[block] = av1_get_txb_entropy_context(
1100 txb_info->qcoeff, txb_info->scan_order, txb_info->eob);
1101 }
1102 return txb_info->eob;
1103}
1104
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001105int hbt_hash_hit(uint32_t hbt_table_index, int hbt_array_index,
1106 TxbInfo *txb_info, const struct macroblock_plane *p, int block,
1107 int *rate_cost) {
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001108 const int16_t *scan = txb_info->scan_order->scan;
1109 int new_eob = 0;
1110 int update = 0;
1111
1112 for (int i = 0; i < txb_info->eob; i++) {
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001113 // Delta convention is negatives go towards zero, so only apply those ones.
1114 if (hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1115 .deltas[i] < 0) {
1116 if (txb_info->qcoeff[scan[i]] > 0)
1117 txb_info->qcoeff[scan[i]] +=
1118 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1119 .deltas[i];
1120 else
1121 txb_info->qcoeff[scan[i]] -=
1122 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1123 .deltas[i];
1124
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001125 update = 1;
1126 update_coeff(scan[i], txb_info->qcoeff[scan[i]], txb_info);
1127 }
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001128 if (txb_info->qcoeff[scan[i]]) new_eob = i + 1;
1129 }
1130
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001131 // Rate_cost can be calculated here instead (av1_cost_coeffs_txb), but
1132 // it is expensive and gives little benefit as long as qc_hash is high bit
1133 *rate_cost =
1134 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1135 .rate_cost;
1136
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001137 if (update) {
1138 txb_info->eob = new_eob;
1139 p->eobs[block] = txb_info->eob;
1140 p->txb_entropy_ctx[block] = av1_get_txb_entropy_context(
1141 txb_info->qcoeff, txb_info->scan_order, txb_info->eob);
1142 }
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001143
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001144 return txb_info->eob;
1145}
1146
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001147int hbt_search_match(uint32_t hbt_ctx_hash, uint32_t hbt_qc_hash,
1148 TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
1149 const LV_MAP_EOB_COST *txb_eob_costs,
1150 const struct macroblock_plane *p, int block, int fast_mode,
1151 int *rate_cost) {
1152 // Check for qcoeff match
1153 int hbt_array_index = hbt_qc_hash % HBT_ARRAY_LENGTH;
1154 int hbt_table_index = hbt_ctx_hash % HBT_TABLE_SIZE;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001155
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001156 if (hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1157 .hbt_qc_hash == hbt_qc_hash &&
1158 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1159 .hbt_ctx_hash == hbt_ctx_hash &&
1160 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1161 .init) {
1162 return hbt_hash_hit(hbt_table_index, hbt_array_index, txb_info, p, block,
1163 rate_cost);
1164 } else {
1165 return hbt_hash_miss(hbt_ctx_hash, hbt_qc_hash, txb_info, txb_costs,
1166 txb_eob_costs, p, block, fast_mode, rate_cost);
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001167 }
1168}
1169
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001170int hbt_create_hashes(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
1171 const LV_MAP_EOB_COST *txb_eob_costs,
1172 const struct macroblock_plane *p, int block,
1173 int fast_mode, int *rate_cost) {
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001174 // Initialize hash table if needed.
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001175 if (hbt_needs_init) {
1176 hbt_init();
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001177 }
1178
1179 //// Hash creation
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001180 uint8_t txb_hash_data[256]; // Asserts below to ensure enough space.
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001181 const int16_t *scan = txb_info->scan_order->scan;
1182 uint8_t chunk = 0;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001183 int hash_data_index = 0;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001184
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001185 // Make qc_hash.
1186 int packing_index = 0; // needed for packing.
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001187 for (int i = 0; i < txb_info->eob; i++) {
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001188 tran_low_t prechunk = txb_info->qcoeff[scan[i]];
1189
1190 // Softening: Improves speed. Aligns with signed deltas.
1191 if (prechunk < 0) prechunk *= -1;
1192
1193 // Early kick out: Don't apply feature if there are large coeffs:
1194 // If this kickout value is removed or raised beyond int8_t,
1195 // widen deltas type in OptTxbQcoeff struct.
1196 assert((int8_t)HBT_KICKOUT == HBT_KICKOUT); // If not, widen types.
1197 if (prechunk > HBT_KICKOUT) {
1198 av1_txb_init_levels(txb_info->qcoeff, txb_info->width, txb_info->height,
1199 txb_info->levels);
1200
Angie Chiang45385b82018-03-02 15:25:58 -08001201 const int update =
1202 optimize_txb(txb_info, txb_costs, txb_eob_costs, rate_cost);
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001203
1204 if (update) {
1205 p->eobs[block] = txb_info->eob;
1206 p->txb_entropy_ctx[block] = av1_get_txb_entropy_context(
1207 txb_info->qcoeff, txb_info->scan_order, txb_info->eob);
1208 }
1209 return txb_info->eob;
1210 }
1211
1212 // Since coeffs are 0 to 3, only 2 bits are needed: pack into bytes
1213 if (packing_index == 0) txb_hash_data[hash_data_index] = 0;
1214 chunk = prechunk << packing_index;
1215 packing_index += 2;
1216 txb_hash_data[hash_data_index] |= chunk;
1217
1218 // Full byte:
1219 if (packing_index == 8) {
1220 packing_index = 0;
1221 hash_data_index++;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001222 }
1223 }
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001224 // Needed when packing_index != 0, to include final byte.
1225 hash_data_index++;
1226 assert(hash_data_index <= 64);
1227 // 31 bit qc_hash: index to array
1228 uint32_t hbt_qc_hash =
Peng Bin8a204cd2018-04-08 13:07:35 +08001229 av1_get_crc32c_value(&crc_calculator, txb_hash_data, hash_data_index);
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001230
1231 // Make ctx_hash.
1232 hash_data_index = 0;
1233 tran_low_t prechunk;
1234
1235 for (int i = 0; i < txb_info->eob; i++) {
1236 // Save as magnitudes towards or away from zero.
1237 if (txb_info->tcoeff[scan[i]] >= 0)
1238 prechunk = txb_info->tcoeff[scan[i]] - txb_info->dqcoeff[scan[i]];
1239 else
1240 prechunk = txb_info->dqcoeff[scan[i]] - txb_info->tcoeff[scan[i]];
1241
1242 chunk = prechunk & 0xff;
1243 txb_hash_data[hash_data_index++] = chunk;
1244 }
1245
1246 // Extra ctx data:
1247 // Include dequants.
1248 txb_hash_data[hash_data_index++] = txb_info->dequant[0] & 0xff;
1249 txb_hash_data[hash_data_index++] = txb_info->dequant[1] & 0xff;
1250 chunk = txb_info->txb_ctx->txb_skip_ctx & 0xff;
1251 txb_hash_data[hash_data_index++] = chunk;
1252 chunk = txb_info->txb_ctx->dc_sign_ctx & 0xff;
1253 txb_hash_data[hash_data_index++] = chunk;
1254 // eob
1255 chunk = txb_info->eob & 0xff;
1256 txb_hash_data[hash_data_index++] = chunk;
1257 // rdmult (int64)
1258 chunk = txb_info->rdmult & 0xff;
1259 txb_hash_data[hash_data_index++] = chunk;
1260 // tx_type
1261 chunk = txb_info->tx_type & 0xff;
1262 txb_hash_data[hash_data_index++] = chunk;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001263 // base_eob_cost
1264 for (int i = 1; i < 3; i++) { // i = 0 are softened away
1265 for (int j = 0; j < SIG_COEF_CONTEXTS_EOB; j++) {
1266 chunk = (txb_costs->base_eob_cost[j][i] & 0xff00) >> 8;
1267 txb_hash_data[hash_data_index++] = chunk;
1268 }
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001269 }
1270 // eob_cost
1271 for (int i = 0; i < 11; i++) {
1272 for (int j = 0; j < 2; j++) {
1273 chunk = (txb_eob_costs->eob_cost[j][i] & 0xff00) >> 8;
1274 txb_hash_data[hash_data_index++] = chunk;
1275 }
1276 }
1277 // dc_sign_cost
1278 for (int i = 0; i < 2; i++) {
1279 for (int j = 0; j < DC_SIGN_CONTEXTS; j++) {
1280 chunk = (txb_costs->dc_sign_cost[j][i] & 0xff00) >> 8;
1281 txb_hash_data[hash_data_index++] = chunk;
1282 }
1283 }
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001284
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001285 assert(hash_data_index <= 256);
1286 // 31 bit ctx_hash: used to index table
1287 uint32_t hbt_ctx_hash =
Peng Bin8a204cd2018-04-08 13:07:35 +08001288 av1_get_crc32c_value(&crc_calculator, txb_hash_data, hash_data_index);
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001289 //// End hash creation
1290
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001291 return hbt_search_match(hbt_ctx_hash, hbt_qc_hash, txb_info, txb_costs,
1292 txb_eob_costs, p, block, fast_mode, rate_cost);
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001293}
1294
Katsuhisa Yuasa9f639962018-04-08 18:00:54 +09001295static AOM_FORCE_INLINE int get_coeff_cost_simple(
1296 int ci, tran_low_t abs_qc, int coeff_ctx,
1297 const LV_MAP_COEFF_COST *txb_costs, int bwl, TX_CLASS tx_class,
1298 const uint8_t *levels) {
Angie Chiang40b07312018-03-30 10:42:55 -07001299 // this simple version assumes the coeff's scan_idx is not DC (scan_idx != 0)
Angie Chiange4ea7482018-03-15 11:36:41 -07001300 // and not the last (scan_idx != eob - 1)
1301 assert(ci > 0);
1302 int cost = txb_costs->base_cost[coeff_ctx][AOMMIN(abs_qc, 3)];
1303 if (abs_qc) {
1304 cost += av1_cost_literal(1);
1305 if (abs_qc > NUM_BASE_LEVELS) {
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001306 const int br_ctx = get_br_ctx(levels, ci, bwl, tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -07001307 cost += get_br_cost(abs_qc, br_ctx, txb_costs->lps_cost[br_ctx]);
1308 cost += get_golomb_cost(abs_qc);
1309 }
1310 }
1311 return cost;
1312}
1313
1314static INLINE int get_coeff_cost_general(int is_last, int ci, tran_low_t abs_qc,
Angie Chiang40b07312018-03-30 10:42:55 -07001315 int sign, int coeff_ctx,
Angie Chiange4ea7482018-03-15 11:36:41 -07001316 int dc_sign_ctx,
1317 const LV_MAP_COEFF_COST *txb_costs,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001318 int bwl, TX_CLASS tx_class,
Angie Chiange4ea7482018-03-15 11:36:41 -07001319 const uint8_t *levels) {
1320 int cost = 0;
1321 if (is_last) {
1322 cost += txb_costs->base_eob_cost[coeff_ctx][AOMMIN(abs_qc, 3) - 1];
1323 } else {
1324 cost += txb_costs->base_cost[coeff_ctx][AOMMIN(abs_qc, 3)];
1325 }
1326 if (abs_qc != 0) {
1327 if (ci == 0) {
Angie Chiang40b07312018-03-30 10:42:55 -07001328 cost += txb_costs->dc_sign_cost[dc_sign_ctx][sign];
Angie Chiange4ea7482018-03-15 11:36:41 -07001329 } else {
1330 cost += av1_cost_literal(1);
1331 }
1332 if (abs_qc > NUM_BASE_LEVELS) {
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001333 const int br_ctx = get_br_ctx(levels, ci, bwl, tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -07001334 cost += get_br_cost(abs_qc, br_ctx, txb_costs->lps_cost[br_ctx]);
1335 cost += get_golomb_cost(abs_qc);
1336 }
1337 }
1338 return cost;
1339}
1340
Angie Chiang40b07312018-03-30 10:42:55 -07001341static INLINE void get_qc_dqc_low(tran_low_t abs_qc, int sign, int dqv,
Angie Chiange4ea7482018-03-15 11:36:41 -07001342 int shift, tran_low_t *qc_low,
1343 tran_low_t *dqc_low) {
1344 tran_low_t abs_qc_low = abs_qc - 1;
Angie Chiang40b07312018-03-30 10:42:55 -07001345 *qc_low = (-sign ^ abs_qc_low) + sign;
1346 assert((sign ? -abs_qc_low : abs_qc_low) == *qc_low);
Angie Chiange4ea7482018-03-15 11:36:41 -07001347 tran_low_t abs_dqc_low = (abs_qc_low * dqv) >> shift;
Angie Chiang40b07312018-03-30 10:42:55 -07001348 *dqc_low = (-sign ^ abs_dqc_low) + sign;
1349 assert((sign ? -abs_dqc_low : abs_dqc_low) == *dqc_low);
Angie Chiange4ea7482018-03-15 11:36:41 -07001350}
1351
1352static INLINE void update_coeff_general(
1353 int *accu_rate, int64_t *accu_dist, int si, int eob, TX_SIZE tx_size,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001354 TX_CLASS tx_class, int bwl, int height, int64_t rdmult, int shift,
Angie Chiange4ea7482018-03-15 11:36:41 -07001355 int dc_sign_ctx, const int16_t *dequant, const int16_t *scan,
1356 const LV_MAP_COEFF_COST *txb_costs, const tran_low_t *tcoeff,
1357 tran_low_t *qcoeff, tran_low_t *dqcoeff, uint8_t *levels) {
1358 const int dqv = dequant[si != 0];
1359 const int ci = scan[si];
1360 const tran_low_t qc = qcoeff[ci];
1361 const int is_last = si == (eob - 1);
1362 const int coeff_ctx = get_lower_levels_ctx_general(
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001363 is_last, si, bwl, height, levels, ci, tx_size, tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -07001364 if (qc == 0) {
1365 *accu_rate += txb_costs->base_cost[coeff_ctx][0];
1366 } else {
Angie Chiang40b07312018-03-30 10:42:55 -07001367 const int sign = (qc < 0) ? 1 : 0;
Angie Chiange4ea7482018-03-15 11:36:41 -07001368 const tran_low_t abs_qc = abs(qc);
1369 const tran_low_t tqc = tcoeff[ci];
1370 const tran_low_t dqc = dqcoeff[ci];
1371 const int64_t dist = get_coeff_dist(tqc, dqc, shift);
1372 const int64_t dist0 = get_coeff_dist(tqc, 0, shift);
1373 const int rate =
Angie Chiang40b07312018-03-30 10:42:55 -07001374 get_coeff_cost_general(is_last, ci, abs_qc, sign, coeff_ctx,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001375 dc_sign_ctx, txb_costs, bwl, tx_class, levels);
Angie Chiange4ea7482018-03-15 11:36:41 -07001376 const int64_t rd = RDCOST(rdmult, rate, dist);
1377
1378 tran_low_t qc_low, dqc_low;
Angie Chiang40b07312018-03-30 10:42:55 -07001379 get_qc_dqc_low(abs_qc, sign, dqv, shift, &qc_low, &dqc_low);
Angie Chiange4ea7482018-03-15 11:36:41 -07001380 const tran_low_t abs_qc_low = abs_qc - 1;
1381 const int64_t dist_low = get_coeff_dist(tqc, dqc_low, shift);
1382 const int rate_low =
Angie Chiang40b07312018-03-30 10:42:55 -07001383 get_coeff_cost_general(is_last, ci, abs_qc_low, sign, coeff_ctx,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001384 dc_sign_ctx, txb_costs, bwl, tx_class, levels);
Angie Chiange4ea7482018-03-15 11:36:41 -07001385 const int64_t rd_low = RDCOST(rdmult, rate_low, dist_low);
1386 if (rd_low < rd) {
1387 qcoeff[ci] = qc_low;
1388 dqcoeff[ci] = dqc_low;
1389 levels[get_padded_idx(ci, bwl)] = AOMMIN(abs_qc_low, INT8_MAX);
1390 *accu_rate += rate_low;
1391 *accu_dist += dist_low - dist0;
1392 } else {
1393 *accu_rate += rate;
1394 *accu_dist += dist - dist0;
1395 }
1396 }
1397}
1398
Katsuhisa Yuasa9f639962018-04-08 18:00:54 +09001399static AOM_FORCE_INLINE void update_coeff_simple(
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001400 int *accu_rate, int si, int eob, TX_SIZE tx_size, TX_CLASS tx_class,
1401 int bwl, int64_t rdmult, int shift, const int16_t *dequant,
1402 const int16_t *scan, const LV_MAP_COEFF_COST *txb_costs,
1403 const tran_low_t *tcoeff, tran_low_t *qcoeff, tran_low_t *dqcoeff,
1404 uint8_t *levels) {
Angie Chiange4ea7482018-03-15 11:36:41 -07001405 const int dqv = dequant[1];
1406 (void)eob;
Angie Chiang40b07312018-03-30 10:42:55 -07001407 // this simple version assumes the coeff's scan_idx is not DC (scan_idx != 0)
Angie Chiange4ea7482018-03-15 11:36:41 -07001408 // and not the last (scan_idx != eob - 1)
1409 assert(si != eob - 1);
1410 assert(si > 0);
1411 const int ci = scan[si];
1412 const tran_low_t qc = qcoeff[ci];
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001413 const int coeff_ctx =
1414 get_lower_levels_ctx(levels, ci, bwl, tx_size, tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -07001415 if (qc == 0) {
1416 *accu_rate += txb_costs->base_cost[coeff_ctx][0];
1417 } else {
1418 const tran_low_t abs_qc = abs(qc);
1419 const tran_low_t tqc = tcoeff[ci];
1420 const tran_low_t dqc = dqcoeff[ci];
Angie Chiange4ea7482018-03-15 11:36:41 -07001421 const int rate = get_coeff_cost_simple(ci, abs_qc, coeff_ctx, txb_costs,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001422 bwl, tx_class, levels);
Jingning Han87f5c342018-04-10 23:10:12 -07001423 if (abs(dqc) < abs(tqc)) {
1424 *accu_rate += rate;
1425 return;
1426 }
1427 const int64_t dist = get_coeff_dist(tqc, dqc, shift);
Angie Chiange4ea7482018-03-15 11:36:41 -07001428 const int64_t rd = RDCOST(rdmult, rate, dist);
1429
Angie Chiang40b07312018-03-30 10:42:55 -07001430 const int sign = (qc < 0) ? 1 : 0;
Angie Chiange4ea7482018-03-15 11:36:41 -07001431 tran_low_t qc_low, dqc_low;
Angie Chiang40b07312018-03-30 10:42:55 -07001432 get_qc_dqc_low(abs_qc, sign, dqv, shift, &qc_low, &dqc_low);
Angie Chiange4ea7482018-03-15 11:36:41 -07001433 const tran_low_t abs_qc_low = abs_qc - 1;
1434 const int64_t dist_low = get_coeff_dist(tqc, dqc_low, shift);
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001435 const int rate_low = get_coeff_cost_simple(
1436 ci, abs_qc_low, coeff_ctx, txb_costs, bwl, tx_class, levels);
Angie Chiange4ea7482018-03-15 11:36:41 -07001437 const int64_t rd_low = RDCOST(rdmult, rate_low, dist_low);
1438 if (rd_low < rd) {
1439 qcoeff[ci] = qc_low;
1440 dqcoeff[ci] = dqc_low;
1441 levels[get_padded_idx(ci, bwl)] = AOMMIN(abs_qc_low, INT8_MAX);
1442 *accu_rate += rate_low;
Angie Chiange4ea7482018-03-15 11:36:41 -07001443 } else {
1444 *accu_rate += rate;
Angie Chiange4ea7482018-03-15 11:36:41 -07001445 }
1446 }
1447}
1448
Katsuhisa Yuasa9f639962018-04-08 18:00:54 +09001449static AOM_FORCE_INLINE void update_coeff_eob(
Angie Chiange4ea7482018-03-15 11:36:41 -07001450 int *accu_rate, int64_t *accu_dist, int *eob, int *nz_num, int *nz_ci,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001451 int si, TX_SIZE tx_size, TX_CLASS tx_class, int bwl, int height,
Angie Chiange4ea7482018-03-15 11:36:41 -07001452 int dc_sign_ctx, int64_t rdmult, int shift, const int16_t *dequant,
1453 const int16_t *scan, const LV_MAP_EOB_COST *txb_eob_costs,
1454 const LV_MAP_COEFF_COST *txb_costs, const tran_low_t *tcoeff,
Jim Bankoski855ac462018-06-07 09:05:00 -07001455 tran_low_t *qcoeff, tran_low_t *dqcoeff, uint8_t *levels, int sharpness) {
Angie Chiange4ea7482018-03-15 11:36:41 -07001456 const int dqv = dequant[si != 0];
1457 assert(si != *eob - 1);
1458 const int ci = scan[si];
1459 const tran_low_t qc = qcoeff[ci];
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001460 const int coeff_ctx =
1461 get_lower_levels_ctx(levels, ci, bwl, tx_size, tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -07001462 if (qc == 0) {
1463 *accu_rate += txb_costs->base_cost[coeff_ctx][0];
1464 } else {
1465 int lower_level = 0;
1466 const tran_low_t abs_qc = abs(qc);
1467 const tran_low_t tqc = tcoeff[ci];
1468 const tran_low_t dqc = dqcoeff[ci];
Angie Chiang40b07312018-03-30 10:42:55 -07001469 const int sign = (qc < 0) ? 1 : 0;
Angie Chiange4ea7482018-03-15 11:36:41 -07001470 const int64_t dist0 = get_coeff_dist(tqc, 0, shift);
1471 int64_t dist = get_coeff_dist(tqc, dqc, shift) - dist0;
1472 int rate =
Angie Chiang40b07312018-03-30 10:42:55 -07001473 get_coeff_cost_general(0, ci, abs_qc, sign, coeff_ctx, dc_sign_ctx,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001474 txb_costs, bwl, tx_class, levels);
Angie Chiange4ea7482018-03-15 11:36:41 -07001475 int64_t rd = RDCOST(rdmult, *accu_rate + rate, *accu_dist + dist);
1476
1477 tran_low_t qc_low, dqc_low;
Angie Chiang40b07312018-03-30 10:42:55 -07001478 get_qc_dqc_low(abs_qc, sign, dqv, shift, &qc_low, &dqc_low);
Angie Chiange4ea7482018-03-15 11:36:41 -07001479 const tran_low_t abs_qc_low = abs_qc - 1;
1480 const int64_t dist_low = get_coeff_dist(tqc, dqc_low, shift) - dist0;
1481 const int rate_low =
Angie Chiang40b07312018-03-30 10:42:55 -07001482 get_coeff_cost_general(0, ci, abs_qc_low, sign, coeff_ctx, dc_sign_ctx,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001483 txb_costs, bwl, tx_class, levels);
Angie Chiange4ea7482018-03-15 11:36:41 -07001484 const int64_t rd_low =
1485 RDCOST(rdmult, *accu_rate + rate_low, *accu_dist + dist_low);
1486
1487 int lower_level_new_eob = 0;
1488 const int new_eob = si + 1;
1489 uint8_t tmp_levels[3];
1490 for (int ni = 0; ni < *nz_num; ++ni) {
1491 const int last_ci = nz_ci[ni];
1492 tmp_levels[ni] = levels[get_padded_idx(last_ci, bwl)];
1493 levels[get_padded_idx(last_ci, bwl)] = 0;
1494 }
1495
1496 const int coeff_ctx_new_eob = get_lower_levels_ctx_general(
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001497 1, si, bwl, height, levels, ci, tx_size, tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -07001498 const int new_eob_cost =
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001499 get_eob_cost(new_eob, txb_eob_costs, txb_costs, tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -07001500 int rate_coeff_eob =
Angie Chiang40b07312018-03-30 10:42:55 -07001501 new_eob_cost + get_coeff_cost_general(1, ci, abs_qc, sign,
Angie Chiange4ea7482018-03-15 11:36:41 -07001502 coeff_ctx_new_eob, dc_sign_ctx,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001503 txb_costs, bwl, tx_class, levels);
Angie Chiange4ea7482018-03-15 11:36:41 -07001504 int64_t dist_new_eob = dist;
1505 int64_t rd_new_eob = RDCOST(rdmult, rate_coeff_eob, dist_new_eob);
1506
1507 if (abs_qc_low > 0) {
1508 const int rate_coeff_eob_low =
1509 new_eob_cost +
Angie Chiang40b07312018-03-30 10:42:55 -07001510 get_coeff_cost_general(1, ci, abs_qc_low, sign, coeff_ctx_new_eob,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001511 dc_sign_ctx, txb_costs, bwl, tx_class, levels);
Angie Chiange4ea7482018-03-15 11:36:41 -07001512 const int64_t dist_new_eob_low = dist_low;
1513 const int64_t rd_new_eob_low =
1514 RDCOST(rdmult, rate_coeff_eob_low, dist_new_eob_low);
1515 if (rd_new_eob_low < rd_new_eob) {
1516 lower_level_new_eob = 1;
1517 rd_new_eob = rd_new_eob_low;
1518 rate_coeff_eob = rate_coeff_eob_low;
1519 dist_new_eob = dist_new_eob_low;
1520 }
1521 }
1522
1523 if (rd_low < rd) {
1524 lower_level = 1;
1525 rd = rd_low;
1526 rate = rate_low;
1527 dist = dist_low;
1528 }
1529
Jim Bankoski855ac462018-06-07 09:05:00 -07001530 if (sharpness == 0 && rd_new_eob < rd) {
Angie Chiange4ea7482018-03-15 11:36:41 -07001531 for (int ni = 0; ni < *nz_num; ++ni) {
1532 int last_ci = nz_ci[ni];
1533 // levels[get_padded_idx(last_ci, bwl)] = 0;
1534 qcoeff[last_ci] = 0;
1535 dqcoeff[last_ci] = 0;
1536 }
1537 *eob = new_eob;
1538 *nz_num = 0;
1539 *accu_rate = rate_coeff_eob;
1540 *accu_dist = dist_new_eob;
1541 lower_level = lower_level_new_eob;
1542 } else {
1543 for (int ni = 0; ni < *nz_num; ++ni) {
1544 const int last_ci = nz_ci[ni];
1545 levels[get_padded_idx(last_ci, bwl)] = tmp_levels[ni];
1546 }
1547 *accu_rate += rate;
1548 *accu_dist += dist;
1549 }
1550
1551 if (lower_level) {
1552 qcoeff[ci] = qc_low;
1553 dqcoeff[ci] = dqc_low;
1554 levels[get_padded_idx(ci, bwl)] = AOMMIN(abs_qc_low, INT8_MAX);
1555 }
1556 if (qcoeff[ci]) {
1557 nz_ci[*nz_num] = ci;
1558 ++*nz_num;
1559 }
1560 }
1561}
1562
Angie Chiangd0397e12018-03-27 19:03:20 -07001563static INLINE void update_skip(int *accu_rate, int64_t accu_dist, int *eob,
1564 int nz_num, int *nz_ci, int64_t rdmult,
1565 int skip_cost, int non_skip_cost,
Jim Bankoski855ac462018-06-07 09:05:00 -07001566 tran_low_t *qcoeff, tran_low_t *dqcoeff,
1567 int sharpness) {
Angie Chiangd0397e12018-03-27 19:03:20 -07001568 const int64_t rd = RDCOST(rdmult, *accu_rate + non_skip_cost, accu_dist);
Angie Chiange4ea7482018-03-15 11:36:41 -07001569 const int64_t rd_new_eob = RDCOST(rdmult, skip_cost, 0);
Jim Bankoski855ac462018-06-07 09:05:00 -07001570 if (sharpness == 0 && rd_new_eob < rd) {
Angie Chiangd0397e12018-03-27 19:03:20 -07001571 for (int i = 0; i < nz_num; ++i) {
1572 const int ci = nz_ci[i];
Angie Chiange4ea7482018-03-15 11:36:41 -07001573 qcoeff[ci] = 0;
1574 dqcoeff[ci] = 0;
Angie Chiangd0397e12018-03-27 19:03:20 -07001575 // no need to set up levels because this is the last step
1576 // levels[get_padded_idx(ci, bwl)] = 0;
Angie Chiange4ea7482018-03-15 11:36:41 -07001577 }
Angie Chiange4ea7482018-03-15 11:36:41 -07001578 *accu_rate = 0;
1579 *eob = 0;
1580 }
1581}
1582
1583int av1_optimize_txb_new(const struct AV1_COMP *cpi, MACROBLOCK *x, int plane,
Xing Jinbd91e942018-06-21 13:43:17 +08001584 int block, TX_SIZE tx_size, TX_TYPE tx_type,
1585 const TXB_CTX *const txb_ctx, int *rate_cost,
1586 int sharpness) {
Angie Chiange4ea7482018-03-15 11:36:41 -07001587 const AV1_COMMON *cm = &cpi->common;
1588 MACROBLOCKD *xd = &x->e_mbd;
1589 const PLANE_TYPE plane_type = get_plane_type(plane);
1590 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001591 const TX_CLASS tx_class = tx_type_to_class[tx_type];
Yue Chen53b53f02018-03-29 14:31:23 -07001592 const MB_MODE_INFO *mbmi = xd->mi[0];
Angie Chiange4ea7482018-03-15 11:36:41 -07001593 const struct macroblock_plane *p = &x->plane[plane];
1594 struct macroblockd_plane *pd = &xd->plane[plane];
1595 tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
1596 tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
1597 const tran_low_t *tcoeff = BLOCK_OFFSET(p->coeff, block);
1598 const int16_t *dequant = p->dequant_QTX;
1599 const int bwl = get_txb_bwl(tx_size);
1600 const int width = get_txb_wide(tx_size);
1601 const int height = get_txb_high(tx_size);
1602 assert(width == (1 << bwl));
1603 const int is_inter = is_inter_block(mbmi);
1604 const SCAN_ORDER *scan_order = get_scan(tx_size, tx_type);
1605 const int16_t *scan = scan_order->scan;
1606 const LV_MAP_COEFF_COST *txb_costs = &x->coeff_costs[txs_ctx][plane_type];
1607 const int eob_multi_size = txsize_log2_minus4[tx_size];
1608 const LV_MAP_EOB_COST *txb_eob_costs =
1609 &x->eob_costs[eob_multi_size][plane_type];
1610
1611 const int shift = av1_get_tx_scale(tx_size);
1612 const int64_t rdmult =
1613 ((x->rdmult * plane_rd_mult[is_inter][plane_type] << (2 * (xd->bd - 8))) +
1614 2) >>
Yue Chende730472018-06-20 10:13:15 -07001615 (sharpness +
1616 (cpi->oxcf.aq_mode == VARIANCE_AQ && mbmi->segment_id < 4
1617 ? 7 - mbmi->segment_id
1618 : 2) +
1619 (cpi->oxcf.aq_mode != VARIANCE_AQ &&
1620 cpi->oxcf.deltaq_mode > NO_DELTA_Q && x->sb_energy_level < 0
1621 ? (3 - x->sb_energy_level)
1622 : 0));
Angie Chiange4ea7482018-03-15 11:36:41 -07001623
1624 uint8_t levels_buf[TX_PAD_2D];
1625 uint8_t *const levels = set_levels(levels_buf, width);
Jim Bankoski855ac462018-06-07 09:05:00 -07001626
Angie Chiange4ea7482018-03-15 11:36:41 -07001627 av1_txb_init_levels(qcoeff, width, height, levels);
1628
1629 // TODO(angirbird): check iqmatrix
1630
1631 const int non_skip_cost = txb_costs->txb_skip_cost[txb_ctx->txb_skip_ctx][0];
1632 const int skip_cost = txb_costs->txb_skip_cost[txb_ctx->txb_skip_ctx][1];
1633 int eob = p->eobs[block];
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001634 const int eob_cost = get_eob_cost(eob, txb_eob_costs, txb_costs, tx_class);
Angie Chiange4ea7482018-03-15 11:36:41 -07001635 int accu_rate = eob_cost;
1636 int64_t accu_dist = 0;
1637 int si = eob - 1;
1638 const int ci = scan[si];
1639 const tran_low_t qc = qcoeff[ci];
1640 const tran_low_t abs_qc = abs(qc);
Angie Chiang40b07312018-03-30 10:42:55 -07001641 const int sign = qc < 0;
Angie Chiange4ea7482018-03-15 11:36:41 -07001642 const int max_nz_num = 2;
1643 int nz_num = 1;
1644 int nz_ci[3] = { ci, 0, 0 };
1645 if (abs_qc >= 2) {
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001646 update_coeff_general(&accu_rate, &accu_dist, si, eob, tx_size, tx_class,
1647 bwl, height, rdmult, shift, txb_ctx->dc_sign_ctx,
1648 dequant, scan, txb_costs, tcoeff, qcoeff, dqcoeff,
1649 levels);
Angie Chiange4ea7482018-03-15 11:36:41 -07001650 --si;
1651 } else {
1652 assert(abs_qc == 1);
1653 const int coeff_ctx = get_lower_levels_ctx_general(
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001654 1, si, bwl, height, levels, ci, tx_size, tx_class);
Angie Chiang40b07312018-03-30 10:42:55 -07001655 accu_rate += get_coeff_cost_general(1, ci, abs_qc, sign, coeff_ctx,
Angie Chiange4ea7482018-03-15 11:36:41 -07001656 txb_ctx->dc_sign_ctx, txb_costs, bwl,
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001657 tx_class, levels);
Angie Chiange4ea7482018-03-15 11:36:41 -07001658 const tran_low_t tqc = tcoeff[ci];
1659 const tran_low_t dqc = dqcoeff[ci];
1660 const int64_t dist = get_coeff_dist(tqc, dqc, shift);
1661 const int64_t dist0 = get_coeff_dist(tqc, 0, shift);
1662 accu_dist += dist - dist0;
1663 --si;
1664 }
1665
Katsuhisa Yuasa9f639962018-04-08 18:00:54 +09001666#define UPDATE_COEFF_EOB_CASE(tx_class_literal) \
1667 case tx_class_literal: \
1668 for (; si >= 0 && nz_num <= max_nz_num; --si) { \
1669 update_coeff_eob(&accu_rate, &accu_dist, &eob, &nz_num, nz_ci, si, \
1670 tx_size, tx_class_literal, bwl, height, \
1671 txb_ctx->dc_sign_ctx, rdmult, shift, dequant, scan, \
1672 txb_eob_costs, txb_costs, tcoeff, qcoeff, dqcoeff, \
Jim Bankoski855ac462018-06-07 09:05:00 -07001673 levels, sharpness); \
Katsuhisa Yuasa9f639962018-04-08 18:00:54 +09001674 } \
1675 break;
1676 switch (tx_class) {
1677 UPDATE_COEFF_EOB_CASE(TX_CLASS_2D);
1678 UPDATE_COEFF_EOB_CASE(TX_CLASS_HORIZ);
1679 UPDATE_COEFF_EOB_CASE(TX_CLASS_VERT);
1680#undef UPDATE_COEFF_EOB_CASE
1681 default: assert(false);
Angie Chiange4ea7482018-03-15 11:36:41 -07001682 }
1683
Angie Chiangd0397e12018-03-27 19:03:20 -07001684 if (si == -1 && nz_num <= max_nz_num) {
1685 update_skip(&accu_rate, accu_dist, &eob, nz_num, nz_ci, rdmult, skip_cost,
Jim Bankoski855ac462018-06-07 09:05:00 -07001686 non_skip_cost, qcoeff, dqcoeff, sharpness);
Angie Chiangd0397e12018-03-27 19:03:20 -07001687 }
1688
Katsuhisa Yuasa9f639962018-04-08 18:00:54 +09001689#define UPDATE_COEFF_SIMPLE_CASE(tx_class_literal) \
1690 case tx_class_literal: \
1691 for (; si >= 1; --si) { \
1692 update_coeff_simple(&accu_rate, si, eob, tx_size, tx_class_literal, bwl, \
1693 rdmult, shift, dequant, scan, txb_costs, tcoeff, \
1694 qcoeff, dqcoeff, levels); \
1695 } \
1696 break;
1697 switch (tx_class) {
1698 UPDATE_COEFF_SIMPLE_CASE(TX_CLASS_2D);
1699 UPDATE_COEFF_SIMPLE_CASE(TX_CLASS_HORIZ);
1700 UPDATE_COEFF_SIMPLE_CASE(TX_CLASS_VERT);
1701#undef UPDATE_COEFF_SIMPLE_CASE
1702 default: assert(false);
Angie Chiange4ea7482018-03-15 11:36:41 -07001703 }
1704
1705 // DC position
1706 if (si == 0) {
Angie Chiangd0397e12018-03-27 19:03:20 -07001707 // no need to update accu_dist because it's not used after this point
1708 int64_t dummy_dist = 0;
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001709 update_coeff_general(&accu_rate, &dummy_dist, si, eob, tx_size, tx_class,
Angie Chiangd0397e12018-03-27 19:03:20 -07001710 bwl, height, rdmult, shift, txb_ctx->dc_sign_ctx,
1711 dequant, scan, txb_costs, tcoeff, qcoeff, dqcoeff,
1712 levels);
Angie Chiange4ea7482018-03-15 11:36:41 -07001713 }
1714
Urvang Joshi553096a2018-05-10 15:27:14 -07001715 const int tx_type_cost = get_tx_type_cost(cm, x, xd, plane, tx_size, tx_type);
Angie Chiange4ea7482018-03-15 11:36:41 -07001716 if (eob == 0)
1717 accu_rate += skip_cost;
1718 else
1719 accu_rate += non_skip_cost + tx_type_cost;
1720
1721 p->eobs[block] = eob;
1722 p->txb_entropy_ctx[block] =
1723 av1_get_txb_entropy_context(qcoeff, scan_order, p->eobs[block]);
1724
1725 *rate_cost = accu_rate;
1726 return eob;
1727}
1728
Angie Chiang40b07312018-03-30 10:42:55 -07001729// This function is deprecated, but we keep it here because hash trellis
Angie Chiange4ea7482018-03-15 11:36:41 -07001730// is not integrated with av1_optimize_txb_new yet
Yaowu Xuefcf1e92018-01-12 17:05:46 -08001731int av1_optimize_txb(const struct AV1_COMP *cpi, MACROBLOCK *x, int plane,
Jingning Han7eab9ff2017-07-06 10:12:54 -07001732 int blk_row, int blk_col, int block, TX_SIZE tx_size,
Cheng Chen82775f62018-01-18 12:09:54 -08001733 TXB_CTX *txb_ctx, int fast_mode, int *rate_cost) {
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001734 const AV1_COMMON *cm = &cpi->common;
Angie Chiang07c57f32017-05-30 18:18:33 -07001735 MACROBLOCKD *const xd = &x->e_mbd;
1736 const PLANE_TYPE plane_type = get_plane_type(plane);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -08001737 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Sarah Parker7c71cc02018-01-29 12:27:58 -08001738 const TX_TYPE tx_type = av1_get_tx_type(plane_type, xd, blk_row, blk_col,
1739 tx_size, cm->reduced_tx_set_used);
Yue Chen53b53f02018-03-29 14:31:23 -07001740 const MB_MODE_INFO *mbmi = xd->mi[0];
Angie Chiang07c57f32017-05-30 18:18:33 -07001741 const struct macroblock_plane *p = &x->plane[plane];
1742 struct macroblockd_plane *pd = &xd->plane[plane];
1743 const int eob = p->eobs[block];
1744 tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
1745 tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
1746 const tran_low_t *tcoeff = BLOCK_OFFSET(p->coeff, block);
Monty Montgomery125c0fc2017-10-26 00:44:35 -04001747 const int16_t *dequant = p->dequant_QTX;
Urvang Joshi80893152017-10-27 11:51:14 -07001748 const int seg_eob = av1_get_max_eob(tx_size);
Angie Chianga9ba58e2017-12-01 19:22:43 -08001749 const int bwl = get_txb_bwl(tx_size);
1750 const int width = get_txb_wide(tx_size);
1751 const int height = get_txb_high(tx_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07001752 const int is_inter = is_inter_block(mbmi);
Yaowu Xuf1e12932018-02-26 15:50:09 -08001753 const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
Angie Chiange15d2e32018-03-02 15:49:06 -08001754 const LV_MAP_COEFF_COST *txb_costs = &x->coeff_costs[txs_ctx][plane_type];
Dake He0db7d0e2017-12-21 15:23:20 -08001755 const int eob_multi_size = txsize_log2_minus4[tx_size];
1756 const LV_MAP_EOB_COST txb_eob_costs =
1757 x->eob_costs[eob_multi_size][plane_type];
Angie Chiang07c57f32017-05-30 18:18:33 -07001758
1759 const int shift = av1_get_tx_scale(tx_size);
1760 const int64_t rdmult =
Jingning Hanb433f4c2017-11-17 15:43:59 -08001761 ((x->rdmult * plane_rd_mult[is_inter][plane_type] << (2 * (xd->bd - 8))) +
1762 2) >>
1763 2;
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001764 uint8_t levels_buf[TX_PAD_2D];
1765 uint8_t *const levels = set_levels(levels_buf, width);
Angie Chiangb3167a62018-01-30 19:37:57 -08001766 const TX_SIZE qm_tx_size = av1_get_adjusted_tx_size(tx_size);
1767 const qm_val_t *iqmatrix =
1768 IS_2D_TRANSFORM(tx_type)
1769 ? pd->seg_iqmatrix[mbmi->segment_id][qm_tx_size]
1770 : cm->giqmatrix[NUM_QM_LEVELS - 1][0][qm_tx_size];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001771 assert(width == (1 << bwl));
Urvang Joshi553096a2018-05-10 15:27:14 -07001772 const int tx_type_cost = get_tx_type_cost(cm, x, xd, plane, tx_size, tx_type);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001773 TxbInfo txb_info = {
Angie Chiang0ed53352018-03-08 12:53:43 -08001774 qcoeff, levels, dqcoeff, tcoeff, dequant, shift,
1775 tx_size, txs_ctx, tx_type, bwl, width, height,
1776 eob, seg_eob, scan_order, txb_ctx, rdmult, &cm->coeff_ctx_table,
1777 iqmatrix, tx_type_cost,
Linfeng Zhang1015a342017-10-24 16:20:41 -07001778 };
1779
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001780 // Hash based trellis (hbt) speed feature: avoid expensive optimize_txb calls
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001781 // by storing the coefficient deltas in a hash table.
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001782 // Currently disabled in speedfeatures.c
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001783 if (eob <= HBT_EOB && eob > 0 && cpi->sf.use_hash_based_trellis) {
Angie Chiange15d2e32018-03-02 15:49:06 -08001784 return hbt_create_hashes(&txb_info, txb_costs, &txb_eob_costs, p, block,
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001785 fast_mode, rate_cost);
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001786 }
1787
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001788 av1_txb_init_levels(qcoeff, width, height, levels);
Urvang Joshi70006e42017-06-14 16:08:55 -07001789
Angie Chiang45385b82018-03-02 15:25:58 -08001790 const int update =
Angie Chiange15d2e32018-03-02 15:49:06 -08001791 optimize_txb(&txb_info, txb_costs, &txb_eob_costs, rate_cost);
Angie Chiang07c57f32017-05-30 18:18:33 -07001792
Jingning Hand7e99112017-12-13 09:47:45 -08001793 if (update) {
1794 p->eobs[block] = txb_info.eob;
1795 p->txb_entropy_ctx[block] =
1796 av1_get_txb_entropy_context(qcoeff, scan_order, txb_info.eob);
1797 }
Angie Chiang07c57f32017-05-30 18:18:33 -07001798 return txb_info.eob;
1799}
Jingning Hand7e99112017-12-13 09:47:45 -08001800
Angie Chiang74e23072017-03-24 14:54:23 -07001801int av1_get_txb_entropy_context(const tran_low_t *qcoeff,
1802 const SCAN_ORDER *scan_order, int eob) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001803 const int16_t *const scan = scan_order->scan;
Angie Chiang74e23072017-03-24 14:54:23 -07001804 int cul_level = 0;
1805 int c;
Jingning Han339cf932017-09-18 10:17:02 -07001806
1807 if (eob == 0) return 0;
Angie Chiang74e23072017-03-24 14:54:23 -07001808 for (c = 0; c < eob; ++c) {
1809 cul_level += abs(qcoeff[scan[c]]);
Jingning Hane3137652018-04-02 11:53:47 -07001810 if (cul_level > COEFF_CONTEXT_MASK) break;
Angie Chiang74e23072017-03-24 14:54:23 -07001811 }
1812
1813 cul_level = AOMMIN(COEFF_CONTEXT_MASK, cul_level);
1814 set_dc_sign(&cul_level, qcoeff[0]);
1815
1816 return cul_level;
1817}
1818
Jingning Han4fe5f672017-05-19 15:46:07 -07001819void av1_update_txb_context_b(int plane, int block, int blk_row, int blk_col,
1820 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
1821 void *arg) {
Jingning Han6171ae72017-05-18 20:15:06 -07001822 struct tokenize_b_args *const args = arg;
Angie Chiang36d616b2017-03-22 13:58:36 -07001823 const AV1_COMP *cpi = args->cpi;
1824 const AV1_COMMON *cm = &cpi->common;
Angie Chiang0397eda2017-03-15 16:57:14 -07001825 ThreadData *const td = args->td;
1826 MACROBLOCK *const x = &td->mb;
1827 MACROBLOCKD *const xd = &x->e_mbd;
1828 struct macroblock_plane *p = &x->plane[plane];
1829 struct macroblockd_plane *pd = &xd->plane[plane];
Angie Chiang36d616b2017-03-22 13:58:36 -07001830 const uint16_t eob = p->eobs[block];
1831 const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
1832 const PLANE_TYPE plane_type = pd->plane_type;
Sarah Parker7c71cc02018-01-29 12:27:58 -08001833 const TX_TYPE tx_type = av1_get_tx_type(plane_type, xd, blk_row, blk_col,
1834 tx_size, cm->reduced_tx_set_used);
Yaowu Xuf1e12932018-02-26 15:50:09 -08001835 const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
Hui Sue674dec2018-04-02 13:02:08 -07001836 const int cul_level = av1_get_txb_entropy_context(qcoeff, scan_order, eob);
1837 av1_set_contexts(xd, pd, plane, plane_bsize, tx_size, cul_level, blk_col,
1838 blk_row);
Angie Chiang0397eda2017-03-15 16:57:14 -07001839}
1840
Urvang Joshi553096a2018-05-10 15:27:14 -07001841static void update_tx_type_count(const AV1_COMMON *cm, MACROBLOCKD *xd,
1842 int blk_row, int blk_col, int plane,
1843 TX_SIZE tx_size, FRAME_COUNTS *counts,
1844 uint8_t allow_update_cdf) {
1845 MB_MODE_INFO *mbmi = xd->mi[0];
1846 int is_inter = is_inter_block(mbmi);
1847 FRAME_CONTEXT *fc = xd->tile_ctx;
1848#if !CONFIG_ENTROPY_STATS
1849 (void)counts;
1850#endif // !CONFIG_ENTROPY_STATS
1851
1852 // Only y plane's tx_type is updated
1853 if (plane > 0) return;
1854 TX_TYPE tx_type = av1_get_tx_type(PLANE_TYPE_Y, xd, blk_row, blk_col, tx_size,
1855 cm->reduced_tx_set_used);
1856 if (get_ext_tx_types(tx_size, is_inter, cm->reduced_tx_set_used) > 1 &&
1857 cm->base_qindex > 0 && !mbmi->skip &&
1858 !segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
1859 const int eset = get_ext_tx_set(tx_size, is_inter, cm->reduced_tx_set_used);
1860 if (eset > 0) {
1861 const TxSetType tx_set_type =
1862 av1_get_ext_tx_set_type(tx_size, is_inter, cm->reduced_tx_set_used);
1863 if (is_inter) {
1864 if (allow_update_cdf) {
1865 update_cdf(fc->inter_ext_tx_cdf[eset][txsize_sqr_map[tx_size]],
1866 av1_ext_tx_ind[tx_set_type][tx_type],
1867 av1_num_ext_tx_set[tx_set_type]);
1868 }
1869#if CONFIG_ENTROPY_STATS
1870 ++counts->inter_ext_tx[eset][txsize_sqr_map[tx_size]]
1871 [av1_ext_tx_ind[tx_set_type][tx_type]];
1872#endif // CONFIG_ENTROPY_STATS
1873 } else {
1874 PREDICTION_MODE intra_dir;
1875 if (mbmi->filter_intra_mode_info.use_filter_intra)
1876 intra_dir = fimode_to_intradir[mbmi->filter_intra_mode_info
1877 .filter_intra_mode];
1878 else
1879 intra_dir = mbmi->mode;
1880#if CONFIG_ENTROPY_STATS
1881 ++counts->intra_ext_tx[eset][txsize_sqr_map[tx_size]][intra_dir]
1882 [av1_ext_tx_ind[tx_set_type][tx_type]];
1883#endif // CONFIG_ENTROPY_STATS
1884 if (allow_update_cdf) {
1885 update_cdf(
1886 fc->intra_ext_tx_cdf[eset][txsize_sqr_map[tx_size]][intra_dir],
1887 av1_ext_tx_ind[tx_set_type][tx_type],
1888 av1_num_ext_tx_set[tx_set_type]);
1889 }
1890 }
1891 }
1892 }
1893}
1894
Jingning Han4fe5f672017-05-19 15:46:07 -07001895void av1_update_and_record_txb_context(int plane, int block, int blk_row,
1896 int blk_col, BLOCK_SIZE plane_bsize,
1897 TX_SIZE tx_size, void *arg) {
Jingning Han6171ae72017-05-18 20:15:06 -07001898 struct tokenize_b_args *const args = arg;
Angie Chiang0397eda2017-03-15 16:57:14 -07001899 const AV1_COMP *cpi = args->cpi;
1900 const AV1_COMMON *cm = &cpi->common;
1901 ThreadData *const td = args->td;
1902 MACROBLOCK *const x = &td->mb;
1903 MACROBLOCKD *const xd = &x->e_mbd;
1904 struct macroblock_plane *p = &x->plane[plane];
1905 struct macroblockd_plane *pd = &xd->plane[plane];
Yue Chen53b53f02018-03-29 14:31:23 -07001906 MB_MODE_INFO *mbmi = xd->mi[0];
Hui Su8763cd32018-04-02 12:29:05 -07001907 const int eob = p->eobs[block];
Angie Chiang85901562017-03-17 12:03:27 -07001908 TXB_CTX txb_ctx;
1909 get_txb_ctx(plane_bsize, tx_size, plane, pd->above_context + blk_col,
1910 pd->left_context + blk_row, &txb_ctx);
Angie Chianga9ba58e2017-12-01 19:22:43 -08001911 const int bwl = get_txb_bwl(tx_size);
1912 const int width = get_txb_wide(tx_size);
1913 const int height = get_txb_high(tx_size);
Yunqing Wang0e141b52017-11-02 15:08:58 -07001914 const uint8_t allow_update_cdf = args->allow_update_cdf;
Hui Su8763cd32018-04-02 12:29:05 -07001915 const TX_SIZE txsize_ctx = get_txsize_entropy_ctx(tx_size);
Jingning Han8f661602017-08-19 08:16:50 -07001916 FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
Yue Chen198738d2018-03-08 17:26:01 -08001917#if CONFIG_ENTROPY_STATS
1918 int cdf_idx = cm->coef_cdf_category;
1919#endif // CONFIG_ENTROPY_STATS
Jingning Han48be0e12017-06-13 12:12:01 -07001920
Hui Su1e959892018-01-22 12:14:43 -08001921#if CONFIG_ENTROPY_STATS
Yue Chen198738d2018-03-08 17:26:01 -08001922 ++td->counts->txb_skip[cdf_idx][txsize_ctx][txb_ctx.txb_skip_ctx][eob == 0];
Hui Su1e959892018-01-22 12:14:43 -08001923#endif // CONFIG_ENTROPY_STATS
Hui Su41d61522018-01-23 10:47:55 -08001924 if (allow_update_cdf) {
1925 update_cdf(ec_ctx->txb_skip_cdf[txsize_ctx][txb_ctx.txb_skip_ctx], eob == 0,
Yunqing Wang0e141b52017-11-02 15:08:58 -07001926 2);
Hui Su41d61522018-01-23 10:47:55 -08001927 }
Angie Chiang0397eda2017-03-15 16:57:14 -07001928
Hui Su8763cd32018-04-02 12:29:05 -07001929 x->mbmi_ext->txb_skip_ctx[plane][block] = txb_ctx.txb_skip_ctx;
Angie Chiang0397eda2017-03-15 16:57:14 -07001930 x->mbmi_ext->eobs[plane][block] = eob;
1931
1932 if (eob == 0) {
Hui Sue674dec2018-04-02 13:02:08 -07001933 av1_set_contexts(xd, pd, plane, plane_bsize, tx_size, 0, blk_col, blk_row);
Angie Chiang0397eda2017-03-15 16:57:14 -07001934 return;
1935 }
1936
Hui Su8763cd32018-04-02 12:29:05 -07001937 tran_low_t *tcoeff = BLOCK_OFFSET(x->mbmi_ext->tcoeff[plane], block);
1938 const int segment_id = mbmi->segment_id;
1939 const int seg_eob = av1_get_tx_eob(&cpi->common.seg, segment_id, tx_size);
1940 const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
1941 memcpy(tcoeff, qcoeff, sizeof(*tcoeff) * seg_eob);
1942
1943 uint8_t levels_buf[TX_PAD_2D];
1944 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001945 av1_txb_init_levels(tcoeff, width, height, levels);
Urvang Joshi553096a2018-05-10 15:27:14 -07001946 update_tx_type_count(cm, xd, blk_row, blk_col, plane, tx_size, td->counts,
1947 allow_update_cdf);
Hui Su8763cd32018-04-02 12:29:05 -07001948
1949 const PLANE_TYPE plane_type = pd->plane_type;
1950 const TX_TYPE tx_type = av1_get_tx_type(plane_type, xd, blk_row, blk_col,
1951 tx_size, cm->reduced_tx_set_used);
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001952 const TX_CLASS tx_class = tx_type_to_class[tx_type];
Hui Su8763cd32018-04-02 12:29:05 -07001953 const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
1954 const int16_t *const scan = scan_order->scan;
Yue Chen198738d2018-03-08 17:26:01 -08001955#if CONFIG_ENTROPY_STATS
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001956 av1_update_eob_context(cdf_idx, eob, tx_size, tx_class, plane_type, ec_ctx,
Yaowu Xu49abec82018-03-13 16:09:01 -07001957 td->counts, allow_update_cdf);
Yue Chen198738d2018-03-08 17:26:01 -08001958#else
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001959 av1_update_eob_context(eob, tx_size, tx_class, plane_type, ec_ctx,
Yue Chen198738d2018-03-08 17:26:01 -08001960 allow_update_cdf);
1961#endif
Hui Su8763cd32018-04-02 12:29:05 -07001962
1963 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001964 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_class, coeff_contexts);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -08001965
Hui Su8763cd32018-04-02 12:29:05 -07001966 for (int c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001967 const int pos = scan[c];
Linfeng Zhangd67c13f2017-12-11 11:49:12 -08001968 const int coeff_ctx = coeff_contexts[pos];
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001969 const tran_low_t v = qcoeff[pos];
Angie Chiang2cc5eb32018-02-14 18:37:22 -08001970 const tran_low_t level = abs(v);
Dake He03a32922017-10-31 08:06:45 -07001971
Dake He4d447692017-12-15 09:10:06 -08001972 if (allow_update_cdf) {
1973 if (c == eob - 1) {
1974 assert(coeff_ctx < 4);
1975 update_cdf(
1976 ec_ctx->coeff_base_eob_cdf[txsize_ctx][plane_type][coeff_ctx],
Angie Chiang2cc5eb32018-02-14 18:37:22 -08001977 AOMMIN(level, 3) - 1, 3);
Dake He4d447692017-12-15 09:10:06 -08001978 } else {
1979 update_cdf(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][coeff_ctx],
Angie Chiang2cc5eb32018-02-14 18:37:22 -08001980 AOMMIN(level, 3), 4);
Dake He4d447692017-12-15 09:10:06 -08001981 }
Dake He3fe369c2017-11-16 17:56:44 -08001982 }
Dake He59881772017-11-24 07:00:02 -08001983 {
Dake He4d447692017-12-15 09:10:06 -08001984 if (c == eob - 1) {
1985 assert(coeff_ctx < 4);
Yue Chen198738d2018-03-08 17:26:01 -08001986#if CONFIG_ENTROPY_STATS
1987 ++td->counts->coeff_base_eob_multi[cdf_idx][txsize_ctx][plane_type]
1988 [coeff_ctx][AOMMIN(level, 3) - 1];
Dake He4d447692017-12-15 09:10:06 -08001989 } else {
Yue Chen198738d2018-03-08 17:26:01 -08001990 ++td->counts->coeff_base_multi[cdf_idx][txsize_ctx][plane_type]
1991 [coeff_ctx][AOMMIN(level, 3)];
1992#endif
Angie Chiang2cc5eb32018-02-14 18:37:22 -08001993 }
1994 }
1995 if (level > NUM_BASE_LEVELS) {
1996 const int base_range = level - 1 - NUM_BASE_LEVELS;
Katsuhisa Yuasa55c95f82018-04-03 00:51:22 +09001997 const int br_ctx = get_br_ctx(levels, pos, bwl, tx_class);
Angie Chiang2cc5eb32018-02-14 18:37:22 -08001998 for (int idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
1999 const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
2000 if (allow_update_cdf) {
Angie Chiang2cfb7142018-02-16 11:24:52 -08002001 update_cdf(ec_ctx->coeff_br_cdf[AOMMIN(txsize_ctx, TX_32X32)]
2002 [plane_type][br_ctx],
2003 k, BR_CDF_SIZE);
Angie Chiang2cc5eb32018-02-14 18:37:22 -08002004 }
2005 for (int lps = 0; lps < BR_CDF_SIZE - 1; lps++) {
2006#if CONFIG_ENTROPY_STATS
Angie Chiang2cc5eb32018-02-14 18:37:22 -08002007 ++td->counts->coeff_lps[AOMMIN(txsize_ctx, TX_32X32)][plane_type][lps]
2008 [br_ctx][lps == k];
Angie Chiang2cc5eb32018-02-14 18:37:22 -08002009#endif // CONFIG_ENTROPY_STATS
2010 if (lps == k) break;
2011 }
Yue Chen198738d2018-03-08 17:26:01 -08002012#if CONFIG_ENTROPY_STATS
2013 ++td->counts->coeff_lps_multi[cdf_idx][AOMMIN(txsize_ctx, TX_32X32)]
2014 [plane_type][br_ctx][k];
2015#endif
Angie Chiang2cc5eb32018-02-14 18:37:22 -08002016 if (k < BR_CDF_SIZE - 1) break;
Dake He59881772017-11-24 07:00:02 -08002017 }
2018 }
Dake Hea47cd6c2017-10-13 18:09:58 -07002019 }
Dake Hea47cd6c2017-10-13 18:09:58 -07002020
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002021 // Update the context needed to code the DC sign (if applicable)
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002022 if (tcoeff[0] != 0) {
Hui Su8763cd32018-04-02 12:29:05 -07002023 const int dc_sign = (tcoeff[0] < 0) ? 1 : 0;
2024 const int dc_sign_ctx = txb_ctx.dc_sign_ctx;
Hui Su1e959892018-01-22 12:14:43 -08002025#if CONFIG_ENTROPY_STATS
Hui Su8763cd32018-04-02 12:29:05 -07002026 ++td->counts->dc_sign[plane_type][dc_sign_ctx][dc_sign];
Hui Su1e959892018-01-22 12:14:43 -08002027#endif // CONFIG_ENTROPY_STATS
Yunqing Wang0e141b52017-11-02 15:08:58 -07002028 if (allow_update_cdf)
Hui Su8763cd32018-04-02 12:29:05 -07002029 update_cdf(ec_ctx->dc_sign_cdf[plane_type][dc_sign_ctx], dc_sign, 2);
Dake He43edb762017-10-26 10:29:46 -07002030 x->mbmi_ext->dc_sign_ctx[plane][block] = dc_sign_ctx;
2031 }
2032
Hui Su8763cd32018-04-02 12:29:05 -07002033 const int cul_level = av1_get_txb_entropy_context(tcoeff, scan_order, eob);
Hui Sue674dec2018-04-02 13:02:08 -07002034 av1_set_contexts(xd, pd, plane, plane_bsize, tx_size, cul_level, blk_col,
2035 blk_row);
Angie Chiang0397eda2017-03-15 16:57:14 -07002036}
2037
2038void av1_update_txb_context(const AV1_COMP *cpi, ThreadData *td,
2039 RUN_TYPE dry_run, BLOCK_SIZE bsize, int *rate,
Yunqing Wang0e141b52017-11-02 15:08:58 -07002040 int mi_row, int mi_col, uint8_t allow_update_cdf) {
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +00002041 const AV1_COMMON *const cm = &cpi->common;
2042 const int num_planes = av1_num_planes(cm);
Angie Chiang0397eda2017-03-15 16:57:14 -07002043 MACROBLOCK *const x = &td->mb;
2044 MACROBLOCKD *const xd = &x->e_mbd;
Yue Chen53b53f02018-03-29 14:31:23 -07002045 MB_MODE_INFO *const mbmi = xd->mi[0];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002046 struct tokenize_b_args arg = { cpi, td, NULL, 0, allow_update_cdf };
Angie Chiang0397eda2017-03-15 16:57:14 -07002047 (void)rate;
2048 (void)mi_row;
2049 (void)mi_col;
2050 if (mbmi->skip) {
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +00002051 av1_reset_skip_context(xd, mi_row, mi_col, bsize, num_planes);
Angie Chiang0397eda2017-03-15 16:57:14 -07002052 return;
2053 }
2054
2055 if (!dry_run) {
Jingning Han94652b82017-04-04 09:45:02 -07002056 av1_foreach_transformed_block(xd, bsize, mi_row, mi_col,
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +00002057 av1_update_and_record_txb_context, &arg,
2058 num_planes);
Angie Chiangc8af6112017-03-16 16:11:22 -07002059 } else if (dry_run == DRY_RUN_NORMAL) {
Jingning Han4fe5f672017-05-19 15:46:07 -07002060 av1_foreach_transformed_block(xd, bsize, mi_row, mi_col,
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +00002061 av1_update_txb_context_b, &arg, num_planes);
Angie Chiangc8af6112017-03-16 16:11:22 -07002062 } else {
2063 printf("DRY_RUN_COSTCOEFFS is not supported yet\n");
2064 assert(0);
Angie Chiang0397eda2017-03-15 16:57:14 -07002065 }
2066}