blob: c678668467fc000080845a659d238c27304bd187 [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"
Angie Chiang808d8592017-04-06 18:36:55 -070021#include "av1/encoder/rdopt.h"
Angie Chiang800df032017-03-22 11:14:12 -070022#include "av1/encoder/subexp.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
Dake Hea47cd6c2017-10-13 18:09:58 -070027typedef struct LevelDownStats {
28 int update;
29 tran_low_t low_qc;
30 tran_low_t low_dqc;
Dake Hea47cd6c2017-10-13 18:09:58 -070031 int64_t dist0;
32 int rate;
33 int rate_low;
34 int64_t dist;
35 int64_t dist_low;
36 int64_t rd;
37 int64_t rd_low;
Dake He4d447692017-12-15 09:10:06 -080038#if CONFIG_LV_MAP_MULTI
39 int64_t nz_rd;
40#else
Dake Hea47cd6c2017-10-13 18:09:58 -070041 int nz_rate; // for eob
Dake He4d447692017-12-15 09:10:06 -080042#endif
Dake Hea47cd6c2017-10-13 18:09:58 -070043 int64_t rd_diff;
44 int cost_diff;
45 int64_t dist_diff;
46 int new_eob;
47} LevelDownStats;
48
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070049void av1_alloc_txb_buf(AV1_COMP *cpi) {
Angie Chiangc484abe2017-03-20 15:43:11 -070050#if 0
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070051 AV1_COMMON *cm = &cpi->common;
52 int mi_block_size = 1 << MI_SIZE_LOG2;
53 // TODO(angiebird): Make sure cm->subsampling_x/y is set correctly, and then
54 // use precise buffer size according to cm->subsampling_x/y
55 int pixel_stride = mi_block_size * cm->mi_cols;
56 int pixel_height = mi_block_size * cm->mi_rows;
57 int i;
58 for (i = 0; i < MAX_MB_PLANE; ++i) {
59 CHECK_MEM_ERROR(
60 cm, cpi->tcoeff_buf[i],
61 aom_malloc(sizeof(*cpi->tcoeff_buf[i]) * pixel_stride * pixel_height));
62 }
Angie Chiangc484abe2017-03-20 15:43:11 -070063#else
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070064 AV1_COMMON *cm = &cpi->common;
Dominic Symes917d6c02017-10-11 18:00:52 +020065 int size = ((cm->mi_rows >> cm->mib_size_log2) + 1) *
66 ((cm->mi_cols >> cm->mib_size_log2) + 1);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070067
Angie Chiang9367e3e2017-10-02 16:28:11 -070068 av1_free_txb_buf(cpi);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070069 // TODO(jingning): This should be further reduced.
70 CHECK_MEM_ERROR(cm, cpi->coeff_buffer_base,
71 aom_malloc(sizeof(*cpi->coeff_buffer_base) * size));
Angie Chiangc484abe2017-03-20 15:43:11 -070072#endif
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070073}
74
75void av1_free_txb_buf(AV1_COMP *cpi) {
Angie Chiangc484abe2017-03-20 15:43:11 -070076#if 0
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070077 int i;
78 for (i = 0; i < MAX_MB_PLANE; ++i) {
79 aom_free(cpi->tcoeff_buf[i]);
80 }
Angie Chiangc484abe2017-03-20 15:43:11 -070081#else
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070082 aom_free(cpi->coeff_buffer_base);
Angie Chiangc484abe2017-03-20 15:43:11 -070083#endif
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070084}
85
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070086void av1_set_coeff_buffer(const AV1_COMP *const cpi, MACROBLOCK *const x,
87 int mi_row, int mi_col) {
Dominic Symes917d6c02017-10-11 18:00:52 +020088 int mib_size_log2 = cpi->common.mib_size_log2;
89 int stride = (cpi->common.mi_cols >> mib_size_log2) + 1;
90 int offset = (mi_row >> mib_size_log2) * stride + (mi_col >> mib_size_log2);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070091 CB_COEFF_BUFFER *coeff_buf = &cpi->coeff_buffer_base[offset];
92 const int txb_offset = x->cb_offset / (TX_SIZE_W_MIN * TX_SIZE_H_MIN);
93 for (int plane = 0; plane < MAX_MB_PLANE; ++plane) {
94 x->mbmi_ext->tcoeff[plane] = coeff_buf->tcoeff[plane] + x->cb_offset;
95 x->mbmi_ext->eobs[plane] = coeff_buf->eobs[plane] + txb_offset;
96 x->mbmi_ext->txb_skip_ctx[plane] =
97 coeff_buf->txb_skip_ctx[plane] + txb_offset;
98 x->mbmi_ext->dc_sign_ctx[plane] =
99 coeff_buf->dc_sign_ctx[plane] + txb_offset;
100 }
101}
102
Angie Chiang80b82262017-02-24 11:39:47 -0800103static void write_golomb(aom_writer *w, int level) {
104 int x = level + 1;
105 int i = x;
106 int length = 0;
107
108 while (i) {
109 i >>= 1;
110 ++length;
111 }
112 assert(length > 0);
113
114 for (i = 0; i < length - 1; ++i) aom_write_bit(w, 0);
115
116 for (i = length - 1; i >= 0; --i) aom_write_bit(w, (x >> i) & 0x01);
117}
118
Dake Hea47cd6c2017-10-13 18:09:58 -0700119static INLINE tran_low_t get_lower_coeff(tran_low_t qc) {
120 if (qc == 0) {
121 return 0;
122 }
123 return qc > 0 ? qc - 1 : qc + 1;
124}
125
Sarah Parker3d752092017-12-20 15:37:55 -0800126static INLINE tran_low_t qcoeff_to_dqcoeff(tran_low_t qc,
127#if CONFIG_NEW_QUANT
128 const tran_low_t *nq_dq,
129#endif // CONFIG_NEW_QUANT
130 int dqv, int shift) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700131 int sgn = qc < 0 ? -1 : 1;
Sarah Parker3d752092017-12-20 15:37:55 -0800132#if CONFIG_NEW_QUANT
133 int dqcoeff = av1_dequant_coeff_nuq(abs(qc), dqv, nq_dq);
134 return sgn * (shift ? ROUND_POWER_OF_TWO(dqcoeff, shift) : dqcoeff);
135#endif // CONFIG_NEW_QUANT
136
Dake Hea47cd6c2017-10-13 18:09:58 -0700137 return sgn * ((abs(qc) * dqv) >> shift);
138}
139
140static INLINE int64_t get_coeff_dist(tran_low_t tcoeff, tran_low_t dqcoeff,
141 int shift) {
Monty Montgomery4a05a582017-11-01 21:21:07 -0400142#if CONFIG_DAALA_TX
143 int depth_shift = (TX_COEFF_DEPTH - 11) * 2;
144 int depth_round = depth_shift > 1 ? (1 << (depth_shift - 1)) : 0;
145 const int64_t diff = tcoeff - dqcoeff;
Montybca9e9e2017-12-14 06:23:29 -0600146 const int64_t error = (diff * diff + depth_round) >> depth_shift;
Monty Montgomery4a05a582017-11-01 21:21:07 -0400147 (void)shift;
148#else
Dake Hea47cd6c2017-10-13 18:09:58 -0700149 const int64_t diff = (tcoeff - dqcoeff) * (1 << shift);
150 const int64_t error = diff * diff;
Monty Montgomery4a05a582017-11-01 21:21:07 -0400151#endif
Dake Hea47cd6c2017-10-13 18:09:58 -0700152 return error;
153}
154
Jingning Han35deaa72017-10-26 15:36:30 -0700155void av1_update_eob_context(int eob, int seg_eob, TX_SIZE tx_size,
156 TX_TYPE tx_type, PLANE_TYPE plane,
Yunqing Wang0e141b52017-11-02 15:08:58 -0700157 FRAME_CONTEXT *ec_ctx, FRAME_COUNTS *counts,
158 uint8_t allow_update_cdf) {
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800159 int eob_extra, dummy;
160 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
161 const int max_eob_pt = get_eob_pos_token(seg_eob, &dummy);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -0800162 TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Dake Hea47cd6c2017-10-13 18:09:58 -0700163
164 for (int i = 1; i < max_eob_pt; i++) {
Jingning Han35deaa72017-10-26 15:36:30 -0700165 int eob_pos_ctx = av1_get_eob_pos_ctx(tx_type, i);
166 counts->eob_flag[txs_ctx][plane][eob_pos_ctx][eob_pt == i]++;
Yunqing Wang0e141b52017-11-02 15:08:58 -0700167 if (allow_update_cdf)
168 update_cdf(ec_ctx->eob_flag_cdf[txs_ctx][plane][eob_pos_ctx], eob_pt == i,
169 2);
Dake Hea47cd6c2017-10-13 18:09:58 -0700170 if (eob_pt == i) {
171 break;
172 }
173 }
Jingning Han00803a72017-10-25 16:04:34 -0700174
Angie Chiang7ab884e2017-10-18 15:57:12 -0700175 if (k_eob_offset_bits[eob_pt] > 0) {
176 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
177 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Jingning Han35deaa72017-10-26 15:36:30 -0700178 counts->eob_extra[txs_ctx][plane][eob_pt][bit]++;
Yunqing Wang0e141b52017-11-02 15:08:58 -0700179 if (allow_update_cdf)
180 update_cdf(ec_ctx->eob_extra_cdf[txs_ctx][plane][eob_pt], bit, 2);
Angie Chiang7ab884e2017-10-18 15:57:12 -0700181 }
Dake Hea47cd6c2017-10-13 18:09:58 -0700182}
183
184static int get_eob_cost(int eob, int seg_eob,
Jingning Han35deaa72017-10-26 15:36:30 -0700185 const LV_MAP_COEFF_COST *txb_costs, TX_TYPE tx_type) {
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800186 int eob_extra, dummy;
187 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
188 const int max_eob_pt = get_eob_pos_token(seg_eob, &dummy);
Dake Hea47cd6c2017-10-13 18:09:58 -0700189 int eob_cost = 0;
190
Dake Hea47cd6c2017-10-13 18:09:58 -0700191 for (int i = 1; i < max_eob_pt; i++) {
Jingning Han35deaa72017-10-26 15:36:30 -0700192 int eob_pos_ctx = av1_get_eob_pos_ctx(tx_type, i);
Dake Hea47cd6c2017-10-13 18:09:58 -0700193 eob_cost += txb_costs->eob_cost[eob_pos_ctx][eob_pt == i];
194 if (eob_pt == i) {
195 break;
196 }
197 }
198 if (k_eob_offset_bits[eob_pt] > 0) {
Angie Chiang7ab884e2017-10-18 15:57:12 -0700199 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
200 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
201 eob_cost += txb_costs->eob_extra_cost[eob_pt][bit];
202 for (int i = 1; i < k_eob_offset_bits[eob_pt]; i++) {
203 eob_shift = k_eob_offset_bits[eob_pt] - 1 - i;
204 bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700205 eob_cost += av1_cost_bit(128, bit);
206 }
207 }
208 return eob_cost;
209}
210
Linfeng Zhang1015a342017-10-24 16:20:41 -0700211static int get_coeff_cost(const tran_low_t qc, const int scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +0100212#if CONFIG_LV_MAP_MULTI
213 const int is_eob,
214#endif
Linfeng Zhang1015a342017-10-24 16:20:41 -0700215 const TxbInfo *const txb_info,
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -0800216 const LV_MAP_COEFF_COST *const txb_costs,
217 const int coeff_ctx);
Dake Hea47cd6c2017-10-13 18:09:58 -0700218
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800219static void get_dist_cost_stats(LevelDownStats *const stats, const int scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +0100220#if CONFIG_LV_MAP_MULTI
221 const int is_eob,
222#endif
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800223 const LV_MAP_COEFF_COST *const txb_costs,
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -0800224 const TxbInfo *const txb_info) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800225 const int16_t *const scan = txb_info->scan_order->scan;
Dake Hea47cd6c2017-10-13 18:09:58 -0700226 const int coeff_idx = scan[scan_idx];
227 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
Linfeng Zhang1015a342017-10-24 16:20:41 -0700228 const uint8_t *const levels = txb_info->levels;
Dake Hea47cd6c2017-10-13 18:09:58 -0700229 stats->new_eob = -1;
230 stats->update = 0;
231
232 const tran_low_t tqc = txb_info->tcoeff[coeff_idx];
233 const int dqv = txb_info->dequant[coeff_idx != 0];
Sarah Parker3d752092017-12-20 15:37:55 -0800234#if CONFIG_NEW_QUANT
235 const tran_low_t *nq_dequant_val = txb_info->nq_dequant_vals[coeff_idx != 0];
236#endif // CONFIG_NEW_QUANT
Dake Hea47cd6c2017-10-13 18:09:58 -0700237
Sarah Parker3d752092017-12-20 15:37:55 -0800238 const tran_low_t dqc = qcoeff_to_dqcoeff(qc,
239#if CONFIG_NEW_QUANT
240 nq_dequant_val,
241#endif // CONFIG_NEW_QUANT
242 dqv, txb_info->shift);
Dake Hea47cd6c2017-10-13 18:09:58 -0700243 const int64_t dqc_dist = get_coeff_dist(tqc, dqc, txb_info->shift);
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -0800244 const int coeff_ctx = get_nz_map_ctx(levels, coeff_idx, txb_info->bwl,
245#if CONFIG_LV_MAP_MULTI
246 txb_info->height, scan_idx, is_eob,
247#endif
248 txb_info->tx_size, txb_info->tx_type);
Linfeng Zhang960e7002017-12-11 13:46:40 -0800249 const int qc_cost = get_coeff_cost(qc, scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +0100250#if CONFIG_LV_MAP_MULTI
Linfeng Zhang960e7002017-12-11 13:46:40 -0800251 is_eob,
Ola Hugosson13892102017-11-06 08:01:44 +0100252#endif
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -0800253 txb_info, txb_costs, coeff_ctx);
Dake Hea47cd6c2017-10-13 18:09:58 -0700254
255 // distortion difference when coefficient is quantized to 0
Sarah Parker3d752092017-12-20 15:37:55 -0800256 const tran_low_t dqc0 = qcoeff_to_dqcoeff(0,
257#if CONFIG_NEW_QUANT
258 nq_dequant_val,
259#endif // CONFIG_NEW_QUANT
260 dqv, txb_info->shift);
Dake Hea47cd6c2017-10-13 18:09:58 -0700261 stats->dist0 = get_coeff_dist(tqc, dqc0, txb_info->shift);
262 stats->dist = dqc_dist - stats->dist0;
263 stats->rate = qc_cost;
264
265 if (qc == 0) {
266 return;
267 }
268 stats->rd = RDCOST(txb_info->rdmult, stats->rate, stats->dist);
269
270 stats->low_qc = get_lower_coeff(qc);
Dake He4d447692017-12-15 09:10:06 -0800271 int low_qc_cost;
Dake Hea47cd6c2017-10-13 18:09:58 -0700272
Ola Hugosson13892102017-11-06 08:01:44 +0100273#if CONFIG_LV_MAP_MULTI
Dake He4d447692017-12-15 09:10:06 -0800274 if (is_eob && stats->low_qc == 0) {
275 stats->low_qc = qc;
276 stats->low_dqc = dqc;
277 low_qc_cost = qc_cost;
278 stats->rd_low = stats->rd; // disable selection of low_qc in this case.
Ola Hugosson13892102017-11-06 08:01:44 +0100279 } else {
Dake He4d447692017-12-15 09:10:06 -0800280#else
281 {
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -0800282#endif
Dake He4d447692017-12-15 09:10:06 -0800283 stats->low_dqc = qcoeff_to_dqcoeff(stats->low_qc,
284#if CONFIG_NEW_QUANT
285 nq_dequant_val,
286#endif // CONFIG_NEW_QUANT
287 dqv, txb_info->shift);
288 const int64_t low_dqc_dist =
289 get_coeff_dist(tqc, stats->low_dqc, txb_info->shift);
290 low_qc_cost = get_coeff_cost(stats->low_qc, scan_idx,
291#if CONFIG_LV_MAP_MULTI
292 is_eob,
293#endif
294 txb_info, txb_costs, coeff_ctx);
295 stats->dist_low = low_dqc_dist - stats->dist0;
296 stats->rate_low = low_qc_cost;
297 stats->rd_low = RDCOST(txb_info->rdmult, stats->rate_low, stats->dist_low);
Ola Hugosson13892102017-11-06 08:01:44 +0100298 }
Dake He4d447692017-12-15 09:10:06 -0800299#if CONFIG_LV_MAP_MULTI
300 (void)levels;
301 const int coeff_ctx_temp =
302 get_nz_map_ctx(levels, coeff_idx, txb_info->bwl,
303#if CONFIG_LV_MAP_MULTI
304 txb_info->height, scan_idx, 1,
305#endif
306 txb_info->tx_size, txb_info->tx_type);
307 const int qc_eob_cost =
308 get_coeff_cost(qc, scan_idx, 1, txb_info, txb_costs, coeff_ctx_temp);
309 int64_t rd_eob = RDCOST(txb_info->rdmult, qc_eob_cost, stats->dist);
310 if (stats->low_qc != 0) {
311 const int low_qc_eob_cost = get_coeff_cost(
312 stats->low_qc, scan_idx, 1, txb_info, txb_costs, coeff_ctx_temp);
313 int64_t rd_eob_low =
314 RDCOST(txb_info->rdmult, low_qc_eob_cost, stats->dist_low);
315 rd_eob = (rd_eob > rd_eob_low) ? rd_eob_low : rd_eob;
316 }
317 stats->nz_rd = AOMMIN(stats->rd_low, stats->rd) - rd_eob;
Ola Hugosson13892102017-11-06 08:01:44 +0100318#else
Linfeng Zhang960e7002017-12-11 13:46:40 -0800319 const int is_nz = (stats->rd_low < stats->rd && stats->low_qc == 0) ? 0 : 1;
320 stats->nz_rate = txb_costs->nz_map_cost[coeff_ctx][is_nz];
Ola Hugosson13892102017-11-06 08:01:44 +0100321#endif
Dake Hea47cd6c2017-10-13 18:09:58 -0700322}
323
Linfeng Zhang1015a342017-10-24 16:20:41 -0700324static INLINE void update_qcoeff(const int coeff_idx, const tran_low_t qc,
325 const TxbInfo *const txb_info) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700326 txb_info->qcoeff[coeff_idx] = qc;
Linfeng Zhangd5647372017-12-05 17:06:07 -0800327 txb_info->levels[get_padded_idx(coeff_idx, txb_info->bwl)] =
Jingning Han5cb408e2017-11-17 14:43:39 -0800328 (uint8_t)clamp(abs(qc), 0, INT8_MAX);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700329}
330
331static INLINE void update_coeff(const int coeff_idx, const tran_low_t qc,
332 const TxbInfo *const txb_info) {
333 update_qcoeff(coeff_idx, qc, txb_info);
Dake Hea47cd6c2017-10-13 18:09:58 -0700334 const int dqv = txb_info->dequant[coeff_idx != 0];
Sarah Parker3d752092017-12-20 15:37:55 -0800335#if CONFIG_NEW_QUANT
336 const tran_low_t *nq_dequant_val = txb_info->nq_dequant_vals[coeff_idx != 0];
337#endif // CONFIG_NEW_QUANT
338 txb_info->dqcoeff[coeff_idx] = qcoeff_to_dqcoeff(qc,
339#if CONFIG_NEW_QUANT
340 nq_dequant_val,
341#endif // CONFIG_NEW_QUANT
342 dqv, txb_info->shift);
Dake Hea47cd6c2017-10-13 18:09:58 -0700343}
344
Linfeng Zhang1015a342017-10-24 16:20:41 -0700345static INLINE void av1_txb_init_levels(const tran_low_t *const coeff,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700346 const int width, const int height,
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700347 uint8_t *const levels) {
348 const int stride = width + TX_PAD_HOR;
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700349 uint8_t *ls = levels;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700350
351 memset(levels - TX_PAD_TOP * stride, 0,
352 sizeof(*levels) * TX_PAD_TOP * stride);
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700353 memset(levels + stride * height, 0,
354 sizeof(*levels) * (TX_PAD_BOTTOM * stride + TX_PAD_END));
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700355
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700356 for (int i = 0; i < height; i++) {
357 for (int j = 0; j < width; j++) {
Jingning Han5cb408e2017-11-17 14:43:39 -0800358 *ls++ = (uint8_t)clamp(abs(coeff[i * width + j]), 0, INT8_MAX);
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700359 }
360 for (int j = 0; j < TX_PAD_HOR; j++) {
361 *ls++ = 0;
362 }
Linfeng Zhang1015a342017-10-24 16:20:41 -0700363 }
364}
365
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800366void av1_get_nz_map_contexts_c(const uint8_t *const levels,
367 const int16_t *const scan, const uint16_t eob,
368 const TX_SIZE tx_size, const TX_TYPE tx_type,
369 int8_t *const coeff_contexts) {
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800370 const int bwl = get_txb_bwl(tx_size);
371#if CONFIG_LV_MAP_MULTI
372 const int height = get_txb_high(tx_size);
373#endif
374 for (int i = 0; i < eob; ++i) {
375 const int pos = scan[i];
376 coeff_contexts[pos] = get_nz_map_ctx(levels, pos, bwl,
377#if CONFIG_LV_MAP_MULTI
378 height, i, i == eob - 1,
379#endif
380 tx_size, tx_type);
381 }
382}
383
Angie Chiang80b82262017-02-24 11:39:47 -0800384void av1_write_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCKD *xd,
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500385 aom_writer *w, int blk_row, int blk_col, int plane,
386 TX_SIZE tx_size, const tran_low_t *tcoeff,
Jingning Han7eab9ff2017-07-06 10:12:54 -0700387 uint16_t eob, TXB_CTX *txb_ctx) {
Angie Chiang80b82262017-02-24 11:39:47 -0800388 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiangcea11f22017-02-24 12:30:40 -0800389 const PLANE_TYPE plane_type = get_plane_type(plane);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -0800390 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Jingning Han19b5c8f2017-07-06 15:10:12 -0700391 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500392 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -0700393 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800394 const int16_t *const scan = scan_order->scan;
Urvang Joshi80893152017-10-27 11:51:14 -0700395 const int seg_eob = av1_get_max_eob(tx_size);
Angie Chiang80b82262017-02-24 11:39:47 -0800396 int c;
Angie Chianga9ba58e2017-12-01 19:22:43 -0800397 const int bwl = get_txb_bwl(tx_size);
398 const int width = get_txb_wide(tx_size);
399 const int height = get_txb_high(tx_size);
Linfeng Zhang848f7bc2017-10-31 15:26:07 -0700400 int update_eob = -1;
Jingning Han41c7f442017-09-05 14:54:00 -0700401 FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700402 uint8_t levels_buf[TX_PAD_2D];
403 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -0800404 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800405 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Angie Chiang80b82262017-02-24 11:39:47 -0800406
Jingning Han94cea4a2017-09-30 14:13:23 -0700407 aom_write_bin(w, eob == 0,
408 ec_ctx->txb_skip_cdf[txs_ctx][txb_ctx->txb_skip_ctx], 2);
Angie Chiang5f0cb5e2017-12-11 16:07:50 -0800409#if CONFIG_TXK_SEL
Angie Chianga3f7d2e2017-12-07 19:51:14 -0800410 if (plane == 0 && eob == 0) {
411 assert(tx_type == DCT_DCT);
412 }
Angie Chiang5f0cb5e2017-12-11 16:07:50 -0800413#endif
Angie Chiang80b82262017-02-24 11:39:47 -0800414 if (eob == 0) return;
Linfeng Zhangce065ca2017-10-17 16:49:30 -0700415
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700416 av1_txb_init_levels(tcoeff, width, height, levels);
Linfeng Zhangce065ca2017-10-17 16:49:30 -0700417
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700418#if CONFIG_TXK_SEL
Debargha Mukherjee3ebb0d02017-12-14 05:05:18 -0800419 av1_write_tx_type(cm, xd, blk_row, blk_col, plane, tx_size, w);
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700420#endif
Angie Chiang80b82262017-02-24 11:39:47 -0800421
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800422 int eob_extra, dummy;
423 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
424 const int max_eob_pt = get_eob_pos_token(seg_eob, &dummy);
Dake Hea47cd6c2017-10-13 18:09:58 -0700425
Dake Hea47cd6c2017-10-13 18:09:58 -0700426 for (int i = 1; i < max_eob_pt; i++) {
Jingning Han35deaa72017-10-26 15:36:30 -0700427 int eob_pos_ctx = av1_get_eob_pos_ctx(tx_type, i);
Dake Hea47cd6c2017-10-13 18:09:58 -0700428
429 aom_write_bin(w, eob_pt == i,
430 ec_ctx->eob_flag_cdf[txs_ctx][plane_type][eob_pos_ctx], 2);
431 // aom_write_symbol(w, eob_pt == i,
432 // ec_ctx->eob_flag_cdf[AOMMIN(txs_ctx,3)][plane_type][eob_pos_ctx], 2);
433 if (eob_pt == i) {
434 break;
435 }
436 }
437
438 if (k_eob_offset_bits[eob_pt] > 0) {
Angie Chiang7ab884e2017-10-18 15:57:12 -0700439 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
440 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
441 aom_write_bin(w, bit, ec_ctx->eob_extra_cdf[txs_ctx][plane_type][eob_pt],
442 2);
443 for (int i = 1; i < k_eob_offset_bits[eob_pt]; i++) {
444 eob_shift = k_eob_offset_bits[eob_pt] - 1 - i;
445 bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700446 aom_write_bit(w, bit);
Dake Hea47cd6c2017-10-13 18:09:58 -0700447 }
448 }
Dake He03a32922017-10-31 08:06:45 -0700449
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800450 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_type, coeff_contexts);
451
452 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800453 const int pos = scan[c];
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800454 const int coeff_ctx = coeff_contexts[pos];
455 const tran_low_t v = tcoeff[pos];
Dake He03a32922017-10-31 08:06:45 -0700456
Ola Hugosson13892102017-11-06 08:01:44 +0100457#if CONFIG_LV_MAP_MULTI
Dake He3fe369c2017-11-16 17:56:44 -0800458 if (c == eob - 1) {
459 aom_write_symbol(
460 w, AOMMIN(abs(v), 3) - 1,
Dake He4d447692017-12-15 09:10:06 -0800461 ec_ctx->coeff_base_eob_cdf[txs_ctx][plane_type][coeff_ctx], 3);
Dake He3fe369c2017-11-16 17:56:44 -0800462 } else {
463 aom_write_symbol(w, AOMMIN(abs(v), 3),
464 ec_ctx->coeff_base_cdf[txs_ctx][plane_type][coeff_ctx],
465 4);
466 }
Dake He4d447692017-12-15 09:10:06 -0800467
Ola Hugosson13892102017-11-06 08:01:44 +0100468#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800469 const int is_nz = (v != 0);
Dake He03a32922017-10-31 08:06:45 -0700470
471 if (c < eob - 1) {
472 aom_write_bin(w, is_nz,
473 ec_ctx->nz_map_cdf[txs_ctx][plane_type][coeff_ctx], 2);
474 }
475 if (is_nz) {
476 const int level = abs(v);
477 int k;
478 for (k = 0; k < NUM_BASE_LEVELS; ++k) {
479 int is_k = (level > (k + 1));
480 int ctx = coeff_ctx;
481 aom_write_bin(w, is_k,
482 ec_ctx->coeff_base_cdf[txs_ctx][plane_type][k][ctx], 2);
483 if (is_k == 0) break;
484 }
485 }
Ola Hugosson13892102017-11-06 08:01:44 +0100486#endif
Dake He03a32922017-10-31 08:06:45 -0700487 }
488 update_eob = eob - 1;
Angie Chiang80b82262017-02-24 11:39:47 -0800489
Dake He43edb762017-10-26 10:29:46 -0700490 // Loop to code all signs in the transform block,
491 // starting with the sign of DC (if applicable)
492 for (c = 0; c < eob; ++c) {
Linfeng Zhang1015a342017-10-24 16:20:41 -0700493 const tran_low_t v = tcoeff[scan[c]];
494 const tran_low_t level = abs(v);
495 const int sign = (v < 0) ? 1 : 0;
Dake He43edb762017-10-26 10:29:46 -0700496 if (level == 0) continue;
497
498 if (c == 0) {
499#if LV_MAP_PROB
500 aom_write_bin(w, sign,
501 ec_ctx->dc_sign_cdf[plane_type][txb_ctx->dc_sign_ctx], 2);
502#else
503 aom_write(w, sign, ec_ctx->dc_sign[plane_type][txb_ctx->dc_sign_ctx]);
504#endif
505 } else {
506 aom_write_bit(w, sign);
507 }
508 }
509
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800510 if (update_eob >= 0) {
Dake He7d01ab52017-11-24 17:53:28 -0800511#if !CONFIG_LV_MAP_MULTI
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800512 av1_get_br_level_counts(levels, width, height, level_counts);
Dake He7d01ab52017-11-24 17:53:28 -0800513#endif
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800514 for (c = update_eob; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800515 const int pos = scan[c];
516 const tran_low_t level = abs(tcoeff[pos]);
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800517 int idx;
518 int ctx;
Angie Chiang80b82262017-02-24 11:39:47 -0800519
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800520 if (level <= NUM_BASE_LEVELS) continue;
Angie Chiang80b82262017-02-24 11:39:47 -0800521
Dake He7d01ab52017-11-24 17:53:28 -0800522// level is above 1.
523#if !CONFIG_LV_MAP_MULTI
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800524 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -0800525#endif
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800526 const int base_range = level - 1 - NUM_BASE_LEVELS;
Ola Hugossone72a2092017-11-12 09:11:53 +0100527#if CONFIG_LV_MAP_MULTI
Dake He7d01ab52017-11-24 17:53:28 -0800528#if USE_CAUSAL_BR_CTX
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800529 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos], tx_type);
Dake He7d01ab52017-11-24 17:53:28 -0800530
531#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800532 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -0800533#endif
Ola Hugossone72a2092017-11-12 09:11:53 +0100534 for (idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800535 const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
Dake Hee2d8f182017-12-14 13:28:00 -0800536 aom_write_symbol(w, k,
537#if 0
Dake He7d01ab52017-11-24 17:53:28 -0800538 ec_ctx->coeff_br_cdf[AOMMIN(txs_ctx, TX_16X16)][plane_type][ctx],
Dake Hee2d8f182017-12-14 13:28:00 -0800539#else
540 ec_ctx->coeff_br_cdf[AOMMIN(txs_ctx, TX_32X32)]
541 [plane_type][ctx],
542#endif
543 BR_CDF_SIZE);
Ola Hugossone72a2092017-11-12 09:11:53 +0100544 if (k < BR_CDF_SIZE - 1) break;
545 }
546 if (base_range < COEFF_BASE_RANGE) continue;
547#else
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800548 int br_set_idx = 0;
549 int br_base = 0;
550 int br_offset = 0;
Jingning Han87b01b52017-08-31 12:07:20 -0700551
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800552 if (base_range >= COEFF_BASE_RANGE)
553 br_set_idx = BASE_RANGE_SETS;
554 else
555 br_set_idx = coeff_to_br_index[base_range];
Jingning Han87b01b52017-08-31 12:07:20 -0700556
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800557 for (idx = 0; idx < BASE_RANGE_SETS; ++idx) {
558 aom_write_bin(w, idx == br_set_idx,
559 ec_ctx->coeff_br_cdf[txs_ctx][plane_type][idx][ctx], 2);
560 if (idx == br_set_idx) {
561 br_base = br_index_to_coeff[br_set_idx];
562 br_offset = base_range - br_base;
563 int extra_bits = (1 << br_extra_bits[idx]) - 1;
564 for (int tok = 0; tok < extra_bits; ++tok) {
565 if (tok == br_offset) {
566 aom_write_bin(w, 1,
567 ec_ctx->coeff_lps_cdf[txs_ctx][plane_type][ctx], 2);
568 break;
569 }
570 aom_write_bin(w, 0, ec_ctx->coeff_lps_cdf[txs_ctx][plane_type][ctx],
Jingning Han94cea4a2017-09-30 14:13:23 -0700571 2);
Jingning Han87b01b52017-08-31 12:07:20 -0700572 }
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800573 // aom_write_literal(w, br_offset, br_extra_bits[idx]);
574 break;
Jingning Han87b01b52017-08-31 12:07:20 -0700575 }
Jingning Han87b01b52017-08-31 12:07:20 -0700576 }
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800577
578 if (br_set_idx < BASE_RANGE_SETS) continue;
Ola Hugossone72a2092017-11-12 09:11:53 +0100579#endif
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800580 // use 0-th order Golomb code to handle the residual level.
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800581 write_golomb(w,
582 abs(tcoeff[pos]) - COEFF_BASE_RANGE - 1 - NUM_BASE_LEVELS);
Jingning Han87b01b52017-08-31 12:07:20 -0700583 }
Angie Chiang80b82262017-02-24 11:39:47 -0800584 }
585}
Angie Chiang47c72182017-02-27 14:30:38 -0800586
Angie Chiang140b3332017-12-12 17:29:25 -0800587typedef struct encode_txb_args {
588 const AV1_COMMON *cm;
589 MACROBLOCK *x;
590 aom_writer *w;
591} ENCODE_TXB_ARGS;
592
593static void av1_write_coeffs_txb_wrap(int plane, int block, int blk_row,
594 int blk_col, BLOCK_SIZE plane_bsize,
595 TX_SIZE tx_size, void *arg) {
596 (void)plane_bsize;
597 ENCODE_TXB_ARGS *enc_args = (ENCODE_TXB_ARGS *)arg;
598 const AV1_COMMON *cm = enc_args->cm;
599 MACROBLOCK *x = enc_args->x;
Angie Chiangc8af6112017-03-16 16:11:22 -0700600 MACROBLOCKD *xd = &x->e_mbd;
Angie Chiang140b3332017-12-12 17:29:25 -0800601 aom_writer *w = enc_args->w;
602 tran_low_t *tcoeff = BLOCK_OFFSET(x->mbmi_ext->tcoeff[plane], block);
603 uint16_t eob = x->mbmi_ext->eobs[plane][block];
604 TXB_CTX txb_ctx = { x->mbmi_ext->txb_skip_ctx[plane][block],
605 x->mbmi_ext->dc_sign_ctx[plane][block] };
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500606 av1_write_coeffs_txb(cm, xd, w, blk_row, blk_col, plane, tx_size, tcoeff, eob,
607 &txb_ctx);
Angie Chiang140b3332017-12-12 17:29:25 -0800608}
609
610void av1_write_coeffs_mb(const AV1_COMMON *const cm, MACROBLOCK *x,
611 aom_writer *w, int plane, BLOCK_SIZE bsize) {
612 ENCODE_TXB_ARGS enc_args = { cm, x, w };
613 MACROBLOCKD *xd = &x->e_mbd;
614 av1_foreach_transformed_block_in_plane(xd, bsize, plane,
615 av1_write_coeffs_txb_wrap, &enc_args);
Angie Chiangc8af6112017-03-16 16:11:22 -0700616}
617
Angie Chiang488f9212017-05-30 12:46:26 -0700618static INLINE int get_br_cost(tran_low_t abs_qc, int ctx,
Angie Chiang26d3e452017-09-29 17:40:02 -0700619 const int *coeff_lps) {
Angie Chiang488f9212017-05-30 12:46:26 -0700620 const tran_low_t min_level = 1 + NUM_BASE_LEVELS;
621 const tran_low_t max_level = 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE;
Jingning Handfd72322017-08-09 14:04:12 -0700622 (void)ctx;
Angie Chiang488f9212017-05-30 12:46:26 -0700623 if (abs_qc >= min_level) {
Angie Chiang488f9212017-05-30 12:46:26 -0700624 if (abs_qc >= max_level)
Jingning Han772dee32017-09-15 08:53:18 -0700625 return coeff_lps[COEFF_BASE_RANGE]; // COEFF_BASE_RANGE * cost0;
Angie Chiang488f9212017-05-30 12:46:26 -0700626 else
Jingning Han772dee32017-09-15 08:53:18 -0700627 return coeff_lps[(abs_qc - min_level)]; // * cost0 + cost1;
Angie Chiang488f9212017-05-30 12:46:26 -0700628 } else {
629 return 0;
630 }
631}
632
633static INLINE int get_base_cost(tran_low_t abs_qc, int ctx,
Jingning Handfd72322017-08-09 14:04:12 -0700634 const int coeff_base[2], int base_idx) {
Angie Chiang488f9212017-05-30 12:46:26 -0700635 const int level = base_idx + 1;
Jingning Handfd72322017-08-09 14:04:12 -0700636 (void)ctx;
Angie Chiang488f9212017-05-30 12:46:26 -0700637 if (abs_qc < level)
638 return 0;
639 else
Jingning Handfd72322017-08-09 14:04:12 -0700640 return coeff_base[abs_qc == level];
Angie Chiang488f9212017-05-30 12:46:26 -0700641}
642
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800643// Note: don't call this function when eob is 0.
644int av1_cost_coeffs_txb(const AV1_COMMON *const cm, const MACROBLOCK *x,
645 const int plane, const int blk_row, const int blk_col,
646 const int block, const TX_SIZE tx_size,
647 const TXB_CTX *const txb_ctx) {
648 const MACROBLOCKD *const xd = &x->e_mbd;
649 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Angie Chiang47c72182017-02-27 14:30:38 -0800650 const PLANE_TYPE plane_type = get_plane_type(plane);
Jingning Han19b5c8f2017-07-06 15:10:12 -0700651 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500652 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800653 const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Angie Chiang47c72182017-02-27 14:30:38 -0800654 const struct macroblock_plane *p = &x->plane[plane];
655 const int eob = p->eobs[block];
656 const tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
657 int c, cost;
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800658 const int txb_skip_ctx = txb_ctx->txb_skip_ctx;
Angie Chianga9ba58e2017-12-01 19:22:43 -0800659 const int bwl = get_txb_bwl(tx_size);
660 const int width = get_txb_wide(tx_size);
661 const int height = get_txb_high(tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -0700662 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800663 const int16_t *const scan = scan_order->scan;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700664 uint8_t levels_buf[TX_PAD_2D];
665 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -0800666 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800667 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800668 const LV_MAP_COEFF_COST *const coeff_costs =
669 &x->coeff_costs[txs_ctx][plane_type];
Angie Chiang47c72182017-02-27 14:30:38 -0800670
Jingning Handfd72322017-08-09 14:04:12 -0700671 cost = coeff_costs->txb_skip_cost[txb_skip_ctx][0];
Angie Chiang47c72182017-02-27 14:30:38 -0800672
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700673 av1_txb_init_levels(qcoeff, width, height, levels);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700674
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700675#if CONFIG_TXK_SEL
Yue Chenb23d00a2017-07-28 17:01:21 -0700676 cost += av1_tx_type_cost(cm, x, xd, mbmi->sb_type, plane, tx_size, tx_type);
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700677#endif
Angie Chiang05917872017-04-15 12:28:56 -0700678
Urvang Joshi80893152017-10-27 11:51:14 -0700679 const int seg_eob = av1_get_max_eob(tx_size);
Jingning Han35deaa72017-10-26 15:36:30 -0700680 int eob_cost = get_eob_cost(eob, seg_eob, coeff_costs, tx_type);
Dake He7d01ab52017-11-24 17:53:28 -0800681#if !CONFIG_LV_MAP_MULTI
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800682 av1_get_br_level_counts(levels, width, height, level_counts);
Dake He7d01ab52017-11-24 17:53:28 -0800683#endif
Dake Hea47cd6c2017-10-13 18:09:58 -0700684 cost += eob_cost;
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800685
686 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_type, coeff_contexts);
687
Dake Hea47cd6c2017-10-13 18:09:58 -0700688 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800689 const int pos = scan[c];
690 const tran_low_t v = qcoeff[pos];
691 const int is_nz = (v != 0);
692 const int level = abs(v);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800693 const int coeff_ctx = coeff_contexts[pos];
Ola Hugosson13892102017-11-06 08:01:44 +0100694#if CONFIG_LV_MAP_MULTI
Dake He3fe369c2017-11-16 17:56:44 -0800695 if (c == eob - 1) {
Dake He4d447692017-12-15 09:10:06 -0800696 cost += coeff_costs->base_eob_cost[coeff_ctx][AOMMIN(level, 3) - 1];
Dake He3fe369c2017-11-16 17:56:44 -0800697 } else {
698 cost += coeff_costs->base_cost[coeff_ctx][AOMMIN(level, 3)];
699 }
Linfeng Zhang1757fb62017-12-11 10:47:59 -0800700#else // CONFIG_LV_MAP_MULTI
Dake Hea47cd6c2017-10-13 18:09:58 -0700701 if (c < eob - 1) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700702 cost += coeff_costs->nz_map_cost[coeff_ctx][is_nz];
703 }
Ola Hugosson13892102017-11-06 08:01:44 +0100704#endif // CONFIG_LV_MAP_MULTI
Dake Hea47cd6c2017-10-13 18:09:58 -0700705
706 if (is_nz) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700707 int sign = (v < 0) ? 1 : 0;
708
709 // sign bit cost
710 if (c == 0) {
711 int dc_sign_ctx = txb_ctx->dc_sign_ctx;
712 cost += coeff_costs->dc_sign_cost[dc_sign_ctx][sign];
713 } else {
714 cost += av1_cost_bit(128, sign);
715 }
Ola Hugosson13892102017-11-06 08:01:44 +0100716#if !CONFIG_LV_MAP_MULTI
Dake He03a32922017-10-31 08:06:45 -0700717 int k;
718 for (k = 0; k < NUM_BASE_LEVELS; ++k) {
719 int is_k = (level > (k + 1));
720 int ctx = coeff_ctx;
721 // get_base_ctx_from_b(c, k, b0, b1, b2);
722 cost += coeff_costs->base_cost[k][ctx][is_k];
723 if (is_k == 0) break;
724 }
Ola Hugosson13892102017-11-06 08:01:44 +0100725#endif // CONFIG_LV_MAP_MULTI
Dake Hea47cd6c2017-10-13 18:09:58 -0700726 if (level > NUM_BASE_LEVELS) {
727 int ctx;
Dake He7d01ab52017-11-24 17:53:28 -0800728#if CONFIG_LV_MAP_MULTI && USE_CAUSAL_BR_CTX
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800729 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos], tx_type);
Dake He7d01ab52017-11-24 17:53:28 -0800730#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800731 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -0800732#endif
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800733 const int base_range = level - 1 - NUM_BASE_LEVELS;
Dake Hea47cd6c2017-10-13 18:09:58 -0700734 if (base_range < COEFF_BASE_RANGE) {
735 cost += coeff_costs->lps_cost[ctx][base_range];
736 } else {
737 cost += coeff_costs->lps_cost[ctx][COEFF_BASE_RANGE];
738 }
739
Dake Hea47cd6c2017-10-13 18:09:58 -0700740 if (level >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
741 // residual cost
742 int r = level - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
743 int ri = r;
744 int length = 0;
745
746 while (ri) {
747 ri >>= 1;
748 ++length;
749 }
750
751 for (ri = 0; ri < length - 1; ++ri) cost += av1_cost_bit(128, 0);
752
753 for (ri = length - 1; ri >= 0; --ri)
754 cost += av1_cost_bit(128, (r >> ri) & 0x01);
755 }
756 }
757 }
758 }
Angie Chiang47c72182017-02-27 14:30:38 -0800759 return cost;
760}
Angie Chiang0397eda2017-03-15 16:57:14 -0700761
Angie Chiang2affb3b2017-05-30 15:23:51 -0700762static INLINE int has_base(tran_low_t qc, int base_idx) {
763 const int level = base_idx + 1;
764 return abs(qc) >= level;
765}
766
Angie Chiang2affb3b2017-05-30 15:23:51 -0700767static INLINE int has_br(tran_low_t qc) {
768 return abs(qc) >= 1 + NUM_BASE_LEVELS;
769}
770
Angie Chiang488f9212017-05-30 12:46:26 -0700771static INLINE int get_sign_bit_cost(tran_low_t qc, int coeff_idx,
Jingning Handfd72322017-08-09 14:04:12 -0700772 const int (*dc_sign_cost)[2],
Angie Chiang488f9212017-05-30 12:46:26 -0700773 int dc_sign_ctx) {
774 const int sign = (qc < 0) ? 1 : 0;
775 // sign bit cost
776 if (coeff_idx == 0) {
Jingning Handfd72322017-08-09 14:04:12 -0700777 return dc_sign_cost[dc_sign_ctx][sign];
Angie Chiang488f9212017-05-30 12:46:26 -0700778 } else {
779 return av1_cost_bit(128, sign);
780 }
781}
782static INLINE int get_golomb_cost(int abs_qc) {
783 if (abs_qc >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
784 // residual cost
785 int r = abs_qc - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
786 int ri = r;
787 int length = 0;
788
789 while (ri) {
790 ri >>= 1;
791 ++length;
792 }
793
794 return av1_cost_literal(2 * length - 1);
795 } else {
796 return 0;
797 }
798}
799
Angie Chiang2affb3b2017-05-30 15:23:51 -0700800void gen_txb_cache(TxbCache *txb_cache, TxbInfo *txb_info) {
Angie Chiang481c01f2017-08-15 16:24:30 -0700801 // gen_nz_count_arr
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800802 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang481c01f2017-08-15 16:24:30 -0700803 const int bwl = txb_info->bwl;
804 const int height = txb_info->height;
Linfeng Zhang72e0b3f2017-10-18 13:32:12 -0700805 const tran_low_t *const qcoeff = txb_info->qcoeff;
Linfeng Zhangb6957c22017-10-25 13:17:28 -0700806 const uint8_t *const levels = txb_info->levels;
Angie Chiangdef11252017-08-18 14:37:32 -0700807 const BASE_CTX_TABLE *base_ctx_table =
808 txb_info->coeff_ctx_table->base_ctx_table;
Angie Chiang481c01f2017-08-15 16:24:30 -0700809 for (int c = 0; c < txb_info->eob; ++c) {
810 const int coeff_idx = scan[c]; // raster order
811 const int row = coeff_idx >> bwl;
812 const int col = coeff_idx - (row << bwl);
Jingning Han3422ac12017-10-25 20:37:53 -0700813
Linfeng Zhangf91f3ca2017-12-05 11:22:41 -0800814 txb_cache->nz_count_arr[coeff_idx] =
Linfeng Zhangd5647372017-12-05 17:06:07 -0800815 get_nz_count(levels + get_padded_idx(coeff_idx, bwl), bwl,
Linfeng Zhangf91f3ca2017-12-05 11:22:41 -0800816 tx_type_to_class[txb_info->tx_type]);
Dake Hea47cd6c2017-10-13 18:09:58 -0700817
Yaowu Xu102ef812017-12-12 11:31:03 -0800818 txb_cache->nz_ctx_arr[coeff_idx] =
819 get_nz_map_ctx_from_stats(0, coeff_idx, bwl, txb_info->tx_size,
820 tx_type_to_class[txb_info->tx_type]);
Angie Chiang481c01f2017-08-15 16:24:30 -0700821
822 // gen_base_count_mag_arr
823 if (!has_base(qcoeff[coeff_idx], 0)) continue;
824 int *base_mag = txb_cache->base_mag_arr[coeff_idx];
Angie Chiang9cde59f2017-08-16 15:24:55 -0700825 int count[NUM_BASE_LEVELS];
826 get_base_count_mag(base_mag, count, qcoeff, bwl, height, row, col);
Angie Chiang481c01f2017-08-15 16:24:30 -0700827
828 for (int i = 0; i < NUM_BASE_LEVELS; ++i) {
Angie Chiang9cde59f2017-08-16 15:24:55 -0700829 if (!has_base(qcoeff[coeff_idx], i)) break;
830 txb_cache->base_count_arr[i][coeff_idx] = count[i];
Angie Chiang481c01f2017-08-15 16:24:30 -0700831 const int level = i + 1;
Angie Chiang9cde59f2017-08-16 15:24:55 -0700832 txb_cache->base_ctx_arr[i][coeff_idx] =
Angie Chiangdef11252017-08-18 14:37:32 -0700833 base_ctx_table[row != 0][col != 0][base_mag[0] > level][count[i]];
Angie Chiang481c01f2017-08-15 16:24:30 -0700834 }
835
836 // gen_br_count_mag_arr
837 if (!has_br(qcoeff[coeff_idx])) continue;
838 int *br_count = txb_cache->br_count_arr + coeff_idx;
839 int *br_mag = txb_cache->br_mag_arr[coeff_idx];
Angie Chiangea8183b2017-08-17 14:36:35 -0700840 *br_count = get_br_count_mag(br_mag, qcoeff, bwl, height, row, col,
841 NUM_BASE_LEVELS);
Angie Chiang481c01f2017-08-15 16:24:30 -0700842 txb_cache->br_ctx_arr[coeff_idx] =
843 get_br_ctx_from_count_mag(row, col, *br_count, br_mag[0]);
844 }
Angie Chiang2affb3b2017-05-30 15:23:51 -0700845}
846
Jingning Handfd72322017-08-09 14:04:12 -0700847static INLINE const int *get_level_prob(int level, int coeff_idx,
848 const TxbCache *txb_cache,
849 const LV_MAP_COEFF_COST *txb_costs) {
Ola Hugosson13892102017-11-06 08:01:44 +0100850#if CONFIG_LV_MAP_MULTI
851 if (level < 1 + NUM_BASE_LEVELS) {
852 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
853 return &txb_costs->base_cost[ctx][level];
854#else
Angie Chiang7afbba42017-05-30 15:59:15 -0700855 if (level == 0) {
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700856 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700857 return txb_costs->nz_map_cost[ctx];
Angie Chiang7afbba42017-05-30 15:59:15 -0700858 } else if (level >= 1 && level < 1 + NUM_BASE_LEVELS) {
859 const int idx = level - 1;
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700860 const int ctx = txb_cache->base_ctx_arr[idx][coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700861 return txb_costs->base_cost[idx][ctx];
Ola Hugosson13892102017-11-06 08:01:44 +0100862#endif
Angie Chiang7afbba42017-05-30 15:59:15 -0700863 } else if (level >= 1 + NUM_BASE_LEVELS &&
864 level < 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700865 const int ctx = txb_cache->br_ctx_arr[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700866 return txb_costs->lps_cost[ctx];
Angie Chiang7afbba42017-05-30 15:59:15 -0700867 } else if (level >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Ola Hugosson13892102017-11-06 08:01:44 +0100868 // printf("get_level_prob does not support golomb\n");
Angie Chiang7afbba42017-05-30 15:59:15 -0700869 assert(0);
870 return 0;
871 } else {
872 assert(0);
873 return 0;
874 }
875}
876
Angie Chiangd19969e2017-05-30 18:02:33 -0700877static INLINE void update_mag_arr(int *mag_arr, int abs_qc) {
878 if (mag_arr[0] == abs_qc) {
879 mag_arr[1] -= 1;
880 assert(mag_arr[1] >= 0);
881 }
882}
883
Angie Chianga530ef42017-05-30 16:32:36 -0700884static INLINE int get_mag_from_mag_arr(const int *mag_arr) {
885 int mag;
886 if (mag_arr[1] > 0) {
887 mag = mag_arr[0];
888 } else if (mag_arr[0] > 0) {
889 mag = mag_arr[0] - 1;
890 } else {
891 // no neighbor
892 assert(mag_arr[0] == 0 && mag_arr[1] == 0);
893 mag = 0;
894 }
895 return mag;
896}
897
898static int neighbor_level_down_update(int *new_count, int *new_mag, int count,
899 const int *mag, int coeff_idx,
900 tran_low_t abs_nb_coeff, int nb_coeff_idx,
901 int level, const TxbInfo *txb_info) {
902 *new_count = count;
903 *new_mag = get_mag_from_mag_arr(mag);
904
905 int update = 0;
906 // check if br_count changes
907 if (abs_nb_coeff == level) {
908 update = 1;
909 *new_count -= 1;
910 assert(*new_count >= 0);
911 }
912 const int row = coeff_idx >> txb_info->bwl;
913 const int col = coeff_idx - (row << txb_info->bwl);
914 const int nb_row = nb_coeff_idx >> txb_info->bwl;
915 const int nb_col = nb_coeff_idx - (nb_row << txb_info->bwl);
916
917 // check if mag changes
918 if (nb_row >= row && nb_col >= col) {
919 if (abs_nb_coeff == mag[0]) {
920 assert(mag[1] > 0);
921 if (mag[1] == 1) {
922 // the nb is the only qc with max mag
923 *new_mag -= 1;
924 assert(*new_mag >= 0);
925 update = 1;
926 }
927 }
928 }
929 return update;
930}
931
932static int try_neighbor_level_down_br(int coeff_idx, int nb_coeff_idx,
933 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700934 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -0700935 const TxbInfo *txb_info) {
936 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
937 const tran_low_t abs_qc = abs(qc);
938 const int level = NUM_BASE_LEVELS + 1;
939 if (abs_qc < level) return 0;
940
941 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
942 const tran_low_t abs_nb_coeff = abs(nb_coeff);
943 const int count = txb_cache->br_count_arr[coeff_idx];
944 const int *mag = txb_cache->br_mag_arr[coeff_idx];
945 int new_count;
946 int new_mag;
947 const int update =
948 neighbor_level_down_update(&new_count, &new_mag, count, mag, coeff_idx,
949 abs_nb_coeff, nb_coeff_idx, level, txb_info);
950 if (update) {
951 const int row = coeff_idx >> txb_info->bwl;
952 const int col = coeff_idx - (row << txb_info->bwl);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700953 const int ctx = txb_cache->br_ctx_arr[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700954 const int org_cost = get_br_cost(abs_qc, ctx, txb_costs->lps_cost[ctx]);
Angie Chianga530ef42017-05-30 16:32:36 -0700955
956 const int new_ctx = get_br_ctx_from_count_mag(row, col, new_count, new_mag);
Jingning Handfd72322017-08-09 14:04:12 -0700957 const int new_cost =
958 get_br_cost(abs_qc, new_ctx, txb_costs->lps_cost[new_ctx]);
Angie Chianga530ef42017-05-30 16:32:36 -0700959 const int cost_diff = -org_cost + new_cost;
960 return cost_diff;
961 } else {
962 return 0;
963 }
964}
965
966static int try_neighbor_level_down_base(int coeff_idx, int nb_coeff_idx,
967 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700968 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -0700969 const TxbInfo *txb_info) {
Ola Hugosson13892102017-11-06 08:01:44 +0100970#if CONFIG_LV_MAP_MULTI
971 // TODO(olah): not implemented yet
972 (void)coeff_idx;
973 (void)nb_coeff_idx;
974 (void)txb_cache;
975 (void)txb_costs;
976 (void)txb_info;
977 return 0;
978#else
Angie Chianga530ef42017-05-30 16:32:36 -0700979 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
980 const tran_low_t abs_qc = abs(qc);
Angie Chiangdef11252017-08-18 14:37:32 -0700981 const BASE_CTX_TABLE *base_ctx_table =
982 txb_info->coeff_ctx_table->base_ctx_table;
Angie Chianga530ef42017-05-30 16:32:36 -0700983
984 int cost_diff = 0;
985 for (int base_idx = 0; base_idx < NUM_BASE_LEVELS; ++base_idx) {
986 const int level = base_idx + 1;
987 if (abs_qc < level) continue;
988
989 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
990 const tran_low_t abs_nb_coeff = abs(nb_coeff);
991
992 const int count = txb_cache->base_count_arr[base_idx][coeff_idx];
993 const int *mag = txb_cache->base_mag_arr[coeff_idx];
994 int new_count;
995 int new_mag;
996 const int update =
997 neighbor_level_down_update(&new_count, &new_mag, count, mag, coeff_idx,
998 abs_nb_coeff, nb_coeff_idx, level, txb_info);
999 if (update) {
1000 const int row = coeff_idx >> txb_info->bwl;
1001 const int col = coeff_idx - (row << txb_info->bwl);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001002 const int ctx = txb_cache->base_ctx_arr[base_idx][coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -07001003 const int org_cost = get_base_cost(
1004 abs_qc, ctx, txb_costs->base_cost[base_idx][ctx], base_idx);
Angie Chianga530ef42017-05-30 16:32:36 -07001005
1006 const int new_ctx =
Angie Chiangdef11252017-08-18 14:37:32 -07001007 base_ctx_table[row != 0][col != 0][new_mag > level][new_count];
Jingning Handfd72322017-08-09 14:04:12 -07001008 const int new_cost = get_base_cost(
1009 abs_qc, new_ctx, txb_costs->base_cost[base_idx][new_ctx], base_idx);
Angie Chianga530ef42017-05-30 16:32:36 -07001010 cost_diff += -org_cost + new_cost;
1011 }
1012 }
1013 return cost_diff;
Ola Hugosson13892102017-11-06 08:01:44 +01001014#endif
Angie Chianga530ef42017-05-30 16:32:36 -07001015}
1016
1017static int try_neighbor_level_down_nz(int coeff_idx, int nb_coeff_idx,
1018 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001019 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -07001020 TxbInfo *txb_info) {
1021 // assume eob doesn't change
1022 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1023 const tran_low_t abs_qc = abs(qc);
1024 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
1025 const tran_low_t abs_nb_coeff = abs(nb_coeff);
1026 if (abs_nb_coeff != 1) return 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001027 const int16_t *const iscan = txb_info->scan_order->iscan;
Angie Chianga530ef42017-05-30 16:32:36 -07001028 const int scan_idx = iscan[coeff_idx];
1029 if (scan_idx == txb_info->seg_eob) return 0;
1030 const int nb_scan_idx = iscan[nb_coeff_idx];
1031 if (nb_scan_idx < scan_idx) {
1032 const int count = txb_cache->nz_count_arr[coeff_idx];
Linfeng Zhang8ac45572017-11-29 11:39:51 -08001033 (void)count;
Angie Chianga530ef42017-05-30 16:32:36 -07001034 assert(count > 0);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001035 update_qcoeff(nb_coeff_idx, get_lower_coeff(nb_coeff), txb_info);
Linfeng Zhang8ac45572017-11-29 11:39:51 -08001036 const int new_ctx = get_nz_map_ctx_from_stats(
Yaowu Xu102ef812017-12-12 11:31:03 -08001037 0, coeff_idx, txb_info->bwl, txb_info->tx_size,
1038 tx_type_to_class[txb_info->tx_type]);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001039 update_qcoeff(nb_coeff_idx, nb_coeff, txb_info);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001040 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
Ola Hugosson13892102017-11-06 08:01:44 +01001041#if CONFIG_LV_MAP_MULTI
1042 const int org_cost = txb_costs->base_cost[ctx][AOMMIN(abs_qc, 3)];
1043 const int new_cost = txb_costs->base_cost[new_ctx][AOMMIN(abs_qc, 3)];
1044#else
Angie Chianga530ef42017-05-30 16:32:36 -07001045 const int is_nz = abs_qc > 0;
Jingning Handfd72322017-08-09 14:04:12 -07001046 const int org_cost = txb_costs->nz_map_cost[ctx][is_nz];
1047 const int new_cost = txb_costs->nz_map_cost[new_ctx][is_nz];
Ola Hugosson13892102017-11-06 08:01:44 +01001048#endif
Angie Chianga530ef42017-05-30 16:32:36 -07001049 const int cost_diff = new_cost - org_cost;
1050 return cost_diff;
1051 } else {
1052 return 0;
1053 }
1054}
1055
1056static int try_self_level_down(tran_low_t *low_coeff, int coeff_idx,
1057 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001058 const LV_MAP_COEFF_COST *txb_costs,
1059 TxbInfo *txb_info) {
Angie Chiang7afbba42017-05-30 15:59:15 -07001060 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1061 if (qc == 0) {
1062 *low_coeff = 0;
1063 return 0;
1064 }
1065 const tran_low_t abs_qc = abs(qc);
1066 *low_coeff = get_lower_coeff(qc);
1067 int cost_diff;
1068 if (*low_coeff == 0) {
1069 const int scan_idx = txb_info->scan_order->iscan[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -07001070 const int *level_cost =
1071 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1072 const int *low_level_cost =
1073 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
Jingning Han3422ac12017-10-25 20:37:53 -07001074
Dake Hea47cd6c2017-10-13 18:09:58 -07001075 if (scan_idx < txb_info->eob - 1) {
Angie Chiang7afbba42017-05-30 15:59:15 -07001076 // When level-0, we code the binary of abs_qc > level
1077 // but when level-k k > 0 we code the binary of abs_qc == level
1078 // That's why wee need this special treatment for level-0 map
1079 // TODO(angiebird): make leve-0 consistent to other levels
Jingning Handfd72322017-08-09 14:04:12 -07001080 cost_diff = -level_cost[1] + low_level_cost[0] - low_level_cost[1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001081 } else {
Jingning Handfd72322017-08-09 14:04:12 -07001082 cost_diff = -level_cost[1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001083 }
1084
Angie Chiang7afbba42017-05-30 15:59:15 -07001085 const int sign_cost = get_sign_bit_cost(
Jingning Handfd72322017-08-09 14:04:12 -07001086 qc, coeff_idx, txb_costs->dc_sign_cost, txb_info->txb_ctx->dc_sign_ctx);
Angie Chiang7afbba42017-05-30 15:59:15 -07001087 cost_diff -= sign_cost;
Jingning Han772dee32017-09-15 08:53:18 -07001088 } else if (abs_qc <= NUM_BASE_LEVELS) {
1089 const int *level_cost =
1090 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1091 const int *low_level_cost =
1092 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1093 cost_diff = -level_cost[1] + low_level_cost[1] - low_level_cost[0];
1094 } else if (abs_qc == NUM_BASE_LEVELS + 1) {
1095 const int *level_cost =
1096 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1097 const int *low_level_cost =
1098 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1099 cost_diff = -level_cost[0] + low_level_cost[1] - low_level_cost[0];
Angie Chiang7afbba42017-05-30 15:59:15 -07001100 } else if (abs_qc < 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Jingning Handfd72322017-08-09 14:04:12 -07001101 const int *level_cost =
1102 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1103 const int *low_level_cost =
1104 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1105
Jingning Han772dee32017-09-15 08:53:18 -07001106 cost_diff = -level_cost[abs_qc - 1 - NUM_BASE_LEVELS] +
1107 low_level_cost[abs(*low_coeff) - 1 - NUM_BASE_LEVELS];
Angie Chiang7afbba42017-05-30 15:59:15 -07001108 } else if (abs_qc == 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Jingning Handfd72322017-08-09 14:04:12 -07001109 const int *low_level_cost =
1110 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
Jingning Han772dee32017-09-15 08:53:18 -07001111 cost_diff = -get_golomb_cost(abs_qc) - low_level_cost[COEFF_BASE_RANGE] +
1112 low_level_cost[COEFF_BASE_RANGE - 1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001113 } else {
1114 assert(abs_qc > 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE);
1115 const tran_low_t abs_low_coeff = abs(*low_coeff);
1116 cost_diff = -get_golomb_cost(abs_qc) + get_golomb_cost(abs_low_coeff);
1117 }
1118 return cost_diff;
1119}
1120
Angie Chianga530ef42017-05-30 16:32:36 -07001121#define COST_MAP_SIZE 5
1122#define COST_MAP_OFFSET 2
1123
1124static INLINE int check_nz_neighbor(tran_low_t qc) { return abs(qc) == 1; }
1125
1126static INLINE int check_base_neighbor(tran_low_t qc) {
1127 return abs(qc) <= 1 + NUM_BASE_LEVELS;
1128}
1129
1130static INLINE int check_br_neighbor(tran_low_t qc) {
1131 return abs(qc) > BR_MAG_OFFSET;
1132}
1133
Angie Chiang87278292017-10-18 09:59:47 -07001134#define FAST_OPTIMIZE_TXB 1
Angie Chiange80957f2017-09-05 10:48:00 -07001135
1136#if FAST_OPTIMIZE_TXB
1137#define ALNB_REF_OFFSET_NUM 2
Linfeng Zhang4afda452017-10-24 10:34:04 -07001138static const int alnb_ref_offset[ALNB_REF_OFFSET_NUM][2] = {
Angie Chiange80957f2017-09-05 10:48:00 -07001139 { -1, 0 }, { 0, -1 },
1140};
1141#define NB_REF_OFFSET_NUM 4
Linfeng Zhang4afda452017-10-24 10:34:04 -07001142static const int nb_ref_offset[NB_REF_OFFSET_NUM][2] = {
Angie Chiange80957f2017-09-05 10:48:00 -07001143 { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 },
1144};
1145#endif // FAST_OPTIMIZE_TXB
1146
Angie Chianga530ef42017-05-30 16:32:36 -07001147// TODO(angiebird): add static to this function once it's called
1148int try_level_down(int coeff_idx, const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001149 const LV_MAP_COEFF_COST *txb_costs, TxbInfo *txb_info,
Angie Chiang25645b72017-09-24 14:28:49 -07001150 int (*cost_map)[COST_MAP_SIZE], int fast_mode) {
1151#if !FAST_OPTIMIZE_TXB
1152 (void)fast_mode;
1153#endif
Angie Chianga530ef42017-05-30 16:32:36 -07001154 if (cost_map) {
1155 for (int i = 0; i < COST_MAP_SIZE; ++i) av1_zero(cost_map[i]);
1156 }
1157
1158 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1159 tran_low_t low_coeff;
1160 if (qc == 0) return 0;
1161 int accu_cost_diff = 0;
1162
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001163 const int16_t *const iscan = txb_info->scan_order->iscan;
Angie Chianga530ef42017-05-30 16:32:36 -07001164 const int eob = txb_info->eob;
1165 const int scan_idx = iscan[coeff_idx];
1166 if (scan_idx < eob) {
1167 const int cost_diff = try_self_level_down(&low_coeff, coeff_idx, txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001168 txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001169 if (cost_map)
1170 cost_map[0 + COST_MAP_OFFSET][0 + COST_MAP_OFFSET] = cost_diff;
1171 accu_cost_diff += cost_diff;
1172 }
1173
1174 const int row = coeff_idx >> txb_info->bwl;
1175 const int col = coeff_idx - (row << txb_info->bwl);
1176 if (check_nz_neighbor(qc)) {
Angie Chiange80957f2017-09-05 10:48:00 -07001177#if FAST_OPTIMIZE_TXB
Linfeng Zhang4afda452017-10-24 10:34:04 -07001178 const int(*ref_offset)[2];
Angie Chiang25645b72017-09-24 14:28:49 -07001179 int ref_num;
1180 if (fast_mode) {
1181 ref_offset = alnb_ref_offset;
1182 ref_num = ALNB_REF_OFFSET_NUM;
1183 } else {
1184 ref_offset = sig_ref_offset;
1185 ref_num = SIG_REF_OFFSET_NUM;
1186 }
Angie Chiange80957f2017-09-05 10:48:00 -07001187#else
Linfeng Zhang4afda452017-10-24 10:34:04 -07001188 const int(*ref_offset)[2] = sig_ref_offset;
Angie Chiange80957f2017-09-05 10:48:00 -07001189 const int ref_num = SIG_REF_OFFSET_NUM;
1190#endif
1191 for (int i = 0; i < ref_num; ++i) {
1192 const int nb_row = row - ref_offset[i][0];
1193 const int nb_col = col - ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001194 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han4cbb3632017-06-13 12:50:33 -07001195
Angie Chiang0c89dca2017-08-17 16:36:18 -07001196 if (nb_row < 0 || nb_col < 0 || nb_row >= txb_info->height ||
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001197 nb_col >= txb_info->width)
Jingning Han3455e762017-06-13 21:15:44 -07001198 continue;
1199
Angie Chianga530ef42017-05-30 16:32:36 -07001200 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001201 if (nb_scan_idx < eob) {
Angie Chianga530ef42017-05-30 16:32:36 -07001202 const int cost_diff = try_neighbor_level_down_nz(
Jingning Handfd72322017-08-09 14:04:12 -07001203 nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001204 if (cost_map)
1205 cost_map[nb_row - row + COST_MAP_OFFSET]
1206 [nb_col - col + COST_MAP_OFFSET] += cost_diff;
1207 accu_cost_diff += cost_diff;
1208 }
1209 }
1210 }
1211
1212 if (check_base_neighbor(qc)) {
Angie Chiange80957f2017-09-05 10:48:00 -07001213#if FAST_OPTIMIZE_TXB
Linfeng Zhang4afda452017-10-24 10:34:04 -07001214 const int(*ref_offset)[2];
Angie Chiang25645b72017-09-24 14:28:49 -07001215 int ref_num;
1216 if (fast_mode) {
1217 ref_offset = nb_ref_offset;
1218 ref_num = NB_REF_OFFSET_NUM;
1219 } else {
1220 ref_offset = base_ref_offset;
1221 ref_num = BASE_CONTEXT_POSITION_NUM;
1222 }
Angie Chiange80957f2017-09-05 10:48:00 -07001223#else
Linfeng Zhangce065ca2017-10-17 16:49:30 -07001224 const int(*ref_offset)[2] = base_ref_offset;
Angie Chiang25645b72017-09-24 14:28:49 -07001225 int ref_num = BASE_CONTEXT_POSITION_NUM;
Angie Chiange80957f2017-09-05 10:48:00 -07001226#endif
1227 for (int i = 0; i < ref_num; ++i) {
1228 const int nb_row = row - ref_offset[i][0];
1229 const int nb_col = col - ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001230 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001231
Angie Chiang0c89dca2017-08-17 16:36:18 -07001232 if (nb_row < 0 || nb_col < 0 || nb_row >= txb_info->height ||
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001233 nb_col >= txb_info->width)
Jingning Han3455e762017-06-13 21:15:44 -07001234 continue;
1235
Angie Chianga530ef42017-05-30 16:32:36 -07001236 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001237 if (nb_scan_idx < eob) {
Angie Chianga530ef42017-05-30 16:32:36 -07001238 const int cost_diff = try_neighbor_level_down_base(
Jingning Handfd72322017-08-09 14:04:12 -07001239 nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001240 if (cost_map)
1241 cost_map[nb_row - row + COST_MAP_OFFSET]
1242 [nb_col - col + COST_MAP_OFFSET] += cost_diff;
1243 accu_cost_diff += cost_diff;
1244 }
1245 }
1246 }
1247
1248 if (check_br_neighbor(qc)) {
Angie Chiange80957f2017-09-05 10:48:00 -07001249#if FAST_OPTIMIZE_TXB
Linfeng Zhang4afda452017-10-24 10:34:04 -07001250 const int(*ref_offset)[2];
Angie Chiang25645b72017-09-24 14:28:49 -07001251 int ref_num;
1252 if (fast_mode) {
1253 ref_offset = nb_ref_offset;
1254 ref_num = NB_REF_OFFSET_NUM;
1255 } else {
1256 ref_offset = br_ref_offset;
1257 ref_num = BR_CONTEXT_POSITION_NUM;
1258 }
Angie Chiange80957f2017-09-05 10:48:00 -07001259#else
Linfeng Zhangce065ca2017-10-17 16:49:30 -07001260 const int(*ref_offset)[2] = br_ref_offset;
Angie Chiange80957f2017-09-05 10:48:00 -07001261 const int ref_num = BR_CONTEXT_POSITION_NUM;
1262#endif
1263 for (int i = 0; i < ref_num; ++i) {
1264 const int nb_row = row - ref_offset[i][0];
1265 const int nb_col = col - ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001266 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001267
Angie Chiang0c89dca2017-08-17 16:36:18 -07001268 if (nb_row < 0 || nb_col < 0 || nb_row >= txb_info->height ||
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001269 nb_col >= txb_info->width)
Jingning Han3455e762017-06-13 21:15:44 -07001270 continue;
1271
Angie Chianga530ef42017-05-30 16:32:36 -07001272 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001273 if (nb_scan_idx < eob) {
Angie Chianga530ef42017-05-30 16:32:36 -07001274 const int cost_diff = try_neighbor_level_down_br(
Jingning Handfd72322017-08-09 14:04:12 -07001275 nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001276 if (cost_map)
1277 cost_map[nb_row - row + COST_MAP_OFFSET]
1278 [nb_col - col + COST_MAP_OFFSET] += cost_diff;
1279 accu_cost_diff += cost_diff;
1280 }
1281 }
1282 }
1283
1284 return accu_cost_diff;
1285}
1286
Angie Chiangc77799b2017-05-30 17:08:17 -07001287static int get_low_coeff_cost(int coeff_idx, const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001288 const LV_MAP_COEFF_COST *txb_costs,
Angie Chiangc77799b2017-05-30 17:08:17 -07001289 const TxbInfo *txb_info) {
1290 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1291 const int abs_qc = abs(qc);
1292 assert(abs_qc <= 1);
1293 int cost = 0;
Jingning Han3422ac12017-10-25 20:37:53 -07001294
Ola Hugosson13892102017-11-06 08:01:44 +01001295#if CONFIG_LV_MAP_MULTI
1296 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
1297 cost += txb_costs->base_cost[ctx][AOMMIN(abs_qc, 3)];
1298 if (qc != 0) {
1299 cost += get_sign_bit_cost(qc, coeff_idx, txb_costs->dc_sign_cost,
1300 txb_info->txb_ctx->dc_sign_ctx);
1301 }
1302#else
1303 const int scan_idx = txb_info->scan_order->iscan[coeff_idx];
Dake Hea47cd6c2017-10-13 18:09:58 -07001304 if (scan_idx < txb_info->eob - 1) {
Jingning Handfd72322017-08-09 14:04:12 -07001305 const int *level_cost = get_level_prob(0, coeff_idx, txb_cache, txb_costs);
1306 cost += level_cost[qc != 0];
Angie Chiangc77799b2017-05-30 17:08:17 -07001307 }
1308
1309 if (qc != 0) {
1310 const int base_idx = 0;
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001311 const int ctx = txb_cache->base_ctx_arr[base_idx][coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -07001312 cost += get_base_cost(abs_qc, ctx, txb_costs->base_cost[base_idx][ctx],
1313 base_idx);
Jingning Handfd72322017-08-09 14:04:12 -07001314 cost += get_sign_bit_cost(qc, coeff_idx, txb_costs->dc_sign_cost,
Angie Chiangc77799b2017-05-30 17:08:17 -07001315 txb_info->txb_ctx->dc_sign_ctx);
1316 }
Ola Hugosson13892102017-11-06 08:01:44 +01001317#endif
Angie Chiangc77799b2017-05-30 17:08:17 -07001318 return cost;
1319}
1320
1321static INLINE void set_eob(TxbInfo *txb_info, int eob) {
1322 txb_info->eob = eob;
Urvang Joshi80893152017-10-27 11:51:14 -07001323 txb_info->seg_eob = av1_get_max_eob(txb_info->tx_size);
Angie Chiangc77799b2017-05-30 17:08:17 -07001324}
1325
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001326static INLINE int get_eob_ctx(const int coeff_idx, // raster order
1327 const TX_SIZE txs_ctx) {
1328 if (txs_ctx == TX_4X4) return av1_coeff_band_4x4[coeff_idx];
1329 if (txs_ctx == TX_8X8) return av1_coeff_band_8x8[coeff_idx];
1330 if (txs_ctx == TX_16X16) return av1_coeff_band_16x16[coeff_idx];
1331 if (txs_ctx == TX_32X32) return av1_coeff_band_32x32[coeff_idx];
1332
1333#if CONFIG_TX64X64
1334 // Since TX64X64 use 32x32 coeff buffer, so it share the same coeff_band with
1335 // TX32X32
1336 if (txs_ctx == TX_64X64) return av1_coeff_band_32x32[coeff_idx];
1337#endif // CONFIG_TX64X64
1338
1339 assert(0 && "Invalid value of txs_ctx");
1340 return 0;
1341}
1342
Angie Chiangc77799b2017-05-30 17:08:17 -07001343// TODO(angiebird): add static to this function once it's called
1344int try_change_eob(int *new_eob, int coeff_idx, const TxbCache *txb_cache,
Angie Chiang25645b72017-09-24 14:28:49 -07001345 const LV_MAP_COEFF_COST *txb_costs, TxbInfo *txb_info,
1346 int fast_mode) {
Angie Chiangc77799b2017-05-30 17:08:17 -07001347 assert(txb_info->eob > 0);
1348 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1349 const int abs_qc = abs(qc);
1350 if (abs_qc != 1) {
1351 *new_eob = -1;
1352 return 0;
1353 }
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001354 const int16_t *const iscan = txb_info->scan_order->iscan;
1355 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiangc77799b2017-05-30 17:08:17 -07001356 const int scan_idx = iscan[coeff_idx];
1357 *new_eob = 0;
1358 int cost_diff = 0;
Jingning Handfd72322017-08-09 14:04:12 -07001359 cost_diff -= get_low_coeff_cost(coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chiangc77799b2017-05-30 17:08:17 -07001360 for (int si = scan_idx - 1; si >= 0; --si) {
1361 const int ci = scan[si];
1362 if (txb_info->qcoeff[ci] != 0) {
1363 *new_eob = si + 1;
1364 break;
1365 } else {
Jingning Handfd72322017-08-09 14:04:12 -07001366 cost_diff -= get_low_coeff_cost(ci, txb_cache, txb_costs, txb_info);
Angie Chiangc77799b2017-05-30 17:08:17 -07001367 }
1368 }
1369
1370 const int org_eob = txb_info->eob;
1371 set_eob(txb_info, *new_eob);
Angie Chiang25645b72017-09-24 14:28:49 -07001372 cost_diff += try_level_down(coeff_idx, txb_cache, txb_costs, txb_info, NULL,
1373 fast_mode);
Angie Chiangc77799b2017-05-30 17:08:17 -07001374 set_eob(txb_info, org_eob);
1375
1376 if (*new_eob > 0) {
1377 // Note that get_eob_ctx does NOT actually account for qcoeff, so we don't
1378 // need to lower down the qcoeff here
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001379 const int eob_ctx = get_eob_ctx(scan[*new_eob - 1], txb_info->txs_ctx);
Jingning Handfd72322017-08-09 14:04:12 -07001380 cost_diff -= txb_costs->eob_cost[eob_ctx][0];
1381 cost_diff += txb_costs->eob_cost[eob_ctx][1];
Angie Chiangc77799b2017-05-30 17:08:17 -07001382 } else {
1383 const int txb_skip_ctx = txb_info->txb_ctx->txb_skip_ctx;
Jingning Handfd72322017-08-09 14:04:12 -07001384 cost_diff -= txb_costs->txb_skip_cost[txb_skip_ctx][0];
1385 cost_diff += txb_costs->txb_skip_cost[txb_skip_ctx][1];
Angie Chiangc77799b2017-05-30 17:08:17 -07001386 }
1387 return cost_diff;
1388}
Angie Chiang47e07072017-05-30 17:27:01 -07001389
Angie Chiangd19969e2017-05-30 18:02:33 -07001390// TODO(angiebird): add static to this function it's called
Linfeng Zhang1015a342017-10-24 16:20:41 -07001391void update_level_down(const int coeff_idx, TxbCache *const txb_cache,
1392 TxbInfo *const txb_info) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001393 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1394 const int abs_qc = abs(qc);
1395 if (qc == 0) return;
1396 const tran_low_t low_coeff = get_lower_coeff(qc);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001397 update_coeff(coeff_idx, low_coeff, txb_info);
Angie Chiangd19969e2017-05-30 18:02:33 -07001398
1399 const int row = coeff_idx >> txb_info->bwl;
1400 const int col = coeff_idx - (row << txb_info->bwl);
1401 const int eob = txb_info->eob;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001402 const int16_t *const iscan = txb_info->scan_order->iscan;
Angie Chiangd19969e2017-05-30 18:02:33 -07001403 for (int i = 0; i < SIG_REF_OFFSET_NUM; ++i) {
1404 const int nb_row = row - sig_ref_offset[i][0];
1405 const int nb_col = col - sig_ref_offset[i][1];
Jingning Han3455e762017-06-13 21:15:44 -07001406
1407 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001408 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001409 continue;
1410
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001411 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiangd19969e2017-05-30 18:02:33 -07001412 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001413 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001414 const int scan_idx = iscan[coeff_idx];
1415 if (scan_idx < nb_scan_idx) {
1416 const int level = 1;
1417 if (abs_qc == level) {
1418 txb_cache->nz_count_arr[nb_coeff_idx] -= 1;
1419 assert(txb_cache->nz_count_arr[nb_coeff_idx] >= 0);
1420 }
Yaowu Xu102ef812017-12-12 11:31:03 -08001421 txb_cache->nz_ctx_arr[nb_coeff_idx] = get_nz_map_ctx_from_stats(
1422 0, nb_coeff_idx, txb_info->bwl, txb_info->tx_size,
1423 tx_type_to_class[txb_info->tx_type]);
Angie Chiangd19969e2017-05-30 18:02:33 -07001424 }
1425 }
1426 }
1427
Angie Chiangdef11252017-08-18 14:37:32 -07001428 const BASE_CTX_TABLE *base_ctx_table =
1429 txb_info->coeff_ctx_table->base_ctx_table;
Angie Chiangd19969e2017-05-30 18:02:33 -07001430 for (int i = 0; i < BASE_CONTEXT_POSITION_NUM; ++i) {
1431 const int nb_row = row - base_ref_offset[i][0];
1432 const int nb_col = col - base_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001433 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001434
1435 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001436 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001437 continue;
1438
Angie Chiangd19969e2017-05-30 18:02:33 -07001439 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
1440 if (!has_base(nb_coeff, 0)) continue;
1441 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001442 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001443 if (row >= nb_row && col >= nb_col)
1444 update_mag_arr(txb_cache->base_mag_arr[nb_coeff_idx], abs_qc);
1445 const int mag =
1446 get_mag_from_mag_arr(txb_cache->base_mag_arr[nb_coeff_idx]);
1447 for (int base_idx = 0; base_idx < NUM_BASE_LEVELS; ++base_idx) {
1448 if (!has_base(nb_coeff, base_idx)) continue;
1449 const int level = base_idx + 1;
1450 if (abs_qc == level) {
1451 txb_cache->base_count_arr[base_idx][nb_coeff_idx] -= 1;
1452 assert(txb_cache->base_count_arr[base_idx][nb_coeff_idx] >= 0);
1453 }
1454 const int count = txb_cache->base_count_arr[base_idx][nb_coeff_idx];
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001455 txb_cache->base_ctx_arr[base_idx][nb_coeff_idx] =
Angie Chiangdef11252017-08-18 14:37:32 -07001456 base_ctx_table[nb_row != 0][nb_col != 0][mag > level][count];
Angie Chiangd19969e2017-05-30 18:02:33 -07001457 }
1458 }
1459 }
1460
1461 for (int i = 0; i < BR_CONTEXT_POSITION_NUM; ++i) {
1462 const int nb_row = row - br_ref_offset[i][0];
1463 const int nb_col = col - br_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001464 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001465
1466 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001467 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001468 continue;
1469
Angie Chiangd19969e2017-05-30 18:02:33 -07001470 const int nb_scan_idx = iscan[nb_coeff_idx];
1471 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
1472 if (!has_br(nb_coeff)) continue;
Jingning Han3455e762017-06-13 21:15:44 -07001473 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001474 const int level = 1 + NUM_BASE_LEVELS;
1475 if (abs_qc == level) {
1476 txb_cache->br_count_arr[nb_coeff_idx] -= 1;
1477 assert(txb_cache->br_count_arr[nb_coeff_idx] >= 0);
1478 }
1479 if (row >= nb_row && col >= nb_col)
1480 update_mag_arr(txb_cache->br_mag_arr[nb_coeff_idx], abs_qc);
1481 const int count = txb_cache->br_count_arr[nb_coeff_idx];
1482 const int mag = get_mag_from_mag_arr(txb_cache->br_mag_arr[nb_coeff_idx]);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001483 txb_cache->br_ctx_arr[nb_coeff_idx] =
Angie Chiangd19969e2017-05-30 18:02:33 -07001484 get_br_ctx_from_count_mag(nb_row, nb_col, count, mag);
Angie Chiangd19969e2017-05-30 18:02:33 -07001485 }
1486 }
1487}
1488
Linfeng Zhang1015a342017-10-24 16:20:41 -07001489static int get_coeff_cost(const tran_low_t qc, const int scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +01001490#if CONFIG_LV_MAP_MULTI
1491 const int is_eob,
1492#endif
Linfeng Zhang1015a342017-10-24 16:20:41 -07001493 const TxbInfo *const txb_info,
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001494 const LV_MAP_COEFF_COST *const txb_costs,
1495 const int coeff_ctx) {
Angie Chiang488f9212017-05-30 12:46:26 -07001496 const TXB_CTX *txb_ctx = txb_info->txb_ctx;
1497 const int is_nz = (qc != 0);
1498 const tran_low_t abs_qc = abs(qc);
1499 int cost = 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001500 const int16_t *const scan = txb_info->scan_order->scan;
1501 const int pos = scan[scan_idx];
Dake He03a32922017-10-31 08:06:45 -07001502
Ola Hugosson13892102017-11-06 08:01:44 +01001503#if CONFIG_LV_MAP_MULTI
Dake He3fe369c2017-11-16 17:56:44 -08001504 if (is_eob) {
Dake He4d447692017-12-15 09:10:06 -08001505 cost += txb_costs->base_eob_cost[coeff_ctx][AOMMIN(abs_qc, 3) - 1];
Dake He3fe369c2017-11-16 17:56:44 -08001506 } else {
1507 cost += txb_costs->base_cost[coeff_ctx][AOMMIN(abs_qc, 3)];
1508 }
Ola Hugosson13892102017-11-06 08:01:44 +01001509#else
Dake Hea47cd6c2017-10-13 18:09:58 -07001510 if (scan_idx < txb_info->eob - 1) {
Jingning Handfd72322017-08-09 14:04:12 -07001511 cost += txb_costs->nz_map_cost[coeff_ctx][is_nz];
Angie Chiang488f9212017-05-30 12:46:26 -07001512 }
Ola Hugosson13892102017-11-06 08:01:44 +01001513#endif
Angie Chiang488f9212017-05-30 12:46:26 -07001514 if (is_nz) {
Jingning Handfd72322017-08-09 14:04:12 -07001515 cost += get_sign_bit_cost(qc, scan_idx, txb_costs->dc_sign_cost,
Angie Chiang488f9212017-05-30 12:46:26 -07001516 txb_ctx->dc_sign_ctx);
1517
Ola Hugosson13892102017-11-06 08:01:44 +01001518#if !CONFIG_LV_MAP_MULTI
Dake He03a32922017-10-31 08:06:45 -07001519 int k;
1520 for (k = 0; k < NUM_BASE_LEVELS; ++k) {
1521 int ctx = coeff_ctx;
1522 int is_k = (abs_qc > (k + 1));
1523
1524 cost += txb_costs->base_cost[k][ctx][is_k];
1525 if (is_k == 0) break;
1526 }
Ola Hugosson13892102017-11-06 08:01:44 +01001527#endif
Angie Chiang488f9212017-05-30 12:46:26 -07001528 if (abs_qc > NUM_BASE_LEVELS) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001529 const int row = pos >> txb_info->bwl;
1530 const int col = pos - (row << txb_info->bwl);
Dake He7d01ab52017-11-24 17:53:28 -08001531
1532#if CONFIG_LV_MAP_MULTI && USE_CAUSAL_BR_CTX
1533 (void)col;
1534 const int count = 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001535 const int ctx = get_br_ctx(txb_info->levels, pos, txb_info->bwl, count,
1536 txb_info->tx_type);
Dake He7d01ab52017-11-24 17:53:28 -08001537#else
Linfeng Zhang97fc4742017-11-07 12:57:25 -08001538 const int count = get_level_count(
1539 txb_info->levels, (1 << txb_info->bwl) + TX_PAD_HOR, row, col,
1540 NUM_BASE_LEVELS, br_ref_offset, BR_CONTEXT_POSITION_NUM);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001541 const int ctx = get_br_ctx(txb_info->levels, pos, txb_info->bwl, count);
Dake He7d01ab52017-11-24 17:53:28 -08001542#endif
Jingning Handfd72322017-08-09 14:04:12 -07001543 cost += get_br_cost(abs_qc, ctx, txb_costs->lps_cost[ctx]);
Angie Chiang488f9212017-05-30 12:46:26 -07001544 cost += get_golomb_cost(abs_qc);
1545 }
Angie Chiang488f9212017-05-30 12:46:26 -07001546 }
1547 return cost;
1548}
1549
Angie Chiang47e07072017-05-30 17:27:01 -07001550#if TEST_OPTIMIZE_TXB
Angie Chiang5e012fe2017-05-30 18:47:39 -07001551#define ALL_REF_OFFSET_NUM 17
Linfeng Zhang4afda452017-10-24 10:34:04 -07001552static const int all_ref_offset[ALL_REF_OFFSET_NUM][2] = {
Angie Chiang5e012fe2017-05-30 18:47:39 -07001553 { 0, 0 }, { -2, -1 }, { -2, 0 }, { -2, 1 }, { -1, -2 }, { -1, -1 },
1554 { -1, 0 }, { -1, 1 }, { 0, -2 }, { 0, -1 }, { 1, -2 }, { 1, -1 },
1555 { 1, 0 }, { 2, 0 }, { 0, 1 }, { 0, 2 }, { 1, 1 },
1556};
1557
Angie Chiang0b2795c2017-09-29 16:00:08 -07001558static int try_level_down_ref(int coeff_idx, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang5e012fe2017-05-30 18:47:39 -07001559 TxbInfo *txb_info,
1560 int (*cost_map)[COST_MAP_SIZE]) {
1561 if (cost_map) {
1562 for (int i = 0; i < COST_MAP_SIZE; ++i) av1_zero(cost_map[i]);
1563 }
1564 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1565 if (qc == 0) return 0;
1566 int row = coeff_idx >> txb_info->bwl;
1567 int col = coeff_idx - (row << txb_info->bwl);
1568 int org_cost = 0;
1569 for (int i = 0; i < ALL_REF_OFFSET_NUM; ++i) {
1570 int nb_row = row - all_ref_offset[i][0];
1571 int nb_col = col - all_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001572 int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001573 int nb_scan_idx = txb_info->scan_order->iscan[nb_coeff_idx];
1574 if (nb_scan_idx < txb_info->eob && nb_row >= 0 && nb_col >= 0 &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001575 nb_row < txb_info->height && nb_col < txb_info->width) {
Linfeng Zhang960e7002017-12-11 13:46:40 -08001576 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001577 const int coeff_ctx =
1578 get_nz_map_ctx(txb_info->levels, nb_coeff_idx, txb_info->bwl,
1579#if CONFIG_LV_MAP_MULTI
1580 txb_info->height, nb_scan_idx, is_eob,
1581#endif
1582 txb_info->tx_size, txb_info->tx_type);
Linfeng Zhang960e7002017-12-11 13:46:40 -08001583 const int cost = get_coeff_cost(nb_coeff, nb_scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +01001584#if CONFIG_LV_MAP_MULTI
Linfeng Zhang960e7002017-12-11 13:46:40 -08001585 is_eob,
Ola Hugosson13892102017-11-06 08:01:44 +01001586#endif
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001587 txb_info, txb_costs, coeff_ctx);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001588 if (cost_map)
1589 cost_map[nb_row - row + COST_MAP_OFFSET]
1590 [nb_col - col + COST_MAP_OFFSET] -= cost;
1591 org_cost += cost;
1592 }
1593 }
Linfeng Zhang1015a342017-10-24 16:20:41 -07001594 update_qcoeff(coeff_idx, get_lower_coeff(qc), txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001595 int new_cost = 0;
1596 for (int i = 0; i < ALL_REF_OFFSET_NUM; ++i) {
1597 int nb_row = row - all_ref_offset[i][0];
1598 int nb_col = col - all_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001599 int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001600 int nb_scan_idx = txb_info->scan_order->iscan[nb_coeff_idx];
1601 if (nb_scan_idx < txb_info->eob && nb_row >= 0 && nb_col >= 0 &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001602 nb_row < txb_info->height && nb_col < txb_info->width) {
Linfeng Zhang960e7002017-12-11 13:46:40 -08001603 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001604 const int coeff_ctx =
1605 get_nz_map_ctx(txb_info->levels, nb_coeff_idx, txb_info->bwl,
1606#if CONFIG_LV_MAP_MULTI
1607 txb_info->height, nb_scan_idx, is_eob,
1608#endif
1609 txb_info->tx_size, txb_info->tx_type);
Linfeng Zhang960e7002017-12-11 13:46:40 -08001610 const int cost = get_coeff_cost(nb_coeff, nb_scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +01001611#if CONFIG_LV_MAP_MULTI
Linfeng Zhang960e7002017-12-11 13:46:40 -08001612 is_eob,
Ola Hugosson13892102017-11-06 08:01:44 +01001613#endif
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001614 txb_info, txb_costs, coeff_ctx);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001615 if (cost_map)
1616 cost_map[nb_row - row + COST_MAP_OFFSET]
1617 [nb_col - col + COST_MAP_OFFSET] += cost;
1618 new_cost += cost;
1619 }
1620 }
Linfeng Zhang1015a342017-10-24 16:20:41 -07001621 update_qcoeff(coeff_idx, qc, txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001622 return new_cost - org_cost;
1623}
1624
1625static void test_level_down(int coeff_idx, const TxbCache *txb_cache,
Angie Chiang0b2795c2017-09-29 16:00:08 -07001626 const LV_MAP_COEFF_COST *txb_costs,
1627 TxbInfo *txb_info) {
Angie Chiang47e07072017-05-30 17:27:01 -07001628 int cost_map[COST_MAP_SIZE][COST_MAP_SIZE];
1629 int ref_cost_map[COST_MAP_SIZE][COST_MAP_SIZE];
1630 const int cost_diff =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001631 try_level_down(coeff_idx, txb_cache, txb_costs, txb_info, cost_map, 0);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001632 const int cost_diff_ref =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001633 try_level_down_ref(coeff_idx, txb_costs, txb_info, ref_cost_map);
Angie Chiang47e07072017-05-30 17:27:01 -07001634 if (cost_diff != cost_diff_ref) {
1635 printf("qc %d cost_diff %d cost_diff_ref %d\n", txb_info->qcoeff[coeff_idx],
1636 cost_diff, cost_diff_ref);
1637 for (int r = 0; r < COST_MAP_SIZE; ++r) {
1638 for (int c = 0; c < COST_MAP_SIZE; ++c) {
1639 printf("%d:%d ", cost_map[r][c], ref_cost_map[r][c]);
1640 }
1641 printf("\n");
1642 }
1643 }
1644}
1645#endif
1646
Angie Chiang488f9212017-05-30 12:46:26 -07001647// TODO(angiebird): make this static once it's called
Jingning Handfd72322017-08-09 14:04:12 -07001648int get_txb_cost(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs) {
Angie Chiang488f9212017-05-30 12:46:26 -07001649 int cost = 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001650 const int txb_skip_ctx = txb_info->txb_ctx->txb_skip_ctx;
1651 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang488f9212017-05-30 12:46:26 -07001652 if (txb_info->eob == 0) {
Jingning Handfd72322017-08-09 14:04:12 -07001653 cost = txb_costs->txb_skip_cost[txb_skip_ctx][1];
Angie Chiang488f9212017-05-30 12:46:26 -07001654 return cost;
1655 }
Jingning Handfd72322017-08-09 14:04:12 -07001656 cost = txb_costs->txb_skip_cost[txb_skip_ctx][0];
Angie Chiang488f9212017-05-30 12:46:26 -07001657 for (int c = 0; c < txb_info->eob; ++c) {
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001658 const int pos = scan[c];
1659 const tran_low_t qc = txb_info->qcoeff[pos];
1660 const int coeff_ctx =
1661 get_nz_map_ctx(txb_info->levels, pos, txb_info->bwl,
1662#if CONFIG_LV_MAP_MULTI
1663 txb_info->height, c, c == txb_info->eob - 1,
1664#endif
1665 txb_info->tx_size, txb_info->tx_type);
Linfeng Zhang960e7002017-12-11 13:46:40 -08001666 const int coeff_cost = get_coeff_cost(qc, c,
Ola Hugosson13892102017-11-06 08:01:44 +01001667#if CONFIG_LV_MAP_MULTI
Linfeng Zhang960e7002017-12-11 13:46:40 -08001668 c == txb_info->eob - 1,
Ola Hugosson13892102017-11-06 08:01:44 +01001669#endif
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001670 txb_info, txb_costs, coeff_ctx);
Angie Chiang488f9212017-05-30 12:46:26 -07001671 cost += coeff_cost;
1672 }
1673 return cost;
1674}
1675
Angie Chiang5e012fe2017-05-30 18:47:39 -07001676#if TEST_OPTIMIZE_TXB
Angie Chiang0b2795c2017-09-29 16:00:08 -07001677void test_try_change_eob(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang5e012fe2017-05-30 18:47:39 -07001678 TxbCache *txb_cache) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001679 const int eob = txb_info->eob;
1680 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001681 if (eob > 0) {
1682 int last_si = eob - 1;
1683 int last_ci = scan[last_si];
1684 int last_coeff = txb_info->qcoeff[last_ci];
1685 if (abs(last_coeff) == 1) {
1686 int new_eob;
1687 int cost_diff =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001688 try_change_eob(&new_eob, last_ci, txb_cache, txb_costs, txb_info, 0);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001689 int org_eob = txb_info->eob;
Angie Chiang0b2795c2017-09-29 16:00:08 -07001690 int cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001691
Linfeng Zhang1015a342017-10-24 16:20:41 -07001692 update_qcoeff(last_ci, get_lower_coeff(last_coeff), txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001693 set_eob(txb_info, new_eob);
Angie Chiang0b2795c2017-09-29 16:00:08 -07001694 int new_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001695 set_eob(txb_info, org_eob);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001696 update_qcoeff(last_ci, last_coeff, txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001697
1698 int ref_cost_diff = -cost + new_cost;
1699 if (cost_diff != ref_cost_diff)
1700 printf("org_eob %d new_eob %d cost_diff %d ref_cost_diff %d\n", org_eob,
1701 new_eob, cost_diff, ref_cost_diff);
1702 }
1703 }
1704}
1705#endif
1706
Angie Chiang47e07072017-05-30 17:27:01 -07001707void try_level_down_facade(LevelDownStats *stats, int scan_idx,
Jingning Handfd72322017-08-09 14:04:12 -07001708 const TxbCache *txb_cache,
1709 const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang25645b72017-09-24 14:28:49 -07001710 TxbInfo *txb_info, int fast_mode) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001711 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang47e07072017-05-30 17:27:01 -07001712 const int coeff_idx = scan[scan_idx];
1713 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1714 stats->new_eob = -1;
1715 stats->update = 0;
1716 if (qc == 0) {
1717 return;
1718 }
1719
1720 const tran_low_t tqc = txb_info->tcoeff[coeff_idx];
1721 const int dqv = txb_info->dequant[coeff_idx != 0];
1722
Sarah Parker3d752092017-12-20 15:37:55 -08001723#if CONFIG_NEW_QUANT
1724 const tran_low_t *nq_dequant_val = txb_info->nq_dequant_vals[coeff_idx != 0];
1725#endif // CONFIG_NEW_QUANT
1726
1727 const tran_low_t dqc = qcoeff_to_dqcoeff(qc,
1728#if CONFIG_NEW_QUANT
1729 nq_dequant_val,
1730#endif // CONFIG_NEW_QUANT
1731 dqv, txb_info->shift);
Jingning Han641c1e52017-10-13 09:42:49 -07001732
1733 if (scan_idx != txb_info->eob - 1)
1734 if (abs(dqc) < abs(tqc)) return;
1735
Angie Chiang47e07072017-05-30 17:27:01 -07001736 const int64_t dqc_dist = get_coeff_dist(tqc, dqc, txb_info->shift);
1737
1738 stats->low_qc = get_lower_coeff(qc);
Sarah Parker3d752092017-12-20 15:37:55 -08001739 stats->low_dqc = qcoeff_to_dqcoeff(stats->low_qc,
1740#if CONFIG_NEW_QUANT
1741 nq_dequant_val,
1742#endif // CONFIG_NEW_QUANT
1743 dqv, txb_info->shift);
Angie Chiang47e07072017-05-30 17:27:01 -07001744 const int64_t low_dqc_dist =
1745 get_coeff_dist(tqc, stats->low_dqc, txb_info->shift);
1746
1747 stats->dist_diff = -dqc_dist + low_dqc_dist;
1748 stats->cost_diff = 0;
1749 stats->new_eob = txb_info->eob;
1750 if (scan_idx == txb_info->eob - 1 && abs(qc) == 1) {
1751 stats->cost_diff = try_change_eob(&stats->new_eob, coeff_idx, txb_cache,
Angie Chiang25645b72017-09-24 14:28:49 -07001752 txb_costs, txb_info, fast_mode);
Angie Chiang47e07072017-05-30 17:27:01 -07001753 } else {
Angie Chiang25645b72017-09-24 14:28:49 -07001754 stats->cost_diff = try_level_down(coeff_idx, txb_cache, txb_costs, txb_info,
1755 NULL, fast_mode);
Angie Chiang47e07072017-05-30 17:27:01 -07001756#if TEST_OPTIMIZE_TXB
Angie Chiang0b2795c2017-09-29 16:00:08 -07001757 test_level_down(coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chiang47e07072017-05-30 17:27:01 -07001758#endif
1759 }
Urvang Joshi70006e42017-06-14 16:08:55 -07001760 stats->rd_diff = RDCOST(txb_info->rdmult, stats->cost_diff, stats->dist_diff);
Angie Chiang47e07072017-05-30 17:27:01 -07001761 if (stats->rd_diff < 0) stats->update = 1;
1762 return;
1763}
Angie Chiang07c57f32017-05-30 18:18:33 -07001764
Jingning Han3422ac12017-10-25 20:37:53 -07001765#if 1
Dake Hea47cd6c2017-10-13 18:09:58 -07001766static int optimize_txb(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
1767 TxbCache *txb_cache, int dry_run, int fast_mode) {
1768 (void)fast_mode;
1769 (void)txb_cache;
1770 int update = 0;
Dake He59881772017-11-24 07:00:02 -08001771 // return update; // TODO(DKHE): training only.
Dake Hea47cd6c2017-10-13 18:09:58 -07001772 if (txb_info->eob == 0) return update;
Urvang Joshi80893152017-10-27 11:51:14 -07001773 const int max_eob = av1_get_max_eob(txb_info->tx_size);
Dake Hea47cd6c2017-10-13 18:09:58 -07001774
1775#if TEST_OPTIMIZE_TXB
1776 int64_t sse;
1777 int64_t org_dist =
1778 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1779 (1 << (2 * txb_info->shift));
1780 int org_cost = get_txb_cost(txb_info, txb_probs);
1781#endif
1782
1783 tran_low_t *org_qcoeff = txb_info->qcoeff;
1784 tran_low_t *org_dqcoeff = txb_info->dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001785 uint8_t *const org_levels = txb_info->levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001786
1787 tran_low_t tmp_qcoeff[MAX_TX_SQUARE];
1788 tran_low_t tmp_dqcoeff[MAX_TX_SQUARE];
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001789 uint8_t tmp_levels_buf[TX_PAD_2D];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001790 uint8_t *const tmp_levels = set_levels(tmp_levels_buf, txb_info->width);
Dake Hea47cd6c2017-10-13 18:09:58 -07001791 const int org_eob = txb_info->eob;
1792 if (dry_run) {
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001793 const int stride = txb_info->width + TX_PAD_HOR;
1794 const int levels_size =
1795
1796 (stride * (txb_info->height + TX_PAD_VER) + TX_PAD_END);
Dake Hea47cd6c2017-10-13 18:09:58 -07001797 memcpy(tmp_qcoeff, org_qcoeff, sizeof(org_qcoeff[0]) * max_eob);
1798 memcpy(tmp_dqcoeff, org_dqcoeff, sizeof(org_dqcoeff[0]) * max_eob);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001799 memcpy(tmp_levels, org_levels - TX_PAD_TOP * stride,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001800 sizeof(org_levels[0]) * levels_size);
Dake Hea47cd6c2017-10-13 18:09:58 -07001801 txb_info->qcoeff = tmp_qcoeff;
1802 txb_info->dqcoeff = tmp_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001803 txb_info->levels = tmp_levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001804 }
1805
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001806 const int16_t *const scan = txb_info->scan_order->scan;
Dake Hea47cd6c2017-10-13 18:09:58 -07001807
1808 // forward optimize the nz_map`
1809 const int init_eob = txb_info->eob;
1810 const int seg_eob = txb_info->seg_eob;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001811 const int eob_cost =
1812 get_eob_cost(init_eob, seg_eob, txb_costs, txb_info->tx_type);
Dake Hea47cd6c2017-10-13 18:09:58 -07001813
1814 // backward optimize the level-k map
1815 int64_t accu_rate = eob_cost;
1816 int64_t accu_dist = 0;
1817 int64_t prev_eob_rd_cost = INT64_MAX;
1818 int64_t cur_eob_rd_cost = 0;
Jingning Han8be58fa2017-12-18 09:46:13 -08001819 int8_t has_nz_tail = 0;
Dake Hea47cd6c2017-10-13 18:09:58 -07001820
1821 for (int si = init_eob - 1; si >= 0; --si) {
1822 const int coeff_idx = scan[si];
1823 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1824
1825 LevelDownStats stats;
Linfeng Zhang960e7002017-12-11 13:46:40 -08001826 get_dist_cost_stats(&stats, si,
Ola Hugosson13892102017-11-06 08:01:44 +01001827#if CONFIG_LV_MAP_MULTI
Linfeng Zhang960e7002017-12-11 13:46:40 -08001828 si == init_eob - 1,
Ola Hugosson13892102017-11-06 08:01:44 +01001829#endif
Linfeng Zhang960e7002017-12-11 13:46:40 -08001830 txb_costs, txb_info);
Dake Hea47cd6c2017-10-13 18:09:58 -07001831
1832 if (qc == 0) {
1833 accu_rate += stats.rate;
1834 } else {
Jingning Han8be58fa2017-12-18 09:46:13 -08001835 if (has_nz_tail < 2) {
1836 // check if it is better to make this the last significant coefficient
1837 int cur_eob_rate =
1838 get_eob_cost(si + 1, seg_eob, txb_costs, txb_info->tx_type);
1839 cur_eob_rd_cost = RDCOST(txb_info->rdmult, cur_eob_rate, 0);
1840 prev_eob_rd_cost =
Dake He4d447692017-12-15 09:10:06 -08001841#if CONFIG_LV_MAP_MULTI
1842 RDCOST(txb_info->rdmult, accu_rate, accu_dist) + stats.nz_rd;
1843#else
Jingning Han8be58fa2017-12-18 09:46:13 -08001844 RDCOST(txb_info->rdmult, accu_rate + stats.nz_rate, accu_dist);
Dake He4d447692017-12-15 09:10:06 -08001845#endif
Jingning Han8be58fa2017-12-18 09:46:13 -08001846 if (cur_eob_rd_cost <= prev_eob_rd_cost) {
1847 update = 1;
1848 for (int j = si + 1; j < txb_info->eob; j++) {
1849 const int coeff_pos_j = scan[j];
1850 update_coeff(coeff_pos_j, 0, txb_info);
1851 }
1852 txb_info->eob = si + 1;
Dake Hea47cd6c2017-10-13 18:09:58 -07001853
Jingning Han8be58fa2017-12-18 09:46:13 -08001854 // rerun cost calculation due to change of eob
1855 accu_rate = cur_eob_rate;
1856 accu_dist = 0;
1857 get_dist_cost_stats(&stats, si,
Ola Hugosson13892102017-11-06 08:01:44 +01001858#if CONFIG_LV_MAP_MULTI
Jingning Han8be58fa2017-12-18 09:46:13 -08001859 1,
Ola Hugosson13892102017-11-06 08:01:44 +01001860#endif
Jingning Han8be58fa2017-12-18 09:46:13 -08001861 txb_costs, txb_info);
Dake He4d447692017-12-15 09:10:06 -08001862 if ((stats.rd_low < stats.rd) && (stats.low_qc != 0)) {
1863 update = 1;
1864 update_coeff(coeff_idx, stats.low_qc, txb_info);
1865 accu_rate += stats.rate_low;
1866 accu_dist += stats.dist_low;
1867 } else {
1868 accu_rate += stats.rate;
1869 accu_dist += stats.dist;
1870 }
Jingning Han8be58fa2017-12-18 09:46:13 -08001871 continue;
1872 }
Dake Hea47cd6c2017-10-13 18:09:58 -07001873 }
1874
1875 int bUpdCoeff = 0;
1876 if (stats.rd_low < stats.rd) {
Dake He4d447692017-12-15 09:10:06 -08001877 if ((si < txb_info->eob - 1)) {
Dake Hea47cd6c2017-10-13 18:09:58 -07001878 bUpdCoeff = 1;
1879 update = 1;
1880 }
Jingning Han8be58fa2017-12-18 09:46:13 -08001881 } else {
1882 ++has_nz_tail;
Dake Hea47cd6c2017-10-13 18:09:58 -07001883 }
1884
1885 if (bUpdCoeff) {
1886 update_coeff(coeff_idx, stats.low_qc, txb_info);
1887 accu_rate += stats.rate_low;
1888 accu_dist += stats.dist_low;
1889 } else {
1890 accu_rate += stats.rate;
1891 accu_dist += stats.dist;
1892 }
1893 }
1894 } // for (si)
Jingning Hana7a6f4e2017-12-13 14:44:08 -08001895
Dake Hea47cd6c2017-10-13 18:09:58 -07001896 int non_zero_blk_rate =
1897 txb_costs->txb_skip_cost[txb_info->txb_ctx->txb_skip_ctx][0];
1898 prev_eob_rd_cost =
1899 RDCOST(txb_info->rdmult, accu_rate + non_zero_blk_rate, accu_dist);
1900
1901 int zero_blk_rate =
1902 txb_costs->txb_skip_cost[txb_info->txb_ctx->txb_skip_ctx][1];
1903 int64_t zero_blk_rd_cost = RDCOST(txb_info->rdmult, zero_blk_rate, 0);
1904 if (zero_blk_rd_cost <= prev_eob_rd_cost) {
1905 update = 1;
1906 for (int j = 0; j < txb_info->eob; j++) {
1907 const int coeff_pos_j = scan[j];
1908 update_coeff(coeff_pos_j, 0, txb_info);
1909 }
1910 txb_info->eob = 0;
1911 }
1912
1913#if TEST_OPTIMIZE_TXB
1914 int cost_diff = 0;
1915 int64_t dist_diff = 0;
1916 int64_t rd_diff = 0;
1917 int64_t new_dist =
1918 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1919 (1 << (2 * txb_info->shift));
1920 int new_cost = get_txb_cost(txb_info, txb_probs);
1921 int64_t ref_dist_diff = new_dist - org_dist;
1922 int ref_cost_diff = new_cost - org_cost;
1923 if (cost_diff != ref_cost_diff || dist_diff != ref_dist_diff)
1924 printf(
1925 "overall rd_diff %ld\ncost_diff %d ref_cost_diff%d\ndist_diff %ld "
1926 "ref_dist_diff %ld\neob %d new_eob %d\n\n",
1927 rd_diff, cost_diff, ref_cost_diff, dist_diff, ref_dist_diff, org_eob,
1928 txb_info->eob);
1929#endif
1930 if (dry_run) {
1931 txb_info->qcoeff = org_qcoeff;
1932 txb_info->dqcoeff = org_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001933 txb_info->levels = org_levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001934 set_eob(txb_info, org_eob);
1935 }
1936 return update;
1937}
1938
1939#else
Jingning Handfd72322017-08-09 14:04:12 -07001940static int optimize_txb(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang25645b72017-09-24 14:28:49 -07001941 TxbCache *txb_cache, int dry_run, int fast_mode) {
Angie Chiang07c57f32017-05-30 18:18:33 -07001942 int update = 0;
1943 if (txb_info->eob == 0) return update;
1944 int cost_diff = 0;
1945 int64_t dist_diff = 0;
1946 int64_t rd_diff = 0;
Urvang Joshi80893152017-10-27 11:51:14 -07001947 const int max_eob = av1_get_max_eob(txb_info->tx_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07001948
1949#if TEST_OPTIMIZE_TXB
1950 int64_t sse;
1951 int64_t org_dist =
1952 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1953 (1 << (2 * txb_info->shift));
Angie Chiang0b2795c2017-09-29 16:00:08 -07001954 int org_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang07c57f32017-05-30 18:18:33 -07001955#endif
1956
1957 tran_low_t *org_qcoeff = txb_info->qcoeff;
1958 tran_low_t *org_dqcoeff = txb_info->dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001959 uint8_t *const org_levels = txb_info->levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07001960
1961 tran_low_t tmp_qcoeff[MAX_TX_SQUARE];
1962 tran_low_t tmp_dqcoeff[MAX_TX_SQUARE];
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001963 uint8_t tmp_levels_buf[TX_PAD_2D];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001964 uint8_t *const tmp_levels = set_levels(tmp_levels_buf, txb_info->width);
Angie Chiang07c57f32017-05-30 18:18:33 -07001965 const int org_eob = txb_info->eob;
1966 if (dry_run) {
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001967 const int stride = txb_info->width + TX_PAD_HOR;
1968 const int levels_size =
1969
1970 (stride * (txb_info->height + TX_PAD_VER) + TX_PAD_END);
Angie Chiang07c57f32017-05-30 18:18:33 -07001971 memcpy(tmp_qcoeff, org_qcoeff, sizeof(org_qcoeff[0]) * max_eob);
1972 memcpy(tmp_dqcoeff, org_dqcoeff, sizeof(org_dqcoeff[0]) * max_eob);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001973 memcpy(tmp_levels, org_levels - TX_PAD_TOP * stride,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001974 sizeof(org_levels[0]) * levels_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07001975 txb_info->qcoeff = tmp_qcoeff;
1976 txb_info->dqcoeff = tmp_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001977 txb_info->levels = tmp_levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07001978 }
1979
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001980 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang07c57f32017-05-30 18:18:33 -07001981
1982 // forward optimize the nz_map
1983 const int cur_eob = txb_info->eob;
1984 for (int si = 0; si < cur_eob; ++si) {
1985 const int coeff_idx = scan[si];
1986 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1987 if (abs(qc) == 1) {
1988 LevelDownStats stats;
Angie Chiang25645b72017-09-24 14:28:49 -07001989 try_level_down_facade(&stats, si, txb_cache, txb_costs, txb_info,
1990 fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07001991 if (stats.update) {
1992 update = 1;
1993 cost_diff += stats.cost_diff;
1994 dist_diff += stats.dist_diff;
1995 rd_diff += stats.rd_diff;
1996 update_level_down(coeff_idx, txb_cache, txb_info);
1997 set_eob(txb_info, stats.new_eob);
1998 }
1999 }
2000 }
2001
2002 // backward optimize the level-k map
Angie Chiang530b3042017-08-17 15:08:58 -07002003 int eob_fix = 0;
Angie Chiang07c57f32017-05-30 18:18:33 -07002004 for (int si = txb_info->eob - 1; si >= 0; --si) {
Angie Chiang530b3042017-08-17 15:08:58 -07002005 const int coeff_idx = scan[si];
2006 if (eob_fix == 1 && txb_info->qcoeff[coeff_idx] == 1) {
2007 // when eob is fixed, there is not need to optimize again when
2008 // abs(qc) == 1
2009 continue;
2010 }
Angie Chiang07c57f32017-05-30 18:18:33 -07002011 LevelDownStats stats;
Angie Chiang25645b72017-09-24 14:28:49 -07002012 try_level_down_facade(&stats, si, txb_cache, txb_costs, txb_info,
2013 fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07002014 if (stats.update) {
2015#if TEST_OPTIMIZE_TXB
2016// printf("si %d low_qc %d cost_diff %d dist_diff %ld rd_diff %ld eob %d new_eob
2017// %d\n", si, stats.low_qc, stats.cost_diff, stats.dist_diff, stats.rd_diff,
2018// txb_info->eob, stats.new_eob);
2019#endif
2020 update = 1;
2021 cost_diff += stats.cost_diff;
2022 dist_diff += stats.dist_diff;
2023 rd_diff += stats.rd_diff;
2024 update_level_down(coeff_idx, txb_cache, txb_info);
2025 set_eob(txb_info, stats.new_eob);
2026 }
Angie Chiang530b3042017-08-17 15:08:58 -07002027 if (eob_fix == 0 && txb_info->qcoeff[coeff_idx] != 0) eob_fix = 1;
Angie Chiang07c57f32017-05-30 18:18:33 -07002028 if (si > txb_info->eob) si = txb_info->eob;
2029 }
2030#if TEST_OPTIMIZE_TXB
2031 int64_t new_dist =
2032 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
2033 (1 << (2 * txb_info->shift));
Angie Chiang0b2795c2017-09-29 16:00:08 -07002034 int new_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang07c57f32017-05-30 18:18:33 -07002035 int64_t ref_dist_diff = new_dist - org_dist;
2036 int ref_cost_diff = new_cost - org_cost;
2037 if (cost_diff != ref_cost_diff || dist_diff != ref_dist_diff)
2038 printf(
2039 "overall rd_diff %ld\ncost_diff %d ref_cost_diff%d\ndist_diff %ld "
2040 "ref_dist_diff %ld\neob %d new_eob %d\n\n",
2041 rd_diff, cost_diff, ref_cost_diff, dist_diff, ref_dist_diff, org_eob,
2042 txb_info->eob);
2043#endif
2044 if (dry_run) {
2045 txb_info->qcoeff = org_qcoeff;
2046 txb_info->dqcoeff = org_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07002047 txb_info->levels = org_levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07002048 set_eob(txb_info, org_eob);
2049 }
2050 return update;
2051}
Dake Hea47cd6c2017-10-13 18:09:58 -07002052#endif
Angie Chiang07c57f32017-05-30 18:18:33 -07002053
2054// These numbers are empirically obtained.
2055static const int plane_rd_mult[REF_TYPES][PLANE_TYPES] = {
Angie Chiang07c57f32017-05-30 18:18:33 -07002056 { 17, 13 }, { 16, 10 },
Angie Chiang07c57f32017-05-30 18:18:33 -07002057};
2058
Jingning Han7eab9ff2017-07-06 10:12:54 -07002059int av1_optimize_txb(const AV1_COMMON *cm, MACROBLOCK *x, int plane,
2060 int blk_row, int blk_col, int block, TX_SIZE tx_size,
Angie Chiang25645b72017-09-24 14:28:49 -07002061 TXB_CTX *txb_ctx, int fast_mode) {
Angie Chiang07c57f32017-05-30 18:18:33 -07002062 MACROBLOCKD *const xd = &x->e_mbd;
2063 const PLANE_TYPE plane_type = get_plane_type(plane);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -08002064 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Jingning Han19b5c8f2017-07-06 15:10:12 -07002065 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002066 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07002067 const MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
2068 const struct macroblock_plane *p = &x->plane[plane];
2069 struct macroblockd_plane *pd = &xd->plane[plane];
2070 const int eob = p->eobs[block];
2071 tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2072 tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
2073 const tran_low_t *tcoeff = BLOCK_OFFSET(p->coeff, block);
Monty Montgomery125c0fc2017-10-26 00:44:35 -04002074 const int16_t *dequant = p->dequant_QTX;
Urvang Joshi80893152017-10-27 11:51:14 -07002075 const int seg_eob = av1_get_max_eob(tx_size);
Angie Chianga9ba58e2017-12-01 19:22:43 -08002076 const int bwl = get_txb_bwl(tx_size);
2077 const int width = get_txb_wide(tx_size);
2078 const int height = get_txb_high(tx_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07002079 const int is_inter = is_inter_block(mbmi);
Angie Chiangbd99b382017-06-20 15:11:16 -07002080 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Jingning Handfd72322017-08-09 14:04:12 -07002081 const LV_MAP_COEFF_COST txb_costs = x->coeff_costs[txs_ctx][plane_type];
Sarah Parker3d752092017-12-20 15:37:55 -08002082#if CONFIG_NEW_QUANT
2083 int dq = get_dq_profile(x->qindex, is_inter, plane_type);
2084 const dequant_val_type_nuq *dequant_val = p->dequant_val_nuq_QTX[dq];
2085#endif // CONFIG_NEW_QUANT
Angie Chiang07c57f32017-05-30 18:18:33 -07002086
Montybca9e9e2017-12-14 06:23:29 -06002087#if CONFIG_DAALA_TX
2088 const int shift = 0;
2089#else
Angie Chiang07c57f32017-05-30 18:18:33 -07002090 const int shift = av1_get_tx_scale(tx_size);
Montybca9e9e2017-12-14 06:23:29 -06002091#endif
Angie Chiang07c57f32017-05-30 18:18:33 -07002092 const int64_t rdmult =
Jingning Hanb433f4c2017-11-17 15:43:59 -08002093 ((x->rdmult * plane_rd_mult[is_inter][plane_type] << (2 * (xd->bd - 8))) +
2094 2) >>
2095 2;
Linfeng Zhang679d81e2017-10-31 15:27:42 -07002096 uint8_t levels_buf[TX_PAD_2D];
2097 uint8_t *const levels = set_levels(levels_buf, width);
Angie Chiang07c57f32017-05-30 18:18:33 -07002098
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002099 assert(width == (1 << bwl));
Linfeng Zhang1015a342017-10-24 16:20:41 -07002100 TxbInfo txb_info = {
Sarah Parker3d752092017-12-20 15:37:55 -08002101 qcoeff,
2102 levels,
2103 dqcoeff,
2104 tcoeff,
2105 dequant,
2106#if CONFIG_NEW_QUANT
2107 dequant_val,
2108#endif // CONFIG_NEW_QUANT
2109 shift,
2110 tx_size,
2111 txs_ctx,
2112 tx_type,
2113 bwl,
2114 width,
2115 height,
2116 eob,
2117 seg_eob,
2118 scan_order,
2119 txb_ctx,
2120 rdmult,
2121 &cm->coeff_ctx_table
Linfeng Zhang1015a342017-10-24 16:20:41 -07002122 };
2123
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002124 av1_txb_init_levels(qcoeff, width, height, levels);
Urvang Joshi70006e42017-06-14 16:08:55 -07002125
Angie Chiang93af45f2017-10-23 18:19:59 -07002126 const int update = optimize_txb(&txb_info, &txb_costs, NULL, 0, fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07002127
Jingning Hand7e99112017-12-13 09:47:45 -08002128 if (update) {
2129 p->eobs[block] = txb_info.eob;
2130 p->txb_entropy_ctx[block] =
2131 av1_get_txb_entropy_context(qcoeff, scan_order, txb_info.eob);
2132 }
Angie Chiang07c57f32017-05-30 18:18:33 -07002133 return txb_info.eob;
2134}
Jingning Hand7e99112017-12-13 09:47:45 -08002135
Angie Chiang74e23072017-03-24 14:54:23 -07002136int av1_get_txb_entropy_context(const tran_low_t *qcoeff,
2137 const SCAN_ORDER *scan_order, int eob) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002138 const int16_t *const scan = scan_order->scan;
Angie Chiang74e23072017-03-24 14:54:23 -07002139 int cul_level = 0;
2140 int c;
Jingning Han339cf932017-09-18 10:17:02 -07002141
2142 if (eob == 0) return 0;
Angie Chiang74e23072017-03-24 14:54:23 -07002143 for (c = 0; c < eob; ++c) {
2144 cul_level += abs(qcoeff[scan[c]]);
2145 }
2146
2147 cul_level = AOMMIN(COEFF_CONTEXT_MASK, cul_level);
2148 set_dc_sign(&cul_level, qcoeff[0]);
2149
2150 return cul_level;
2151}
2152
Jingning Han4fe5f672017-05-19 15:46:07 -07002153void av1_update_txb_context_b(int plane, int block, int blk_row, int blk_col,
2154 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
2155 void *arg) {
Jingning Han6171ae72017-05-18 20:15:06 -07002156 struct tokenize_b_args *const args = arg;
Angie Chiang36d616b2017-03-22 13:58:36 -07002157 const AV1_COMP *cpi = args->cpi;
2158 const AV1_COMMON *cm = &cpi->common;
Angie Chiang0397eda2017-03-15 16:57:14 -07002159 ThreadData *const td = args->td;
2160 MACROBLOCK *const x = &td->mb;
2161 MACROBLOCKD *const xd = &x->e_mbd;
Angie Chiang36d616b2017-03-22 13:58:36 -07002162 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiang0397eda2017-03-15 16:57:14 -07002163 struct macroblock_plane *p = &x->plane[plane];
2164 struct macroblockd_plane *pd = &xd->plane[plane];
Angie Chiang36d616b2017-03-22 13:58:36 -07002165 const uint16_t eob = p->eobs[block];
2166 const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2167 const PLANE_TYPE plane_type = pd->plane_type;
Jingning Han19b5c8f2017-07-06 15:10:12 -07002168 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002169 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07002170 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Angie Chiang0397eda2017-03-15 16:57:14 -07002171 (void)plane_bsize;
Angie Chiang36d616b2017-03-22 13:58:36 -07002172
Angie Chiang74e23072017-03-24 14:54:23 -07002173 int cul_level = av1_get_txb_entropy_context(qcoeff, scan_order, eob);
Angie Chiang36d616b2017-03-22 13:58:36 -07002174 av1_set_contexts(xd, pd, plane, tx_size, cul_level, blk_col, blk_row);
Angie Chiang0397eda2017-03-15 16:57:14 -07002175}
2176
Jingning Han4fe5f672017-05-19 15:46:07 -07002177void av1_update_and_record_txb_context(int plane, int block, int blk_row,
2178 int blk_col, BLOCK_SIZE plane_bsize,
2179 TX_SIZE tx_size, void *arg) {
Jingning Han6171ae72017-05-18 20:15:06 -07002180 struct tokenize_b_args *const args = arg;
Angie Chiang0397eda2017-03-15 16:57:14 -07002181 const AV1_COMP *cpi = args->cpi;
2182 const AV1_COMMON *cm = &cpi->common;
2183 ThreadData *const td = args->td;
2184 MACROBLOCK *const x = &td->mb;
2185 MACROBLOCKD *const xd = &x->e_mbd;
2186 struct macroblock_plane *p = &x->plane[plane];
2187 struct macroblockd_plane *pd = &xd->plane[plane];
2188 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Linfeng Zhang848f7bc2017-10-31 15:26:07 -07002189 int eob = p->eobs[block], update_eob = -1;
Angie Chiang0397eda2017-03-15 16:57:14 -07002190 const PLANE_TYPE plane_type = pd->plane_type;
2191 const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2192 tran_low_t *tcoeff = BLOCK_OFFSET(x->mbmi_ext->tcoeff[plane], block);
2193 const int segment_id = mbmi->segment_id;
Jingning Han19b5c8f2017-07-06 15:10:12 -07002194 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002195 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07002196 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002197 const int16_t *const scan = scan_order->scan;
hui suc0cf71d2017-07-20 16:38:50 -07002198 const int seg_eob = av1_get_tx_eob(&cpi->common.seg, segment_id, tx_size);
Linfeng Zhang1015a342017-10-24 16:20:41 -07002199 int c;
Angie Chiang85901562017-03-17 12:03:27 -07002200 TXB_CTX txb_ctx;
2201 get_txb_ctx(plane_bsize, tx_size, plane, pd->above_context + blk_col,
2202 pd->left_context + blk_row, &txb_ctx);
Angie Chianga9ba58e2017-12-01 19:22:43 -08002203 const int bwl = get_txb_bwl(tx_size);
2204 const int width = get_txb_wide(tx_size);
2205 const int height = get_txb_high(tx_size);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07002206 uint8_t levels_buf[TX_PAD_2D];
2207 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -08002208 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Yunqing Wang0e141b52017-11-02 15:08:58 -07002209 const uint8_t allow_update_cdf = args->allow_update_cdf;
Angie Chiang0397eda2017-03-15 16:57:14 -07002210
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -08002211 TX_SIZE txsize_ctx = get_txsize_entropy_ctx(tx_size);
Jingning Han8f661602017-08-19 08:16:50 -07002212 FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
Linfeng Zhangd67c13f2017-12-11 11:49:12 -08002213 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Jingning Han48be0e12017-06-13 12:12:01 -07002214
Angie Chiang0397eda2017-03-15 16:57:14 -07002215 memcpy(tcoeff, qcoeff, sizeof(*tcoeff) * seg_eob);
2216
Jingning Han48be0e12017-06-13 12:12:01 -07002217 ++td->counts->txb_skip[txsize_ctx][txb_ctx.txb_skip_ctx][eob == 0];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002218 if (allow_update_cdf)
2219 update_bin(ec_ctx->txb_skip_cdf[txsize_ctx][txb_ctx.txb_skip_ctx], eob == 0,
2220 2);
Angie Chiang85901562017-03-17 12:03:27 -07002221 x->mbmi_ext->txb_skip_ctx[plane][block] = txb_ctx.txb_skip_ctx;
Angie Chiang0397eda2017-03-15 16:57:14 -07002222
2223 x->mbmi_ext->eobs[plane][block] = eob;
2224
2225 if (eob == 0) {
2226 av1_set_contexts(xd, pd, plane, tx_size, 0, blk_col, blk_row);
2227 return;
2228 }
2229
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002230 av1_txb_init_levels(tcoeff, width, height, levels);
Linfeng Zhangce065ca2017-10-17 16:49:30 -07002231
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002232#if CONFIG_TXK_SEL
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002233 av1_update_tx_type_count(cm, xd, blk_row, blk_col, plane, mbmi->sb_type,
Debargha Mukherjee3ebb0d02017-12-14 05:05:18 -08002234 tx_size, td->counts, allow_update_cdf);
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002235#endif
Angie Chiang0397eda2017-03-15 16:57:14 -07002236
Dake He4d447692017-12-15 09:10:06 -08002237#if !CONFIG_LV_MAP_MULTI
Dake Hea47cd6c2017-10-13 18:09:58 -07002238 unsigned int(*nz_map_count)[SIG_COEF_CONTEXTS][2] =
2239 &(td->counts->nz_map[txsize_ctx][plane_type]);
Dake He4d447692017-12-15 09:10:06 -08002240#endif
Jingning Han35deaa72017-10-26 15:36:30 -07002241 av1_update_eob_context(eob, seg_eob, tx_size, tx_type, plane_type, ec_ctx,
Yunqing Wang0e141b52017-11-02 15:08:58 -07002242 td->counts, allow_update_cdf);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -08002243
2244 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_type, coeff_contexts);
2245
Dake He03a32922017-10-31 08:06:45 -07002246 update_eob = eob - 1;
Dake Hea47cd6c2017-10-13 18:09:58 -07002247 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002248 const int pos = scan[c];
Linfeng Zhangd67c13f2017-12-11 11:49:12 -08002249 const int coeff_ctx = coeff_contexts[pos];
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002250 const tran_low_t v = qcoeff[pos];
2251 const int is_nz = (v != 0);
Dake He03a32922017-10-31 08:06:45 -07002252
Ola Hugosson13892102017-11-06 08:01:44 +01002253#if CONFIG_LV_MAP_MULTI
2254 (void)is_nz;
Dake He4d447692017-12-15 09:10:06 -08002255 if (allow_update_cdf) {
2256 if (c == eob - 1) {
2257 assert(coeff_ctx < 4);
2258 update_cdf(
2259 ec_ctx->coeff_base_eob_cdf[txsize_ctx][plane_type][coeff_ctx],
2260 AOMMIN(abs(v), 3) - 1, 3);
2261 } else {
2262 update_cdf(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][coeff_ctx],
2263 AOMMIN(abs(v), 3), 4);
2264 }
Dake He3fe369c2017-11-16 17:56:44 -08002265 }
Dake He59881772017-11-24 07:00:02 -08002266 {
Dake He4d447692017-12-15 09:10:06 -08002267 if (c == eob - 1) {
2268 assert(coeff_ctx < 4);
2269 ++td->counts->coeff_base_eob_multi[txsize_ctx][plane_type][coeff_ctx]
2270 [AOMMIN(abs(v), 3) - 1];
2271 } else {
2272 ++td->counts->coeff_base_multi[txsize_ctx][plane_type][coeff_ctx]
2273 [AOMMIN(abs(v), 3)];
Dake He59881772017-11-24 07:00:02 -08002274 }
2275 }
2276
Dake He3fe369c2017-11-16 17:56:44 -08002277#else
Dake He03a32922017-10-31 08:06:45 -07002278 if (c < eob - 1) {
2279 ++(*nz_map_count)[coeff_ctx][is_nz];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002280 if (allow_update_cdf)
2281 update_cdf(ec_ctx->nz_map_cdf[txsize_ctx][plane_type][coeff_ctx], is_nz,
2282 2);
Dake He03a32922017-10-31 08:06:45 -07002283 }
2284
2285 if (is_nz) {
2286 int k;
2287 for (k = 0; k < NUM_BASE_LEVELS; ++k) {
2288 int ctx = coeff_ctx;
2289 int is_k = (abs(v) > (k + 1));
2290
2291 ++td->counts->coeff_base[txsize_ctx][plane_type][k][ctx][is_k];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002292 if (allow_update_cdf)
2293 update_bin(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][k][ctx],
2294 is_k, 2);
Dake He03a32922017-10-31 08:06:45 -07002295 if (is_k == 0) break;
2296 }
2297 }
Dake He03a32922017-10-31 08:06:45 -07002298#endif
Dake Hea47cd6c2017-10-13 18:09:58 -07002299 }
Dake Hea47cd6c2017-10-13 18:09:58 -07002300
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002301 // Update the context needed to code the DC sign (if applicable)
2302 const int sign = (tcoeff[0] < 0) ? 1 : 0;
2303 if (tcoeff[0] != 0) {
Dake He43edb762017-10-26 10:29:46 -07002304 int dc_sign_ctx = txb_ctx.dc_sign_ctx;
2305
2306 ++td->counts->dc_sign[plane_type][dc_sign_ctx][sign];
2307#if LV_MAP_PROB
Yunqing Wang0e141b52017-11-02 15:08:58 -07002308 if (allow_update_cdf)
2309 update_bin(ec_ctx->dc_sign_cdf[plane_type][dc_sign_ctx], sign, 2);
Dake He43edb762017-10-26 10:29:46 -07002310#endif
2311 x->mbmi_ext->dc_sign_ctx[plane][block] = dc_sign_ctx;
2312 }
2313
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002314 if (update_eob >= 0) {
Dake He7d01ab52017-11-24 17:53:28 -08002315#if !CONFIG_LV_MAP_MULTI
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002316 av1_get_br_level_counts(levels, width, height, level_counts);
Dake He7d01ab52017-11-24 17:53:28 -08002317#endif
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002318 for (c = update_eob; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002319 const int pos = scan[c];
2320 const tran_low_t level = abs(tcoeff[pos]);
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002321 int idx;
2322 int ctx;
Angie Chiang0397eda2017-03-15 16:57:14 -07002323
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002324 if (level <= NUM_BASE_LEVELS) continue;
Angie Chiang0397eda2017-03-15 16:57:14 -07002325
Dake He7d01ab52017-11-24 17:53:28 -08002326// level is above 1.
2327#if !CONFIG_LV_MAP_MULTI
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002328 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -08002329#endif
Jingning Han87b01b52017-08-31 12:07:20 -07002330
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002331 const int base_range = level - 1 - NUM_BASE_LEVELS;
Ola Hugossone72a2092017-11-12 09:11:53 +01002332#if CONFIG_LV_MAP_MULTI
Dake He7d01ab52017-11-24 17:53:28 -08002333#if USE_CAUSAL_BR_CTX
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002334 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos], tx_type);
Dake He7d01ab52017-11-24 17:53:28 -08002335#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002336 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -08002337#endif
Ola Hugossone72a2092017-11-12 09:11:53 +01002338 for (idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002339 const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
Dake He4d447692017-12-15 09:10:06 -08002340 if (allow_update_cdf) {
2341 update_cdf(
Dake Hee2d8f182017-12-14 13:28:00 -08002342#if 0
Dake He7d01ab52017-11-24 17:53:28 -08002343 ec_ctx->coeff_br_cdf[AOMMIN(txsize_ctx, TX_16X16)][plane_type][ctx],
Dake Hee2d8f182017-12-14 13:28:00 -08002344#else
Dake He4d447692017-12-15 09:10:06 -08002345 ec_ctx
2346 ->coeff_br_cdf[AOMMIN(txsize_ctx, TX_32X32)][plane_type][ctx],
Dake Hee2d8f182017-12-14 13:28:00 -08002347#endif
Dake He4d447692017-12-15 09:10:06 -08002348 k, BR_CDF_SIZE);
2349 }
Dake He7d01ab52017-11-24 17:53:28 -08002350 for (int lps = 0; lps < BR_CDF_SIZE - 1; lps++) {
Dake Hee2d8f182017-12-14 13:28:00 -08002351#if 0
Dake He7d01ab52017-11-24 17:53:28 -08002352 ++td->counts->coeff_lps[AOMMIN(txsize_ctx, TX_16X16)][plane_type][lps]
2353 [ctx][lps == k];
Dake Hee2d8f182017-12-14 13:28:00 -08002354#else
2355 ++td->counts->coeff_lps[AOMMIN(txsize_ctx, TX_32X32)][plane_type][lps]
2356 [ctx][lps == k];
2357#endif
Dake He59881772017-11-24 07:00:02 -08002358 if (lps == k) break;
2359 }
Dake Hee2d8f182017-12-14 13:28:00 -08002360 ++td->counts->coeff_lps_multi[AOMMIN(txsize_ctx, TX_32X32)][plane_type]
2361 [ctx][k];
Dake He59881772017-11-24 07:00:02 -08002362
Ola Hugossone72a2092017-11-12 09:11:53 +01002363 if (k < BR_CDF_SIZE - 1) break;
2364 }
2365#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002366 const int br_set_idx = base_range < COEFF_BASE_RANGE
2367 ? coeff_to_br_index[base_range]
2368 : BASE_RANGE_SETS;
Jingning Han87b01b52017-08-31 12:07:20 -07002369
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002370 for (idx = 0; idx < BASE_RANGE_SETS; ++idx) {
2371 if (idx == br_set_idx) {
2372 int br_base = br_index_to_coeff[br_set_idx];
2373 int br_offset = base_range - br_base;
2374 ++td->counts->coeff_br[txsize_ctx][plane_type][idx][ctx][1];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002375 if (allow_update_cdf)
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002376 update_bin(ec_ctx->coeff_br_cdf[txsize_ctx][plane_type][idx][ctx],
2377 1, 2);
2378 int extra_bits = (1 << br_extra_bits[idx]) - 1;
2379 for (int tok = 0; tok < extra_bits; ++tok) {
2380 if (br_offset == tok) {
2381 ++td->counts->coeff_lps[txsize_ctx][plane_type][ctx][1];
2382 if (allow_update_cdf)
2383 update_bin(ec_ctx->coeff_lps_cdf[txsize_ctx][plane_type][ctx],
2384 1, 2);
2385 break;
2386 }
2387 ++td->counts->coeff_lps[txsize_ctx][plane_type][ctx][0];
2388 if (allow_update_cdf)
2389 update_bin(ec_ctx->coeff_lps_cdf[txsize_ctx][plane_type][ctx], 0,
2390 2);
2391 }
2392 break;
Jingning Han87b01b52017-08-31 12:07:20 -07002393 }
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002394 ++td->counts->coeff_br[txsize_ctx][plane_type][idx][ctx][0];
2395 if (allow_update_cdf)
2396 update_bin(ec_ctx->coeff_br_cdf[txsize_ctx][plane_type][idx][ctx], 0,
2397 2);
Jingning Han87b01b52017-08-31 12:07:20 -07002398 }
Ola Hugossone72a2092017-11-12 09:11:53 +01002399#endif
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002400 // use 0-th order Golomb code to handle the residual level.
Jingning Han87b01b52017-08-31 12:07:20 -07002401 }
Angie Chiang0397eda2017-03-15 16:57:14 -07002402 }
Angie Chiang36d616b2017-03-22 13:58:36 -07002403
Angie Chiang63d190a2017-10-23 15:43:05 -07002404 int cul_level = av1_get_txb_entropy_context(tcoeff, scan_order, eob);
Angie Chiang0397eda2017-03-15 16:57:14 -07002405 av1_set_contexts(xd, pd, plane, tx_size, cul_level, blk_col, blk_row);
2406}
2407
2408void av1_update_txb_context(const AV1_COMP *cpi, ThreadData *td,
2409 RUN_TYPE dry_run, BLOCK_SIZE bsize, int *rate,
Yunqing Wang0e141b52017-11-02 15:08:58 -07002410 int mi_row, int mi_col, uint8_t allow_update_cdf) {
Angie Chiang0397eda2017-03-15 16:57:14 -07002411 MACROBLOCK *const x = &td->mb;
2412 MACROBLOCKD *const xd = &x->e_mbd;
2413 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yunqing Wang0e141b52017-11-02 15:08:58 -07002414 struct tokenize_b_args arg = { cpi, td, NULL, 0, allow_update_cdf };
Angie Chiang0397eda2017-03-15 16:57:14 -07002415 (void)rate;
2416 (void)mi_row;
2417 (void)mi_col;
2418 if (mbmi->skip) {
Timothy B. Terriberrya2d5cde2017-05-10 18:33:50 -07002419 av1_reset_skip_context(xd, mi_row, mi_col, bsize);
Angie Chiang0397eda2017-03-15 16:57:14 -07002420 return;
2421 }
2422
2423 if (!dry_run) {
Jingning Han94652b82017-04-04 09:45:02 -07002424 av1_foreach_transformed_block(xd, bsize, mi_row, mi_col,
Jingning Han4fe5f672017-05-19 15:46:07 -07002425 av1_update_and_record_txb_context, &arg);
Angie Chiangc8af6112017-03-16 16:11:22 -07002426 } else if (dry_run == DRY_RUN_NORMAL) {
Jingning Han4fe5f672017-05-19 15:46:07 -07002427 av1_foreach_transformed_block(xd, bsize, mi_row, mi_col,
2428 av1_update_txb_context_b, &arg);
Angie Chiangc8af6112017-03-16 16:11:22 -07002429 } else {
2430 printf("DRY_RUN_COSTCOEFFS is not supported yet\n");
2431 assert(0);
Angie Chiang0397eda2017-03-15 16:57:14 -07002432 }
2433}
Angie Chiang800df032017-03-22 11:14:12 -07002434
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002435#if CONFIG_TXK_SEL
Angie Chiang808d8592017-04-06 18:36:55 -07002436int64_t av1_search_txk_type(const AV1_COMP *cpi, MACROBLOCK *x, int plane,
2437 int block, int blk_row, int blk_col,
2438 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
Angie Chiang65a39bb2017-04-11 16:50:04 -07002439 const ENTROPY_CONTEXT *a, const ENTROPY_CONTEXT *l,
2440 int use_fast_coef_costing, RD_STATS *rd_stats) {
Angie Chiang808d8592017-04-06 18:36:55 -07002441 const AV1_COMMON *cm = &cpi->common;
2442 MACROBLOCKD *xd = &x->e_mbd;
2443 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
2444 TX_TYPE txk_start = DCT_DCT;
2445 TX_TYPE txk_end = TX_TYPES - 1;
2446 TX_TYPE best_tx_type = txk_start;
2447 int64_t best_rd = INT64_MAX;
Angie Chiang4e16ea62017-12-15 17:58:44 -08002448 uint8_t best_txb_ctx = 0;
2449 uint16_t best_eob = 0;
Jingning Hane3b81bc2017-06-23 11:43:52 -07002450 RD_STATS best_rd_stats;
Angie Chiang808d8592017-04-06 18:36:55 -07002451 TX_TYPE tx_type;
Jingning Hane3b81bc2017-06-23 11:43:52 -07002452
2453 av1_invalid_rd_stats(&best_rd_stats);
2454
Angie Chiang808d8592017-04-06 18:36:55 -07002455 for (tx_type = txk_start; tx_type <= txk_end; ++tx_type) {
Angie Chiangbce07f12017-12-01 16:34:31 -08002456 if (plane == 0)
2457 mbmi->txk_type[(blk_row << MAX_MIB_SIZE_LOG2) + blk_col] = tx_type;
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002458 TX_TYPE ref_tx_type =
2459 av1_get_tx_type(get_plane_type(plane), xd, blk_row, blk_col, tx_size);
Angie Chiang00491e02017-04-11 17:55:10 -07002460 if (tx_type != ref_tx_type) {
hui su45b64752017-07-12 16:54:35 -07002461 // use av1_get_tx_type() to check if the tx_type is valid for the current
2462 // mode if it's not, we skip it here.
Angie Chiang00491e02017-04-11 17:55:10 -07002463 continue;
2464 }
Jingning Hane57d6322017-07-03 18:50:25 -07002465
Hui Suddbcde22017-09-18 17:22:02 -07002466 const int is_inter = is_inter_block(mbmi);
Angie Chiang53bf1e92017-11-29 16:53:07 -08002467 const TxSetType tx_set_type = get_ext_tx_set_type(
2468 tx_size, mbmi->sb_type, is_inter, cm->reduced_tx_set_used);
Hui Suddbcde22017-09-18 17:22:02 -07002469 if (!av1_ext_tx_used[tx_set_type][tx_type]) continue;
Jingning Hane57d6322017-07-03 18:50:25 -07002470
Angie Chiang808d8592017-04-06 18:36:55 -07002471 RD_STATS this_rd_stats;
2472 av1_invalid_rd_stats(&this_rd_stats);
Sarah Parker792c2ec2017-12-21 16:08:22 -08002473 if (cpi->sf.optimize_coefficients != FULL_TRELLIS_OPT) {
2474 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize,
2475 tx_size, AV1_XFORM_QUANT_B);
2476 } else {
2477 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize,
2478 tx_size, AV1_XFORM_QUANT_FP);
2479 av1_optimize_b(cm, x, plane, blk_row, blk_col, block, plane_bsize,
2480 tx_size, a, l, 1);
2481 }
Angie Chiang808d8592017-04-06 18:36:55 -07002482 av1_dist_block(cpi, x, plane, plane_bsize, block, blk_row, blk_col, tx_size,
Angie Chiang2ed03a32017-04-16 18:00:06 -07002483 &this_rd_stats.dist, &this_rd_stats.sse,
2484 OUTPUT_HAS_PREDICTED_PIXELS);
Angie Chiangbd99b382017-06-20 15:11:16 -07002485 const SCAN_ORDER *scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Jingning Han7eab9ff2017-07-06 10:12:54 -07002486 this_rd_stats.rate =
2487 av1_cost_coeffs(cpi, x, plane, blk_row, blk_col, block, tx_size,
2488 scan_order, a, l, use_fast_coef_costing);
Urvang Joshi70006e42017-06-14 16:08:55 -07002489 int rd = RDCOST(x->rdmult, this_rd_stats.rate, this_rd_stats.dist);
Jingning Han19b5c8f2017-07-06 15:10:12 -07002490
Angie Chiang808d8592017-04-06 18:36:55 -07002491 if (rd < best_rd) {
2492 best_rd = rd;
Jingning Hane3b81bc2017-06-23 11:43:52 -07002493 best_rd_stats = this_rd_stats;
Angie Chiang808d8592017-04-06 18:36:55 -07002494 best_tx_type = tx_type;
Angie Chiang4e16ea62017-12-15 17:58:44 -08002495 best_txb_ctx = x->plane[plane].txb_entropy_ctx[block];
2496 best_eob = x->plane[plane].eobs[block];
Angie Chiang808d8592017-04-06 18:36:55 -07002497 }
2498 }
Jingning Hane3b81bc2017-06-23 11:43:52 -07002499
2500 av1_merge_rd_stats(rd_stats, &best_rd_stats);
2501
Angie Chianga3f7d2e2017-12-07 19:51:14 -08002502 if (best_eob == 0) best_tx_type = DCT_DCT;
Jingning Han19b5c8f2017-07-06 15:10:12 -07002503
Angie Chiangbce07f12017-12-01 16:34:31 -08002504 if (plane == 0)
2505 mbmi->txk_type[(blk_row << MAX_MIB_SIZE_LOG2) + blk_col] = best_tx_type;
Angie Chiang4e16ea62017-12-15 17:58:44 -08002506 x->plane[plane].txb_entropy_ctx[block] = best_txb_ctx;
Angie Chiang6f90fb22017-12-20 16:30:20 -08002507 x->plane[plane].eobs[block] = best_eob;
Jingning Han47558172017-07-05 16:33:19 -07002508
Angie Chiang2ed03a32017-04-16 18:00:06 -07002509 if (!is_inter_block(mbmi)) {
Sarah Parker792c2ec2017-12-21 16:08:22 -08002510 // intra mode needs decoded result such that the next transform block
2511 // can use it for prediction.
2512 if (cpi->sf.optimize_coefficients != FULL_TRELLIS_OPT) {
2513 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize,
2514 tx_size, AV1_XFORM_QUANT_B);
2515 } else {
2516 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize,
2517 tx_size, AV1_XFORM_QUANT_FP);
2518 av1_optimize_b(cm, x, plane, blk_row, blk_col, block, plane_bsize,
2519 tx_size, a, l, 1);
2520 }
Jingning Han47558172017-07-05 16:33:19 -07002521
Angie Chiang2ed03a32017-04-16 18:00:06 -07002522 av1_inverse_transform_block_facade(xd, plane, block, blk_row, blk_col,
Frederic Barbier33b39f02017-11-21 11:11:24 +01002523 x->plane[plane].eobs[block],
2524 cm->reduced_tx_set_used);
Angie Chiang2ed03a32017-04-16 18:00:06 -07002525 }
Angie Chiang808d8592017-04-06 18:36:55 -07002526 return best_rd;
2527}
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002528#endif // CONFIG_TXK_SEL