blob: fd12d0b0c176ea885da8d01d0b7a74fdca433ef0 [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
Linfeng Zhangae7b2f32017-11-08 15:46:57 -080012#include "aom_ports/mem.h"
Angie Chiang80b82262017-02-24 11:39:47 -080013#include "av1/common/scan.h"
Angie Chiang0397eda2017-03-15 16:57:14 -070014#include "av1/common/blockd.h"
Angie Chiange50f3ec2017-04-10 15:50:33 -070015#include "av1/common/idct.h"
Angie Chiang0397eda2017-03-15 16:57:14 -070016#include "av1/common/pred_common.h"
Angie Chiang1628fcc2017-04-13 16:30:30 -070017#include "av1/encoder/bitstream.h"
18#include "av1/encoder/encodeframe.h"
Angie Chiang47c72182017-02-27 14:30:38 -080019#include "av1/encoder/cost.h"
Angie Chiang80b82262017-02-24 11:39:47 -080020#include "av1/encoder/encodetxb.h"
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -080021#include "av1/encoder/hash.h"
Angie Chiang808d8592017-04-06 18:36:55 -070022#include "av1/encoder/rdopt.h"
Angie Chiang0397eda2017-03-15 16:57:14 -070023#include "av1/encoder/tokenize.h"
Angie Chiang80b82262017-02-24 11:39:47 -080024
Angie Chiang47e07072017-05-30 17:27:01 -070025#define TEST_OPTIMIZE_TXB 0
26
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -080027static int hbt_hash_needs_init = 1;
28static CRC_CALCULATOR crc_calculator;
29static CRC_CALCULATOR crc_calculator2;
30static const int HBT_HASH_EOB = 16; // also the length in opt_qcoeff
31
32typedef struct OptTxbQcoeff {
33 uint32_t hbt_hash_match;
34 double hits;
35 tran_low_t opt_qcoeff[16];
36} OptTxbQcoeff;
37
38OptTxbQcoeff hbt_hash_table[65536][16];
39
Dake Hea47cd6c2017-10-13 18:09:58 -070040typedef struct LevelDownStats {
41 int update;
42 tran_low_t low_qc;
43 tran_low_t low_dqc;
Dake Hea47cd6c2017-10-13 18:09:58 -070044 int64_t dist0;
45 int rate;
46 int rate_low;
47 int64_t dist;
48 int64_t dist_low;
49 int64_t rd;
50 int64_t rd_low;
Dake He4d447692017-12-15 09:10:06 -080051 int64_t nz_rd;
Dake Hea47cd6c2017-10-13 18:09:58 -070052 int64_t rd_diff;
53 int cost_diff;
54 int64_t dist_diff;
55 int new_eob;
56} LevelDownStats;
57
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070058void av1_alloc_txb_buf(AV1_COMP *cpi) {
Angie Chiangc484abe2017-03-20 15:43:11 -070059#if 0
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070060 AV1_COMMON *cm = &cpi->common;
61 int mi_block_size = 1 << MI_SIZE_LOG2;
62 // TODO(angiebird): Make sure cm->subsampling_x/y is set correctly, and then
63 // use precise buffer size according to cm->subsampling_x/y
64 int pixel_stride = mi_block_size * cm->mi_cols;
65 int pixel_height = mi_block_size * cm->mi_rows;
66 int i;
67 for (i = 0; i < MAX_MB_PLANE; ++i) {
68 CHECK_MEM_ERROR(
69 cm, cpi->tcoeff_buf[i],
70 aom_malloc(sizeof(*cpi->tcoeff_buf[i]) * pixel_stride * pixel_height));
71 }
Angie Chiangc484abe2017-03-20 15:43:11 -070072#else
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070073 AV1_COMMON *cm = &cpi->common;
Dominic Symes917d6c02017-10-11 18:00:52 +020074 int size = ((cm->mi_rows >> cm->mib_size_log2) + 1) *
75 ((cm->mi_cols >> cm->mib_size_log2) + 1);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070076
Angie Chiang9367e3e2017-10-02 16:28:11 -070077 av1_free_txb_buf(cpi);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070078 // TODO(jingning): This should be further reduced.
79 CHECK_MEM_ERROR(cm, cpi->coeff_buffer_base,
80 aom_malloc(sizeof(*cpi->coeff_buffer_base) * size));
Angie Chiangc484abe2017-03-20 15:43:11 -070081#endif
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070082}
83
84void av1_free_txb_buf(AV1_COMP *cpi) {
Angie Chiangc484abe2017-03-20 15:43:11 -070085#if 0
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070086 int i;
87 for (i = 0; i < MAX_MB_PLANE; ++i) {
88 aom_free(cpi->tcoeff_buf[i]);
89 }
Angie Chiangc484abe2017-03-20 15:43:11 -070090#else
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070091 aom_free(cpi->coeff_buffer_base);
Angie Chiangc484abe2017-03-20 15:43:11 -070092#endif
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070093}
94
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070095void av1_set_coeff_buffer(const AV1_COMP *const cpi, MACROBLOCK *const x,
96 int mi_row, int mi_col) {
Dominic Symes917d6c02017-10-11 18:00:52 +020097 int mib_size_log2 = cpi->common.mib_size_log2;
98 int stride = (cpi->common.mi_cols >> mib_size_log2) + 1;
99 int offset = (mi_row >> mib_size_log2) * stride + (mi_col >> mib_size_log2);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -0700100 CB_COEFF_BUFFER *coeff_buf = &cpi->coeff_buffer_base[offset];
101 const int txb_offset = x->cb_offset / (TX_SIZE_W_MIN * TX_SIZE_H_MIN);
102 for (int plane = 0; plane < MAX_MB_PLANE; ++plane) {
103 x->mbmi_ext->tcoeff[plane] = coeff_buf->tcoeff[plane] + x->cb_offset;
104 x->mbmi_ext->eobs[plane] = coeff_buf->eobs[plane] + txb_offset;
105 x->mbmi_ext->txb_skip_ctx[plane] =
106 coeff_buf->txb_skip_ctx[plane] + txb_offset;
107 x->mbmi_ext->dc_sign_ctx[plane] =
108 coeff_buf->dc_sign_ctx[plane] + txb_offset;
109 }
110}
111
Angie Chiang80b82262017-02-24 11:39:47 -0800112static void write_golomb(aom_writer *w, int level) {
113 int x = level + 1;
114 int i = x;
115 int length = 0;
116
117 while (i) {
118 i >>= 1;
119 ++length;
120 }
121 assert(length > 0);
122
123 for (i = 0; i < length - 1; ++i) aom_write_bit(w, 0);
124
125 for (i = length - 1; i >= 0; --i) aom_write_bit(w, (x >> i) & 0x01);
126}
127
Dake Hea47cd6c2017-10-13 18:09:58 -0700128static INLINE tran_low_t get_lower_coeff(tran_low_t qc) {
129 if (qc == 0) {
130 return 0;
131 }
132 return qc > 0 ? qc - 1 : qc + 1;
133}
134
Sarah Parker3d752092017-12-20 15:37:55 -0800135static INLINE tran_low_t qcoeff_to_dqcoeff(tran_low_t qc,
136#if CONFIG_NEW_QUANT
137 const tran_low_t *nq_dq,
138#endif // CONFIG_NEW_QUANT
139 int dqv, int shift) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700140 int sgn = qc < 0 ? -1 : 1;
Sarah Parker3d752092017-12-20 15:37:55 -0800141#if CONFIG_NEW_QUANT
Sarah Parker8a086e02018-01-10 14:56:42 -0800142 int dqcoeff = av1_dequant_coeff_nuq(abs(qc), dqv, nq_dq, shift);
143 return sgn * dqcoeff;
Sarah Parker3d752092017-12-20 15:37:55 -0800144#endif // CONFIG_NEW_QUANT
145
Dake Hea47cd6c2017-10-13 18:09:58 -0700146 return sgn * ((abs(qc) * dqv) >> shift);
147}
148
149static INLINE int64_t get_coeff_dist(tran_low_t tcoeff, tran_low_t dqcoeff,
150 int shift) {
Monty Montgomery4a05a582017-11-01 21:21:07 -0400151#if CONFIG_DAALA_TX
152 int depth_shift = (TX_COEFF_DEPTH - 11) * 2;
153 int depth_round = depth_shift > 1 ? (1 << (depth_shift - 1)) : 0;
154 const int64_t diff = tcoeff - dqcoeff;
Montybca9e9e2017-12-14 06:23:29 -0600155 const int64_t error = (diff * diff + depth_round) >> depth_shift;
Monty Montgomery4a05a582017-11-01 21:21:07 -0400156 (void)shift;
157#else
Dake Hea47cd6c2017-10-13 18:09:58 -0700158 const int64_t diff = (tcoeff - dqcoeff) * (1 << shift);
159 const int64_t error = diff * diff;
Monty Montgomery4a05a582017-11-01 21:21:07 -0400160#endif
Dake Hea47cd6c2017-10-13 18:09:58 -0700161 return error;
162}
163
Jingning Han35deaa72017-10-26 15:36:30 -0700164void av1_update_eob_context(int eob, int seg_eob, TX_SIZE tx_size,
165 TX_TYPE tx_type, PLANE_TYPE plane,
Yunqing Wang0e141b52017-11-02 15:08:58 -0700166 FRAME_CONTEXT *ec_ctx, FRAME_COUNTS *counts,
167 uint8_t allow_update_cdf) {
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800168 int eob_extra, dummy;
169 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
170 const int max_eob_pt = get_eob_pos_token(seg_eob, &dummy);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -0800171 TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Dake Hea47cd6c2017-10-13 18:09:58 -0700172
Dake He0db7d0e2017-12-21 15:23:20 -0800173 (void)max_eob_pt;
174 const int eob_multi_size = txsize_log2_minus4[tx_size];
175 const int eob_multi_ctx = (tx_type_to_class[tx_type] == TX_CLASS_2D) ? 0 : 1;
176
177 switch (eob_multi_size) {
178 case 0:
179 ++counts->eob_multi16[plane][eob_multi_ctx][eob_pt - 1];
180 if (allow_update_cdf)
181 update_cdf(ec_ctx->eob_flag_cdf16[plane][eob_multi_ctx], eob_pt - 1, 5);
182 break;
183 case 1:
184 ++counts->eob_multi32[plane][eob_multi_ctx][eob_pt - 1];
185 if (allow_update_cdf)
186 update_cdf(ec_ctx->eob_flag_cdf32[plane][eob_multi_ctx], eob_pt - 1, 6);
187 break;
188 case 2:
189 ++counts->eob_multi64[plane][eob_multi_ctx][eob_pt - 1];
190 if (allow_update_cdf)
191 update_cdf(ec_ctx->eob_flag_cdf64[plane][eob_multi_ctx], eob_pt - 1, 7);
192 break;
193 case 3:
194 ++counts->eob_multi128[plane][eob_multi_ctx][eob_pt - 1];
195 if (allow_update_cdf)
196 update_cdf(ec_ctx->eob_flag_cdf128[plane][eob_multi_ctx], eob_pt - 1,
197 8);
198 break;
199 case 4:
200 ++counts->eob_multi256[plane][eob_multi_ctx][eob_pt - 1];
201 if (allow_update_cdf)
202 update_cdf(ec_ctx->eob_flag_cdf256[plane][eob_multi_ctx], eob_pt - 1,
203 9);
204 break;
205 case 5:
206 ++counts->eob_multi512[plane][eob_multi_ctx][eob_pt - 1];
207 if (allow_update_cdf)
208 update_cdf(ec_ctx->eob_flag_cdf512[plane][eob_multi_ctx], eob_pt - 1,
209 10);
210 break;
211 case 6:
212 default:
213 ++counts->eob_multi1024[plane][eob_multi_ctx][eob_pt - 1];
214 if (allow_update_cdf)
215 update_cdf(ec_ctx->eob_flag_cdf1024[plane][eob_multi_ctx], eob_pt - 1,
216 11);
217 break;
218 }
Jingning Han00803a72017-10-25 16:04:34 -0700219
Angie Chiang7ab884e2017-10-18 15:57:12 -0700220 if (k_eob_offset_bits[eob_pt] > 0) {
221 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
222 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Jingning Han35deaa72017-10-26 15:36:30 -0700223 counts->eob_extra[txs_ctx][plane][eob_pt][bit]++;
Yunqing Wang0e141b52017-11-02 15:08:58 -0700224 if (allow_update_cdf)
225 update_cdf(ec_ctx->eob_extra_cdf[txs_ctx][plane][eob_pt], bit, 2);
Angie Chiang7ab884e2017-10-18 15:57:12 -0700226 }
Dake Hea47cd6c2017-10-13 18:09:58 -0700227}
228
229static int get_eob_cost(int eob, int seg_eob,
Dake He0db7d0e2017-12-21 15:23:20 -0800230 const LV_MAP_EOB_COST *txb_eob_costs,
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100231 const LV_MAP_COEFF_COST *txb_costs, TX_TYPE tx_type) {
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800232 int eob_extra, dummy;
233 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
234 const int max_eob_pt = get_eob_pos_token(seg_eob, &dummy);
Dake Hea47cd6c2017-10-13 18:09:58 -0700235 int eob_cost = 0;
Dake He0db7d0e2017-12-21 15:23:20 -0800236 (void)max_eob_pt;
237 const int eob_multi_ctx = (tx_type_to_class[tx_type] == TX_CLASS_2D) ? 0 : 1;
238 eob_cost = txb_eob_costs->eob_cost[eob_multi_ctx][eob_pt - 1];
Dake He0db7d0e2017-12-21 15:23:20 -0800239
Dake Hea47cd6c2017-10-13 18:09:58 -0700240 if (k_eob_offset_bits[eob_pt] > 0) {
Angie Chiang7ab884e2017-10-18 15:57:12 -0700241 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
242 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
243 eob_cost += txb_costs->eob_extra_cost[eob_pt][bit];
244 for (int i = 1; i < k_eob_offset_bits[eob_pt]; i++) {
245 eob_shift = k_eob_offset_bits[eob_pt] - 1 - i;
246 bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700247 eob_cost += av1_cost_bit(128, bit);
248 }
249 }
250 return eob_cost;
251}
252
Linfeng Zhang1015a342017-10-24 16:20:41 -0700253static int get_coeff_cost(const tran_low_t qc, const int scan_idx,
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100254 const int is_eob, const TxbInfo *const txb_info,
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -0800255 const LV_MAP_COEFF_COST *const txb_costs,
256 const int coeff_ctx);
Dake Hea47cd6c2017-10-13 18:09:58 -0700257
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800258static void get_dist_cost_stats(LevelDownStats *const stats, const int scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +0100259 const int is_eob,
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800260 const LV_MAP_COEFF_COST *const txb_costs,
Cheng Chen37d88732018-01-09 14:02:41 -0800261 const TxbInfo *const txb_info,
262 int has_nz_tail) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800263 const int16_t *const scan = txb_info->scan_order->scan;
Dake Hea47cd6c2017-10-13 18:09:58 -0700264 const int coeff_idx = scan[scan_idx];
265 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
Linfeng Zhang1015a342017-10-24 16:20:41 -0700266 const uint8_t *const levels = txb_info->levels;
Dake Hea47cd6c2017-10-13 18:09:58 -0700267 stats->new_eob = -1;
268 stats->update = 0;
Debargha Mukherjeee2f6b162018-01-04 17:23:05 -0800269 stats->rd_low = 0;
270 stats->rd = 0;
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100271 // TODO(mfo): explore if there's a better way to prevent compiler init
272 // warnings
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -0800273 stats->nz_rd = 0;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -0800274 stats->dist_low = 0;
275 stats->rate_low = 0;
276 stats->low_qc = 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700277
278 const tran_low_t tqc = txb_info->tcoeff[coeff_idx];
279 const int dqv = txb_info->dequant[coeff_idx != 0];
Sarah Parker3d752092017-12-20 15:37:55 -0800280#if CONFIG_NEW_QUANT
281 const tran_low_t *nq_dequant_val = txb_info->nq_dequant_vals[coeff_idx != 0];
282#endif // CONFIG_NEW_QUANT
Dake Hea47cd6c2017-10-13 18:09:58 -0700283
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100284 const int coeff_ctx =
285 get_nz_map_ctx(levels, coeff_idx, txb_info->bwl, txb_info->height,
286 scan_idx, is_eob, txb_info->tx_size, txb_info->tx_type);
287 const int qc_cost =
288 get_coeff_cost(qc, scan_idx, is_eob, txb_info, txb_costs, coeff_ctx);
Dake Hea47cd6c2017-10-13 18:09:58 -0700289 if (qc == 0) {
Cheng Chen79641202018-01-04 18:52:52 -0800290 stats->dist = 0;
291 stats->rate = qc_cost;
Dake Hea47cd6c2017-10-13 18:09:58 -0700292 return;
Cheng Chen79641202018-01-04 18:52:52 -0800293 } else {
294 const tran_low_t dqc = qcoeff_to_dqcoeff(qc,
295#if CONFIG_NEW_QUANT
296 nq_dequant_val,
297#endif // CONFIG_NEW_QUANT
298 dqv, txb_info->shift);
299 const int64_t dqc_dist = get_coeff_dist(tqc, dqc, txb_info->shift);
300
301 // distortion difference when coefficient is quantized to 0
302 const tran_low_t dqc0 = qcoeff_to_dqcoeff(0,
303#if CONFIG_NEW_QUANT
304 nq_dequant_val,
305#endif // CONFIG_NEW_QUANT
306 dqv, txb_info->shift);
307
308 stats->dist0 = get_coeff_dist(tqc, dqc0, txb_info->shift);
309 stats->dist = dqc_dist - stats->dist0;
310 stats->rate = qc_cost;
Dake Hea47cd6c2017-10-13 18:09:58 -0700311 }
Cheng Chen79641202018-01-04 18:52:52 -0800312
Dake Hea47cd6c2017-10-13 18:09:58 -0700313 stats->rd = RDCOST(txb_info->rdmult, stats->rate, stats->dist);
314
315 stats->low_qc = get_lower_coeff(qc);
Dake Hea47cd6c2017-10-13 18:09:58 -0700316
Dake He4d447692017-12-15 09:10:06 -0800317 if (is_eob && stats->low_qc == 0) {
Dake He4d447692017-12-15 09:10:06 -0800318 stats->rd_low = stats->rd; // disable selection of low_qc in this case.
Ola Hugosson13892102017-11-06 08:01:44 +0100319 } else {
Cheng Chen37d88732018-01-09 14:02:41 -0800320 if (stats->low_qc == 0) {
321 stats->dist_low = 0;
322 } else {
323 stats->low_dqc = qcoeff_to_dqcoeff(stats->low_qc,
Dake He4d447692017-12-15 09:10:06 -0800324#if CONFIG_NEW_QUANT
Cheng Chen37d88732018-01-09 14:02:41 -0800325 nq_dequant_val,
Dake He4d447692017-12-15 09:10:06 -0800326#endif // CONFIG_NEW_QUANT
Cheng Chen37d88732018-01-09 14:02:41 -0800327 dqv, txb_info->shift);
328 const int64_t low_dqc_dist =
329 get_coeff_dist(tqc, stats->low_dqc, txb_info->shift);
330 stats->dist_low = low_dqc_dist - stats->dist0;
331 }
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100332 const int low_qc_cost = get_coeff_cost(stats->low_qc, scan_idx, is_eob,
Yaowu Xu0154f2b2018-01-04 09:01:17 -0800333 txb_info, txb_costs, coeff_ctx);
Dake He4d447692017-12-15 09:10:06 -0800334 stats->rate_low = low_qc_cost;
335 stats->rd_low = RDCOST(txb_info->rdmult, stats->rate_low, stats->dist_low);
Ola Hugosson13892102017-11-06 08:01:44 +0100336 }
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100337 if ((has_nz_tail < 2) && ((scan_idx == txb_info->eob - 1) || !is_eob)) {
Cheng Chen37d88732018-01-09 14:02:41 -0800338 (void)levels;
339 const int coeff_ctx_temp =
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100340 get_nz_map_ctx(levels, coeff_idx, txb_info->bwl, txb_info->height,
341 scan_idx, 1, txb_info->tx_size, txb_info->tx_type);
Cheng Chen37d88732018-01-09 14:02:41 -0800342 const int qc_eob_cost =
343 get_coeff_cost(qc, scan_idx, 1, txb_info, txb_costs, coeff_ctx_temp);
344 int64_t rd_eob = RDCOST(txb_info->rdmult, qc_eob_cost, stats->dist);
345 if (stats->low_qc != 0) {
346 const int low_qc_eob_cost = get_coeff_cost(
347 stats->low_qc, scan_idx, 1, txb_info, txb_costs, coeff_ctx_temp);
348 int64_t rd_eob_low =
349 RDCOST(txb_info->rdmult, low_qc_eob_cost, stats->dist_low);
350 rd_eob = (rd_eob > rd_eob_low) ? rd_eob_low : rd_eob;
351 }
352
353 stats->nz_rd = AOMMIN(stats->rd_low, stats->rd) - rd_eob;
Cheng Chen37d88732018-01-09 14:02:41 -0800354 }
Dake Hea47cd6c2017-10-13 18:09:58 -0700355}
356
Linfeng Zhang1015a342017-10-24 16:20:41 -0700357static INLINE void update_qcoeff(const int coeff_idx, const tran_low_t qc,
358 const TxbInfo *const txb_info) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700359 txb_info->qcoeff[coeff_idx] = qc;
Linfeng Zhangd5647372017-12-05 17:06:07 -0800360 txb_info->levels[get_padded_idx(coeff_idx, txb_info->bwl)] =
Jingning Han5cb408e2017-11-17 14:43:39 -0800361 (uint8_t)clamp(abs(qc), 0, INT8_MAX);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700362}
363
364static INLINE void update_coeff(const int coeff_idx, const tran_low_t qc,
365 const TxbInfo *const txb_info) {
366 update_qcoeff(coeff_idx, qc, txb_info);
Dake Hea47cd6c2017-10-13 18:09:58 -0700367 const int dqv = txb_info->dequant[coeff_idx != 0];
Sarah Parker3d752092017-12-20 15:37:55 -0800368#if CONFIG_NEW_QUANT
369 const tran_low_t *nq_dequant_val = txb_info->nq_dequant_vals[coeff_idx != 0];
370#endif // CONFIG_NEW_QUANT
371 txb_info->dqcoeff[coeff_idx] = qcoeff_to_dqcoeff(qc,
372#if CONFIG_NEW_QUANT
373 nq_dequant_val,
374#endif // CONFIG_NEW_QUANT
375 dqv, txb_info->shift);
Dake Hea47cd6c2017-10-13 18:09:58 -0700376}
377
Linfeng Zhang1015a342017-10-24 16:20:41 -0700378static INLINE void av1_txb_init_levels(const tran_low_t *const coeff,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700379 const int width, const int height,
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700380 uint8_t *const levels) {
381 const int stride = width + TX_PAD_HOR;
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700382 uint8_t *ls = levels;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700383
384 memset(levels - TX_PAD_TOP * stride, 0,
385 sizeof(*levels) * TX_PAD_TOP * stride);
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700386 memset(levels + stride * height, 0,
387 sizeof(*levels) * (TX_PAD_BOTTOM * stride + TX_PAD_END));
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700388
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700389 for (int i = 0; i < height; i++) {
390 for (int j = 0; j < width; j++) {
Jingning Han5cb408e2017-11-17 14:43:39 -0800391 *ls++ = (uint8_t)clamp(abs(coeff[i * width + j]), 0, INT8_MAX);
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700392 }
393 for (int j = 0; j < TX_PAD_HOR; j++) {
394 *ls++ = 0;
395 }
Linfeng Zhang1015a342017-10-24 16:20:41 -0700396 }
397}
398
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800399void av1_get_nz_map_contexts_c(const uint8_t *const levels,
400 const int16_t *const scan, const uint16_t eob,
401 const TX_SIZE tx_size, const TX_TYPE tx_type,
402 int8_t *const coeff_contexts) {
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800403 const int bwl = get_txb_bwl(tx_size);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800404 const int height = get_txb_high(tx_size);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800405 for (int i = 0; i < eob; ++i) {
406 const int pos = scan[i];
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100407 coeff_contexts[pos] = get_nz_map_ctx(levels, pos, bwl, height, i,
408 i == eob - 1, tx_size, tx_type);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800409 }
410}
411
Angie Chiang80b82262017-02-24 11:39:47 -0800412void av1_write_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCKD *xd,
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500413 aom_writer *w, int blk_row, int blk_col, int plane,
414 TX_SIZE tx_size, const tran_low_t *tcoeff,
Jingning Han7eab9ff2017-07-06 10:12:54 -0700415 uint16_t eob, TXB_CTX *txb_ctx) {
Angie Chiang80b82262017-02-24 11:39:47 -0800416 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiangcea11f22017-02-24 12:30:40 -0800417 const PLANE_TYPE plane_type = get_plane_type(plane);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -0800418 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Jingning Han19b5c8f2017-07-06 15:10:12 -0700419 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500420 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -0700421 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800422 const int16_t *const scan = scan_order->scan;
Urvang Joshi80893152017-10-27 11:51:14 -0700423 const int seg_eob = av1_get_max_eob(tx_size);
Angie Chiang80b82262017-02-24 11:39:47 -0800424 int c;
Angie Chianga9ba58e2017-12-01 19:22:43 -0800425 const int bwl = get_txb_bwl(tx_size);
426 const int width = get_txb_wide(tx_size);
427 const int height = get_txb_high(tx_size);
Linfeng Zhang848f7bc2017-10-31 15:26:07 -0700428 int update_eob = -1;
Jingning Han41c7f442017-09-05 14:54:00 -0700429 FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700430 uint8_t levels_buf[TX_PAD_2D];
431 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -0800432 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800433 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Angie Chiang80b82262017-02-24 11:39:47 -0800434
Jingning Han94cea4a2017-09-30 14:13:23 -0700435 aom_write_bin(w, eob == 0,
436 ec_ctx->txb_skip_cdf[txs_ctx][txb_ctx->txb_skip_ctx], 2);
Angie Chiang5f0cb5e2017-12-11 16:07:50 -0800437#if CONFIG_TXK_SEL
Angie Chianga3f7d2e2017-12-07 19:51:14 -0800438 if (plane == 0 && eob == 0) {
439 assert(tx_type == DCT_DCT);
440 }
Angie Chiang5f0cb5e2017-12-11 16:07:50 -0800441#endif
Angie Chiang80b82262017-02-24 11:39:47 -0800442 if (eob == 0) return;
Linfeng Zhangce065ca2017-10-17 16:49:30 -0700443
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700444 av1_txb_init_levels(tcoeff, width, height, levels);
Linfeng Zhangce065ca2017-10-17 16:49:30 -0700445
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700446#if CONFIG_TXK_SEL
Debargha Mukherjee3ebb0d02017-12-14 05:05:18 -0800447 av1_write_tx_type(cm, xd, blk_row, blk_col, plane, tx_size, w);
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700448#endif
Angie Chiang80b82262017-02-24 11:39:47 -0800449
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800450 int eob_extra, dummy;
451 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
452 const int max_eob_pt = get_eob_pos_token(seg_eob, &dummy);
Dake Hea47cd6c2017-10-13 18:09:58 -0700453
Dake He0db7d0e2017-12-21 15:23:20 -0800454 (void)max_eob_pt;
455 const int eob_multi_size = txsize_log2_minus4[tx_size];
456 const int eob_multi_ctx = (tx_type_to_class[tx_type] == TX_CLASS_2D) ? 0 : 1;
457 switch (eob_multi_size) {
458 case 0:
459 aom_write_symbol(w, eob_pt - 1,
460 ec_ctx->eob_flag_cdf16[plane_type][eob_multi_ctx], 5);
461 break;
462 case 1:
463 aom_write_symbol(w, eob_pt - 1,
464 ec_ctx->eob_flag_cdf32[plane_type][eob_multi_ctx], 6);
465 break;
466 case 2:
467 aom_write_symbol(w, eob_pt - 1,
468 ec_ctx->eob_flag_cdf64[plane_type][eob_multi_ctx], 7);
469 break;
470 case 3:
471 aom_write_symbol(w, eob_pt - 1,
472 ec_ctx->eob_flag_cdf128[plane_type][eob_multi_ctx], 8);
473 break;
474 case 4:
475 aom_write_symbol(w, eob_pt - 1,
476 ec_ctx->eob_flag_cdf256[plane_type][eob_multi_ctx], 9);
477 break;
478 case 5:
479 aom_write_symbol(w, eob_pt - 1,
480 ec_ctx->eob_flag_cdf512[plane_type][eob_multi_ctx], 10);
481 break;
482 default:
483 aom_write_symbol(w, eob_pt - 1,
484 ec_ctx->eob_flag_cdf1024[plane_type][eob_multi_ctx], 11);
485 break;
486 }
487
Dake Hea47cd6c2017-10-13 18:09:58 -0700488 if (k_eob_offset_bits[eob_pt] > 0) {
Angie Chiang7ab884e2017-10-18 15:57:12 -0700489 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
490 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
491 aom_write_bin(w, bit, ec_ctx->eob_extra_cdf[txs_ctx][plane_type][eob_pt],
492 2);
493 for (int i = 1; i < k_eob_offset_bits[eob_pt]; i++) {
494 eob_shift = k_eob_offset_bits[eob_pt] - 1 - i;
495 bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700496 aom_write_bit(w, bit);
Dake Hea47cd6c2017-10-13 18:09:58 -0700497 }
498 }
Dake He03a32922017-10-31 08:06:45 -0700499
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800500 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_type, coeff_contexts);
501
502 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800503 const int pos = scan[c];
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800504 const int coeff_ctx = coeff_contexts[pos];
505 const tran_low_t v = tcoeff[pos];
Dake He03a32922017-10-31 08:06:45 -0700506
Dake He3fe369c2017-11-16 17:56:44 -0800507 if (c == eob - 1) {
508 aom_write_symbol(
509 w, AOMMIN(abs(v), 3) - 1,
Dake He4d447692017-12-15 09:10:06 -0800510 ec_ctx->coeff_base_eob_cdf[txs_ctx][plane_type][coeff_ctx], 3);
Dake He3fe369c2017-11-16 17:56:44 -0800511 } else {
512 aom_write_symbol(w, AOMMIN(abs(v), 3),
513 ec_ctx->coeff_base_cdf[txs_ctx][plane_type][coeff_ctx],
514 4);
515 }
Dake He03a32922017-10-31 08:06:45 -0700516 }
517 update_eob = eob - 1;
Angie Chiang80b82262017-02-24 11:39:47 -0800518
Dake He43edb762017-10-26 10:29:46 -0700519 // Loop to code all signs in the transform block,
520 // starting with the sign of DC (if applicable)
521 for (c = 0; c < eob; ++c) {
Linfeng Zhang1015a342017-10-24 16:20:41 -0700522 const tran_low_t v = tcoeff[scan[c]];
523 const tran_low_t level = abs(v);
524 const int sign = (v < 0) ? 1 : 0;
Dake He43edb762017-10-26 10:29:46 -0700525 if (level == 0) continue;
526
527 if (c == 0) {
Dake He43edb762017-10-26 10:29:46 -0700528 aom_write_bin(w, sign,
529 ec_ctx->dc_sign_cdf[plane_type][txb_ctx->dc_sign_ctx], 2);
Dake He43edb762017-10-26 10:29:46 -0700530 } else {
531 aom_write_bit(w, sign);
532 }
533 }
534
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800535 if (update_eob >= 0) {
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800536 for (c = update_eob; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800537 const int pos = scan[c];
538 const tran_low_t level = abs(tcoeff[pos]);
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800539 int idx;
540 int ctx;
Angie Chiang80b82262017-02-24 11:39:47 -0800541
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800542 if (level <= NUM_BASE_LEVELS) continue;
Angie Chiang80b82262017-02-24 11:39:47 -0800543
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100544 // level is above 1.
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800545 const int base_range = level - 1 - NUM_BASE_LEVELS;
Dake He7d01ab52017-11-24 17:53:28 -0800546#if USE_CAUSAL_BR_CTX
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800547 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos], tx_type);
Dake He7d01ab52017-11-24 17:53:28 -0800548
549#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800550 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -0800551#endif
Ola Hugossone72a2092017-11-12 09:11:53 +0100552 for (idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800553 const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
Dake Hee2d8f182017-12-14 13:28:00 -0800554 aom_write_symbol(w, k,
555#if 0
Dake He7d01ab52017-11-24 17:53:28 -0800556 ec_ctx->coeff_br_cdf[AOMMIN(txs_ctx, TX_16X16)][plane_type][ctx],
Dake Hee2d8f182017-12-14 13:28:00 -0800557#else
558 ec_ctx->coeff_br_cdf[AOMMIN(txs_ctx, TX_32X32)]
559 [plane_type][ctx],
560#endif
561 BR_CDF_SIZE);
Ola Hugossone72a2092017-11-12 09:11:53 +0100562 if (k < BR_CDF_SIZE - 1) break;
563 }
564 if (base_range < COEFF_BASE_RANGE) continue;
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800565 // use 0-th order Golomb code to handle the residual level.
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800566 write_golomb(w,
567 abs(tcoeff[pos]) - COEFF_BASE_RANGE - 1 - NUM_BASE_LEVELS);
Jingning Han87b01b52017-08-31 12:07:20 -0700568 }
Angie Chiang80b82262017-02-24 11:39:47 -0800569 }
570}
Angie Chiang47c72182017-02-27 14:30:38 -0800571
Angie Chiang140b3332017-12-12 17:29:25 -0800572typedef struct encode_txb_args {
573 const AV1_COMMON *cm;
574 MACROBLOCK *x;
575 aom_writer *w;
576} ENCODE_TXB_ARGS;
577
Jingning Han4b48cd12018-01-11 15:56:42 -0800578static void av1_write_coeffs_txb_wrap(const AV1_COMMON *cm, MACROBLOCK *x,
579 aom_writer *w, int plane, int block,
580 int blk_row, int blk_col,
581 TX_SIZE tx_size) {
Angie Chiangc8af6112017-03-16 16:11:22 -0700582 MACROBLOCKD *xd = &x->e_mbd;
Angie Chiang140b3332017-12-12 17:29:25 -0800583 tran_low_t *tcoeff = BLOCK_OFFSET(x->mbmi_ext->tcoeff[plane], block);
584 uint16_t eob = x->mbmi_ext->eobs[plane][block];
585 TXB_CTX txb_ctx = { x->mbmi_ext->txb_skip_ctx[plane][block],
586 x->mbmi_ext->dc_sign_ctx[plane][block] };
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500587 av1_write_coeffs_txb(cm, xd, w, blk_row, blk_col, plane, tx_size, tcoeff, eob,
588 &txb_ctx);
Angie Chiang140b3332017-12-12 17:29:25 -0800589}
590
Jingning Han4b48cd12018-01-11 15:56:42 -0800591void av1_write_coeffs_mb(const AV1_COMMON *const cm, MACROBLOCK *x, int mi_row,
592 int mi_col, aom_writer *w, int plane,
593 BLOCK_SIZE bsize) {
Angie Chiang140b3332017-12-12 17:29:25 -0800594 MACROBLOCKD *xd = &x->e_mbd;
Jingning Han4b48cd12018-01-11 15:56:42 -0800595 const struct macroblockd_plane *const pd = &xd->plane[plane];
596 const TX_SIZE tx_size = av1_get_tx_size(plane, xd);
597 const int stepr = tx_size_high_unit[tx_size];
598 const int stepc = tx_size_wide_unit[tx_size];
599 const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
600 int row, col;
601 const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
602 const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
603
604 if (!is_chroma_reference(mi_row, mi_col, bsize, pd->subsampling_x,
605 pd->subsampling_y))
606 return;
607
608 int blk_row, blk_col;
609 int block = 0;
610 const int step = stepr * stepc;
611 const BLOCK_SIZE max_unit_bsize = get_plane_block_size(BLOCK_64X64, pd);
612 int mu_blocks_wide = block_size_wide[max_unit_bsize] >> tx_size_wide_log2[0];
613 int mu_blocks_high = block_size_high[max_unit_bsize] >> tx_size_high_log2[0];
614 mu_blocks_wide = AOMMIN(max_blocks_wide, mu_blocks_wide);
615 mu_blocks_high = AOMMIN(max_blocks_high, mu_blocks_high);
616
617 for (row = 0; row < max_blocks_high; row += mu_blocks_high) {
618 const int unit_height = AOMMIN(mu_blocks_high + row, max_blocks_high);
619 for (col = 0; col < max_blocks_wide; col += mu_blocks_wide) {
620 const int unit_width = AOMMIN(mu_blocks_wide + col, max_blocks_wide);
621
622 for (blk_row = row; blk_row < unit_height; blk_row += stepr) {
623 for (blk_col = col; blk_col < unit_width; blk_col += stepc) {
624 av1_write_coeffs_txb_wrap(cm, x, w, plane, block, blk_row, blk_col,
625 tx_size);
626 block += step;
627 }
628 }
629 }
630 }
Angie Chiangc8af6112017-03-16 16:11:22 -0700631}
632
Angie Chiang488f9212017-05-30 12:46:26 -0700633static INLINE int get_br_cost(tran_low_t abs_qc, int ctx,
Angie Chiang26d3e452017-09-29 17:40:02 -0700634 const int *coeff_lps) {
Angie Chiang488f9212017-05-30 12:46:26 -0700635 const tran_low_t min_level = 1 + NUM_BASE_LEVELS;
636 const tran_low_t max_level = 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE;
Jingning Handfd72322017-08-09 14:04:12 -0700637 (void)ctx;
Angie Chiang488f9212017-05-30 12:46:26 -0700638 if (abs_qc >= min_level) {
Angie Chiang488f9212017-05-30 12:46:26 -0700639 if (abs_qc >= max_level)
Jingning Han772dee32017-09-15 08:53:18 -0700640 return coeff_lps[COEFF_BASE_RANGE]; // COEFF_BASE_RANGE * cost0;
Angie Chiang488f9212017-05-30 12:46:26 -0700641 else
Jingning Han772dee32017-09-15 08:53:18 -0700642 return coeff_lps[(abs_qc - min_level)]; // * cost0 + cost1;
Angie Chiang488f9212017-05-30 12:46:26 -0700643 } else {
644 return 0;
645 }
646}
647
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800648// Note: don't call this function when eob is 0.
649int av1_cost_coeffs_txb(const AV1_COMMON *const cm, const MACROBLOCK *x,
650 const int plane, const int blk_row, const int blk_col,
651 const int block, const TX_SIZE tx_size,
652 const TXB_CTX *const txb_ctx) {
653 const MACROBLOCKD *const xd = &x->e_mbd;
654 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Angie Chiang47c72182017-02-27 14:30:38 -0800655 const PLANE_TYPE plane_type = get_plane_type(plane);
Jingning Han19b5c8f2017-07-06 15:10:12 -0700656 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500657 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800658 const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Angie Chiang47c72182017-02-27 14:30:38 -0800659 const struct macroblock_plane *p = &x->plane[plane];
660 const int eob = p->eobs[block];
661 const tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
662 int c, cost;
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800663 const int txb_skip_ctx = txb_ctx->txb_skip_ctx;
Angie Chianga9ba58e2017-12-01 19:22:43 -0800664 const int bwl = get_txb_bwl(tx_size);
665 const int width = get_txb_wide(tx_size);
666 const int height = get_txb_high(tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -0700667 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800668 const int16_t *const scan = scan_order->scan;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700669 uint8_t levels_buf[TX_PAD_2D];
670 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -0800671 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800672 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800673 const LV_MAP_COEFF_COST *const coeff_costs =
674 &x->coeff_costs[txs_ctx][plane_type];
Angie Chiang47c72182017-02-27 14:30:38 -0800675
Dake He0db7d0e2017-12-21 15:23:20 -0800676 const int eob_multi_size = txsize_log2_minus4[tx_size];
677 const LV_MAP_EOB_COST *const eob_costs =
678 &x->eob_costs[eob_multi_size][plane_type];
Dake He56416352017-12-26 15:43:34 -0800679 // eob must be greater than 0 here.
680 assert(eob > 0);
Jingning Handfd72322017-08-09 14:04:12 -0700681 cost = coeff_costs->txb_skip_cost[txb_skip_ctx][0];
Angie Chiang47c72182017-02-27 14:30:38 -0800682
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700683 av1_txb_init_levels(qcoeff, width, height, levels);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700684
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700685#if CONFIG_TXK_SEL
Yue Chenb23d00a2017-07-28 17:01:21 -0700686 cost += av1_tx_type_cost(cm, x, xd, mbmi->sb_type, plane, tx_size, tx_type);
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700687#endif
Angie Chiang05917872017-04-15 12:28:56 -0700688
Urvang Joshi80893152017-10-27 11:51:14 -0700689 const int seg_eob = av1_get_max_eob(tx_size);
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100690 int eob_cost = get_eob_cost(eob, seg_eob, eob_costs, coeff_costs, tx_type);
Dake Hea47cd6c2017-10-13 18:09:58 -0700691 cost += eob_cost;
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800692
693 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_type, coeff_contexts);
694
Dake Hea47cd6c2017-10-13 18:09:58 -0700695 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800696 const int pos = scan[c];
697 const tran_low_t v = qcoeff[pos];
698 const int is_nz = (v != 0);
699 const int level = abs(v);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800700 const int coeff_ctx = coeff_contexts[pos];
Dake He3fe369c2017-11-16 17:56:44 -0800701 if (c == eob - 1) {
Dake He4d447692017-12-15 09:10:06 -0800702 cost += coeff_costs->base_eob_cost[coeff_ctx][AOMMIN(level, 3) - 1];
Dake He3fe369c2017-11-16 17:56:44 -0800703 } else {
704 cost += coeff_costs->base_cost[coeff_ctx][AOMMIN(level, 3)];
705 }
Dake Hea47cd6c2017-10-13 18:09:58 -0700706
707 if (is_nz) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700708 int sign = (v < 0) ? 1 : 0;
709
710 // sign bit cost
711 if (c == 0) {
712 int dc_sign_ctx = txb_ctx->dc_sign_ctx;
713 cost += coeff_costs->dc_sign_cost[dc_sign_ctx][sign];
714 } else {
715 cost += av1_cost_bit(128, sign);
716 }
Dake Hea47cd6c2017-10-13 18:09:58 -0700717 if (level > NUM_BASE_LEVELS) {
718 int ctx;
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100719#if USE_CAUSAL_BR_CTX
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800720 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos], tx_type);
Dake He7d01ab52017-11-24 17:53:28 -0800721#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800722 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -0800723#endif
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800724 const int base_range = level - 1 - NUM_BASE_LEVELS;
Dake Hea47cd6c2017-10-13 18:09:58 -0700725 if (base_range < COEFF_BASE_RANGE) {
726 cost += coeff_costs->lps_cost[ctx][base_range];
727 } else {
728 cost += coeff_costs->lps_cost[ctx][COEFF_BASE_RANGE];
729 }
730
Dake Hea47cd6c2017-10-13 18:09:58 -0700731 if (level >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
732 // residual cost
733 int r = level - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
734 int ri = r;
735 int length = 0;
736
737 while (ri) {
738 ri >>= 1;
739 ++length;
740 }
741
742 for (ri = 0; ri < length - 1; ++ri) cost += av1_cost_bit(128, 0);
743
744 for (ri = length - 1; ri >= 0; --ri)
745 cost += av1_cost_bit(128, (r >> ri) & 0x01);
746 }
747 }
748 }
749 }
Angie Chiang47c72182017-02-27 14:30:38 -0800750 return cost;
751}
Angie Chiang0397eda2017-03-15 16:57:14 -0700752
Angie Chiang2affb3b2017-05-30 15:23:51 -0700753static INLINE int has_base(tran_low_t qc, int base_idx) {
754 const int level = base_idx + 1;
755 return abs(qc) >= level;
756}
757
Angie Chiang2affb3b2017-05-30 15:23:51 -0700758static INLINE int has_br(tran_low_t qc) {
759 return abs(qc) >= 1 + NUM_BASE_LEVELS;
760}
761
Angie Chiang488f9212017-05-30 12:46:26 -0700762static INLINE int get_sign_bit_cost(tran_low_t qc, int coeff_idx,
Jingning Handfd72322017-08-09 14:04:12 -0700763 const int (*dc_sign_cost)[2],
Angie Chiang488f9212017-05-30 12:46:26 -0700764 int dc_sign_ctx) {
765 const int sign = (qc < 0) ? 1 : 0;
766 // sign bit cost
767 if (coeff_idx == 0) {
Jingning Handfd72322017-08-09 14:04:12 -0700768 return dc_sign_cost[dc_sign_ctx][sign];
Angie Chiang488f9212017-05-30 12:46:26 -0700769 } else {
770 return av1_cost_bit(128, sign);
771 }
772}
773static INLINE int get_golomb_cost(int abs_qc) {
774 if (abs_qc >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
775 // residual cost
776 int r = abs_qc - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
777 int ri = r;
778 int length = 0;
779
780 while (ri) {
781 ri >>= 1;
782 ++length;
783 }
784
785 return av1_cost_literal(2 * length - 1);
786 } else {
787 return 0;
788 }
789}
790
Angie Chiang2affb3b2017-05-30 15:23:51 -0700791void gen_txb_cache(TxbCache *txb_cache, TxbInfo *txb_info) {
Angie Chiang481c01f2017-08-15 16:24:30 -0700792 // gen_nz_count_arr
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800793 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang481c01f2017-08-15 16:24:30 -0700794 const int bwl = txb_info->bwl;
795 const int height = txb_info->height;
Linfeng Zhang72e0b3f2017-10-18 13:32:12 -0700796 const tran_low_t *const qcoeff = txb_info->qcoeff;
Linfeng Zhangb6957c22017-10-25 13:17:28 -0700797 const uint8_t *const levels = txb_info->levels;
Angie Chiangdef11252017-08-18 14:37:32 -0700798 const BASE_CTX_TABLE *base_ctx_table =
799 txb_info->coeff_ctx_table->base_ctx_table;
Angie Chiang481c01f2017-08-15 16:24:30 -0700800 for (int c = 0; c < txb_info->eob; ++c) {
801 const int coeff_idx = scan[c]; // raster order
802 const int row = coeff_idx >> bwl;
803 const int col = coeff_idx - (row << bwl);
Jingning Han3422ac12017-10-25 20:37:53 -0700804
Linfeng Zhangf91f3ca2017-12-05 11:22:41 -0800805 txb_cache->nz_count_arr[coeff_idx] =
Linfeng Zhangd5647372017-12-05 17:06:07 -0800806 get_nz_count(levels + get_padded_idx(coeff_idx, bwl), bwl,
Linfeng Zhangf91f3ca2017-12-05 11:22:41 -0800807 tx_type_to_class[txb_info->tx_type]);
Dake Hea47cd6c2017-10-13 18:09:58 -0700808
Yaowu Xu102ef812017-12-12 11:31:03 -0800809 txb_cache->nz_ctx_arr[coeff_idx] =
810 get_nz_map_ctx_from_stats(0, coeff_idx, bwl, txb_info->tx_size,
811 tx_type_to_class[txb_info->tx_type]);
Angie Chiang481c01f2017-08-15 16:24:30 -0700812
813 // gen_base_count_mag_arr
814 if (!has_base(qcoeff[coeff_idx], 0)) continue;
815 int *base_mag = txb_cache->base_mag_arr[coeff_idx];
Angie Chiang9cde59f2017-08-16 15:24:55 -0700816 int count[NUM_BASE_LEVELS];
817 get_base_count_mag(base_mag, count, qcoeff, bwl, height, row, col);
Angie Chiang481c01f2017-08-15 16:24:30 -0700818
819 for (int i = 0; i < NUM_BASE_LEVELS; ++i) {
Angie Chiang9cde59f2017-08-16 15:24:55 -0700820 if (!has_base(qcoeff[coeff_idx], i)) break;
821 txb_cache->base_count_arr[i][coeff_idx] = count[i];
Angie Chiang481c01f2017-08-15 16:24:30 -0700822 const int level = i + 1;
Angie Chiang9cde59f2017-08-16 15:24:55 -0700823 txb_cache->base_ctx_arr[i][coeff_idx] =
Angie Chiangdef11252017-08-18 14:37:32 -0700824 base_ctx_table[row != 0][col != 0][base_mag[0] > level][count[i]];
Angie Chiang481c01f2017-08-15 16:24:30 -0700825 }
826
827 // gen_br_count_mag_arr
828 if (!has_br(qcoeff[coeff_idx])) continue;
829 int *br_count = txb_cache->br_count_arr + coeff_idx;
830 int *br_mag = txb_cache->br_mag_arr[coeff_idx];
Angie Chiangea8183b2017-08-17 14:36:35 -0700831 *br_count = get_br_count_mag(br_mag, qcoeff, bwl, height, row, col,
832 NUM_BASE_LEVELS);
Angie Chiang481c01f2017-08-15 16:24:30 -0700833 txb_cache->br_ctx_arr[coeff_idx] =
834 get_br_ctx_from_count_mag(row, col, *br_count, br_mag[0]);
835 }
Angie Chiang2affb3b2017-05-30 15:23:51 -0700836}
837
Jingning Handfd72322017-08-09 14:04:12 -0700838static INLINE const int *get_level_prob(int level, int coeff_idx,
839 const TxbCache *txb_cache,
840 const LV_MAP_COEFF_COST *txb_costs) {
Ola Hugosson13892102017-11-06 08:01:44 +0100841 if (level < 1 + NUM_BASE_LEVELS) {
842 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
843 return &txb_costs->base_cost[ctx][level];
Angie Chiang7afbba42017-05-30 15:59:15 -0700844 } else if (level >= 1 + NUM_BASE_LEVELS &&
845 level < 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700846 const int ctx = txb_cache->br_ctx_arr[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700847 return txb_costs->lps_cost[ctx];
Angie Chiang7afbba42017-05-30 15:59:15 -0700848 } else if (level >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Ola Hugosson13892102017-11-06 08:01:44 +0100849 // printf("get_level_prob does not support golomb\n");
Angie Chiang7afbba42017-05-30 15:59:15 -0700850 assert(0);
851 return 0;
852 } else {
853 assert(0);
854 return 0;
855 }
856}
857
Angie Chiangd19969e2017-05-30 18:02:33 -0700858static INLINE void update_mag_arr(int *mag_arr, int abs_qc) {
859 if (mag_arr[0] == abs_qc) {
860 mag_arr[1] -= 1;
861 assert(mag_arr[1] >= 0);
862 }
863}
864
Angie Chianga530ef42017-05-30 16:32:36 -0700865static INLINE int get_mag_from_mag_arr(const int *mag_arr) {
866 int mag;
867 if (mag_arr[1] > 0) {
868 mag = mag_arr[0];
869 } else if (mag_arr[0] > 0) {
870 mag = mag_arr[0] - 1;
871 } else {
872 // no neighbor
873 assert(mag_arr[0] == 0 && mag_arr[1] == 0);
874 mag = 0;
875 }
876 return mag;
877}
878
879static int neighbor_level_down_update(int *new_count, int *new_mag, int count,
880 const int *mag, int coeff_idx,
881 tran_low_t abs_nb_coeff, int nb_coeff_idx,
882 int level, const TxbInfo *txb_info) {
883 *new_count = count;
884 *new_mag = get_mag_from_mag_arr(mag);
885
886 int update = 0;
887 // check if br_count changes
888 if (abs_nb_coeff == level) {
889 update = 1;
890 *new_count -= 1;
891 assert(*new_count >= 0);
892 }
893 const int row = coeff_idx >> txb_info->bwl;
894 const int col = coeff_idx - (row << txb_info->bwl);
895 const int nb_row = nb_coeff_idx >> txb_info->bwl;
896 const int nb_col = nb_coeff_idx - (nb_row << txb_info->bwl);
897
898 // check if mag changes
899 if (nb_row >= row && nb_col >= col) {
900 if (abs_nb_coeff == mag[0]) {
901 assert(mag[1] > 0);
902 if (mag[1] == 1) {
903 // the nb is the only qc with max mag
904 *new_mag -= 1;
905 assert(*new_mag >= 0);
906 update = 1;
907 }
908 }
909 }
910 return update;
911}
912
913static int try_neighbor_level_down_br(int coeff_idx, int nb_coeff_idx,
914 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700915 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -0700916 const TxbInfo *txb_info) {
917 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
918 const tran_low_t abs_qc = abs(qc);
919 const int level = NUM_BASE_LEVELS + 1;
920 if (abs_qc < level) return 0;
921
922 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
923 const tran_low_t abs_nb_coeff = abs(nb_coeff);
924 const int count = txb_cache->br_count_arr[coeff_idx];
925 const int *mag = txb_cache->br_mag_arr[coeff_idx];
926 int new_count;
927 int new_mag;
928 const int update =
929 neighbor_level_down_update(&new_count, &new_mag, count, mag, coeff_idx,
930 abs_nb_coeff, nb_coeff_idx, level, txb_info);
931 if (update) {
932 const int row = coeff_idx >> txb_info->bwl;
933 const int col = coeff_idx - (row << txb_info->bwl);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700934 const int ctx = txb_cache->br_ctx_arr[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700935 const int org_cost = get_br_cost(abs_qc, ctx, txb_costs->lps_cost[ctx]);
Angie Chianga530ef42017-05-30 16:32:36 -0700936
937 const int new_ctx = get_br_ctx_from_count_mag(row, col, new_count, new_mag);
Jingning Handfd72322017-08-09 14:04:12 -0700938 const int new_cost =
939 get_br_cost(abs_qc, new_ctx, txb_costs->lps_cost[new_ctx]);
Angie Chianga530ef42017-05-30 16:32:36 -0700940 const int cost_diff = -org_cost + new_cost;
941 return cost_diff;
942 } else {
943 return 0;
944 }
945}
946
947static int try_neighbor_level_down_base(int coeff_idx, int nb_coeff_idx,
948 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700949 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -0700950 const TxbInfo *txb_info) {
Ola Hugosson13892102017-11-06 08:01:44 +0100951 // TODO(olah): not implemented yet
952 (void)coeff_idx;
953 (void)nb_coeff_idx;
954 (void)txb_cache;
955 (void)txb_costs;
956 (void)txb_info;
957 return 0;
Angie Chianga530ef42017-05-30 16:32:36 -0700958}
959
960static int try_neighbor_level_down_nz(int coeff_idx, int nb_coeff_idx,
961 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700962 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -0700963 TxbInfo *txb_info) {
964 // assume eob doesn't change
965 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
966 const tran_low_t abs_qc = abs(qc);
967 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
968 const tran_low_t abs_nb_coeff = abs(nb_coeff);
969 if (abs_nb_coeff != 1) return 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800970 const int16_t *const iscan = txb_info->scan_order->iscan;
Angie Chianga530ef42017-05-30 16:32:36 -0700971 const int scan_idx = iscan[coeff_idx];
972 if (scan_idx == txb_info->seg_eob) return 0;
973 const int nb_scan_idx = iscan[nb_coeff_idx];
974 if (nb_scan_idx < scan_idx) {
975 const int count = txb_cache->nz_count_arr[coeff_idx];
Linfeng Zhang8ac45572017-11-29 11:39:51 -0800976 (void)count;
Angie Chianga530ef42017-05-30 16:32:36 -0700977 assert(count > 0);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700978 update_qcoeff(nb_coeff_idx, get_lower_coeff(nb_coeff), txb_info);
Linfeng Zhang8ac45572017-11-29 11:39:51 -0800979 const int new_ctx = get_nz_map_ctx_from_stats(
Yaowu Xu102ef812017-12-12 11:31:03 -0800980 0, coeff_idx, txb_info->bwl, txb_info->tx_size,
981 tx_type_to_class[txb_info->tx_type]);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700982 update_qcoeff(nb_coeff_idx, nb_coeff, txb_info);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700983 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
Ola Hugosson13892102017-11-06 08:01:44 +0100984 const int org_cost = txb_costs->base_cost[ctx][AOMMIN(abs_qc, 3)];
985 const int new_cost = txb_costs->base_cost[new_ctx][AOMMIN(abs_qc, 3)];
Angie Chianga530ef42017-05-30 16:32:36 -0700986 const int cost_diff = new_cost - org_cost;
987 return cost_diff;
988 } else {
989 return 0;
990 }
991}
992
993static int try_self_level_down(tran_low_t *low_coeff, int coeff_idx,
994 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700995 const LV_MAP_COEFF_COST *txb_costs,
996 TxbInfo *txb_info) {
Angie Chiang7afbba42017-05-30 15:59:15 -0700997 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
998 if (qc == 0) {
999 *low_coeff = 0;
1000 return 0;
1001 }
1002 const tran_low_t abs_qc = abs(qc);
1003 *low_coeff = get_lower_coeff(qc);
1004 int cost_diff;
1005 if (*low_coeff == 0) {
1006 const int scan_idx = txb_info->scan_order->iscan[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -07001007 const int *level_cost =
1008 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1009 const int *low_level_cost =
1010 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
Jingning Han3422ac12017-10-25 20:37:53 -07001011
Dake Hea47cd6c2017-10-13 18:09:58 -07001012 if (scan_idx < txb_info->eob - 1) {
Angie Chiang7afbba42017-05-30 15:59:15 -07001013 // When level-0, we code the binary of abs_qc > level
1014 // but when level-k k > 0 we code the binary of abs_qc == level
1015 // That's why wee need this special treatment for level-0 map
1016 // TODO(angiebird): make leve-0 consistent to other levels
Jingning Handfd72322017-08-09 14:04:12 -07001017 cost_diff = -level_cost[1] + low_level_cost[0] - low_level_cost[1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001018 } else {
Jingning Handfd72322017-08-09 14:04:12 -07001019 cost_diff = -level_cost[1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001020 }
1021
Angie Chiang7afbba42017-05-30 15:59:15 -07001022 const int sign_cost = get_sign_bit_cost(
Jingning Handfd72322017-08-09 14:04:12 -07001023 qc, coeff_idx, txb_costs->dc_sign_cost, txb_info->txb_ctx->dc_sign_ctx);
Angie Chiang7afbba42017-05-30 15:59:15 -07001024 cost_diff -= sign_cost;
Jingning Han772dee32017-09-15 08:53:18 -07001025 } else if (abs_qc <= NUM_BASE_LEVELS) {
1026 const int *level_cost =
1027 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1028 const int *low_level_cost =
1029 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1030 cost_diff = -level_cost[1] + low_level_cost[1] - low_level_cost[0];
1031 } else if (abs_qc == NUM_BASE_LEVELS + 1) {
1032 const int *level_cost =
1033 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1034 const int *low_level_cost =
1035 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1036 cost_diff = -level_cost[0] + low_level_cost[1] - low_level_cost[0];
Angie Chiang7afbba42017-05-30 15:59:15 -07001037 } else if (abs_qc < 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Jingning Handfd72322017-08-09 14:04:12 -07001038 const int *level_cost =
1039 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1040 const int *low_level_cost =
1041 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1042
Jingning Han772dee32017-09-15 08:53:18 -07001043 cost_diff = -level_cost[abs_qc - 1 - NUM_BASE_LEVELS] +
1044 low_level_cost[abs(*low_coeff) - 1 - NUM_BASE_LEVELS];
Angie Chiang7afbba42017-05-30 15:59:15 -07001045 } else if (abs_qc == 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Jingning Handfd72322017-08-09 14:04:12 -07001046 const int *low_level_cost =
1047 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
Jingning Han772dee32017-09-15 08:53:18 -07001048 cost_diff = -get_golomb_cost(abs_qc) - low_level_cost[COEFF_BASE_RANGE] +
1049 low_level_cost[COEFF_BASE_RANGE - 1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001050 } else {
1051 assert(abs_qc > 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE);
1052 const tran_low_t abs_low_coeff = abs(*low_coeff);
1053 cost_diff = -get_golomb_cost(abs_qc) + get_golomb_cost(abs_low_coeff);
1054 }
1055 return cost_diff;
1056}
1057
Angie Chianga530ef42017-05-30 16:32:36 -07001058#define COST_MAP_SIZE 5
1059#define COST_MAP_OFFSET 2
1060
1061static INLINE int check_nz_neighbor(tran_low_t qc) { return abs(qc) == 1; }
1062
1063static INLINE int check_base_neighbor(tran_low_t qc) {
1064 return abs(qc) <= 1 + NUM_BASE_LEVELS;
1065}
1066
1067static INLINE int check_br_neighbor(tran_low_t qc) {
1068 return abs(qc) > BR_MAG_OFFSET;
1069}
1070
Angie Chiang87278292017-10-18 09:59:47 -07001071#define FAST_OPTIMIZE_TXB 1
Angie Chiange80957f2017-09-05 10:48:00 -07001072
1073#if FAST_OPTIMIZE_TXB
1074#define ALNB_REF_OFFSET_NUM 2
Linfeng Zhang4afda452017-10-24 10:34:04 -07001075static const int alnb_ref_offset[ALNB_REF_OFFSET_NUM][2] = {
Angie Chiange80957f2017-09-05 10:48:00 -07001076 { -1, 0 }, { 0, -1 },
1077};
1078#define NB_REF_OFFSET_NUM 4
Linfeng Zhang4afda452017-10-24 10:34:04 -07001079static const int nb_ref_offset[NB_REF_OFFSET_NUM][2] = {
Angie Chiange80957f2017-09-05 10:48:00 -07001080 { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 },
1081};
1082#endif // FAST_OPTIMIZE_TXB
1083
Angie Chianga530ef42017-05-30 16:32:36 -07001084// TODO(angiebird): add static to this function once it's called
1085int try_level_down(int coeff_idx, const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001086 const LV_MAP_COEFF_COST *txb_costs, TxbInfo *txb_info,
Angie Chiang25645b72017-09-24 14:28:49 -07001087 int (*cost_map)[COST_MAP_SIZE], int fast_mode) {
1088#if !FAST_OPTIMIZE_TXB
1089 (void)fast_mode;
1090#endif
Angie Chianga530ef42017-05-30 16:32:36 -07001091 if (cost_map) {
1092 for (int i = 0; i < COST_MAP_SIZE; ++i) av1_zero(cost_map[i]);
1093 }
1094
1095 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1096 tran_low_t low_coeff;
1097 if (qc == 0) return 0;
1098 int accu_cost_diff = 0;
1099
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001100 const int16_t *const iscan = txb_info->scan_order->iscan;
Angie Chianga530ef42017-05-30 16:32:36 -07001101 const int eob = txb_info->eob;
1102 const int scan_idx = iscan[coeff_idx];
1103 if (scan_idx < eob) {
1104 const int cost_diff = try_self_level_down(&low_coeff, coeff_idx, txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001105 txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001106 if (cost_map)
1107 cost_map[0 + COST_MAP_OFFSET][0 + COST_MAP_OFFSET] = cost_diff;
1108 accu_cost_diff += cost_diff;
1109 }
1110
1111 const int row = coeff_idx >> txb_info->bwl;
1112 const int col = coeff_idx - (row << txb_info->bwl);
1113 if (check_nz_neighbor(qc)) {
Angie Chiange80957f2017-09-05 10:48:00 -07001114#if FAST_OPTIMIZE_TXB
Linfeng Zhang4afda452017-10-24 10:34:04 -07001115 const int(*ref_offset)[2];
Angie Chiang25645b72017-09-24 14:28:49 -07001116 int ref_num;
1117 if (fast_mode) {
1118 ref_offset = alnb_ref_offset;
1119 ref_num = ALNB_REF_OFFSET_NUM;
1120 } else {
1121 ref_offset = sig_ref_offset;
1122 ref_num = SIG_REF_OFFSET_NUM;
1123 }
Angie Chiange80957f2017-09-05 10:48:00 -07001124#else
Linfeng Zhang4afda452017-10-24 10:34:04 -07001125 const int(*ref_offset)[2] = sig_ref_offset;
Angie Chiange80957f2017-09-05 10:48:00 -07001126 const int ref_num = SIG_REF_OFFSET_NUM;
1127#endif
1128 for (int i = 0; i < ref_num; ++i) {
1129 const int nb_row = row - ref_offset[i][0];
1130 const int nb_col = col - ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001131 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han4cbb3632017-06-13 12:50:33 -07001132
Angie Chiang0c89dca2017-08-17 16:36:18 -07001133 if (nb_row < 0 || nb_col < 0 || nb_row >= txb_info->height ||
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001134 nb_col >= txb_info->width)
Jingning Han3455e762017-06-13 21:15:44 -07001135 continue;
1136
Angie Chianga530ef42017-05-30 16:32:36 -07001137 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001138 if (nb_scan_idx < eob) {
Angie Chianga530ef42017-05-30 16:32:36 -07001139 const int cost_diff = try_neighbor_level_down_nz(
Jingning Handfd72322017-08-09 14:04:12 -07001140 nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001141 if (cost_map)
1142 cost_map[nb_row - row + COST_MAP_OFFSET]
1143 [nb_col - col + COST_MAP_OFFSET] += cost_diff;
1144 accu_cost_diff += cost_diff;
1145 }
1146 }
1147 }
1148
1149 if (check_base_neighbor(qc)) {
Angie Chiange80957f2017-09-05 10:48:00 -07001150#if FAST_OPTIMIZE_TXB
Linfeng Zhang4afda452017-10-24 10:34:04 -07001151 const int(*ref_offset)[2];
Angie Chiang25645b72017-09-24 14:28:49 -07001152 int ref_num;
1153 if (fast_mode) {
1154 ref_offset = nb_ref_offset;
1155 ref_num = NB_REF_OFFSET_NUM;
1156 } else {
1157 ref_offset = base_ref_offset;
1158 ref_num = BASE_CONTEXT_POSITION_NUM;
1159 }
Angie Chiange80957f2017-09-05 10:48:00 -07001160#else
Linfeng Zhangce065ca2017-10-17 16:49:30 -07001161 const int(*ref_offset)[2] = base_ref_offset;
Angie Chiang25645b72017-09-24 14:28:49 -07001162 int ref_num = BASE_CONTEXT_POSITION_NUM;
Angie Chiange80957f2017-09-05 10:48:00 -07001163#endif
1164 for (int i = 0; i < ref_num; ++i) {
1165 const int nb_row = row - ref_offset[i][0];
1166 const int nb_col = col - ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001167 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001168
Angie Chiang0c89dca2017-08-17 16:36:18 -07001169 if (nb_row < 0 || nb_col < 0 || nb_row >= txb_info->height ||
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001170 nb_col >= txb_info->width)
Jingning Han3455e762017-06-13 21:15:44 -07001171 continue;
1172
Angie Chianga530ef42017-05-30 16:32:36 -07001173 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001174 if (nb_scan_idx < eob) {
Angie Chianga530ef42017-05-30 16:32:36 -07001175 const int cost_diff = try_neighbor_level_down_base(
Jingning Handfd72322017-08-09 14:04:12 -07001176 nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001177 if (cost_map)
1178 cost_map[nb_row - row + COST_MAP_OFFSET]
1179 [nb_col - col + COST_MAP_OFFSET] += cost_diff;
1180 accu_cost_diff += cost_diff;
1181 }
1182 }
1183 }
1184
1185 if (check_br_neighbor(qc)) {
Angie Chiange80957f2017-09-05 10:48:00 -07001186#if FAST_OPTIMIZE_TXB
Linfeng Zhang4afda452017-10-24 10:34:04 -07001187 const int(*ref_offset)[2];
Angie Chiang25645b72017-09-24 14:28:49 -07001188 int ref_num;
1189 if (fast_mode) {
1190 ref_offset = nb_ref_offset;
1191 ref_num = NB_REF_OFFSET_NUM;
1192 } else {
1193 ref_offset = br_ref_offset;
1194 ref_num = BR_CONTEXT_POSITION_NUM;
1195 }
Angie Chiange80957f2017-09-05 10:48:00 -07001196#else
Linfeng Zhangce065ca2017-10-17 16:49:30 -07001197 const int(*ref_offset)[2] = br_ref_offset;
Angie Chiange80957f2017-09-05 10:48:00 -07001198 const int ref_num = BR_CONTEXT_POSITION_NUM;
1199#endif
1200 for (int i = 0; i < ref_num; ++i) {
1201 const int nb_row = row - ref_offset[i][0];
1202 const int nb_col = col - ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001203 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001204
Angie Chiang0c89dca2017-08-17 16:36:18 -07001205 if (nb_row < 0 || nb_col < 0 || nb_row >= txb_info->height ||
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001206 nb_col >= txb_info->width)
Jingning Han3455e762017-06-13 21:15:44 -07001207 continue;
1208
Angie Chianga530ef42017-05-30 16:32:36 -07001209 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001210 if (nb_scan_idx < eob) {
Angie Chianga530ef42017-05-30 16:32:36 -07001211 const int cost_diff = try_neighbor_level_down_br(
Jingning Handfd72322017-08-09 14:04:12 -07001212 nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001213 if (cost_map)
1214 cost_map[nb_row - row + COST_MAP_OFFSET]
1215 [nb_col - col + COST_MAP_OFFSET] += cost_diff;
1216 accu_cost_diff += cost_diff;
1217 }
1218 }
1219 }
1220
1221 return accu_cost_diff;
1222}
1223
Angie Chiangc77799b2017-05-30 17:08:17 -07001224static INLINE void set_eob(TxbInfo *txb_info, int eob) {
1225 txb_info->eob = eob;
Urvang Joshi80893152017-10-27 11:51:14 -07001226 txb_info->seg_eob = av1_get_max_eob(txb_info->tx_size);
Angie Chiangc77799b2017-05-30 17:08:17 -07001227}
1228
Angie Chiangd19969e2017-05-30 18:02:33 -07001229// TODO(angiebird): add static to this function it's called
Linfeng Zhang1015a342017-10-24 16:20:41 -07001230void update_level_down(const int coeff_idx, TxbCache *const txb_cache,
1231 TxbInfo *const txb_info) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001232 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1233 const int abs_qc = abs(qc);
1234 if (qc == 0) return;
1235 const tran_low_t low_coeff = get_lower_coeff(qc);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001236 update_coeff(coeff_idx, low_coeff, txb_info);
Angie Chiangd19969e2017-05-30 18:02:33 -07001237
1238 const int row = coeff_idx >> txb_info->bwl;
1239 const int col = coeff_idx - (row << txb_info->bwl);
1240 const int eob = txb_info->eob;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001241 const int16_t *const iscan = txb_info->scan_order->iscan;
Angie Chiangd19969e2017-05-30 18:02:33 -07001242 for (int i = 0; i < SIG_REF_OFFSET_NUM; ++i) {
1243 const int nb_row = row - sig_ref_offset[i][0];
1244 const int nb_col = col - sig_ref_offset[i][1];
Jingning Han3455e762017-06-13 21:15:44 -07001245
1246 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001247 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001248 continue;
1249
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001250 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiangd19969e2017-05-30 18:02:33 -07001251 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001252 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001253 const int scan_idx = iscan[coeff_idx];
1254 if (scan_idx < nb_scan_idx) {
1255 const int level = 1;
1256 if (abs_qc == level) {
1257 txb_cache->nz_count_arr[nb_coeff_idx] -= 1;
1258 assert(txb_cache->nz_count_arr[nb_coeff_idx] >= 0);
1259 }
Yaowu Xu102ef812017-12-12 11:31:03 -08001260 txb_cache->nz_ctx_arr[nb_coeff_idx] = get_nz_map_ctx_from_stats(
1261 0, nb_coeff_idx, txb_info->bwl, txb_info->tx_size,
1262 tx_type_to_class[txb_info->tx_type]);
Angie Chiangd19969e2017-05-30 18:02:33 -07001263 }
1264 }
1265 }
1266
Angie Chiangdef11252017-08-18 14:37:32 -07001267 const BASE_CTX_TABLE *base_ctx_table =
1268 txb_info->coeff_ctx_table->base_ctx_table;
Angie Chiangd19969e2017-05-30 18:02:33 -07001269 for (int i = 0; i < BASE_CONTEXT_POSITION_NUM; ++i) {
1270 const int nb_row = row - base_ref_offset[i][0];
1271 const int nb_col = col - base_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001272 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001273
1274 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001275 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001276 continue;
1277
Angie Chiangd19969e2017-05-30 18:02:33 -07001278 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
1279 if (!has_base(nb_coeff, 0)) continue;
1280 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001281 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001282 if (row >= nb_row && col >= nb_col)
1283 update_mag_arr(txb_cache->base_mag_arr[nb_coeff_idx], abs_qc);
1284 const int mag =
1285 get_mag_from_mag_arr(txb_cache->base_mag_arr[nb_coeff_idx]);
1286 for (int base_idx = 0; base_idx < NUM_BASE_LEVELS; ++base_idx) {
1287 if (!has_base(nb_coeff, base_idx)) continue;
1288 const int level = base_idx + 1;
1289 if (abs_qc == level) {
1290 txb_cache->base_count_arr[base_idx][nb_coeff_idx] -= 1;
1291 assert(txb_cache->base_count_arr[base_idx][nb_coeff_idx] >= 0);
1292 }
1293 const int count = txb_cache->base_count_arr[base_idx][nb_coeff_idx];
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001294 txb_cache->base_ctx_arr[base_idx][nb_coeff_idx] =
Angie Chiangdef11252017-08-18 14:37:32 -07001295 base_ctx_table[nb_row != 0][nb_col != 0][mag > level][count];
Angie Chiangd19969e2017-05-30 18:02:33 -07001296 }
1297 }
1298 }
1299
1300 for (int i = 0; i < BR_CONTEXT_POSITION_NUM; ++i) {
1301 const int nb_row = row - br_ref_offset[i][0];
1302 const int nb_col = col - br_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001303 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001304
1305 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001306 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001307 continue;
1308
Angie Chiangd19969e2017-05-30 18:02:33 -07001309 const int nb_scan_idx = iscan[nb_coeff_idx];
1310 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
1311 if (!has_br(nb_coeff)) continue;
Jingning Han3455e762017-06-13 21:15:44 -07001312 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001313 const int level = 1 + NUM_BASE_LEVELS;
1314 if (abs_qc == level) {
1315 txb_cache->br_count_arr[nb_coeff_idx] -= 1;
1316 assert(txb_cache->br_count_arr[nb_coeff_idx] >= 0);
1317 }
1318 if (row >= nb_row && col >= nb_col)
1319 update_mag_arr(txb_cache->br_mag_arr[nb_coeff_idx], abs_qc);
1320 const int count = txb_cache->br_count_arr[nb_coeff_idx];
1321 const int mag = get_mag_from_mag_arr(txb_cache->br_mag_arr[nb_coeff_idx]);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001322 txb_cache->br_ctx_arr[nb_coeff_idx] =
Angie Chiangd19969e2017-05-30 18:02:33 -07001323 get_br_ctx_from_count_mag(nb_row, nb_col, count, mag);
Angie Chiangd19969e2017-05-30 18:02:33 -07001324 }
1325 }
1326}
1327
Linfeng Zhang1015a342017-10-24 16:20:41 -07001328static int get_coeff_cost(const tran_low_t qc, const int scan_idx,
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001329 const int is_eob, const TxbInfo *const txb_info,
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001330 const LV_MAP_COEFF_COST *const txb_costs,
1331 const int coeff_ctx) {
Angie Chiang488f9212017-05-30 12:46:26 -07001332 const TXB_CTX *txb_ctx = txb_info->txb_ctx;
1333 const int is_nz = (qc != 0);
1334 const tran_low_t abs_qc = abs(qc);
1335 int cost = 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001336 const int16_t *const scan = txb_info->scan_order->scan;
1337 const int pos = scan[scan_idx];
Dake He03a32922017-10-31 08:06:45 -07001338
Dake He3fe369c2017-11-16 17:56:44 -08001339 if (is_eob) {
Dake He4d447692017-12-15 09:10:06 -08001340 cost += txb_costs->base_eob_cost[coeff_ctx][AOMMIN(abs_qc, 3) - 1];
Dake He3fe369c2017-11-16 17:56:44 -08001341 } else {
1342 cost += txb_costs->base_cost[coeff_ctx][AOMMIN(abs_qc, 3)];
1343 }
Angie Chiang488f9212017-05-30 12:46:26 -07001344 if (is_nz) {
Jingning Handfd72322017-08-09 14:04:12 -07001345 cost += get_sign_bit_cost(qc, scan_idx, txb_costs->dc_sign_cost,
Angie Chiang488f9212017-05-30 12:46:26 -07001346 txb_ctx->dc_sign_ctx);
1347
Angie Chiang488f9212017-05-30 12:46:26 -07001348 if (abs_qc > NUM_BASE_LEVELS) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001349 const int row = pos >> txb_info->bwl;
1350 const int col = pos - (row << txb_info->bwl);
Dake He7d01ab52017-11-24 17:53:28 -08001351
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001352#if USE_CAUSAL_BR_CTX
Dake He7d01ab52017-11-24 17:53:28 -08001353 (void)col;
1354 const int count = 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001355 const int ctx = get_br_ctx(txb_info->levels, pos, txb_info->bwl, count,
1356 txb_info->tx_type);
Dake He7d01ab52017-11-24 17:53:28 -08001357#else
Linfeng Zhang97fc4742017-11-07 12:57:25 -08001358 const int count = get_level_count(
1359 txb_info->levels, (1 << txb_info->bwl) + TX_PAD_HOR, row, col,
1360 NUM_BASE_LEVELS, br_ref_offset, BR_CONTEXT_POSITION_NUM);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001361 const int ctx = get_br_ctx(txb_info->levels, pos, txb_info->bwl, count);
Dake He7d01ab52017-11-24 17:53:28 -08001362#endif
Jingning Handfd72322017-08-09 14:04:12 -07001363 cost += get_br_cost(abs_qc, ctx, txb_costs->lps_cost[ctx]);
Angie Chiang488f9212017-05-30 12:46:26 -07001364 cost += get_golomb_cost(abs_qc);
1365 }
Angie Chiang488f9212017-05-30 12:46:26 -07001366 }
1367 return cost;
1368}
1369
Angie Chiang47e07072017-05-30 17:27:01 -07001370#if TEST_OPTIMIZE_TXB
Angie Chiang5e012fe2017-05-30 18:47:39 -07001371#define ALL_REF_OFFSET_NUM 17
Linfeng Zhang4afda452017-10-24 10:34:04 -07001372static const int all_ref_offset[ALL_REF_OFFSET_NUM][2] = {
Angie Chiang5e012fe2017-05-30 18:47:39 -07001373 { 0, 0 }, { -2, -1 }, { -2, 0 }, { -2, 1 }, { -1, -2 }, { -1, -1 },
1374 { -1, 0 }, { -1, 1 }, { 0, -2 }, { 0, -1 }, { 1, -2 }, { 1, -1 },
1375 { 1, 0 }, { 2, 0 }, { 0, 1 }, { 0, 2 }, { 1, 1 },
1376};
1377
Angie Chiang0b2795c2017-09-29 16:00:08 -07001378static int try_level_down_ref(int coeff_idx, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang5e012fe2017-05-30 18:47:39 -07001379 TxbInfo *txb_info,
1380 int (*cost_map)[COST_MAP_SIZE]) {
1381 if (cost_map) {
1382 for (int i = 0; i < COST_MAP_SIZE; ++i) av1_zero(cost_map[i]);
1383 }
1384 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1385 if (qc == 0) return 0;
1386 int row = coeff_idx >> txb_info->bwl;
1387 int col = coeff_idx - (row << txb_info->bwl);
1388 int org_cost = 0;
1389 for (int i = 0; i < ALL_REF_OFFSET_NUM; ++i) {
1390 int nb_row = row - all_ref_offset[i][0];
1391 int nb_col = col - all_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001392 int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001393 int nb_scan_idx = txb_info->scan_order->iscan[nb_coeff_idx];
1394 if (nb_scan_idx < txb_info->eob && nb_row >= 0 && nb_col >= 0 &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001395 nb_row < txb_info->height && nb_col < txb_info->width) {
Linfeng Zhang960e7002017-12-11 13:46:40 -08001396 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001397 const int coeff_ctx = get_nz_map_ctx(
1398 txb_info->levels, nb_coeff_idx, txb_info->bwl, txb_info->height,
1399 nb_scan_idx, is_eob, txb_info->tx_size, txb_info->tx_type);
1400 const int cost = get_coeff_cost(nb_coeff, nb_scan_idx, is_eob, txb_info,
1401 txb_costs, coeff_ctx);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001402 if (cost_map)
1403 cost_map[nb_row - row + COST_MAP_OFFSET]
1404 [nb_col - col + COST_MAP_OFFSET] -= cost;
1405 org_cost += cost;
1406 }
1407 }
Linfeng Zhang1015a342017-10-24 16:20:41 -07001408 update_qcoeff(coeff_idx, get_lower_coeff(qc), txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001409 int new_cost = 0;
1410 for (int i = 0; i < ALL_REF_OFFSET_NUM; ++i) {
1411 int nb_row = row - all_ref_offset[i][0];
1412 int nb_col = col - all_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001413 int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001414 int nb_scan_idx = txb_info->scan_order->iscan[nb_coeff_idx];
1415 if (nb_scan_idx < txb_info->eob && nb_row >= 0 && nb_col >= 0 &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001416 nb_row < txb_info->height && nb_col < txb_info->width) {
Linfeng Zhang960e7002017-12-11 13:46:40 -08001417 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001418 const int coeff_ctx = get_nz_map_ctx(
1419 txb_info->levels, nb_coeff_idx, txb_info->bwl, txb_info->height,
1420 nb_scan_idx, is_eob, txb_info->tx_size, txb_info->tx_type);
1421 const int cost = get_coeff_cost(nb_coeff, nb_scan_idx, is_eob, txb_info,
1422 txb_costs, coeff_ctx);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001423 if (cost_map)
1424 cost_map[nb_row - row + COST_MAP_OFFSET]
1425 [nb_col - col + COST_MAP_OFFSET] += cost;
1426 new_cost += cost;
1427 }
1428 }
Linfeng Zhang1015a342017-10-24 16:20:41 -07001429 update_qcoeff(coeff_idx, qc, txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001430 return new_cost - org_cost;
1431}
1432
1433static void test_level_down(int coeff_idx, const TxbCache *txb_cache,
Angie Chiang0b2795c2017-09-29 16:00:08 -07001434 const LV_MAP_COEFF_COST *txb_costs,
1435 TxbInfo *txb_info) {
Angie Chiang47e07072017-05-30 17:27:01 -07001436 int cost_map[COST_MAP_SIZE][COST_MAP_SIZE];
1437 int ref_cost_map[COST_MAP_SIZE][COST_MAP_SIZE];
1438 const int cost_diff =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001439 try_level_down(coeff_idx, txb_cache, txb_costs, txb_info, cost_map, 0);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001440 const int cost_diff_ref =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001441 try_level_down_ref(coeff_idx, txb_costs, txb_info, ref_cost_map);
Angie Chiang47e07072017-05-30 17:27:01 -07001442 if (cost_diff != cost_diff_ref) {
1443 printf("qc %d cost_diff %d cost_diff_ref %d\n", txb_info->qcoeff[coeff_idx],
1444 cost_diff, cost_diff_ref);
1445 for (int r = 0; r < COST_MAP_SIZE; ++r) {
1446 for (int c = 0; c < COST_MAP_SIZE; ++c) {
1447 printf("%d:%d ", cost_map[r][c], ref_cost_map[r][c]);
1448 }
1449 printf("\n");
1450 }
1451 }
1452}
1453#endif
1454
Angie Chiang488f9212017-05-30 12:46:26 -07001455// TODO(angiebird): make this static once it's called
Jingning Handfd72322017-08-09 14:04:12 -07001456int get_txb_cost(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs) {
Angie Chiang488f9212017-05-30 12:46:26 -07001457 int cost = 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001458 const int txb_skip_ctx = txb_info->txb_ctx->txb_skip_ctx;
1459 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang488f9212017-05-30 12:46:26 -07001460 if (txb_info->eob == 0) {
Jingning Handfd72322017-08-09 14:04:12 -07001461 cost = txb_costs->txb_skip_cost[txb_skip_ctx][1];
Angie Chiang488f9212017-05-30 12:46:26 -07001462 return cost;
1463 }
Jingning Handfd72322017-08-09 14:04:12 -07001464 cost = txb_costs->txb_skip_cost[txb_skip_ctx][0];
Angie Chiang488f9212017-05-30 12:46:26 -07001465 for (int c = 0; c < txb_info->eob; ++c) {
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001466 const int pos = scan[c];
1467 const tran_low_t qc = txb_info->qcoeff[pos];
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001468 const int coeff_ctx = get_nz_map_ctx(
1469 txb_info->levels, pos, txb_info->bwl, txb_info->height, c,
1470 c == txb_info->eob - 1, txb_info->tx_size, txb_info->tx_type);
1471 const int coeff_cost = get_coeff_cost(qc, c, c == txb_info->eob - 1,
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001472 txb_info, txb_costs, coeff_ctx);
Angie Chiang488f9212017-05-30 12:46:26 -07001473 cost += coeff_cost;
1474 }
1475 return cost;
1476}
1477
Angie Chiang5e012fe2017-05-30 18:47:39 -07001478#if TEST_OPTIMIZE_TXB
Angie Chiang0b2795c2017-09-29 16:00:08 -07001479void test_try_change_eob(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang5e012fe2017-05-30 18:47:39 -07001480 TxbCache *txb_cache) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001481 const int eob = txb_info->eob;
1482 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001483 if (eob > 0) {
1484 int last_si = eob - 1;
1485 int last_ci = scan[last_si];
1486 int last_coeff = txb_info->qcoeff[last_ci];
1487 if (abs(last_coeff) == 1) {
1488 int new_eob;
1489 int cost_diff =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001490 try_change_eob(&new_eob, last_ci, txb_cache, txb_costs, txb_info, 0);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001491 int org_eob = txb_info->eob;
Angie Chiang0b2795c2017-09-29 16:00:08 -07001492 int cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001493
Linfeng Zhang1015a342017-10-24 16:20:41 -07001494 update_qcoeff(last_ci, get_lower_coeff(last_coeff), txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001495 set_eob(txb_info, new_eob);
Angie Chiang0b2795c2017-09-29 16:00:08 -07001496 int new_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001497 set_eob(txb_info, org_eob);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001498 update_qcoeff(last_ci, last_coeff, txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001499
1500 int ref_cost_diff = -cost + new_cost;
1501 if (cost_diff != ref_cost_diff)
1502 printf("org_eob %d new_eob %d cost_diff %d ref_cost_diff %d\n", org_eob,
1503 new_eob, cost_diff, ref_cost_diff);
1504 }
1505 }
1506}
1507#endif
1508
Jingning Han3422ac12017-10-25 20:37:53 -07001509#if 1
Dake Hea47cd6c2017-10-13 18:09:58 -07001510static int optimize_txb(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Dake He0db7d0e2017-12-21 15:23:20 -08001511 const LV_MAP_EOB_COST *txb_eob_costs,
Dake Hea47cd6c2017-10-13 18:09:58 -07001512 TxbCache *txb_cache, int dry_run, int fast_mode) {
1513 (void)fast_mode;
1514 (void)txb_cache;
1515 int update = 0;
Dake He59881772017-11-24 07:00:02 -08001516 // return update; // TODO(DKHE): training only.
Dake Hea47cd6c2017-10-13 18:09:58 -07001517 if (txb_info->eob == 0) return update;
Urvang Joshi80893152017-10-27 11:51:14 -07001518 const int max_eob = av1_get_max_eob(txb_info->tx_size);
Dake Hea47cd6c2017-10-13 18:09:58 -07001519
1520#if TEST_OPTIMIZE_TXB
1521 int64_t sse;
1522 int64_t org_dist =
1523 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1524 (1 << (2 * txb_info->shift));
1525 int org_cost = get_txb_cost(txb_info, txb_probs);
1526#endif
1527
1528 tran_low_t *org_qcoeff = txb_info->qcoeff;
1529 tran_low_t *org_dqcoeff = txb_info->dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001530 uint8_t *const org_levels = txb_info->levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001531
1532 tran_low_t tmp_qcoeff[MAX_TX_SQUARE];
1533 tran_low_t tmp_dqcoeff[MAX_TX_SQUARE];
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001534 uint8_t tmp_levels_buf[TX_PAD_2D];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001535 uint8_t *const tmp_levels = set_levels(tmp_levels_buf, txb_info->width);
Dake Hea47cd6c2017-10-13 18:09:58 -07001536 const int org_eob = txb_info->eob;
1537 if (dry_run) {
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001538 const int stride = txb_info->width + TX_PAD_HOR;
1539 const int levels_size =
1540
1541 (stride * (txb_info->height + TX_PAD_VER) + TX_PAD_END);
Dake Hea47cd6c2017-10-13 18:09:58 -07001542 memcpy(tmp_qcoeff, org_qcoeff, sizeof(org_qcoeff[0]) * max_eob);
1543 memcpy(tmp_dqcoeff, org_dqcoeff, sizeof(org_dqcoeff[0]) * max_eob);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001544 memcpy(tmp_levels, org_levels - TX_PAD_TOP * stride,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001545 sizeof(org_levels[0]) * levels_size);
Dake Hea47cd6c2017-10-13 18:09:58 -07001546 txb_info->qcoeff = tmp_qcoeff;
1547 txb_info->dqcoeff = tmp_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001548 txb_info->levels = tmp_levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001549 }
1550
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001551 const int16_t *const scan = txb_info->scan_order->scan;
Dake Hea47cd6c2017-10-13 18:09:58 -07001552
1553 // forward optimize the nz_map`
1554 const int init_eob = txb_info->eob;
1555 const int seg_eob = txb_info->seg_eob;
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001556 const int eob_cost = get_eob_cost(init_eob, seg_eob, txb_eob_costs, txb_costs,
Dake He0db7d0e2017-12-21 15:23:20 -08001557 txb_info->tx_type);
Dake Hea47cd6c2017-10-13 18:09:58 -07001558
1559 // backward optimize the level-k map
1560 int64_t accu_rate = eob_cost;
1561 int64_t accu_dist = 0;
1562 int64_t prev_eob_rd_cost = INT64_MAX;
1563 int64_t cur_eob_rd_cost = 0;
Jingning Han8be58fa2017-12-18 09:46:13 -08001564 int8_t has_nz_tail = 0;
Dake Hea47cd6c2017-10-13 18:09:58 -07001565
1566 for (int si = init_eob - 1; si >= 0; --si) {
1567 const int coeff_idx = scan[si];
1568 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1569
1570 LevelDownStats stats;
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001571 get_dist_cost_stats(&stats, si, si == init_eob - 1, txb_costs, txb_info,
1572 has_nz_tail);
Dake Hea47cd6c2017-10-13 18:09:58 -07001573
1574 if (qc == 0) {
1575 accu_rate += stats.rate;
1576 } else {
Jingning Han8be58fa2017-12-18 09:46:13 -08001577 if (has_nz_tail < 2) {
1578 // check if it is better to make this the last significant coefficient
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001579 int cur_eob_rate = get_eob_cost(si + 1, seg_eob, txb_eob_costs,
1580 txb_costs, txb_info->tx_type);
Jingning Han8be58fa2017-12-18 09:46:13 -08001581 cur_eob_rd_cost = RDCOST(txb_info->rdmult, cur_eob_rate, 0);
1582 prev_eob_rd_cost =
Dake He4d447692017-12-15 09:10:06 -08001583 RDCOST(txb_info->rdmult, accu_rate, accu_dist) + stats.nz_rd;
Jingning Han8be58fa2017-12-18 09:46:13 -08001584 if (cur_eob_rd_cost <= prev_eob_rd_cost) {
1585 update = 1;
1586 for (int j = si + 1; j < txb_info->eob; j++) {
1587 const int coeff_pos_j = scan[j];
1588 update_coeff(coeff_pos_j, 0, txb_info);
1589 }
1590 txb_info->eob = si + 1;
Dake Hea47cd6c2017-10-13 18:09:58 -07001591
Jingning Han8be58fa2017-12-18 09:46:13 -08001592 // rerun cost calculation due to change of eob
1593 accu_rate = cur_eob_rate;
1594 accu_dist = 0;
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001595 get_dist_cost_stats(&stats, si, 1, txb_costs, txb_info, has_nz_tail);
Dake He4d447692017-12-15 09:10:06 -08001596 if ((stats.rd_low < stats.rd) && (stats.low_qc != 0)) {
1597 update = 1;
1598 update_coeff(coeff_idx, stats.low_qc, txb_info);
1599 accu_rate += stats.rate_low;
1600 accu_dist += stats.dist_low;
1601 } else {
1602 accu_rate += stats.rate;
1603 accu_dist += stats.dist;
1604 }
Jingning Han8be58fa2017-12-18 09:46:13 -08001605 continue;
1606 }
Dake Hea47cd6c2017-10-13 18:09:58 -07001607 }
1608
1609 int bUpdCoeff = 0;
1610 if (stats.rd_low < stats.rd) {
Dake He4d447692017-12-15 09:10:06 -08001611 if ((si < txb_info->eob - 1)) {
Dake Hea47cd6c2017-10-13 18:09:58 -07001612 bUpdCoeff = 1;
1613 update = 1;
1614 }
Jingning Han8be58fa2017-12-18 09:46:13 -08001615 } else {
1616 ++has_nz_tail;
Dake Hea47cd6c2017-10-13 18:09:58 -07001617 }
1618
1619 if (bUpdCoeff) {
1620 update_coeff(coeff_idx, stats.low_qc, txb_info);
1621 accu_rate += stats.rate_low;
1622 accu_dist += stats.dist_low;
1623 } else {
1624 accu_rate += stats.rate;
1625 accu_dist += stats.dist;
1626 }
1627 }
1628 } // for (si)
Jingning Hana7a6f4e2017-12-13 14:44:08 -08001629
Dake Hea47cd6c2017-10-13 18:09:58 -07001630 int non_zero_blk_rate =
1631 txb_costs->txb_skip_cost[txb_info->txb_ctx->txb_skip_ctx][0];
1632 prev_eob_rd_cost =
1633 RDCOST(txb_info->rdmult, accu_rate + non_zero_blk_rate, accu_dist);
1634
1635 int zero_blk_rate =
1636 txb_costs->txb_skip_cost[txb_info->txb_ctx->txb_skip_ctx][1];
1637 int64_t zero_blk_rd_cost = RDCOST(txb_info->rdmult, zero_blk_rate, 0);
1638 if (zero_blk_rd_cost <= prev_eob_rd_cost) {
1639 update = 1;
1640 for (int j = 0; j < txb_info->eob; j++) {
1641 const int coeff_pos_j = scan[j];
1642 update_coeff(coeff_pos_j, 0, txb_info);
1643 }
1644 txb_info->eob = 0;
1645 }
1646
1647#if TEST_OPTIMIZE_TXB
1648 int cost_diff = 0;
1649 int64_t dist_diff = 0;
1650 int64_t rd_diff = 0;
1651 int64_t new_dist =
1652 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1653 (1 << (2 * txb_info->shift));
1654 int new_cost = get_txb_cost(txb_info, txb_probs);
1655 int64_t ref_dist_diff = new_dist - org_dist;
1656 int ref_cost_diff = new_cost - org_cost;
1657 if (cost_diff != ref_cost_diff || dist_diff != ref_dist_diff)
1658 printf(
1659 "overall rd_diff %ld\ncost_diff %d ref_cost_diff%d\ndist_diff %ld "
1660 "ref_dist_diff %ld\neob %d new_eob %d\n\n",
1661 rd_diff, cost_diff, ref_cost_diff, dist_diff, ref_dist_diff, org_eob,
1662 txb_info->eob);
1663#endif
1664 if (dry_run) {
1665 txb_info->qcoeff = org_qcoeff;
1666 txb_info->dqcoeff = org_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001667 txb_info->levels = org_levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001668 set_eob(txb_info, org_eob);
1669 }
1670 return update;
1671}
1672
1673#else
Jingning Handfd72322017-08-09 14:04:12 -07001674static int optimize_txb(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang25645b72017-09-24 14:28:49 -07001675 TxbCache *txb_cache, int dry_run, int fast_mode) {
Angie Chiang07c57f32017-05-30 18:18:33 -07001676 int update = 0;
1677 if (txb_info->eob == 0) return update;
1678 int cost_diff = 0;
1679 int64_t dist_diff = 0;
1680 int64_t rd_diff = 0;
Urvang Joshi80893152017-10-27 11:51:14 -07001681 const int max_eob = av1_get_max_eob(txb_info->tx_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07001682
1683#if TEST_OPTIMIZE_TXB
1684 int64_t sse;
1685 int64_t org_dist =
1686 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1687 (1 << (2 * txb_info->shift));
Angie Chiang0b2795c2017-09-29 16:00:08 -07001688 int org_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang07c57f32017-05-30 18:18:33 -07001689#endif
1690
1691 tran_low_t *org_qcoeff = txb_info->qcoeff;
1692 tran_low_t *org_dqcoeff = txb_info->dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001693 uint8_t *const org_levels = txb_info->levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07001694
1695 tran_low_t tmp_qcoeff[MAX_TX_SQUARE];
1696 tran_low_t tmp_dqcoeff[MAX_TX_SQUARE];
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001697 uint8_t tmp_levels_buf[TX_PAD_2D];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001698 uint8_t *const tmp_levels = set_levels(tmp_levels_buf, txb_info->width);
Angie Chiang07c57f32017-05-30 18:18:33 -07001699 const int org_eob = txb_info->eob;
1700 if (dry_run) {
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001701 const int stride = txb_info->width + TX_PAD_HOR;
1702 const int levels_size =
1703
1704 (stride * (txb_info->height + TX_PAD_VER) + TX_PAD_END);
Angie Chiang07c57f32017-05-30 18:18:33 -07001705 memcpy(tmp_qcoeff, org_qcoeff, sizeof(org_qcoeff[0]) * max_eob);
1706 memcpy(tmp_dqcoeff, org_dqcoeff, sizeof(org_dqcoeff[0]) * max_eob);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001707 memcpy(tmp_levels, org_levels - TX_PAD_TOP * stride,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001708 sizeof(org_levels[0]) * levels_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07001709 txb_info->qcoeff = tmp_qcoeff;
1710 txb_info->dqcoeff = tmp_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001711 txb_info->levels = tmp_levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07001712 }
1713
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001714 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang07c57f32017-05-30 18:18:33 -07001715
1716 // forward optimize the nz_map
1717 const int cur_eob = txb_info->eob;
1718 for (int si = 0; si < cur_eob; ++si) {
1719 const int coeff_idx = scan[si];
1720 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1721 if (abs(qc) == 1) {
1722 LevelDownStats stats;
Angie Chiang25645b72017-09-24 14:28:49 -07001723 try_level_down_facade(&stats, si, txb_cache, txb_costs, txb_info,
1724 fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07001725 if (stats.update) {
1726 update = 1;
1727 cost_diff += stats.cost_diff;
1728 dist_diff += stats.dist_diff;
1729 rd_diff += stats.rd_diff;
1730 update_level_down(coeff_idx, txb_cache, txb_info);
1731 set_eob(txb_info, stats.new_eob);
1732 }
1733 }
1734 }
1735
1736 // backward optimize the level-k map
Angie Chiang530b3042017-08-17 15:08:58 -07001737 int eob_fix = 0;
Angie Chiang07c57f32017-05-30 18:18:33 -07001738 for (int si = txb_info->eob - 1; si >= 0; --si) {
Angie Chiang530b3042017-08-17 15:08:58 -07001739 const int coeff_idx = scan[si];
1740 if (eob_fix == 1 && txb_info->qcoeff[coeff_idx] == 1) {
1741 // when eob is fixed, there is not need to optimize again when
1742 // abs(qc) == 1
1743 continue;
1744 }
Angie Chiang07c57f32017-05-30 18:18:33 -07001745 LevelDownStats stats;
Angie Chiang25645b72017-09-24 14:28:49 -07001746 try_level_down_facade(&stats, si, txb_cache, txb_costs, txb_info,
1747 fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07001748 if (stats.update) {
1749#if TEST_OPTIMIZE_TXB
1750// printf("si %d low_qc %d cost_diff %d dist_diff %ld rd_diff %ld eob %d new_eob
1751// %d\n", si, stats.low_qc, stats.cost_diff, stats.dist_diff, stats.rd_diff,
1752// txb_info->eob, stats.new_eob);
1753#endif
1754 update = 1;
1755 cost_diff += stats.cost_diff;
1756 dist_diff += stats.dist_diff;
1757 rd_diff += stats.rd_diff;
1758 update_level_down(coeff_idx, txb_cache, txb_info);
1759 set_eob(txb_info, stats.new_eob);
1760 }
Angie Chiang530b3042017-08-17 15:08:58 -07001761 if (eob_fix == 0 && txb_info->qcoeff[coeff_idx] != 0) eob_fix = 1;
Angie Chiang07c57f32017-05-30 18:18:33 -07001762 if (si > txb_info->eob) si = txb_info->eob;
1763 }
1764#if TEST_OPTIMIZE_TXB
1765 int64_t new_dist =
1766 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1767 (1 << (2 * txb_info->shift));
Angie Chiang0b2795c2017-09-29 16:00:08 -07001768 int new_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang07c57f32017-05-30 18:18:33 -07001769 int64_t ref_dist_diff = new_dist - org_dist;
1770 int ref_cost_diff = new_cost - org_cost;
1771 if (cost_diff != ref_cost_diff || dist_diff != ref_dist_diff)
1772 printf(
1773 "overall rd_diff %ld\ncost_diff %d ref_cost_diff%d\ndist_diff %ld "
1774 "ref_dist_diff %ld\neob %d new_eob %d\n\n",
1775 rd_diff, cost_diff, ref_cost_diff, dist_diff, ref_dist_diff, org_eob,
1776 txb_info->eob);
1777#endif
1778 if (dry_run) {
1779 txb_info->qcoeff = org_qcoeff;
1780 txb_info->dqcoeff = org_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001781 txb_info->levels = org_levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07001782 set_eob(txb_info, org_eob);
1783 }
1784 return update;
1785}
Dake Hea47cd6c2017-10-13 18:09:58 -07001786#endif
Angie Chiang07c57f32017-05-30 18:18:33 -07001787
1788// These numbers are empirically obtained.
1789static const int plane_rd_mult[REF_TYPES][PLANE_TYPES] = {
Angie Chiang07c57f32017-05-30 18:18:33 -07001790 { 17, 13 }, { 16, 10 },
Angie Chiang07c57f32017-05-30 18:18:33 -07001791};
1792
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001793void hbt_hash_init() {
1794 av1_crc_calculator_init(&crc_calculator, 16, 0x5D6DCB); // ctx 16 bit hash
1795 av1_crc_calculator_init(&crc_calculator2, 16, 0x5D6DCB); // qc 16 bit hash
1796 memset(hbt_hash_table, 0, sizeof(hbt_hash_table[0][0]) * 65536 * 16);
1797 hbt_hash_needs_init = 0;
1798}
1799
1800int hbt_hash_miss(int found_index, uint16_t hbt_hash_index,
1801 uint32_t hbt_hash_match, TxbInfo *txb_info,
1802 const LV_MAP_COEFF_COST *txb_costs,
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001803 const LV_MAP_EOB_COST *txb_eob_costs,
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001804 const struct macroblock_plane *p, int block, int fast_mode) {
1805 const int16_t *scan = txb_info->scan_order->scan;
1806
1807 av1_txb_init_levels(txb_info->qcoeff, txb_info->width, txb_info->height,
1808 txb_info->levels);
1809 // The hash_based_trellis speed feature requires lv_map_multi, so always true.
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001810 const int update =
1811 optimize_txb(txb_info, txb_costs, txb_eob_costs, NULL, 0, fast_mode);
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001812
1813 if (update) {
1814 // Overwrite old lowest entry
1815 hbt_hash_table[hbt_hash_index][found_index].hbt_hash_match = hbt_hash_match;
1816 hbt_hash_table[hbt_hash_index][found_index].hits = 1.0;
1817 for (int i = 0; i < txb_info->eob; i++) {
1818 hbt_hash_table[hbt_hash_index][found_index].opt_qcoeff[i] =
1819 txb_info->qcoeff[scan[i]];
1820 }
1821 for (int i = txb_info->eob; i < HBT_HASH_EOB; i++) {
1822 hbt_hash_table[hbt_hash_index][found_index].opt_qcoeff[i] = 0;
1823 }
1824
1825 p->eobs[block] = txb_info->eob;
1826 p->txb_entropy_ctx[block] = av1_get_txb_entropy_context(
1827 txb_info->qcoeff, txb_info->scan_order, txb_info->eob);
1828 }
1829 return txb_info->eob;
1830}
1831
1832int hbt_hash_hit(uint16_t hbt_hash_index, int found_index, TxbInfo *txb_info,
1833 const struct macroblock_plane *p, int block) {
1834 const int16_t *scan = txb_info->scan_order->scan;
1835 int new_eob = 0;
1836 int update = 0;
1837
1838 for (int i = 0; i < txb_info->eob; i++) {
1839 if (txb_info->qcoeff[scan[i]] !=
1840 hbt_hash_table[hbt_hash_index][found_index].opt_qcoeff[i]) {
1841 txb_info->qcoeff[scan[i]] =
1842 hbt_hash_table[hbt_hash_index][found_index].opt_qcoeff[i];
1843 update = 1;
1844 update_coeff(scan[i], txb_info->qcoeff[scan[i]], txb_info);
1845 }
1846
1847 if (txb_info->qcoeff[scan[i]]) new_eob = i + 1;
1848 }
1849
1850 if (update) {
1851 txb_info->eob = new_eob;
1852 p->eobs[block] = txb_info->eob;
1853 p->txb_entropy_ctx[block] = av1_get_txb_entropy_context(
1854 txb_info->qcoeff, txb_info->scan_order, txb_info->eob);
1855 }
1856 return txb_info->eob;
1857}
1858
1859int search_hbt_hash_match(uint16_t hbt_hash_index, uint32_t hbt_hash_match,
1860 TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001861 const LV_MAP_EOB_COST *txb_eob_costs,
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001862 const struct macroblock_plane *p, int block,
1863 int fast_mode) {
1864 // Decay all hits
1865 double lowest_hits = 1.0;
1866 int lowest_index = 0;
1867
1868 for (int i = 0; i < 16; i++) {
1869 hbt_hash_table[hbt_hash_index][i].hits *= 31.0;
1870 hbt_hash_table[hbt_hash_index][i].hits /= 32.0;
1871
1872 if (hbt_hash_table[hbt_hash_index][i].hits < lowest_hits) {
1873 lowest_hits = hbt_hash_table[hbt_hash_index][i].hits;
1874 lowest_index = i;
1875 }
1876 }
1877
1878 // Search soft hash vector for qcoeff match
1879 int found_index = -1;
1880 for (int i = 0; i < 16; i++) { // OptTxbQcoeff array has fixed size of 16.
1881 if (hbt_hash_table[hbt_hash_index][i].hbt_hash_match == hbt_hash_match) {
1882 found_index = i;
1883 hbt_hash_table[hbt_hash_index][i].hits += 1.0;
1884 break; // Found a match and it's at found_index
1885 }
1886 }
1887
1888 if (found_index == -1) { // Add new OptTxbQcoeff into array.
1889 return hbt_hash_miss(lowest_index, hbt_hash_index, hbt_hash_match, txb_info,
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001890 txb_costs, txb_eob_costs, p, block, fast_mode);
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001891 } else { // Retrieve data from array.
1892 return hbt_hash_hit(hbt_hash_index, found_index, txb_info, p, block);
1893 }
1894}
1895
1896int hash_based_trellis_mode(TxbInfo *txb_info,
1897 const LV_MAP_COEFF_COST *txb_costs,
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001898 const LV_MAP_EOB_COST *txb_eob_costs,
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001899 const struct macroblock_plane *p, int block,
1900 int fast_mode, TXB_CTX *txb_ctx) {
1901 // Initialize hash table if needed.
1902 if (hbt_hash_needs_init) {
1903 hbt_hash_init();
1904 }
1905
1906 //// Hash creation
1907 // TODO(mfo): use exact length once input finalized
1908 uint8_t txb_hash_data[256];
1909 const int16_t *scan = txb_info->scan_order->scan;
1910 uint8_t chunk = 0;
1911
1912 uint16_t ctx_hash = 0;
1913 uint32_t qc_hash = 0;
1914
1915 int hash_data_index = 0;
1916 for (int i = 0; i < txb_info->eob; i++) {
1917 // Data softening: data from -3 -> 3 is left alone,
1918 // while 'large' data is put into buckets of 16s
1919 // Consider bucketing less than 16 down to 4 instead of 0
1920 // if(txb_info->qcoeff[scan[i]] < 4 && txb_info->qcoeff[scan[i]] > -4)
1921 chunk = (txb_info->qcoeff[scan[i]]) & 0xff;
1922 /*else if(txb_info->qcoeff[scan[i]] < 16 && txb_info->qcoeff[scan[i]] > -16)
1923 chunk = (txb_info->qcoeff[scan[i]]) & 0xfc; //
1924 else
1925 chunk = (txb_info->qcoeff[scan[i]]) & 0xf0; // greater than 16*/
1926 txb_hash_data[hash_data_index++] = chunk;
1927
1928 chunk = ((txb_info->qcoeff[scan[i]]) & 0xff00) >> 8;
1929 txb_hash_data[hash_data_index++] = chunk;
1930 }
1931 assert(hash_data_index <= 256);
1932 // 16 bit
1933 qc_hash = av1_get_crc_value(&crc_calculator2, txb_hash_data, hash_data_index);
1934
1935 hash_data_index = 0;
1936 // tcoeff
1937 for (int i = 0; i < txb_info->eob; i++) {
1938 chunk = (txb_info->tcoeff[scan[i]] - txb_info->dqcoeff[scan[i]]) & 0xff;
1939 txb_hash_data[hash_data_index++] = chunk;
1940 }
1941 // txb_ctx
1942 chunk = txb_ctx->txb_skip_ctx & 0xff;
1943 txb_hash_data[hash_data_index++] = chunk;
1944 chunk = txb_ctx->dc_sign_ctx & 0xff;
1945 txb_hash_data[hash_data_index++] = chunk;
1946 // dequant
1947 chunk = txb_info->dequant[0] & 0xff;
1948 txb_hash_data[hash_data_index++] = chunk;
1949 chunk = (txb_info->dequant[0] & 0xff00) >> 8;
1950 txb_hash_data[hash_data_index++] = chunk;
1951 chunk = txb_info->dequant[1] & 0xff;
1952 txb_hash_data[hash_data_index++] = chunk;
1953 chunk = (txb_info->dequant[1] & 0xff00) >> 8;
1954 txb_hash_data[hash_data_index++] = chunk;
1955 // txb_skip_cost
1956 /*for (int i = 0; i < 2; i++) {
1957 for (int j = 0; j < TXB_SKIP_CONTEXTS; j++) {
1958 chunk = (txb_costs->txb_skip_cost[j][i] & 0xff00) >> 8;
1959 txb_hash_data[hash_data_index++] = chunk;
1960 }
1961 }
1962 // base_eob_cost
1963 for (int i = 1; i < 3; i++) { // i = 0 are softened away
1964 for (int j = 0; j < SIG_COEF_CONTEXTS_EOB; j++) {
1965 chunk = (txb_costs->base_eob_cost[j][i] & 0xff00) >> 8;
1966 txb_hash_data[hash_data_index++] = chunk;
1967 }
1968 }*/
1969 assert(hash_data_index <= 256);
1970 // Gives 16 bit hash for ctx
1971 ctx_hash = av1_get_crc_value(&crc_calculator, txb_hash_data, hash_data_index);
1972
1973 uint16_t hbt_hash_index = ctx_hash; // 16 bit ctx_hash: index to table
1974 uint32_t hbt_hash_match = qc_hash; // 16 bit qc_hash: matched in array
1975 //// End hash creation
1976
1977 return search_hbt_hash_match(hbt_hash_index, hbt_hash_match, txb_info,
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001978 txb_costs, txb_eob_costs, p, block, fast_mode);
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001979}
1980
1981int av1_optimize_txb(const AV1_COMP *const cpi, MACROBLOCK *x, int plane,
Jingning Han7eab9ff2017-07-06 10:12:54 -07001982 int blk_row, int blk_col, int block, TX_SIZE tx_size,
Angie Chiang25645b72017-09-24 14:28:49 -07001983 TXB_CTX *txb_ctx, int fast_mode) {
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001984 const AV1_COMMON *cm = &cpi->common;
Angie Chiang07c57f32017-05-30 18:18:33 -07001985 MACROBLOCKD *const xd = &x->e_mbd;
1986 const PLANE_TYPE plane_type = get_plane_type(plane);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -08001987 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Jingning Han19b5c8f2017-07-06 15:10:12 -07001988 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -05001989 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07001990 const MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
1991 const struct macroblock_plane *p = &x->plane[plane];
1992 struct macroblockd_plane *pd = &xd->plane[plane];
1993 const int eob = p->eobs[block];
1994 tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
1995 tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
1996 const tran_low_t *tcoeff = BLOCK_OFFSET(p->coeff, block);
Monty Montgomery125c0fc2017-10-26 00:44:35 -04001997 const int16_t *dequant = p->dequant_QTX;
Urvang Joshi80893152017-10-27 11:51:14 -07001998 const int seg_eob = av1_get_max_eob(tx_size);
Angie Chianga9ba58e2017-12-01 19:22:43 -08001999 const int bwl = get_txb_bwl(tx_size);
2000 const int width = get_txb_wide(tx_size);
2001 const int height = get_txb_high(tx_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07002002 const int is_inter = is_inter_block(mbmi);
Angie Chiangbd99b382017-06-20 15:11:16 -07002003 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Jingning Handfd72322017-08-09 14:04:12 -07002004 const LV_MAP_COEFF_COST txb_costs = x->coeff_costs[txs_ctx][plane_type];
Sarah Parker3d752092017-12-20 15:37:55 -08002005#if CONFIG_NEW_QUANT
Debargha Mukherjeee15b8ad2017-12-26 07:10:40 -08002006 int dq = get_dq_profile(cm->dq_type, x->qindex, is_inter, plane_type);
Sarah Parker3d752092017-12-20 15:37:55 -08002007 const dequant_val_type_nuq *dequant_val = p->dequant_val_nuq_QTX[dq];
2008#endif // CONFIG_NEW_QUANT
Dake He0db7d0e2017-12-21 15:23:20 -08002009 const int eob_multi_size = txsize_log2_minus4[tx_size];
2010 const LV_MAP_EOB_COST txb_eob_costs =
2011 x->eob_costs[eob_multi_size][plane_type];
Angie Chiang07c57f32017-05-30 18:18:33 -07002012
Montybca9e9e2017-12-14 06:23:29 -06002013#if CONFIG_DAALA_TX
2014 const int shift = 0;
2015#else
Angie Chiang07c57f32017-05-30 18:18:33 -07002016 const int shift = av1_get_tx_scale(tx_size);
Montybca9e9e2017-12-14 06:23:29 -06002017#endif
Angie Chiang07c57f32017-05-30 18:18:33 -07002018 const int64_t rdmult =
Jingning Hanb433f4c2017-11-17 15:43:59 -08002019 ((x->rdmult * plane_rd_mult[is_inter][plane_type] << (2 * (xd->bd - 8))) +
2020 2) >>
2021 2;
Linfeng Zhang679d81e2017-10-31 15:27:42 -07002022 uint8_t levels_buf[TX_PAD_2D];
2023 uint8_t *const levels = set_levels(levels_buf, width);
Angie Chiang07c57f32017-05-30 18:18:33 -07002024
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002025 assert(width == (1 << bwl));
Linfeng Zhang1015a342017-10-24 16:20:41 -07002026 TxbInfo txb_info = {
Sarah Parker3d752092017-12-20 15:37:55 -08002027 qcoeff,
2028 levels,
2029 dqcoeff,
2030 tcoeff,
2031 dequant,
2032#if CONFIG_NEW_QUANT
2033 dequant_val,
2034#endif // CONFIG_NEW_QUANT
2035 shift,
2036 tx_size,
2037 txs_ctx,
2038 tx_type,
2039 bwl,
2040 width,
2041 height,
2042 eob,
2043 seg_eob,
2044 scan_order,
2045 txb_ctx,
2046 rdmult,
2047 &cm->coeff_ctx_table
Linfeng Zhang1015a342017-10-24 16:20:41 -07002048 };
2049
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08002050 // Hash based trellis (hbt) speed feature: avoid expensive optimize_txb calls
2051 // by storing the optimized coefficients in a hash table.
2052 // Currently disabled in speedfeatures.c
2053 if (eob <= HBT_HASH_EOB && eob > 0 && cpi->sf.use_hash_based_trellis) {
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01002054 return hash_based_trellis_mode(&txb_info, &txb_costs, &txb_eob_costs, p,
2055 block, fast_mode, txb_ctx);
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08002056 }
2057
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002058 av1_txb_init_levels(qcoeff, width, height, levels);
Urvang Joshi70006e42017-06-14 16:08:55 -07002059
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01002060 const int update =
2061 optimize_txb(&txb_info, &txb_costs, &txb_eob_costs, NULL, 0, fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07002062
Jingning Hand7e99112017-12-13 09:47:45 -08002063 if (update) {
2064 p->eobs[block] = txb_info.eob;
2065 p->txb_entropy_ctx[block] =
2066 av1_get_txb_entropy_context(qcoeff, scan_order, txb_info.eob);
2067 }
Angie Chiang07c57f32017-05-30 18:18:33 -07002068 return txb_info.eob;
2069}
Jingning Hand7e99112017-12-13 09:47:45 -08002070
Angie Chiang74e23072017-03-24 14:54:23 -07002071int av1_get_txb_entropy_context(const tran_low_t *qcoeff,
2072 const SCAN_ORDER *scan_order, int eob) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002073 const int16_t *const scan = scan_order->scan;
Angie Chiang74e23072017-03-24 14:54:23 -07002074 int cul_level = 0;
2075 int c;
Jingning Han339cf932017-09-18 10:17:02 -07002076
2077 if (eob == 0) return 0;
Angie Chiang74e23072017-03-24 14:54:23 -07002078 for (c = 0; c < eob; ++c) {
2079 cul_level += abs(qcoeff[scan[c]]);
2080 }
2081
2082 cul_level = AOMMIN(COEFF_CONTEXT_MASK, cul_level);
2083 set_dc_sign(&cul_level, qcoeff[0]);
2084
2085 return cul_level;
2086}
2087
Jingning Han4fe5f672017-05-19 15:46:07 -07002088void av1_update_txb_context_b(int plane, int block, int blk_row, int blk_col,
2089 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
2090 void *arg) {
Jingning Han6171ae72017-05-18 20:15:06 -07002091 struct tokenize_b_args *const args = arg;
Angie Chiang36d616b2017-03-22 13:58:36 -07002092 const AV1_COMP *cpi = args->cpi;
2093 const AV1_COMMON *cm = &cpi->common;
Angie Chiang0397eda2017-03-15 16:57:14 -07002094 ThreadData *const td = args->td;
2095 MACROBLOCK *const x = &td->mb;
2096 MACROBLOCKD *const xd = &x->e_mbd;
Angie Chiang36d616b2017-03-22 13:58:36 -07002097 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiang0397eda2017-03-15 16:57:14 -07002098 struct macroblock_plane *p = &x->plane[plane];
2099 struct macroblockd_plane *pd = &xd->plane[plane];
Angie Chiang36d616b2017-03-22 13:58:36 -07002100 const uint16_t eob = p->eobs[block];
2101 const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2102 const PLANE_TYPE plane_type = pd->plane_type;
Jingning Han19b5c8f2017-07-06 15:10:12 -07002103 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002104 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07002105 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Angie Chiang0397eda2017-03-15 16:57:14 -07002106 (void)plane_bsize;
Angie Chiang36d616b2017-03-22 13:58:36 -07002107
Angie Chiang74e23072017-03-24 14:54:23 -07002108 int cul_level = av1_get_txb_entropy_context(qcoeff, scan_order, eob);
Angie Chiang36d616b2017-03-22 13:58:36 -07002109 av1_set_contexts(xd, pd, plane, tx_size, cul_level, blk_col, blk_row);
Angie Chiang0397eda2017-03-15 16:57:14 -07002110}
2111
Jingning Han4fe5f672017-05-19 15:46:07 -07002112void av1_update_and_record_txb_context(int plane, int block, int blk_row,
2113 int blk_col, BLOCK_SIZE plane_bsize,
2114 TX_SIZE tx_size, void *arg) {
Jingning Han6171ae72017-05-18 20:15:06 -07002115 struct tokenize_b_args *const args = arg;
Angie Chiang0397eda2017-03-15 16:57:14 -07002116 const AV1_COMP *cpi = args->cpi;
2117 const AV1_COMMON *cm = &cpi->common;
2118 ThreadData *const td = args->td;
2119 MACROBLOCK *const x = &td->mb;
2120 MACROBLOCKD *const xd = &x->e_mbd;
2121 struct macroblock_plane *p = &x->plane[plane];
2122 struct macroblockd_plane *pd = &xd->plane[plane];
2123 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Linfeng Zhang848f7bc2017-10-31 15:26:07 -07002124 int eob = p->eobs[block], update_eob = -1;
Angie Chiang0397eda2017-03-15 16:57:14 -07002125 const PLANE_TYPE plane_type = pd->plane_type;
2126 const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2127 tran_low_t *tcoeff = BLOCK_OFFSET(x->mbmi_ext->tcoeff[plane], block);
2128 const int segment_id = mbmi->segment_id;
Jingning Han19b5c8f2017-07-06 15:10:12 -07002129 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002130 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07002131 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002132 const int16_t *const scan = scan_order->scan;
hui suc0cf71d2017-07-20 16:38:50 -07002133 const int seg_eob = av1_get_tx_eob(&cpi->common.seg, segment_id, tx_size);
Linfeng Zhang1015a342017-10-24 16:20:41 -07002134 int c;
Angie Chiang85901562017-03-17 12:03:27 -07002135 TXB_CTX txb_ctx;
2136 get_txb_ctx(plane_bsize, tx_size, plane, pd->above_context + blk_col,
2137 pd->left_context + blk_row, &txb_ctx);
Angie Chianga9ba58e2017-12-01 19:22:43 -08002138 const int bwl = get_txb_bwl(tx_size);
2139 const int width = get_txb_wide(tx_size);
2140 const int height = get_txb_high(tx_size);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07002141 uint8_t levels_buf[TX_PAD_2D];
2142 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -08002143 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Yunqing Wang0e141b52017-11-02 15:08:58 -07002144 const uint8_t allow_update_cdf = args->allow_update_cdf;
Angie Chiang0397eda2017-03-15 16:57:14 -07002145
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -08002146 TX_SIZE txsize_ctx = get_txsize_entropy_ctx(tx_size);
Jingning Han8f661602017-08-19 08:16:50 -07002147 FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
Linfeng Zhangd67c13f2017-12-11 11:49:12 -08002148 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Jingning Han48be0e12017-06-13 12:12:01 -07002149
Angie Chiang0397eda2017-03-15 16:57:14 -07002150 memcpy(tcoeff, qcoeff, sizeof(*tcoeff) * seg_eob);
2151
Jingning Han48be0e12017-06-13 12:12:01 -07002152 ++td->counts->txb_skip[txsize_ctx][txb_ctx.txb_skip_ctx][eob == 0];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002153 if (allow_update_cdf)
2154 update_bin(ec_ctx->txb_skip_cdf[txsize_ctx][txb_ctx.txb_skip_ctx], eob == 0,
2155 2);
Angie Chiang85901562017-03-17 12:03:27 -07002156 x->mbmi_ext->txb_skip_ctx[plane][block] = txb_ctx.txb_skip_ctx;
Angie Chiang0397eda2017-03-15 16:57:14 -07002157
2158 x->mbmi_ext->eobs[plane][block] = eob;
2159
2160 if (eob == 0) {
2161 av1_set_contexts(xd, pd, plane, tx_size, 0, blk_col, blk_row);
2162 return;
2163 }
2164
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002165 av1_txb_init_levels(tcoeff, width, height, levels);
Linfeng Zhangce065ca2017-10-17 16:49:30 -07002166
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002167#if CONFIG_TXK_SEL
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002168 av1_update_tx_type_count(cm, xd, blk_row, blk_col, plane, mbmi->sb_type,
Debargha Mukherjee3ebb0d02017-12-14 05:05:18 -08002169 tx_size, td->counts, allow_update_cdf);
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002170#endif
Angie Chiang0397eda2017-03-15 16:57:14 -07002171
Jingning Han35deaa72017-10-26 15:36:30 -07002172 av1_update_eob_context(eob, seg_eob, tx_size, tx_type, plane_type, ec_ctx,
Yunqing Wang0e141b52017-11-02 15:08:58 -07002173 td->counts, allow_update_cdf);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -08002174
2175 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_type, coeff_contexts);
2176
Dake He03a32922017-10-31 08:06:45 -07002177 update_eob = eob - 1;
Dake Hea47cd6c2017-10-13 18:09:58 -07002178 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002179 const int pos = scan[c];
Linfeng Zhangd67c13f2017-12-11 11:49:12 -08002180 const int coeff_ctx = coeff_contexts[pos];
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002181 const tran_low_t v = qcoeff[pos];
2182 const int is_nz = (v != 0);
Dake He03a32922017-10-31 08:06:45 -07002183
Ola Hugosson13892102017-11-06 08:01:44 +01002184 (void)is_nz;
Dake He4d447692017-12-15 09:10:06 -08002185 if (allow_update_cdf) {
2186 if (c == eob - 1) {
2187 assert(coeff_ctx < 4);
2188 update_cdf(
2189 ec_ctx->coeff_base_eob_cdf[txsize_ctx][plane_type][coeff_ctx],
2190 AOMMIN(abs(v), 3) - 1, 3);
2191 } else {
2192 update_cdf(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][coeff_ctx],
2193 AOMMIN(abs(v), 3), 4);
2194 }
Dake He3fe369c2017-11-16 17:56:44 -08002195 }
Dake He59881772017-11-24 07:00:02 -08002196 {
Dake He4d447692017-12-15 09:10:06 -08002197 if (c == eob - 1) {
2198 assert(coeff_ctx < 4);
2199 ++td->counts->coeff_base_eob_multi[txsize_ctx][plane_type][coeff_ctx]
2200 [AOMMIN(abs(v), 3) - 1];
2201 } else {
2202 ++td->counts->coeff_base_multi[txsize_ctx][plane_type][coeff_ctx]
2203 [AOMMIN(abs(v), 3)];
Dake He59881772017-11-24 07:00:02 -08002204 }
2205 }
Dake Hea47cd6c2017-10-13 18:09:58 -07002206 }
Dake Hea47cd6c2017-10-13 18:09:58 -07002207
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002208 // Update the context needed to code the DC sign (if applicable)
2209 const int sign = (tcoeff[0] < 0) ? 1 : 0;
2210 if (tcoeff[0] != 0) {
Dake He43edb762017-10-26 10:29:46 -07002211 int dc_sign_ctx = txb_ctx.dc_sign_ctx;
2212
2213 ++td->counts->dc_sign[plane_type][dc_sign_ctx][sign];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002214 if (allow_update_cdf)
2215 update_bin(ec_ctx->dc_sign_cdf[plane_type][dc_sign_ctx], sign, 2);
Dake He43edb762017-10-26 10:29:46 -07002216 x->mbmi_ext->dc_sign_ctx[plane][block] = dc_sign_ctx;
2217 }
2218
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002219 if (update_eob >= 0) {
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002220 for (c = update_eob; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002221 const int pos = scan[c];
2222 const tran_low_t level = abs(tcoeff[pos]);
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002223 int idx;
2224 int ctx;
Angie Chiang0397eda2017-03-15 16:57:14 -07002225
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002226 if (level <= NUM_BASE_LEVELS) continue;
Angie Chiang0397eda2017-03-15 16:57:14 -07002227
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01002228 // level is above 1.
Jingning Han87b01b52017-08-31 12:07:20 -07002229
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002230 const int base_range = level - 1 - NUM_BASE_LEVELS;
Dake He7d01ab52017-11-24 17:53:28 -08002231#if USE_CAUSAL_BR_CTX
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002232 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos], tx_type);
Dake He7d01ab52017-11-24 17:53:28 -08002233#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002234 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -08002235#endif
Ola Hugossone72a2092017-11-12 09:11:53 +01002236 for (idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002237 const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
Dake He4d447692017-12-15 09:10:06 -08002238 if (allow_update_cdf) {
2239 update_cdf(
Dake Hee2d8f182017-12-14 13:28:00 -08002240#if 0
Dake He7d01ab52017-11-24 17:53:28 -08002241 ec_ctx->coeff_br_cdf[AOMMIN(txsize_ctx, TX_16X16)][plane_type][ctx],
Dake Hee2d8f182017-12-14 13:28:00 -08002242#else
Dake He4d447692017-12-15 09:10:06 -08002243 ec_ctx
2244 ->coeff_br_cdf[AOMMIN(txsize_ctx, TX_32X32)][plane_type][ctx],
Dake Hee2d8f182017-12-14 13:28:00 -08002245#endif
Dake He4d447692017-12-15 09:10:06 -08002246 k, BR_CDF_SIZE);
2247 }
Dake He7d01ab52017-11-24 17:53:28 -08002248 for (int lps = 0; lps < BR_CDF_SIZE - 1; lps++) {
Dake Hee2d8f182017-12-14 13:28:00 -08002249#if 0
Dake He7d01ab52017-11-24 17:53:28 -08002250 ++td->counts->coeff_lps[AOMMIN(txsize_ctx, TX_16X16)][plane_type][lps]
2251 [ctx][lps == k];
Dake Hee2d8f182017-12-14 13:28:00 -08002252#else
2253 ++td->counts->coeff_lps[AOMMIN(txsize_ctx, TX_32X32)][plane_type][lps]
2254 [ctx][lps == k];
2255#endif
Dake He59881772017-11-24 07:00:02 -08002256 if (lps == k) break;
2257 }
Dake Hee2d8f182017-12-14 13:28:00 -08002258 ++td->counts->coeff_lps_multi[AOMMIN(txsize_ctx, TX_32X32)][plane_type]
2259 [ctx][k];
Dake He59881772017-11-24 07:00:02 -08002260
Ola Hugossone72a2092017-11-12 09:11:53 +01002261 if (k < BR_CDF_SIZE - 1) break;
2262 }
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002263 // use 0-th order Golomb code to handle the residual level.
Jingning Han87b01b52017-08-31 12:07:20 -07002264 }
Angie Chiang0397eda2017-03-15 16:57:14 -07002265 }
Angie Chiang36d616b2017-03-22 13:58:36 -07002266
Angie Chiang63d190a2017-10-23 15:43:05 -07002267 int cul_level = av1_get_txb_entropy_context(tcoeff, scan_order, eob);
Angie Chiang0397eda2017-03-15 16:57:14 -07002268 av1_set_contexts(xd, pd, plane, tx_size, cul_level, blk_col, blk_row);
2269}
2270
2271void av1_update_txb_context(const AV1_COMP *cpi, ThreadData *td,
2272 RUN_TYPE dry_run, BLOCK_SIZE bsize, int *rate,
Yunqing Wang0e141b52017-11-02 15:08:58 -07002273 int mi_row, int mi_col, uint8_t allow_update_cdf) {
Angie Chiang0397eda2017-03-15 16:57:14 -07002274 MACROBLOCK *const x = &td->mb;
2275 MACROBLOCKD *const xd = &x->e_mbd;
2276 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yunqing Wang0e141b52017-11-02 15:08:58 -07002277 struct tokenize_b_args arg = { cpi, td, NULL, 0, allow_update_cdf };
Angie Chiang0397eda2017-03-15 16:57:14 -07002278 (void)rate;
2279 (void)mi_row;
2280 (void)mi_col;
2281 if (mbmi->skip) {
Timothy B. Terriberrya2d5cde2017-05-10 18:33:50 -07002282 av1_reset_skip_context(xd, mi_row, mi_col, bsize);
Angie Chiang0397eda2017-03-15 16:57:14 -07002283 return;
2284 }
2285
2286 if (!dry_run) {
Jingning Han94652b82017-04-04 09:45:02 -07002287 av1_foreach_transformed_block(xd, bsize, mi_row, mi_col,
Jingning Han4fe5f672017-05-19 15:46:07 -07002288 av1_update_and_record_txb_context, &arg);
Angie Chiangc8af6112017-03-16 16:11:22 -07002289 } else if (dry_run == DRY_RUN_NORMAL) {
Jingning Han4fe5f672017-05-19 15:46:07 -07002290 av1_foreach_transformed_block(xd, bsize, mi_row, mi_col,
2291 av1_update_txb_context_b, &arg);
Angie Chiangc8af6112017-03-16 16:11:22 -07002292 } else {
2293 printf("DRY_RUN_COSTCOEFFS is not supported yet\n");
2294 assert(0);
Angie Chiang0397eda2017-03-15 16:57:14 -07002295 }
2296}
Angie Chiang800df032017-03-22 11:14:12 -07002297
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002298#if CONFIG_TXK_SEL
Angie Chiang808d8592017-04-06 18:36:55 -07002299int64_t av1_search_txk_type(const AV1_COMP *cpi, MACROBLOCK *x, int plane,
2300 int block, int blk_row, int blk_col,
2301 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
Angie Chiang65a39bb2017-04-11 16:50:04 -07002302 const ENTROPY_CONTEXT *a, const ENTROPY_CONTEXT *l,
2303 int use_fast_coef_costing, RD_STATS *rd_stats) {
Angie Chiang808d8592017-04-06 18:36:55 -07002304 const AV1_COMMON *cm = &cpi->common;
2305 MACROBLOCKD *xd = &x->e_mbd;
2306 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
2307 TX_TYPE txk_start = DCT_DCT;
2308 TX_TYPE txk_end = TX_TYPES - 1;
2309 TX_TYPE best_tx_type = txk_start;
2310 int64_t best_rd = INT64_MAX;
Angie Chiang4e16ea62017-12-15 17:58:44 -08002311 uint8_t best_txb_ctx = 0;
2312 uint16_t best_eob = 0;
Jingning Hane3b81bc2017-06-23 11:43:52 -07002313 RD_STATS best_rd_stats;
Angie Chiang808d8592017-04-06 18:36:55 -07002314 TX_TYPE tx_type;
Jingning Hane3b81bc2017-06-23 11:43:52 -07002315
2316 av1_invalid_rd_stats(&best_rd_stats);
2317
Angie Chiang808d8592017-04-06 18:36:55 -07002318 for (tx_type = txk_start; tx_type <= txk_end; ++tx_type) {
Angie Chiangbce07f12017-12-01 16:34:31 -08002319 if (plane == 0)
2320 mbmi->txk_type[(blk_row << MAX_MIB_SIZE_LOG2) + blk_col] = tx_type;
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002321 TX_TYPE ref_tx_type =
2322 av1_get_tx_type(get_plane_type(plane), xd, blk_row, blk_col, tx_size);
Angie Chiang00491e02017-04-11 17:55:10 -07002323 if (tx_type != ref_tx_type) {
hui su45b64752017-07-12 16:54:35 -07002324 // use av1_get_tx_type() to check if the tx_type is valid for the current
2325 // mode if it's not, we skip it here.
Angie Chiang00491e02017-04-11 17:55:10 -07002326 continue;
2327 }
Jingning Hane57d6322017-07-03 18:50:25 -07002328
Hui Suddbcde22017-09-18 17:22:02 -07002329 const int is_inter = is_inter_block(mbmi);
Angie Chiang53bf1e92017-11-29 16:53:07 -08002330 const TxSetType tx_set_type = get_ext_tx_set_type(
2331 tx_size, mbmi->sb_type, is_inter, cm->reduced_tx_set_used);
Hui Suddbcde22017-09-18 17:22:02 -07002332 if (!av1_ext_tx_used[tx_set_type][tx_type]) continue;
Jingning Hane57d6322017-07-03 18:50:25 -07002333
Angie Chiang808d8592017-04-06 18:36:55 -07002334 RD_STATS this_rd_stats;
2335 av1_invalid_rd_stats(&this_rd_stats);
Sarah Parker792c2ec2017-12-21 16:08:22 -08002336 if (cpi->sf.optimize_coefficients != FULL_TRELLIS_OPT) {
2337 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize,
2338 tx_size, AV1_XFORM_QUANT_B);
2339 } else {
2340 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize,
2341 tx_size, AV1_XFORM_QUANT_FP);
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08002342 av1_optimize_b(cpi, x, plane, blk_row, blk_col, block, plane_bsize,
Sarah Parker792c2ec2017-12-21 16:08:22 -08002343 tx_size, a, l, 1);
2344 }
Angie Chiang808d8592017-04-06 18:36:55 -07002345 av1_dist_block(cpi, x, plane, plane_bsize, block, blk_row, blk_col, tx_size,
Angie Chiang2ed03a32017-04-16 18:00:06 -07002346 &this_rd_stats.dist, &this_rd_stats.sse,
2347 OUTPUT_HAS_PREDICTED_PIXELS);
Angie Chiangbd99b382017-06-20 15:11:16 -07002348 const SCAN_ORDER *scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Jingning Han7eab9ff2017-07-06 10:12:54 -07002349 this_rd_stats.rate =
2350 av1_cost_coeffs(cpi, x, plane, blk_row, blk_col, block, tx_size,
2351 scan_order, a, l, use_fast_coef_costing);
Jingning Han721c4c32018-01-03 09:05:08 -08002352 int64_t rd = RDCOST(x->rdmult, this_rd_stats.rate, this_rd_stats.dist);
Jingning Han19b5c8f2017-07-06 15:10:12 -07002353
Angie Chiang808d8592017-04-06 18:36:55 -07002354 if (rd < best_rd) {
2355 best_rd = rd;
Jingning Hane3b81bc2017-06-23 11:43:52 -07002356 best_rd_stats = this_rd_stats;
Angie Chiang808d8592017-04-06 18:36:55 -07002357 best_tx_type = tx_type;
Angie Chiang4e16ea62017-12-15 17:58:44 -08002358 best_txb_ctx = x->plane[plane].txb_entropy_ctx[block];
2359 best_eob = x->plane[plane].eobs[block];
Angie Chiang808d8592017-04-06 18:36:55 -07002360 }
2361 }
Jingning Hane3b81bc2017-06-23 11:43:52 -07002362
2363 av1_merge_rd_stats(rd_stats, &best_rd_stats);
2364
Angie Chianga3f7d2e2017-12-07 19:51:14 -08002365 if (best_eob == 0) best_tx_type = DCT_DCT;
Jingning Han19b5c8f2017-07-06 15:10:12 -07002366
Angie Chiangbce07f12017-12-01 16:34:31 -08002367 if (plane == 0)
2368 mbmi->txk_type[(blk_row << MAX_MIB_SIZE_LOG2) + blk_col] = best_tx_type;
Angie Chiang4e16ea62017-12-15 17:58:44 -08002369 x->plane[plane].txb_entropy_ctx[block] = best_txb_ctx;
Angie Chiang6f90fb22017-12-20 16:30:20 -08002370 x->plane[plane].eobs[block] = best_eob;
Jingning Han47558172017-07-05 16:33:19 -07002371
Angie Chiang2ed03a32017-04-16 18:00:06 -07002372 if (!is_inter_block(mbmi)) {
Sarah Parker792c2ec2017-12-21 16:08:22 -08002373 // intra mode needs decoded result such that the next transform block
2374 // can use it for prediction.
2375 if (cpi->sf.optimize_coefficients != FULL_TRELLIS_OPT) {
2376 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize,
2377 tx_size, AV1_XFORM_QUANT_B);
2378 } else {
2379 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize,
2380 tx_size, AV1_XFORM_QUANT_FP);
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08002381 av1_optimize_b(cpi, x, plane, blk_row, blk_col, block, plane_bsize,
Sarah Parker792c2ec2017-12-21 16:08:22 -08002382 tx_size, a, l, 1);
2383 }
Jingning Han47558172017-07-05 16:33:19 -07002384
Angie Chiang2ed03a32017-04-16 18:00:06 -07002385 av1_inverse_transform_block_facade(xd, plane, block, blk_row, blk_col,
Frederic Barbier33b39f02017-11-21 11:11:24 +01002386 x->plane[plane].eobs[block],
2387 cm->reduced_tx_set_used);
Angie Chiang2ed03a32017-04-16 18:00:06 -07002388 }
Angie Chiang808d8592017-04-06 18:36:55 -07002389 return best_rd;
2390}
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002391#endif // CONFIG_TXK_SEL