blob: 21d4a1dba2f7351bd6551c390cfc0bede75a453d [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;
38 int nz_rate; // for eob
Dake Hea47cd6c2017-10-13 18:09:58 -070039 int64_t rd_diff;
40 int cost_diff;
41 int64_t dist_diff;
42 int new_eob;
43} LevelDownStats;
44
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070045void av1_alloc_txb_buf(AV1_COMP *cpi) {
Angie Chiangc484abe2017-03-20 15:43:11 -070046#if 0
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070047 AV1_COMMON *cm = &cpi->common;
48 int mi_block_size = 1 << MI_SIZE_LOG2;
49 // TODO(angiebird): Make sure cm->subsampling_x/y is set correctly, and then
50 // use precise buffer size according to cm->subsampling_x/y
51 int pixel_stride = mi_block_size * cm->mi_cols;
52 int pixel_height = mi_block_size * cm->mi_rows;
53 int i;
54 for (i = 0; i < MAX_MB_PLANE; ++i) {
55 CHECK_MEM_ERROR(
56 cm, cpi->tcoeff_buf[i],
57 aom_malloc(sizeof(*cpi->tcoeff_buf[i]) * pixel_stride * pixel_height));
58 }
Angie Chiangc484abe2017-03-20 15:43:11 -070059#else
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070060 AV1_COMMON *cm = &cpi->common;
61 int size = ((cm->mi_rows >> MAX_MIB_SIZE_LOG2) + 1) *
62 ((cm->mi_cols >> MAX_MIB_SIZE_LOG2) + 1);
63
Angie Chiang9367e3e2017-10-02 16:28:11 -070064 av1_free_txb_buf(cpi);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070065 // TODO(jingning): This should be further reduced.
66 CHECK_MEM_ERROR(cm, cpi->coeff_buffer_base,
67 aom_malloc(sizeof(*cpi->coeff_buffer_base) * size));
Angie Chiangc484abe2017-03-20 15:43:11 -070068#endif
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070069}
70
71void av1_free_txb_buf(AV1_COMP *cpi) {
Angie Chiangc484abe2017-03-20 15:43:11 -070072#if 0
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070073 int i;
74 for (i = 0; i < MAX_MB_PLANE; ++i) {
75 aom_free(cpi->tcoeff_buf[i]);
76 }
Angie Chiangc484abe2017-03-20 15:43:11 -070077#else
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070078 aom_free(cpi->coeff_buffer_base);
Angie Chiangc484abe2017-03-20 15:43:11 -070079#endif
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070080}
81
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070082void av1_set_coeff_buffer(const AV1_COMP *const cpi, MACROBLOCK *const x,
83 int mi_row, int mi_col) {
84 int stride = (cpi->common.mi_cols >> MAX_MIB_SIZE_LOG2) + 1;
85 int offset =
86 (mi_row >> MAX_MIB_SIZE_LOG2) * stride + (mi_col >> MAX_MIB_SIZE_LOG2);
87 CB_COEFF_BUFFER *coeff_buf = &cpi->coeff_buffer_base[offset];
88 const int txb_offset = x->cb_offset / (TX_SIZE_W_MIN * TX_SIZE_H_MIN);
89 for (int plane = 0; plane < MAX_MB_PLANE; ++plane) {
90 x->mbmi_ext->tcoeff[plane] = coeff_buf->tcoeff[plane] + x->cb_offset;
91 x->mbmi_ext->eobs[plane] = coeff_buf->eobs[plane] + txb_offset;
92 x->mbmi_ext->txb_skip_ctx[plane] =
93 coeff_buf->txb_skip_ctx[plane] + txb_offset;
94 x->mbmi_ext->dc_sign_ctx[plane] =
95 coeff_buf->dc_sign_ctx[plane] + txb_offset;
96 }
97}
98
Angie Chiang80b82262017-02-24 11:39:47 -080099static void write_golomb(aom_writer *w, int level) {
100 int x = level + 1;
101 int i = x;
102 int length = 0;
103
104 while (i) {
105 i >>= 1;
106 ++length;
107 }
108 assert(length > 0);
109
110 for (i = 0; i < length - 1; ++i) aom_write_bit(w, 0);
111
112 for (i = length - 1; i >= 0; --i) aom_write_bit(w, (x >> i) & 0x01);
113}
114
Dake Hea47cd6c2017-10-13 18:09:58 -0700115static INLINE tran_low_t get_lower_coeff(tran_low_t qc) {
116 if (qc == 0) {
117 return 0;
118 }
119 return qc > 0 ? qc - 1 : qc + 1;
120}
121
122static INLINE tran_low_t qcoeff_to_dqcoeff(tran_low_t qc, int dqv, int shift) {
123 int sgn = qc < 0 ? -1 : 1;
124 return sgn * ((abs(qc) * dqv) >> shift);
125}
126
127static INLINE int64_t get_coeff_dist(tran_low_t tcoeff, tran_low_t dqcoeff,
128 int shift) {
129 const int64_t diff = (tcoeff - dqcoeff) * (1 << shift);
130 const int64_t error = diff * diff;
131 return error;
132}
133
Jingning Han35deaa72017-10-26 15:36:30 -0700134void av1_update_eob_context(int eob, int seg_eob, TX_SIZE tx_size,
135 TX_TYPE tx_type, PLANE_TYPE plane,
Yunqing Wang0e141b52017-11-02 15:08:58 -0700136 FRAME_CONTEXT *ec_ctx, FRAME_COUNTS *counts,
137 uint8_t allow_update_cdf) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700138 int16_t eob_extra;
139 int16_t eob_pt = get_eob_pos_token(eob, &eob_extra);
140 int16_t dummy;
141 int16_t max_eob_pt = get_eob_pos_token(seg_eob, &dummy);
Jingning Han35deaa72017-10-26 15:36:30 -0700142 TX_SIZE txs_ctx = get_txsize_context(tx_size);
Dake Hea47cd6c2017-10-13 18:09:58 -0700143
144 for (int i = 1; i < max_eob_pt; i++) {
Jingning Han35deaa72017-10-26 15:36:30 -0700145 int eob_pos_ctx = av1_get_eob_pos_ctx(tx_type, i);
146 counts->eob_flag[txs_ctx][plane][eob_pos_ctx][eob_pt == i]++;
Yunqing Wang0e141b52017-11-02 15:08:58 -0700147 if (allow_update_cdf)
148 update_cdf(ec_ctx->eob_flag_cdf[txs_ctx][plane][eob_pos_ctx], eob_pt == i,
149 2);
Dake Hea47cd6c2017-10-13 18:09:58 -0700150 if (eob_pt == i) {
151 break;
152 }
153 }
Jingning Han00803a72017-10-25 16:04:34 -0700154
Angie Chiang7ab884e2017-10-18 15:57:12 -0700155 if (k_eob_offset_bits[eob_pt] > 0) {
156 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
157 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Jingning Han35deaa72017-10-26 15:36:30 -0700158 counts->eob_extra[txs_ctx][plane][eob_pt][bit]++;
Yunqing Wang0e141b52017-11-02 15:08:58 -0700159 if (allow_update_cdf)
160 update_cdf(ec_ctx->eob_extra_cdf[txs_ctx][plane][eob_pt], bit, 2);
Angie Chiang7ab884e2017-10-18 15:57:12 -0700161 }
Dake Hea47cd6c2017-10-13 18:09:58 -0700162}
163
164static int get_eob_cost(int eob, int seg_eob,
Jingning Han35deaa72017-10-26 15:36:30 -0700165 const LV_MAP_COEFF_COST *txb_costs, TX_TYPE tx_type) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700166 int16_t eob_extra;
167 int16_t eob_pt = get_eob_pos_token(eob, &eob_extra);
168 int16_t dummy;
169 int16_t max_eob_pt = get_eob_pos_token(seg_eob, &dummy);
170 int eob_cost = 0;
171
172 // printf("Enc: [%d, %d], (%d, %d) ", seg_eob, eob, eob_pt, eob_extra);
173 for (int i = 1; i < max_eob_pt; i++) {
Jingning Han35deaa72017-10-26 15:36:30 -0700174 int eob_pos_ctx = av1_get_eob_pos_ctx(tx_type, i);
Dake Hea47cd6c2017-10-13 18:09:58 -0700175 eob_cost += txb_costs->eob_cost[eob_pos_ctx][eob_pt == i];
176 if (eob_pt == i) {
177 break;
178 }
179 }
180 if (k_eob_offset_bits[eob_pt] > 0) {
Angie Chiang7ab884e2017-10-18 15:57:12 -0700181 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
182 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
183 eob_cost += txb_costs->eob_extra_cost[eob_pt][bit];
184 for (int i = 1; i < k_eob_offset_bits[eob_pt]; i++) {
185 eob_shift = k_eob_offset_bits[eob_pt] - 1 - i;
186 bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700187 eob_cost += av1_cost_bit(128, bit);
188 }
189 }
190 return eob_cost;
191}
192
Linfeng Zhang1015a342017-10-24 16:20:41 -0700193static int get_coeff_cost(const tran_low_t qc, const int scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +0100194#if CONFIG_LV_MAP_MULTI
195 const int is_eob,
196#endif
Linfeng Zhang1015a342017-10-24 16:20:41 -0700197 const TxbInfo *const txb_info,
198 const LV_MAP_COEFF_COST *const txb_costs);
Dake Hea47cd6c2017-10-13 18:09:58 -0700199
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800200static void get_dist_cost_stats(LevelDownStats *stats, int scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +0100201#if CONFIG_LV_MAP_MULTI
202 const int is_eob,
203#endif
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800204 const LV_MAP_COEFF_COST *txb_costs,
205 TxbInfo *txb_info) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700206 const int16_t *scan = txb_info->scan_order->scan;
207 const int coeff_idx = scan[scan_idx];
208 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
Linfeng Zhang1015a342017-10-24 16:20:41 -0700209 const uint8_t *const levels = txb_info->levels;
Dake Hea47cd6c2017-10-13 18:09:58 -0700210 stats->new_eob = -1;
211 stats->update = 0;
212
213 const tran_low_t tqc = txb_info->tcoeff[coeff_idx];
214 const int dqv = txb_info->dequant[coeff_idx != 0];
215
216 const tran_low_t dqc = qcoeff_to_dqcoeff(qc, dqv, txb_info->shift);
217 const int64_t dqc_dist = get_coeff_dist(tqc, dqc, txb_info->shift);
Ola Hugosson13892102017-11-06 08:01:44 +0100218#if CONFIG_LV_MAP_MULTI
219 const int qc_cost = get_coeff_cost(qc, scan_idx, is_eob, txb_info, txb_costs);
220#else
Dake Hea47cd6c2017-10-13 18:09:58 -0700221 const int qc_cost = get_coeff_cost(qc, scan_idx, txb_info, txb_costs);
Ola Hugosson13892102017-11-06 08:01:44 +0100222#endif
Dake Hea47cd6c2017-10-13 18:09:58 -0700223
224 // distortion difference when coefficient is quantized to 0
225 const tran_low_t dqc0 = qcoeff_to_dqcoeff(0, dqv, txb_info->shift);
226 stats->dist0 = get_coeff_dist(tqc, dqc0, txb_info->shift);
227 stats->dist = dqc_dist - stats->dist0;
228 stats->rate = qc_cost;
229
230 if (qc == 0) {
231 return;
232 }
233 stats->rd = RDCOST(txb_info->rdmult, stats->rate, stats->dist);
234
235 stats->low_qc = get_lower_coeff(qc);
236 stats->low_dqc = qcoeff_to_dqcoeff(stats->low_qc, dqv, txb_info->shift);
237 const int64_t low_dqc_dist =
238 get_coeff_dist(tqc, stats->low_dqc, txb_info->shift);
Ola Hugosson13892102017-11-06 08:01:44 +0100239#if CONFIG_LV_MAP_MULTI
240 const int low_qc_cost =
241 get_coeff_cost(stats->low_qc, scan_idx, is_eob, txb_info, txb_costs);
242#else
Dake Hea47cd6c2017-10-13 18:09:58 -0700243 const int low_qc_cost =
244 get_coeff_cost(stats->low_qc, scan_idx, txb_info, txb_costs);
Ola Hugosson13892102017-11-06 08:01:44 +0100245#endif
Dake Hea47cd6c2017-10-13 18:09:58 -0700246 stats->dist_low = low_dqc_dist - stats->dist0;
247 stats->rate_low = low_qc_cost;
248 stats->rd_low = RDCOST(txb_info->rdmult, stats->rate_low, stats->dist_low);
249
Ola Hugosson13892102017-11-06 08:01:44 +0100250#if CONFIG_LV_MAP_MULTI
251 int coeff_ctx = get_nz_map_ctx(levels, scan_idx, scan, txb_info->bwl,
252 txb_info->height, txb_info->tx_type, is_eob);
253 if ((stats->rd_low < stats->rd) && (stats->low_qc == 0)) {
254 stats->nz_rate = txb_costs->base_cost[coeff_ctx][0];
255 } else {
256 // TODO(olah): revisit what non-zero cost should be used here
257 stats->nz_rate = txb_costs->base_cost[coeff_ctx][1];
258 }
259#else
Linfeng Zhang1015a342017-10-24 16:20:41 -0700260 int coeff_ctx = get_nz_map_ctx(levels, scan_idx, scan, txb_info->bwl,
Linfeng Zhangb6957c22017-10-25 13:17:28 -0700261 txb_info->height, txb_info->tx_type);
Dake Hea47cd6c2017-10-13 18:09:58 -0700262 if ((stats->rd_low < stats->rd) && (stats->low_qc == 0)) {
263 stats->nz_rate = txb_costs->nz_map_cost[coeff_ctx][0];
264 } else {
265 stats->nz_rate = txb_costs->nz_map_cost[coeff_ctx][1];
266 }
Ola Hugosson13892102017-11-06 08:01:44 +0100267#endif
Dake Hea47cd6c2017-10-13 18:09:58 -0700268}
269
Linfeng Zhang1015a342017-10-24 16:20:41 -0700270static INLINE void update_qcoeff(const int coeff_idx, const tran_low_t qc,
271 const TxbInfo *const txb_info) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700272 txb_info->qcoeff[coeff_idx] = qc;
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700273 txb_info->levels[get_paded_idx(coeff_idx, txb_info->bwl)] =
274 (uint8_t)clamp(abs(qc), 0, UINT8_MAX);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700275}
276
277static INLINE void update_coeff(const int coeff_idx, const tran_low_t qc,
278 const TxbInfo *const txb_info) {
279 update_qcoeff(coeff_idx, qc, txb_info);
Dake Hea47cd6c2017-10-13 18:09:58 -0700280 const int dqv = txb_info->dequant[coeff_idx != 0];
281 txb_info->dqcoeff[coeff_idx] = qcoeff_to_dqcoeff(qc, dqv, txb_info->shift);
282}
283
Linfeng Zhang1015a342017-10-24 16:20:41 -0700284static INLINE void av1_txb_init_levels(const tran_low_t *const coeff,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700285 const int width, const int height,
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700286 uint8_t *const levels) {
287 const int stride = width + TX_PAD_HOR;
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700288 uint8_t *ls = levels;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700289
290 memset(levels - TX_PAD_TOP * stride, 0,
291 sizeof(*levels) * TX_PAD_TOP * stride);
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700292 memset(levels + stride * height, 0,
293 sizeof(*levels) * (TX_PAD_BOTTOM * stride + TX_PAD_END));
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700294
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700295 for (int i = 0; i < height; i++) {
296 for (int j = 0; j < width; j++) {
297 *ls++ = (uint8_t)clamp(abs(coeff[i * width + j]), 0, UINT8_MAX);
298 }
299 for (int j = 0; j < TX_PAD_HOR; j++) {
300 *ls++ = 0;
301 }
Linfeng Zhang1015a342017-10-24 16:20:41 -0700302 }
303}
304
Angie Chiang80b82262017-02-24 11:39:47 -0800305void av1_write_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCKD *xd,
Jingning Han7eab9ff2017-07-06 10:12:54 -0700306 aom_writer *w, int blk_row, int blk_col, int block,
307 int plane, TX_SIZE tx_size, const tran_low_t *tcoeff,
308 uint16_t eob, TXB_CTX *txb_ctx) {
Angie Chiang80b82262017-02-24 11:39:47 -0800309 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiangcea11f22017-02-24 12:30:40 -0800310 const PLANE_TYPE plane_type = get_plane_type(plane);
Jingning Han48be0e12017-06-13 12:12:01 -0700311 const TX_SIZE txs_ctx = get_txsize_context(tx_size);
Jingning Han19b5c8f2017-07-06 15:10:12 -0700312 const TX_TYPE tx_type =
313 av1_get_tx_type(plane_type, xd, blk_row, blk_col, block, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -0700314 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Angie Chiang80b82262017-02-24 11:39:47 -0800315 const int16_t *scan = scan_order->scan;
Linfeng Zhangce065ca2017-10-17 16:49:30 -0700316 const int seg_eob = tx_size_2d[tx_size];
Angie Chiang80b82262017-02-24 11:39:47 -0800317 int c;
Angie Chiang80b82262017-02-24 11:39:47 -0800318 const int bwl = b_width_log2_lookup[txsize_to_bsize[tx_size]] + 2;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700319 const int width = tx_size_wide[tx_size];
Jingning Han341d79e2017-06-13 15:57:59 -0700320 const int height = tx_size_high[tx_size];
Linfeng Zhang848f7bc2017-10-31 15:26:07 -0700321 int update_eob = -1;
Jingning Han41c7f442017-09-05 14:54:00 -0700322 FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700323 uint8_t levels_buf[TX_PAD_2D];
324 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -0800325 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Angie Chiang80b82262017-02-24 11:39:47 -0800326
Jingning Han7eab9ff2017-07-06 10:12:54 -0700327 (void)blk_row;
328 (void)blk_col;
Jingning Han94cea4a2017-09-30 14:13:23 -0700329 aom_write_bin(w, eob == 0,
330 ec_ctx->txb_skip_cdf[txs_ctx][txb_ctx->txb_skip_ctx], 2);
Angie Chiang80b82262017-02-24 11:39:47 -0800331 if (eob == 0) return;
Linfeng Zhangce065ca2017-10-17 16:49:30 -0700332
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700333 av1_txb_init_levels(tcoeff, width, height, levels);
Linfeng Zhangce065ca2017-10-17 16:49:30 -0700334
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700335#if CONFIG_TXK_SEL
Jingning Han19b5c8f2017-07-06 15:10:12 -0700336 av1_write_tx_type(cm, xd, blk_row, blk_col, block, plane,
337 get_min_tx_size(tx_size), w);
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700338#endif
Angie Chiang80b82262017-02-24 11:39:47 -0800339
Dake Hea47cd6c2017-10-13 18:09:58 -0700340 int16_t eob_extra;
341 int16_t eob_pt = get_eob_pos_token(eob, &eob_extra);
342 int16_t dummy;
343 int16_t max_eob_pt = get_eob_pos_token(seg_eob, &dummy);
344
345 // printf("Enc: [%d, %d], (%d, %d) ", seg_eob, eob, eob_pt, eob_extra);
346 for (int i = 1; i < max_eob_pt; i++) {
Jingning Han35deaa72017-10-26 15:36:30 -0700347 int eob_pos_ctx = av1_get_eob_pos_ctx(tx_type, i);
Dake Hea47cd6c2017-10-13 18:09:58 -0700348
349 aom_write_bin(w, eob_pt == i,
350 ec_ctx->eob_flag_cdf[txs_ctx][plane_type][eob_pos_ctx], 2);
351 // aom_write_symbol(w, eob_pt == i,
352 // ec_ctx->eob_flag_cdf[AOMMIN(txs_ctx,3)][plane_type][eob_pos_ctx], 2);
353 if (eob_pt == i) {
354 break;
355 }
356 }
357
358 if (k_eob_offset_bits[eob_pt] > 0) {
Angie Chiang7ab884e2017-10-18 15:57:12 -0700359 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
360 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
361 aom_write_bin(w, bit, ec_ctx->eob_extra_cdf[txs_ctx][plane_type][eob_pt],
362 2);
363 for (int i = 1; i < k_eob_offset_bits[eob_pt]; i++) {
364 eob_shift = k_eob_offset_bits[eob_pt] - 1 - i;
365 bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700366 aom_write_bit(w, bit);
367 // printf("%d ", bit);
368 }
369 }
Dake He03a32922017-10-31 08:06:45 -0700370
371#if USE_CAUSAL_BASE_CTX
372 int coeff_ctx = 0;
373 for (int i = 0; i < eob; ++i) {
374 c = eob - 1 - i;
Dake He03a32922017-10-31 08:06:45 -0700375
Ola Hugosson13892102017-11-06 08:01:44 +0100376#if CONFIG_LV_MAP_MULTI
377 coeff_ctx =
378 get_nz_map_ctx(levels, c, scan, bwl, height, tx_type, c == eob - 1);
379 tran_low_t v = tcoeff[scan[c]];
380 aom_write_cdf4(w, AOMMIN(abs(v), 3),
381 ec_ctx->coeff_base_cdf[txs_ctx][plane_type][coeff_ctx], 4);
382#else
383 coeff_ctx = get_nz_map_ctx(levels, c, scan, bwl, height, tx_type);
Dake He03a32922017-10-31 08:06:45 -0700384 tran_low_t v = tcoeff[scan[c]];
385 int is_nz = (v != 0);
386
387 if (c < eob - 1) {
388 aom_write_bin(w, is_nz,
389 ec_ctx->nz_map_cdf[txs_ctx][plane_type][coeff_ctx], 2);
390 }
391 if (is_nz) {
392 const int level = abs(v);
393 int k;
394 for (k = 0; k < NUM_BASE_LEVELS; ++k) {
395 int is_k = (level > (k + 1));
396 int ctx = coeff_ctx;
397 aom_write_bin(w, is_k,
398 ec_ctx->coeff_base_cdf[txs_ctx][plane_type][k][ctx], 2);
399 if (is_k == 0) break;
400 }
401 }
Ola Hugosson13892102017-11-06 08:01:44 +0100402#endif
Dake He03a32922017-10-31 08:06:45 -0700403 }
404 update_eob = eob - 1;
405#else
Dake Hea47cd6c2017-10-13 18:09:58 -0700406 for (int i = 1; i < eob; ++i) {
407 c = eob - 1 - i;
Linfeng Zhangb6957c22017-10-25 13:17:28 -0700408 int coeff_ctx = get_nz_map_ctx(levels, c, scan, bwl, height, tx_type);
Dake Hea47cd6c2017-10-13 18:09:58 -0700409
410 tran_low_t v = tcoeff[scan[c]];
411 int is_nz = (v != 0);
412
Dake Hea47cd6c2017-10-13 18:09:58 -0700413 aom_write_bin(w, is_nz, ec_ctx->nz_map_cdf[txs_ctx][plane_type][coeff_ctx],
414 2);
Dake Hea47cd6c2017-10-13 18:09:58 -0700415 }
416
Dake Hea47cd6c2017-10-13 18:09:58 -0700417 for (int i = 0; i < NUM_BASE_LEVELS; ++i) {
Linfeng Zhangf72e1382017-11-01 13:59:41 -0700418 av1_get_base_level_counts(levels, i, width, height, level_counts);
Angie Chiang80b82262017-02-24 11:39:47 -0800419 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhang1015a342017-10-24 16:20:41 -0700420 const tran_low_t level = abs(tcoeff[scan[c]]);
Angie Chiang80b82262017-02-24 11:39:47 -0800421 int ctx;
422
423 if (level <= i) continue;
424
Linfeng Zhangf72e1382017-11-01 13:59:41 -0700425 ctx = get_base_ctx(levels, scan[c], bwl, i, level_counts[scan[c]]);
Angie Chiang80b82262017-02-24 11:39:47 -0800426
427 if (level == i + 1) {
Jingning Han94cea4a2017-09-30 14:13:23 -0700428 aom_write_bin(w, 1, ec_ctx->coeff_base_cdf[txs_ctx][plane_type][i][ctx],
429 2);
Angie Chiang80b82262017-02-24 11:39:47 -0800430 continue;
431 }
Jingning Han24b0cf92017-08-18 22:50:18 -0700432
Jingning Han94cea4a2017-09-30 14:13:23 -0700433 aom_write_bin(w, 0, ec_ctx->coeff_base_cdf[txs_ctx][plane_type][i][ctx],
434 2);
Angie Chiang80b82262017-02-24 11:39:47 -0800435 update_eob = AOMMAX(update_eob, c);
436 }
437 }
Dake He03a32922017-10-31 08:06:45 -0700438#endif
Angie Chiang80b82262017-02-24 11:39:47 -0800439
Dake He43edb762017-10-26 10:29:46 -0700440 // Loop to code all signs in the transform block,
441 // starting with the sign of DC (if applicable)
442 for (c = 0; c < eob; ++c) {
Linfeng Zhang1015a342017-10-24 16:20:41 -0700443 const tran_low_t v = tcoeff[scan[c]];
444 const tran_low_t level = abs(v);
445 const int sign = (v < 0) ? 1 : 0;
Dake He43edb762017-10-26 10:29:46 -0700446 if (level == 0) continue;
447
448 if (c == 0) {
449#if LV_MAP_PROB
450 aom_write_bin(w, sign,
451 ec_ctx->dc_sign_cdf[plane_type][txb_ctx->dc_sign_ctx], 2);
452#else
453 aom_write(w, sign, ec_ctx->dc_sign[plane_type][txb_ctx->dc_sign_ctx]);
454#endif
455 } else {
456 aom_write_bit(w, sign);
457 }
458 }
459
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800460 if (update_eob >= 0) {
461 av1_get_br_level_counts(levels, width, height, level_counts);
462 for (c = update_eob; c >= 0; --c) {
463 const tran_low_t level = abs(tcoeff[scan[c]]);
464 int idx;
465 int ctx;
Angie Chiang80b82262017-02-24 11:39:47 -0800466
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800467 if (level <= NUM_BASE_LEVELS) continue;
Angie Chiang80b82262017-02-24 11:39:47 -0800468
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800469 // level is above 1.
470 ctx = get_br_ctx(levels, scan[c], bwl, level_counts[scan[c]]);
Jingning Han87b01b52017-08-31 12:07:20 -0700471
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800472 int base_range = level - 1 - NUM_BASE_LEVELS;
Ola Hugossone72a2092017-11-12 09:11:53 +0100473#if CONFIG_LV_MAP_MULTI
474 for (idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
475 int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
476 aom_write_cdf4(w, k, ec_ctx->coeff_br_cdf[txs_ctx][plane_type][ctx],
477 BR_CDF_SIZE);
478 if (k < BR_CDF_SIZE - 1) break;
479 }
480 if (base_range < COEFF_BASE_RANGE) continue;
481#else
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800482 int br_set_idx = 0;
483 int br_base = 0;
484 int br_offset = 0;
Jingning Han87b01b52017-08-31 12:07:20 -0700485
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800486 if (base_range >= COEFF_BASE_RANGE)
487 br_set_idx = BASE_RANGE_SETS;
488 else
489 br_set_idx = coeff_to_br_index[base_range];
Jingning Han87b01b52017-08-31 12:07:20 -0700490
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800491 for (idx = 0; idx < BASE_RANGE_SETS; ++idx) {
Ola Hugosson13892102017-11-06 08:01:44 +0100492 // printf("br: %d %d %d %d\n", txs_ctx, plane_type, idx, ctx);
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800493 aom_write_bin(w, idx == br_set_idx,
494 ec_ctx->coeff_br_cdf[txs_ctx][plane_type][idx][ctx], 2);
495 if (idx == br_set_idx) {
496 br_base = br_index_to_coeff[br_set_idx];
497 br_offset = base_range - br_base;
498 int extra_bits = (1 << br_extra_bits[idx]) - 1;
499 for (int tok = 0; tok < extra_bits; ++tok) {
500 if (tok == br_offset) {
501 aom_write_bin(w, 1,
502 ec_ctx->coeff_lps_cdf[txs_ctx][plane_type][ctx], 2);
503 break;
504 }
505 aom_write_bin(w, 0, ec_ctx->coeff_lps_cdf[txs_ctx][plane_type][ctx],
Jingning Han94cea4a2017-09-30 14:13:23 -0700506 2);
Jingning Han87b01b52017-08-31 12:07:20 -0700507 }
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800508 // aom_write_literal(w, br_offset, br_extra_bits[idx]);
509 break;
Jingning Han87b01b52017-08-31 12:07:20 -0700510 }
Jingning Han87b01b52017-08-31 12:07:20 -0700511 }
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800512
513 if (br_set_idx < BASE_RANGE_SETS) continue;
Ola Hugossone72a2092017-11-12 09:11:53 +0100514#endif
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800515 // use 0-th order Golomb code to handle the residual level.
516 write_golomb(
517 w, abs(tcoeff[scan[c]]) - COEFF_BASE_RANGE - 1 - NUM_BASE_LEVELS);
Jingning Han87b01b52017-08-31 12:07:20 -0700518 }
Angie Chiang80b82262017-02-24 11:39:47 -0800519 }
520}
Angie Chiang47c72182017-02-27 14:30:38 -0800521
Angie Chiangc8af6112017-03-16 16:11:22 -0700522void av1_write_coeffs_mb(const AV1_COMMON *const cm, MACROBLOCK *x,
523 aom_writer *w, int plane) {
524 MACROBLOCKD *xd = &x->e_mbd;
525 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
526 BLOCK_SIZE bsize = mbmi->sb_type;
527 struct macroblockd_plane *pd = &xd->plane[plane];
Angie Chiangc8af6112017-03-16 16:11:22 -0700528 const BLOCK_SIZE plane_bsize =
Angie Chiangee4a34c2017-06-07 15:23:17 -0700529 AOMMAX(BLOCK_4X4, get_plane_block_size(bsize, pd));
Angie Chiang8d6bc802017-04-12 15:14:05 -0700530 const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
531 const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
hui su0c6244b2017-07-12 17:11:43 -0700532 const TX_SIZE tx_size = av1_get_tx_size(plane, xd);
Angie Chiangc8af6112017-03-16 16:11:22 -0700533 const int bkw = tx_size_wide_unit[tx_size];
534 const int bkh = tx_size_high_unit[tx_size];
535 const int step = tx_size_wide_unit[tx_size] * tx_size_high_unit[tx_size];
536 int row, col;
537 int block = 0;
Angie Chiang8d6bc802017-04-12 15:14:05 -0700538 for (row = 0; row < max_blocks_high; row += bkh) {
539 for (col = 0; col < max_blocks_wide; col += bkw) {
Angie Chiangc8af6112017-03-16 16:11:22 -0700540 tran_low_t *tcoeff = BLOCK_OFFSET(x->mbmi_ext->tcoeff[plane], block);
541 uint16_t eob = x->mbmi_ext->eobs[plane][block];
542 TXB_CTX txb_ctx = { x->mbmi_ext->txb_skip_ctx[plane][block],
543 x->mbmi_ext->dc_sign_ctx[plane][block] };
Jingning Han7eab9ff2017-07-06 10:12:54 -0700544 av1_write_coeffs_txb(cm, xd, w, row, col, block, plane, tx_size, tcoeff,
545 eob, &txb_ctx);
Angie Chiangc8af6112017-03-16 16:11:22 -0700546 block += step;
547 }
548 }
549}
550
Yaowu Xu9b803912017-11-16 08:16:33 -0800551#if !USE_CAUSAL_BASE_CTX
Linfeng Zhang841a84d2017-10-30 14:31:11 -0700552static INLINE void get_base_ctx_set(const uint8_t *const levels,
553 const int c, // raster order
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700554 const int bwl,
Angie Chiang47c72182017-02-27 14:30:38 -0800555 int ctx_set[NUM_BASE_LEVELS]) {
556 const int row = c >> bwl;
557 const int col = c - (row << bwl);
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700558 const int width = 1 << bwl;
559 const int stride = width + TX_PAD_HOR;
Jingning Hane775b8b2017-10-26 16:56:22 -0700560 int mag_count[NUM_BASE_LEVELS] = { 0 };
561 int nb_mag[NUM_BASE_LEVELS][3] = { { 0 } };
Angie Chiang47c72182017-02-27 14:30:38 -0800562 int idx;
Angie Chiang47c72182017-02-27 14:30:38 -0800563 int i;
564
565 for (idx = 0; idx < BASE_CONTEXT_POSITION_NUM; ++idx) {
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700566 const int ref_row = row + base_ref_offset[idx][0];
567 const int ref_col = col + base_ref_offset[idx][1];
568 const int pos = ref_row * stride + ref_col;
Linfeng Zhang841a84d2017-10-30 14:31:11 -0700569 const uint8_t abs_coeff = levels[pos];
Angie Chiang47c72182017-02-27 14:30:38 -0800570
571 for (i = 0; i < NUM_BASE_LEVELS; ++i) {
572 ctx_set[i] += abs_coeff > i;
Jingning Hane775b8b2017-10-26 16:56:22 -0700573 if (base_ref_offset[idx][0] == 0 && base_ref_offset[idx][1] == 1)
574 nb_mag[i][0] = abs_coeff;
575 if (base_ref_offset[idx][0] == 1 && base_ref_offset[idx][1] == 0)
576 nb_mag[i][1] = abs_coeff;
577 if (base_ref_offset[idx][0] == 1 && base_ref_offset[idx][1] == 1)
578 nb_mag[i][2] = abs_coeff;
Angie Chiang47c72182017-02-27 14:30:38 -0800579 }
580 }
581
582 for (i = 0; i < NUM_BASE_LEVELS; ++i) {
Jingning Hane775b8b2017-10-26 16:56:22 -0700583 for (idx = 0; idx < 3; ++idx) mag_count[i] += nb_mag[i][idx] > i + 1;
584 ctx_set[i] = get_base_ctx_from_count_mag(row, col, ctx_set[i],
585 AOMMIN(2, mag_count[i]));
Angie Chiang47c72182017-02-27 14:30:38 -0800586 }
587 return;
588}
Yaowu Xu9b803912017-11-16 08:16:33 -0800589#endif
Angie Chiang47c72182017-02-27 14:30:38 -0800590
Angie Chiang488f9212017-05-30 12:46:26 -0700591static INLINE int get_br_cost(tran_low_t abs_qc, int ctx,
Angie Chiang26d3e452017-09-29 17:40:02 -0700592 const int *coeff_lps) {
Angie Chiang488f9212017-05-30 12:46:26 -0700593 const tran_low_t min_level = 1 + NUM_BASE_LEVELS;
594 const tran_low_t max_level = 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE;
Jingning Handfd72322017-08-09 14:04:12 -0700595 (void)ctx;
Angie Chiang488f9212017-05-30 12:46:26 -0700596 if (abs_qc >= min_level) {
Angie Chiang488f9212017-05-30 12:46:26 -0700597 if (abs_qc >= max_level)
Jingning Han772dee32017-09-15 08:53:18 -0700598 return coeff_lps[COEFF_BASE_RANGE]; // COEFF_BASE_RANGE * cost0;
Angie Chiang488f9212017-05-30 12:46:26 -0700599 else
Jingning Han772dee32017-09-15 08:53:18 -0700600 return coeff_lps[(abs_qc - min_level)]; // * cost0 + cost1;
Angie Chiang488f9212017-05-30 12:46:26 -0700601 } else {
602 return 0;
603 }
604}
605
606static INLINE int get_base_cost(tran_low_t abs_qc, int ctx,
Jingning Handfd72322017-08-09 14:04:12 -0700607 const int coeff_base[2], int base_idx) {
Angie Chiang488f9212017-05-30 12:46:26 -0700608 const int level = base_idx + 1;
Jingning Handfd72322017-08-09 14:04:12 -0700609 (void)ctx;
Angie Chiang488f9212017-05-30 12:46:26 -0700610 if (abs_qc < level)
611 return 0;
612 else
Jingning Handfd72322017-08-09 14:04:12 -0700613 return coeff_base[abs_qc == level];
Angie Chiang488f9212017-05-30 12:46:26 -0700614}
615
Angie Chiang3627de22017-08-18 20:15:59 -0700616int av1_cost_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCK *x, int plane,
Jingning Han7eab9ff2017-07-06 10:12:54 -0700617 int blk_row, int blk_col, int block, TX_SIZE tx_size,
618 TXB_CTX *txb_ctx) {
Angie Chiang47c72182017-02-27 14:30:38 -0800619 MACROBLOCKD *const xd = &x->e_mbd;
Jingning Han48be0e12017-06-13 12:12:01 -0700620 TX_SIZE txs_ctx = get_txsize_context(tx_size);
Angie Chiang47c72182017-02-27 14:30:38 -0800621 const PLANE_TYPE plane_type = get_plane_type(plane);
Jingning Han19b5c8f2017-07-06 15:10:12 -0700622 const TX_TYPE tx_type =
623 av1_get_tx_type(plane_type, xd, blk_row, blk_col, block, tx_size);
Angie Chiang47c72182017-02-27 14:30:38 -0800624 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
625 const struct macroblock_plane *p = &x->plane[plane];
626 const int eob = p->eobs[block];
627 const tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
628 int c, cost;
Angie Chiang47c72182017-02-27 14:30:38 -0800629 int txb_skip_ctx = txb_ctx->txb_skip_ctx;
Angie Chiang47c72182017-02-27 14:30:38 -0800630
631 const int bwl = b_width_log2_lookup[txsize_to_bsize[tx_size]] + 2;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700632 const int width = tx_size_wide[tx_size];
Jingning Han341d79e2017-06-13 15:57:59 -0700633 const int height = tx_size_high[tx_size];
634
Angie Chiangbd99b382017-06-20 15:11:16 -0700635 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Angie Chiang47c72182017-02-27 14:30:38 -0800636 const int16_t *scan = scan_order->scan;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700637 uint8_t levels_buf[TX_PAD_2D];
638 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -0800639 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Angie Chiang47c72182017-02-27 14:30:38 -0800640
Jingning Handfd72322017-08-09 14:04:12 -0700641 LV_MAP_COEFF_COST *coeff_costs = &x->coeff_costs[txs_ctx][plane_type];
642
Angie Chiang47c72182017-02-27 14:30:38 -0800643 cost = 0;
644
645 if (eob == 0) {
Jingning Handfd72322017-08-09 14:04:12 -0700646 cost = coeff_costs->txb_skip_cost[txb_skip_ctx][1];
Angie Chiang47c72182017-02-27 14:30:38 -0800647 return cost;
648 }
Jingning Handfd72322017-08-09 14:04:12 -0700649 cost = coeff_costs->txb_skip_cost[txb_skip_ctx][0];
Angie Chiang47c72182017-02-27 14:30:38 -0800650
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700651 av1_txb_init_levels(qcoeff, width, height, levels);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700652
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700653#if CONFIG_TXK_SEL
Yue Chenb23d00a2017-07-28 17:01:21 -0700654 cost += av1_tx_type_cost(cm, x, xd, mbmi->sb_type, plane, tx_size, tx_type);
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700655#endif
Angie Chiang05917872017-04-15 12:28:56 -0700656
Dake Hea47cd6c2017-10-13 18:09:58 -0700657 const int seg_eob = tx_size_2d[tx_size];
Jingning Han35deaa72017-10-26 15:36:30 -0700658 int eob_cost = get_eob_cost(eob, seg_eob, coeff_costs, tx_type);
Dake Hea47cd6c2017-10-13 18:09:58 -0700659
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800660 av1_get_br_level_counts(levels, width, height, level_counts);
Dake Hea47cd6c2017-10-13 18:09:58 -0700661 cost += eob_cost;
Dake He03a32922017-10-31 08:06:45 -0700662#if USE_CAUSAL_BASE_CTX
663 int coeff_ctx = 0;
664#endif
Dake Hea47cd6c2017-10-13 18:09:58 -0700665 for (c = eob - 1; c >= 0; --c) {
666 tran_low_t v = qcoeff[scan[c]];
667 int is_nz = (v != 0);
668 int level = abs(v);
Ola Hugosson13892102017-11-06 08:01:44 +0100669#if CONFIG_LV_MAP_MULTI
670 coeff_ctx =
671 get_nz_map_ctx(levels, c, scan, bwl, height, tx_type, c == eob - 1);
672 cost += coeff_costs->base_cost[coeff_ctx][AOMMIN(level, 3)];
673#else // CONFIG_LV_MAP_MULTI
Dake He03a32922017-10-31 08:06:45 -0700674#if USE_CAUSAL_BASE_CTX
Linfeng Zhangb6957c22017-10-25 13:17:28 -0700675 coeff_ctx = get_nz_map_ctx(levels, c, scan, bwl, height, tx_type);
Dake He03a32922017-10-31 08:06:45 -0700676#endif
Dake Hea47cd6c2017-10-13 18:09:58 -0700677
678 if (c < eob - 1) {
Dake He03a32922017-10-31 08:06:45 -0700679#if !USE_CAUSAL_BASE_CTX
Linfeng Zhangb6957c22017-10-25 13:17:28 -0700680 int coeff_ctx = get_nz_map_ctx(levels, c, scan, bwl, height, tx_type);
Dake He03a32922017-10-31 08:06:45 -0700681#endif
Dake Hea47cd6c2017-10-13 18:09:58 -0700682 cost += coeff_costs->nz_map_cost[coeff_ctx][is_nz];
683 }
Ola Hugosson13892102017-11-06 08:01:44 +0100684#endif // CONFIG_LV_MAP_MULTI
Dake Hea47cd6c2017-10-13 18:09:58 -0700685
686 if (is_nz) {
Dake He03a32922017-10-31 08:06:45 -0700687#if !USE_CAUSAL_BASE_CTX
Dake Hea47cd6c2017-10-13 18:09:58 -0700688 int ctx_ls[NUM_BASE_LEVELS] = { 0 };
Dake He03a32922017-10-31 08:06:45 -0700689#endif
Dake Hea47cd6c2017-10-13 18:09:58 -0700690 int sign = (v < 0) ? 1 : 0;
691
692 // sign bit cost
693 if (c == 0) {
694 int dc_sign_ctx = txb_ctx->dc_sign_ctx;
695 cost += coeff_costs->dc_sign_cost[dc_sign_ctx][sign];
696 } else {
697 cost += av1_cost_bit(128, sign);
698 }
Ola Hugosson13892102017-11-06 08:01:44 +0100699#if !CONFIG_LV_MAP_MULTI
Dake He03a32922017-10-31 08:06:45 -0700700#if USE_CAUSAL_BASE_CTX
701 int k;
702 for (k = 0; k < NUM_BASE_LEVELS; ++k) {
703 int is_k = (level > (k + 1));
704 int ctx = coeff_ctx;
705 // get_base_ctx_from_b(c, k, b0, b1, b2);
706 cost += coeff_costs->base_cost[k][ctx][is_k];
707 if (is_k == 0) break;
708 }
709#else
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700710 get_base_ctx_set(levels, scan[c], bwl, ctx_ls);
Dake Hea47cd6c2017-10-13 18:09:58 -0700711
712 int i;
713 for (i = 0; i < NUM_BASE_LEVELS; ++i) {
714 if (level <= i) continue;
715
716 if (level == i + 1) {
717 cost += coeff_costs->base_cost[i][ctx_ls[i]][1];
718 continue;
719 }
720 cost += coeff_costs->base_cost[i][ctx_ls[i]][0];
721 }
Dake He03a32922017-10-31 08:06:45 -0700722#endif
Ola Hugosson13892102017-11-06 08:01:44 +0100723#endif // CONFIG_LV_MAP_MULTI
Dake Hea47cd6c2017-10-13 18:09:58 -0700724 if (level > NUM_BASE_LEVELS) {
725 int ctx;
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800726 ctx = get_br_ctx(levels, scan[c], bwl, level_counts[scan[c]]);
Dake Hea47cd6c2017-10-13 18:09:58 -0700727 int base_range = level - 1 - NUM_BASE_LEVELS;
728 if (base_range < COEFF_BASE_RANGE) {
729 cost += coeff_costs->lps_cost[ctx][base_range];
730 } else {
731 cost += coeff_costs->lps_cost[ctx][COEFF_BASE_RANGE];
732 }
733
Dake Hea47cd6c2017-10-13 18:09:58 -0700734 if (level >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
735 // residual cost
736 int r = level - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
737 int ri = r;
738 int length = 0;
739
740 while (ri) {
741 ri >>= 1;
742 ++length;
743 }
744
745 for (ri = 0; ri < length - 1; ++ri) cost += av1_cost_bit(128, 0);
746
747 for (ri = length - 1; ri >= 0; --ri)
748 cost += av1_cost_bit(128, (r >> ri) & 0x01);
749 }
750 }
751 }
752 }
Angie Chiang47c72182017-02-27 14:30:38 -0800753 return cost;
754}
Angie Chiang0397eda2017-03-15 16:57:14 -0700755
Angie Chiang2affb3b2017-05-30 15:23:51 -0700756static INLINE int has_base(tran_low_t qc, int base_idx) {
757 const int level = base_idx + 1;
758 return abs(qc) >= level;
759}
760
Angie Chiang2affb3b2017-05-30 15:23:51 -0700761static INLINE int has_br(tran_low_t qc) {
762 return abs(qc) >= 1 + NUM_BASE_LEVELS;
763}
764
Angie Chiang488f9212017-05-30 12:46:26 -0700765static INLINE int get_sign_bit_cost(tran_low_t qc, int coeff_idx,
Jingning Handfd72322017-08-09 14:04:12 -0700766 const int (*dc_sign_cost)[2],
Angie Chiang488f9212017-05-30 12:46:26 -0700767 int dc_sign_ctx) {
768 const int sign = (qc < 0) ? 1 : 0;
769 // sign bit cost
770 if (coeff_idx == 0) {
Jingning Handfd72322017-08-09 14:04:12 -0700771 return dc_sign_cost[dc_sign_ctx][sign];
Angie Chiang488f9212017-05-30 12:46:26 -0700772 } else {
773 return av1_cost_bit(128, sign);
774 }
775}
776static INLINE int get_golomb_cost(int abs_qc) {
777 if (abs_qc >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
778 // residual cost
779 int r = abs_qc - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
780 int ri = r;
781 int length = 0;
782
783 while (ri) {
784 ri >>= 1;
785 ++length;
786 }
787
788 return av1_cost_literal(2 * length - 1);
789 } else {
790 return 0;
791 }
792}
793
Angie Chiang2affb3b2017-05-30 15:23:51 -0700794void gen_txb_cache(TxbCache *txb_cache, TxbInfo *txb_info) {
Angie Chiang481c01f2017-08-15 16:24:30 -0700795 // gen_nz_count_arr
Angie Chiang2affb3b2017-05-30 15:23:51 -0700796 const int16_t *scan = txb_info->scan_order->scan;
Angie Chiang481c01f2017-08-15 16:24:30 -0700797 const int bwl = txb_info->bwl;
798 const int height = txb_info->height;
Linfeng Zhang72e0b3f2017-10-18 13:32:12 -0700799 const tran_low_t *const qcoeff = txb_info->qcoeff;
Linfeng Zhangb6957c22017-10-25 13:17:28 -0700800 const uint8_t *const levels = txb_info->levels;
Angie Chiangdef11252017-08-18 14:37:32 -0700801 const BASE_CTX_TABLE *base_ctx_table =
802 txb_info->coeff_ctx_table->base_ctx_table;
Angie Chiang481c01f2017-08-15 16:24:30 -0700803 for (int c = 0; c < txb_info->eob; ++c) {
804 const int coeff_idx = scan[c]; // raster order
805 const int row = coeff_idx >> bwl;
806 const int col = coeff_idx - (row << bwl);
Jingning Han3422ac12017-10-25 20:37:53 -0700807
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700808 txb_cache->nz_count_arr[coeff_idx] =
809 get_nz_count(levels, bwl, row, col, get_tx_class(txb_info->tx_type));
Dake Hea47cd6c2017-10-13 18:09:58 -0700810
Angie Chiang481c01f2017-08-15 16:24:30 -0700811 const int nz_count = txb_cache->nz_count_arr[coeff_idx];
Dake He03a32922017-10-31 08:06:45 -0700812 txb_cache->nz_ctx_arr[coeff_idx] =
813 get_nz_map_ctx_from_count(nz_count, coeff_idx, bwl, height,
814#if USE_CAUSAL_BASE_CTX
815 0,
816#endif
817 txb_info->tx_type);
Angie Chiang481c01f2017-08-15 16:24:30 -0700818
819 // gen_base_count_mag_arr
820 if (!has_base(qcoeff[coeff_idx], 0)) continue;
821 int *base_mag = txb_cache->base_mag_arr[coeff_idx];
Angie Chiang9cde59f2017-08-16 15:24:55 -0700822 int count[NUM_BASE_LEVELS];
823 get_base_count_mag(base_mag, count, qcoeff, bwl, height, row, col);
Angie Chiang481c01f2017-08-15 16:24:30 -0700824
825 for (int i = 0; i < NUM_BASE_LEVELS; ++i) {
Angie Chiang9cde59f2017-08-16 15:24:55 -0700826 if (!has_base(qcoeff[coeff_idx], i)) break;
827 txb_cache->base_count_arr[i][coeff_idx] = count[i];
Angie Chiang481c01f2017-08-15 16:24:30 -0700828 const int level = i + 1;
Angie Chiang9cde59f2017-08-16 15:24:55 -0700829 txb_cache->base_ctx_arr[i][coeff_idx] =
Angie Chiangdef11252017-08-18 14:37:32 -0700830 base_ctx_table[row != 0][col != 0][base_mag[0] > level][count[i]];
Angie Chiang481c01f2017-08-15 16:24:30 -0700831 }
832
833 // gen_br_count_mag_arr
834 if (!has_br(qcoeff[coeff_idx])) continue;
835 int *br_count = txb_cache->br_count_arr + coeff_idx;
836 int *br_mag = txb_cache->br_mag_arr[coeff_idx];
Angie Chiangea8183b2017-08-17 14:36:35 -0700837 *br_count = get_br_count_mag(br_mag, qcoeff, bwl, height, row, col,
838 NUM_BASE_LEVELS);
Angie Chiang481c01f2017-08-15 16:24:30 -0700839 txb_cache->br_ctx_arr[coeff_idx] =
840 get_br_ctx_from_count_mag(row, col, *br_count, br_mag[0]);
841 }
Angie Chiang2affb3b2017-05-30 15:23:51 -0700842}
843
Jingning Handfd72322017-08-09 14:04:12 -0700844static INLINE const int *get_level_prob(int level, int coeff_idx,
845 const TxbCache *txb_cache,
846 const LV_MAP_COEFF_COST *txb_costs) {
Ola Hugosson13892102017-11-06 08:01:44 +0100847#if CONFIG_LV_MAP_MULTI
848 if (level < 1 + NUM_BASE_LEVELS) {
849 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
850 return &txb_costs->base_cost[ctx][level];
851#else
Angie Chiang7afbba42017-05-30 15:59:15 -0700852 if (level == 0) {
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700853 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700854 return txb_costs->nz_map_cost[ctx];
Angie Chiang7afbba42017-05-30 15:59:15 -0700855 } else if (level >= 1 && level < 1 + NUM_BASE_LEVELS) {
856 const int idx = level - 1;
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700857 const int ctx = txb_cache->base_ctx_arr[idx][coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700858 return txb_costs->base_cost[idx][ctx];
Ola Hugosson13892102017-11-06 08:01:44 +0100859#endif
Angie Chiang7afbba42017-05-30 15:59:15 -0700860 } else if (level >= 1 + NUM_BASE_LEVELS &&
861 level < 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700862 const int ctx = txb_cache->br_ctx_arr[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700863 return txb_costs->lps_cost[ctx];
Angie Chiang7afbba42017-05-30 15:59:15 -0700864 } else if (level >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Ola Hugosson13892102017-11-06 08:01:44 +0100865 // printf("get_level_prob does not support golomb\n");
Angie Chiang7afbba42017-05-30 15:59:15 -0700866 assert(0);
867 return 0;
868 } else {
869 assert(0);
870 return 0;
871 }
872}
873
Angie Chiangd19969e2017-05-30 18:02:33 -0700874static INLINE void update_mag_arr(int *mag_arr, int abs_qc) {
875 if (mag_arr[0] == abs_qc) {
876 mag_arr[1] -= 1;
877 assert(mag_arr[1] >= 0);
878 }
879}
880
Angie Chianga530ef42017-05-30 16:32:36 -0700881static INLINE int get_mag_from_mag_arr(const int *mag_arr) {
882 int mag;
883 if (mag_arr[1] > 0) {
884 mag = mag_arr[0];
885 } else if (mag_arr[0] > 0) {
886 mag = mag_arr[0] - 1;
887 } else {
888 // no neighbor
889 assert(mag_arr[0] == 0 && mag_arr[1] == 0);
890 mag = 0;
891 }
892 return mag;
893}
894
895static int neighbor_level_down_update(int *new_count, int *new_mag, int count,
896 const int *mag, int coeff_idx,
897 tran_low_t abs_nb_coeff, int nb_coeff_idx,
898 int level, const TxbInfo *txb_info) {
899 *new_count = count;
900 *new_mag = get_mag_from_mag_arr(mag);
901
902 int update = 0;
903 // check if br_count changes
904 if (abs_nb_coeff == level) {
905 update = 1;
906 *new_count -= 1;
907 assert(*new_count >= 0);
908 }
909 const int row = coeff_idx >> txb_info->bwl;
910 const int col = coeff_idx - (row << txb_info->bwl);
911 const int nb_row = nb_coeff_idx >> txb_info->bwl;
912 const int nb_col = nb_coeff_idx - (nb_row << txb_info->bwl);
913
914 // check if mag changes
915 if (nb_row >= row && nb_col >= col) {
916 if (abs_nb_coeff == mag[0]) {
917 assert(mag[1] > 0);
918 if (mag[1] == 1) {
919 // the nb is the only qc with max mag
920 *new_mag -= 1;
921 assert(*new_mag >= 0);
922 update = 1;
923 }
924 }
925 }
926 return update;
927}
928
929static int try_neighbor_level_down_br(int coeff_idx, int nb_coeff_idx,
930 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700931 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -0700932 const TxbInfo *txb_info) {
933 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
934 const tran_low_t abs_qc = abs(qc);
935 const int level = NUM_BASE_LEVELS + 1;
936 if (abs_qc < level) return 0;
937
938 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
939 const tran_low_t abs_nb_coeff = abs(nb_coeff);
940 const int count = txb_cache->br_count_arr[coeff_idx];
941 const int *mag = txb_cache->br_mag_arr[coeff_idx];
942 int new_count;
943 int new_mag;
944 const int update =
945 neighbor_level_down_update(&new_count, &new_mag, count, mag, coeff_idx,
946 abs_nb_coeff, nb_coeff_idx, level, txb_info);
947 if (update) {
948 const int row = coeff_idx >> txb_info->bwl;
949 const int col = coeff_idx - (row << txb_info->bwl);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700950 const int ctx = txb_cache->br_ctx_arr[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700951 const int org_cost = get_br_cost(abs_qc, ctx, txb_costs->lps_cost[ctx]);
Angie Chianga530ef42017-05-30 16:32:36 -0700952
953 const int new_ctx = get_br_ctx_from_count_mag(row, col, new_count, new_mag);
Jingning Handfd72322017-08-09 14:04:12 -0700954 const int new_cost =
955 get_br_cost(abs_qc, new_ctx, txb_costs->lps_cost[new_ctx]);
Angie Chianga530ef42017-05-30 16:32:36 -0700956 const int cost_diff = -org_cost + new_cost;
957 return cost_diff;
958 } else {
959 return 0;
960 }
961}
962
963static int try_neighbor_level_down_base(int coeff_idx, int nb_coeff_idx,
964 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700965 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -0700966 const TxbInfo *txb_info) {
Ola Hugosson13892102017-11-06 08:01:44 +0100967#if CONFIG_LV_MAP_MULTI
968 // TODO(olah): not implemented yet
969 (void)coeff_idx;
970 (void)nb_coeff_idx;
971 (void)txb_cache;
972 (void)txb_costs;
973 (void)txb_info;
974 return 0;
975#else
Angie Chianga530ef42017-05-30 16:32:36 -0700976 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
977 const tran_low_t abs_qc = abs(qc);
Angie Chiangdef11252017-08-18 14:37:32 -0700978 const BASE_CTX_TABLE *base_ctx_table =
979 txb_info->coeff_ctx_table->base_ctx_table;
Angie Chianga530ef42017-05-30 16:32:36 -0700980
981 int cost_diff = 0;
982 for (int base_idx = 0; base_idx < NUM_BASE_LEVELS; ++base_idx) {
983 const int level = base_idx + 1;
984 if (abs_qc < level) continue;
985
986 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
987 const tran_low_t abs_nb_coeff = abs(nb_coeff);
988
989 const int count = txb_cache->base_count_arr[base_idx][coeff_idx];
990 const int *mag = txb_cache->base_mag_arr[coeff_idx];
991 int new_count;
992 int new_mag;
993 const int update =
994 neighbor_level_down_update(&new_count, &new_mag, count, mag, coeff_idx,
995 abs_nb_coeff, nb_coeff_idx, level, txb_info);
996 if (update) {
997 const int row = coeff_idx >> txb_info->bwl;
998 const int col = coeff_idx - (row << txb_info->bwl);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700999 const int ctx = txb_cache->base_ctx_arr[base_idx][coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -07001000 const int org_cost = get_base_cost(
1001 abs_qc, ctx, txb_costs->base_cost[base_idx][ctx], base_idx);
Angie Chianga530ef42017-05-30 16:32:36 -07001002
1003 const int new_ctx =
Angie Chiangdef11252017-08-18 14:37:32 -07001004 base_ctx_table[row != 0][col != 0][new_mag > level][new_count];
Jingning Handfd72322017-08-09 14:04:12 -07001005 const int new_cost = get_base_cost(
1006 abs_qc, new_ctx, txb_costs->base_cost[base_idx][new_ctx], base_idx);
Angie Chianga530ef42017-05-30 16:32:36 -07001007 cost_diff += -org_cost + new_cost;
1008 }
1009 }
1010 return cost_diff;
Ola Hugosson13892102017-11-06 08:01:44 +01001011#endif
Angie Chianga530ef42017-05-30 16:32:36 -07001012}
1013
1014static int try_neighbor_level_down_nz(int coeff_idx, int nb_coeff_idx,
1015 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001016 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -07001017 TxbInfo *txb_info) {
1018 // assume eob doesn't change
1019 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1020 const tran_low_t abs_qc = abs(qc);
1021 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
1022 const tran_low_t abs_nb_coeff = abs(nb_coeff);
1023 if (abs_nb_coeff != 1) return 0;
1024 const int16_t *iscan = txb_info->scan_order->iscan;
1025 const int scan_idx = iscan[coeff_idx];
1026 if (scan_idx == txb_info->seg_eob) return 0;
1027 const int nb_scan_idx = iscan[nb_coeff_idx];
1028 if (nb_scan_idx < scan_idx) {
1029 const int count = txb_cache->nz_count_arr[coeff_idx];
1030 assert(count > 0);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001031 update_qcoeff(nb_coeff_idx, get_lower_coeff(nb_coeff), txb_info);
Dake He03a32922017-10-31 08:06:45 -07001032 const int new_ctx = get_nz_map_ctx_from_count(
1033 count - 1, coeff_idx, txb_info->bwl, txb_info->height,
1034#if USE_CAUSAL_BASE_CTX
1035 0,
1036#endif
1037 txb_info->tx_type);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001038 update_qcoeff(nb_coeff_idx, nb_coeff, txb_info);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001039 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
Ola Hugosson13892102017-11-06 08:01:44 +01001040#if CONFIG_LV_MAP_MULTI
1041 const int org_cost = txb_costs->base_cost[ctx][AOMMIN(abs_qc, 3)];
1042 const int new_cost = txb_costs->base_cost[new_ctx][AOMMIN(abs_qc, 3)];
1043#else
Angie Chianga530ef42017-05-30 16:32:36 -07001044 const int is_nz = abs_qc > 0;
Jingning Handfd72322017-08-09 14:04:12 -07001045 const int org_cost = txb_costs->nz_map_cost[ctx][is_nz];
1046 const int new_cost = txb_costs->nz_map_cost[new_ctx][is_nz];
Ola Hugosson13892102017-11-06 08:01:44 +01001047#endif
Angie Chianga530ef42017-05-30 16:32:36 -07001048 const int cost_diff = new_cost - org_cost;
1049 return cost_diff;
1050 } else {
1051 return 0;
1052 }
1053}
1054
1055static int try_self_level_down(tran_low_t *low_coeff, int coeff_idx,
1056 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001057 const LV_MAP_COEFF_COST *txb_costs,
1058 TxbInfo *txb_info) {
Angie Chiang7afbba42017-05-30 15:59:15 -07001059 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1060 if (qc == 0) {
1061 *low_coeff = 0;
1062 return 0;
1063 }
1064 const tran_low_t abs_qc = abs(qc);
1065 *low_coeff = get_lower_coeff(qc);
1066 int cost_diff;
1067 if (*low_coeff == 0) {
1068 const int scan_idx = txb_info->scan_order->iscan[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -07001069 const int *level_cost =
1070 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1071 const int *low_level_cost =
1072 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
Jingning Han3422ac12017-10-25 20:37:53 -07001073
Dake Hea47cd6c2017-10-13 18:09:58 -07001074 if (scan_idx < txb_info->eob - 1) {
Angie Chiang7afbba42017-05-30 15:59:15 -07001075 // When level-0, we code the binary of abs_qc > level
1076 // but when level-k k > 0 we code the binary of abs_qc == level
1077 // That's why wee need this special treatment for level-0 map
1078 // TODO(angiebird): make leve-0 consistent to other levels
Jingning Handfd72322017-08-09 14:04:12 -07001079 cost_diff = -level_cost[1] + low_level_cost[0] - low_level_cost[1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001080 } else {
Jingning Handfd72322017-08-09 14:04:12 -07001081 cost_diff = -level_cost[1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001082 }
1083
Angie Chiang7afbba42017-05-30 15:59:15 -07001084 const int sign_cost = get_sign_bit_cost(
Jingning Handfd72322017-08-09 14:04:12 -07001085 qc, coeff_idx, txb_costs->dc_sign_cost, txb_info->txb_ctx->dc_sign_ctx);
Angie Chiang7afbba42017-05-30 15:59:15 -07001086 cost_diff -= sign_cost;
Jingning Han772dee32017-09-15 08:53:18 -07001087 } else if (abs_qc <= NUM_BASE_LEVELS) {
1088 const int *level_cost =
1089 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1090 const int *low_level_cost =
1091 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1092 cost_diff = -level_cost[1] + low_level_cost[1] - low_level_cost[0];
1093 } else if (abs_qc == NUM_BASE_LEVELS + 1) {
1094 const int *level_cost =
1095 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1096 const int *low_level_cost =
1097 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1098 cost_diff = -level_cost[0] + low_level_cost[1] - low_level_cost[0];
Angie Chiang7afbba42017-05-30 15:59:15 -07001099 } else if (abs_qc < 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Jingning Handfd72322017-08-09 14:04:12 -07001100 const int *level_cost =
1101 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1102 const int *low_level_cost =
1103 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1104
Jingning Han772dee32017-09-15 08:53:18 -07001105 cost_diff = -level_cost[abs_qc - 1 - NUM_BASE_LEVELS] +
1106 low_level_cost[abs(*low_coeff) - 1 - NUM_BASE_LEVELS];
Angie Chiang7afbba42017-05-30 15:59:15 -07001107 } else if (abs_qc == 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Jingning Handfd72322017-08-09 14:04:12 -07001108 const int *low_level_cost =
1109 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
Jingning Han772dee32017-09-15 08:53:18 -07001110 cost_diff = -get_golomb_cost(abs_qc) - low_level_cost[COEFF_BASE_RANGE] +
1111 low_level_cost[COEFF_BASE_RANGE - 1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001112 } else {
1113 assert(abs_qc > 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE);
1114 const tran_low_t abs_low_coeff = abs(*low_coeff);
1115 cost_diff = -get_golomb_cost(abs_qc) + get_golomb_cost(abs_low_coeff);
1116 }
1117 return cost_diff;
1118}
1119
Angie Chianga530ef42017-05-30 16:32:36 -07001120#define COST_MAP_SIZE 5
1121#define COST_MAP_OFFSET 2
1122
1123static INLINE int check_nz_neighbor(tran_low_t qc) { return abs(qc) == 1; }
1124
1125static INLINE int check_base_neighbor(tran_low_t qc) {
1126 return abs(qc) <= 1 + NUM_BASE_LEVELS;
1127}
1128
1129static INLINE int check_br_neighbor(tran_low_t qc) {
1130 return abs(qc) > BR_MAG_OFFSET;
1131}
1132
Angie Chiang87278292017-10-18 09:59:47 -07001133#define FAST_OPTIMIZE_TXB 1
Angie Chiange80957f2017-09-05 10:48:00 -07001134
1135#if FAST_OPTIMIZE_TXB
1136#define ALNB_REF_OFFSET_NUM 2
Linfeng Zhang4afda452017-10-24 10:34:04 -07001137static const int alnb_ref_offset[ALNB_REF_OFFSET_NUM][2] = {
Angie Chiange80957f2017-09-05 10:48:00 -07001138 { -1, 0 }, { 0, -1 },
1139};
1140#define NB_REF_OFFSET_NUM 4
Linfeng Zhang4afda452017-10-24 10:34:04 -07001141static const int nb_ref_offset[NB_REF_OFFSET_NUM][2] = {
Angie Chiange80957f2017-09-05 10:48:00 -07001142 { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 },
1143};
1144#endif // FAST_OPTIMIZE_TXB
1145
Angie Chianga530ef42017-05-30 16:32:36 -07001146// TODO(angiebird): add static to this function once it's called
1147int try_level_down(int coeff_idx, const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001148 const LV_MAP_COEFF_COST *txb_costs, TxbInfo *txb_info,
Angie Chiang25645b72017-09-24 14:28:49 -07001149 int (*cost_map)[COST_MAP_SIZE], int fast_mode) {
1150#if !FAST_OPTIMIZE_TXB
1151 (void)fast_mode;
1152#endif
Angie Chianga530ef42017-05-30 16:32:36 -07001153 if (cost_map) {
1154 for (int i = 0; i < COST_MAP_SIZE; ++i) av1_zero(cost_map[i]);
1155 }
1156
1157 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1158 tran_low_t low_coeff;
1159 if (qc == 0) return 0;
1160 int accu_cost_diff = 0;
1161
1162 const int16_t *iscan = txb_info->scan_order->iscan;
1163 const int eob = txb_info->eob;
1164 const int scan_idx = iscan[coeff_idx];
1165 if (scan_idx < eob) {
1166 const int cost_diff = try_self_level_down(&low_coeff, coeff_idx, txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001167 txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001168 if (cost_map)
1169 cost_map[0 + COST_MAP_OFFSET][0 + COST_MAP_OFFSET] = cost_diff;
1170 accu_cost_diff += cost_diff;
1171 }
1172
1173 const int row = coeff_idx >> txb_info->bwl;
1174 const int col = coeff_idx - (row << txb_info->bwl);
1175 if (check_nz_neighbor(qc)) {
Angie Chiange80957f2017-09-05 10:48:00 -07001176#if FAST_OPTIMIZE_TXB
Linfeng Zhang4afda452017-10-24 10:34:04 -07001177 const int(*ref_offset)[2];
Angie Chiang25645b72017-09-24 14:28:49 -07001178 int ref_num;
1179 if (fast_mode) {
1180 ref_offset = alnb_ref_offset;
1181 ref_num = ALNB_REF_OFFSET_NUM;
1182 } else {
1183 ref_offset = sig_ref_offset;
1184 ref_num = SIG_REF_OFFSET_NUM;
1185 }
Angie Chiange80957f2017-09-05 10:48:00 -07001186#else
Linfeng Zhang4afda452017-10-24 10:34:04 -07001187 const int(*ref_offset)[2] = sig_ref_offset;
Angie Chiange80957f2017-09-05 10:48:00 -07001188 const int ref_num = SIG_REF_OFFSET_NUM;
1189#endif
1190 for (int i = 0; i < ref_num; ++i) {
1191 const int nb_row = row - ref_offset[i][0];
1192 const int nb_col = col - ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001193 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han4cbb3632017-06-13 12:50:33 -07001194
Angie Chiang0c89dca2017-08-17 16:36:18 -07001195 if (nb_row < 0 || nb_col < 0 || nb_row >= txb_info->height ||
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001196 nb_col >= txb_info->width)
Jingning Han3455e762017-06-13 21:15:44 -07001197 continue;
1198
Angie Chianga530ef42017-05-30 16:32:36 -07001199 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001200 if (nb_scan_idx < eob) {
Angie Chianga530ef42017-05-30 16:32:36 -07001201 const int cost_diff = try_neighbor_level_down_nz(
Jingning Handfd72322017-08-09 14:04:12 -07001202 nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001203 if (cost_map)
1204 cost_map[nb_row - row + COST_MAP_OFFSET]
1205 [nb_col - col + COST_MAP_OFFSET] += cost_diff;
1206 accu_cost_diff += cost_diff;
1207 }
1208 }
1209 }
1210
1211 if (check_base_neighbor(qc)) {
Angie Chiange80957f2017-09-05 10:48:00 -07001212#if FAST_OPTIMIZE_TXB
Linfeng Zhang4afda452017-10-24 10:34:04 -07001213 const int(*ref_offset)[2];
Angie Chiang25645b72017-09-24 14:28:49 -07001214 int ref_num;
1215 if (fast_mode) {
1216 ref_offset = nb_ref_offset;
1217 ref_num = NB_REF_OFFSET_NUM;
1218 } else {
1219 ref_offset = base_ref_offset;
1220 ref_num = BASE_CONTEXT_POSITION_NUM;
1221 }
Angie Chiange80957f2017-09-05 10:48:00 -07001222#else
Linfeng Zhangce065ca2017-10-17 16:49:30 -07001223 const int(*ref_offset)[2] = base_ref_offset;
Angie Chiang25645b72017-09-24 14:28:49 -07001224 int ref_num = BASE_CONTEXT_POSITION_NUM;
Angie Chiange80957f2017-09-05 10:48:00 -07001225#endif
1226 for (int i = 0; i < ref_num; ++i) {
1227 const int nb_row = row - ref_offset[i][0];
1228 const int nb_col = col - ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001229 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001230
Angie Chiang0c89dca2017-08-17 16:36:18 -07001231 if (nb_row < 0 || nb_col < 0 || nb_row >= txb_info->height ||
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001232 nb_col >= txb_info->width)
Jingning Han3455e762017-06-13 21:15:44 -07001233 continue;
1234
Angie Chianga530ef42017-05-30 16:32:36 -07001235 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001236 if (nb_scan_idx < eob) {
Angie Chianga530ef42017-05-30 16:32:36 -07001237 const int cost_diff = try_neighbor_level_down_base(
Jingning Handfd72322017-08-09 14:04:12 -07001238 nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001239 if (cost_map)
1240 cost_map[nb_row - row + COST_MAP_OFFSET]
1241 [nb_col - col + COST_MAP_OFFSET] += cost_diff;
1242 accu_cost_diff += cost_diff;
1243 }
1244 }
1245 }
1246
1247 if (check_br_neighbor(qc)) {
Angie Chiange80957f2017-09-05 10:48:00 -07001248#if FAST_OPTIMIZE_TXB
Linfeng Zhang4afda452017-10-24 10:34:04 -07001249 const int(*ref_offset)[2];
Angie Chiang25645b72017-09-24 14:28:49 -07001250 int ref_num;
1251 if (fast_mode) {
1252 ref_offset = nb_ref_offset;
1253 ref_num = NB_REF_OFFSET_NUM;
1254 } else {
1255 ref_offset = br_ref_offset;
1256 ref_num = BR_CONTEXT_POSITION_NUM;
1257 }
Angie Chiange80957f2017-09-05 10:48:00 -07001258#else
Linfeng Zhangce065ca2017-10-17 16:49:30 -07001259 const int(*ref_offset)[2] = br_ref_offset;
Angie Chiange80957f2017-09-05 10:48:00 -07001260 const int ref_num = BR_CONTEXT_POSITION_NUM;
1261#endif
1262 for (int i = 0; i < ref_num; ++i) {
1263 const int nb_row = row - ref_offset[i][0];
1264 const int nb_col = col - ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001265 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001266
Angie Chiang0c89dca2017-08-17 16:36:18 -07001267 if (nb_row < 0 || nb_col < 0 || nb_row >= txb_info->height ||
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001268 nb_col >= txb_info->width)
Jingning Han3455e762017-06-13 21:15:44 -07001269 continue;
1270
Angie Chianga530ef42017-05-30 16:32:36 -07001271 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001272 if (nb_scan_idx < eob) {
Angie Chianga530ef42017-05-30 16:32:36 -07001273 const int cost_diff = try_neighbor_level_down_br(
Jingning Handfd72322017-08-09 14:04:12 -07001274 nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001275 if (cost_map)
1276 cost_map[nb_row - row + COST_MAP_OFFSET]
1277 [nb_col - col + COST_MAP_OFFSET] += cost_diff;
1278 accu_cost_diff += cost_diff;
1279 }
1280 }
1281 }
1282
1283 return accu_cost_diff;
1284}
1285
Angie Chiangc77799b2017-05-30 17:08:17 -07001286static int get_low_coeff_cost(int coeff_idx, const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001287 const LV_MAP_COEFF_COST *txb_costs,
Angie Chiangc77799b2017-05-30 17:08:17 -07001288 const TxbInfo *txb_info) {
1289 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1290 const int abs_qc = abs(qc);
1291 assert(abs_qc <= 1);
1292 int cost = 0;
Jingning Han3422ac12017-10-25 20:37:53 -07001293
Ola Hugosson13892102017-11-06 08:01:44 +01001294#if CONFIG_LV_MAP_MULTI
1295 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
1296 cost += txb_costs->base_cost[ctx][AOMMIN(abs_qc, 3)];
1297 if (qc != 0) {
1298 cost += get_sign_bit_cost(qc, coeff_idx, txb_costs->dc_sign_cost,
1299 txb_info->txb_ctx->dc_sign_ctx);
1300 }
1301#else
1302 const int scan_idx = txb_info->scan_order->iscan[coeff_idx];
Dake Hea47cd6c2017-10-13 18:09:58 -07001303 if (scan_idx < txb_info->eob - 1) {
Jingning Handfd72322017-08-09 14:04:12 -07001304 const int *level_cost = get_level_prob(0, coeff_idx, txb_cache, txb_costs);
1305 cost += level_cost[qc != 0];
Angie Chiangc77799b2017-05-30 17:08:17 -07001306 }
1307
1308 if (qc != 0) {
1309 const int base_idx = 0;
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001310 const int ctx = txb_cache->base_ctx_arr[base_idx][coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -07001311 cost += get_base_cost(abs_qc, ctx, txb_costs->base_cost[base_idx][ctx],
1312 base_idx);
Jingning Handfd72322017-08-09 14:04:12 -07001313 cost += get_sign_bit_cost(qc, coeff_idx, txb_costs->dc_sign_cost,
Angie Chiangc77799b2017-05-30 17:08:17 -07001314 txb_info->txb_ctx->dc_sign_ctx);
1315 }
Ola Hugosson13892102017-11-06 08:01:44 +01001316#endif
Angie Chiangc77799b2017-05-30 17:08:17 -07001317 return cost;
1318}
1319
1320static INLINE void set_eob(TxbInfo *txb_info, int eob) {
1321 txb_info->eob = eob;
Dake Hea47cd6c2017-10-13 18:09:58 -07001322 txb_info->seg_eob = tx_size_2d[txb_info->tx_size];
Angie Chiangc77799b2017-05-30 17:08:17 -07001323}
1324
1325// TODO(angiebird): add static to this function once it's called
1326int try_change_eob(int *new_eob, int coeff_idx, const TxbCache *txb_cache,
Angie Chiang25645b72017-09-24 14:28:49 -07001327 const LV_MAP_COEFF_COST *txb_costs, TxbInfo *txb_info,
1328 int fast_mode) {
Angie Chiangc77799b2017-05-30 17:08:17 -07001329 assert(txb_info->eob > 0);
1330 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1331 const int abs_qc = abs(qc);
1332 if (abs_qc != 1) {
1333 *new_eob = -1;
1334 return 0;
1335 }
1336 const int16_t *iscan = txb_info->scan_order->iscan;
1337 const int16_t *scan = txb_info->scan_order->scan;
1338 const int scan_idx = iscan[coeff_idx];
1339 *new_eob = 0;
1340 int cost_diff = 0;
Jingning Handfd72322017-08-09 14:04:12 -07001341 cost_diff -= get_low_coeff_cost(coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chiangc77799b2017-05-30 17:08:17 -07001342 // int coeff_cost =
Angie Chiang5e012fe2017-05-30 18:47:39 -07001343 // get_coeff_cost(qc, scan_idx, txb_info, txb_probs);
Angie Chiangc77799b2017-05-30 17:08:17 -07001344 // if (-cost_diff != coeff_cost) {
1345 // printf("-cost_diff %d coeff_cost %d\n", -cost_diff, coeff_cost);
1346 // get_low_coeff_cost(coeff_idx, txb_cache, txb_probs, txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001347 // get_coeff_cost(qc, scan_idx, txb_info, txb_probs);
Angie Chiangc77799b2017-05-30 17:08:17 -07001348 // }
1349 for (int si = scan_idx - 1; si >= 0; --si) {
1350 const int ci = scan[si];
1351 if (txb_info->qcoeff[ci] != 0) {
1352 *new_eob = si + 1;
1353 break;
1354 } else {
Jingning Handfd72322017-08-09 14:04:12 -07001355 cost_diff -= get_low_coeff_cost(ci, txb_cache, txb_costs, txb_info);
Angie Chiangc77799b2017-05-30 17:08:17 -07001356 }
1357 }
1358
1359 const int org_eob = txb_info->eob;
1360 set_eob(txb_info, *new_eob);
Angie Chiang25645b72017-09-24 14:28:49 -07001361 cost_diff += try_level_down(coeff_idx, txb_cache, txb_costs, txb_info, NULL,
1362 fast_mode);
Angie Chiangc77799b2017-05-30 17:08:17 -07001363 set_eob(txb_info, org_eob);
1364
1365 if (*new_eob > 0) {
1366 // Note that get_eob_ctx does NOT actually account for qcoeff, so we don't
1367 // need to lower down the qcoeff here
Linfeng Zhang7f7e89f2017-10-17 17:07:41 -07001368 const int eob_ctx =
1369 get_eob_ctx(scan[*new_eob - 1], txb_info->txs_ctx, txb_info->tx_type);
Jingning Handfd72322017-08-09 14:04:12 -07001370 cost_diff -= txb_costs->eob_cost[eob_ctx][0];
1371 cost_diff += txb_costs->eob_cost[eob_ctx][1];
Angie Chiangc77799b2017-05-30 17:08:17 -07001372 } else {
1373 const int txb_skip_ctx = txb_info->txb_ctx->txb_skip_ctx;
Jingning Handfd72322017-08-09 14:04:12 -07001374 cost_diff -= txb_costs->txb_skip_cost[txb_skip_ctx][0];
1375 cost_diff += txb_costs->txb_skip_cost[txb_skip_ctx][1];
Angie Chiangc77799b2017-05-30 17:08:17 -07001376 }
1377 return cost_diff;
1378}
Angie Chiang47e07072017-05-30 17:27:01 -07001379
Angie Chiangd19969e2017-05-30 18:02:33 -07001380// TODO(angiebird): add static to this function it's called
Linfeng Zhang1015a342017-10-24 16:20:41 -07001381void update_level_down(const int coeff_idx, TxbCache *const txb_cache,
1382 TxbInfo *const txb_info) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001383 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1384 const int abs_qc = abs(qc);
1385 if (qc == 0) return;
1386 const tran_low_t low_coeff = get_lower_coeff(qc);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001387 update_coeff(coeff_idx, low_coeff, txb_info);
Angie Chiangd19969e2017-05-30 18:02:33 -07001388
1389 const int row = coeff_idx >> txb_info->bwl;
1390 const int col = coeff_idx - (row << txb_info->bwl);
1391 const int eob = txb_info->eob;
1392 const int16_t *iscan = txb_info->scan_order->iscan;
1393 for (int i = 0; i < SIG_REF_OFFSET_NUM; ++i) {
1394 const int nb_row = row - sig_ref_offset[i][0];
1395 const int nb_col = col - sig_ref_offset[i][1];
Jingning Han3455e762017-06-13 21:15:44 -07001396
1397 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001398 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001399 continue;
1400
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001401 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiangd19969e2017-05-30 18:02:33 -07001402 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001403 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001404 const int scan_idx = iscan[coeff_idx];
1405 if (scan_idx < nb_scan_idx) {
1406 const int level = 1;
1407 if (abs_qc == level) {
1408 txb_cache->nz_count_arr[nb_coeff_idx] -= 1;
1409 assert(txb_cache->nz_count_arr[nb_coeff_idx] >= 0);
1410 }
1411 const int count = txb_cache->nz_count_arr[nb_coeff_idx];
Dake He03a32922017-10-31 08:06:45 -07001412 txb_cache->nz_ctx_arr[nb_coeff_idx] = get_nz_map_ctx_from_count(
1413 count, nb_coeff_idx, txb_info->bwl, txb_info->height,
1414#if USE_CAUSAL_BASE_CTX
1415 0,
1416#endif
1417 txb_info->tx_type);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001418 // int ref_ctx = get_nz_map_ctx(txb_info->levels, nb_coeff_idx,
Linfeng Zhangb6957c22017-10-25 13:17:28 -07001419 // txb_info->bwl, tx_type);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001420 // if (ref_ctx != txb_cache->nz_ctx_arr[nb_coeff_idx])
Angie Chiangd19969e2017-05-30 18:02:33 -07001421 // printf("nz ctx %d ref_ctx %d\n",
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001422 // txb_cache->nz_ctx_arr[nb_coeff_idx], ref_ctx);
Angie Chiangd19969e2017-05-30 18:02:33 -07001423 }
1424 }
1425 }
1426
Angie Chiangdef11252017-08-18 14:37:32 -07001427 const BASE_CTX_TABLE *base_ctx_table =
1428 txb_info->coeff_ctx_table->base_ctx_table;
Angie Chiangd19969e2017-05-30 18:02:33 -07001429 for (int i = 0; i < BASE_CONTEXT_POSITION_NUM; ++i) {
1430 const int nb_row = row - base_ref_offset[i][0];
1431 const int nb_col = col - base_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001432 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001433
1434 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001435 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001436 continue;
1437
Angie Chiangd19969e2017-05-30 18:02:33 -07001438 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
1439 if (!has_base(nb_coeff, 0)) continue;
1440 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001441 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001442 if (row >= nb_row && col >= nb_col)
1443 update_mag_arr(txb_cache->base_mag_arr[nb_coeff_idx], abs_qc);
1444 const int mag =
1445 get_mag_from_mag_arr(txb_cache->base_mag_arr[nb_coeff_idx]);
1446 for (int base_idx = 0; base_idx < NUM_BASE_LEVELS; ++base_idx) {
1447 if (!has_base(nb_coeff, base_idx)) continue;
1448 const int level = base_idx + 1;
1449 if (abs_qc == level) {
1450 txb_cache->base_count_arr[base_idx][nb_coeff_idx] -= 1;
1451 assert(txb_cache->base_count_arr[base_idx][nb_coeff_idx] >= 0);
1452 }
1453 const int count = txb_cache->base_count_arr[base_idx][nb_coeff_idx];
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001454 txb_cache->base_ctx_arr[base_idx][nb_coeff_idx] =
Angie Chiangdef11252017-08-18 14:37:32 -07001455 base_ctx_table[nb_row != 0][nb_col != 0][mag > level][count];
Angie Chiangd19969e2017-05-30 18:02:33 -07001456 // int ref_ctx = get_base_ctx(txb_info->qcoeff, nb_coeff_idx,
Linfeng Zhang8c841f72017-10-18 15:32:29 -07001457 // txb_info->bwl, level - 1);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001458 // if (ref_ctx != txb_cache->base_ctx_arr[base_idx][nb_coeff_idx]) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001459 // printf("base ctx %d ref_ctx %d\n",
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001460 // txb_cache->base_ctx_arr[base_idx][nb_coeff_idx], ref_ctx);
Angie Chiangd19969e2017-05-30 18:02:33 -07001461 // }
1462 }
1463 }
1464 }
1465
1466 for (int i = 0; i < BR_CONTEXT_POSITION_NUM; ++i) {
1467 const int nb_row = row - br_ref_offset[i][0];
1468 const int nb_col = col - br_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001469 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001470
1471 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001472 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001473 continue;
1474
Angie Chiangd19969e2017-05-30 18:02:33 -07001475 const int nb_scan_idx = iscan[nb_coeff_idx];
1476 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
1477 if (!has_br(nb_coeff)) continue;
Jingning Han3455e762017-06-13 21:15:44 -07001478 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001479 const int level = 1 + NUM_BASE_LEVELS;
1480 if (abs_qc == level) {
1481 txb_cache->br_count_arr[nb_coeff_idx] -= 1;
1482 assert(txb_cache->br_count_arr[nb_coeff_idx] >= 0);
1483 }
1484 if (row >= nb_row && col >= nb_col)
1485 update_mag_arr(txb_cache->br_mag_arr[nb_coeff_idx], abs_qc);
1486 const int count = txb_cache->br_count_arr[nb_coeff_idx];
1487 const int mag = get_mag_from_mag_arr(txb_cache->br_mag_arr[nb_coeff_idx]);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001488 txb_cache->br_ctx_arr[nb_coeff_idx] =
Angie Chiangd19969e2017-05-30 18:02:33 -07001489 get_br_ctx_from_count_mag(nb_row, nb_col, count, mag);
1490 // int ref_ctx = get_level_ctx(txb_info->qcoeff, nb_coeff_idx,
1491 // txb_info->bwl);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001492 // if (ref_ctx != txb_cache->br_ctx_arr[nb_coeff_idx]) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001493 // printf("base ctx %d ref_ctx %d\n",
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001494 // txb_cache->br_ctx_arr[nb_coeff_idx], ref_ctx);
Angie Chiangd19969e2017-05-30 18:02:33 -07001495 // }
1496 }
1497 }
1498}
1499
Linfeng Zhang1015a342017-10-24 16:20:41 -07001500static int get_coeff_cost(const tran_low_t qc, const int scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +01001501#if CONFIG_LV_MAP_MULTI
1502 const int is_eob,
1503#endif
Linfeng Zhang1015a342017-10-24 16:20:41 -07001504 const TxbInfo *const txb_info,
1505 const LV_MAP_COEFF_COST *const txb_costs) {
Angie Chiang488f9212017-05-30 12:46:26 -07001506 const TXB_CTX *txb_ctx = txb_info->txb_ctx;
1507 const int is_nz = (qc != 0);
1508 const tran_low_t abs_qc = abs(qc);
1509 int cost = 0;
1510 const int16_t *scan = txb_info->scan_order->scan;
Dake He03a32922017-10-31 08:06:45 -07001511
Ola Hugosson13892102017-11-06 08:01:44 +01001512#if CONFIG_LV_MAP_MULTI
1513 int coeff_ctx =
1514 get_nz_map_ctx(txb_info->levels, scan_idx, scan, txb_info->bwl,
1515 txb_info->height, txb_info->tx_type, is_eob);
1516 cost += txb_costs->base_cost[coeff_ctx][AOMMIN(abs_qc, 3)];
1517#else
Dake He03a32922017-10-31 08:06:45 -07001518#if USE_CAUSAL_BASE_CTX
1519 int coeff_ctx =
Linfeng Zhangb6957c22017-10-25 13:17:28 -07001520 get_nz_map_ctx(txb_info->levels, scan_idx, scan, txb_info->bwl,
1521 txb_info->height, txb_info->tx_type);
Dake He03a32922017-10-31 08:06:45 -07001522#endif
Dake Hea47cd6c2017-10-13 18:09:58 -07001523 if (scan_idx < txb_info->eob - 1) {
Dake He03a32922017-10-31 08:06:45 -07001524#if !USE_CAUSAL_BASE_CTX
Angie Chiange9125ba2017-08-20 12:03:41 -07001525 int coeff_ctx =
Linfeng Zhang1015a342017-10-24 16:20:41 -07001526 get_nz_map_ctx(txb_info->levels, scan_idx, scan, txb_info->bwl,
Linfeng Zhangb6957c22017-10-25 13:17:28 -07001527 txb_info->height, txb_info->tx_type);
Dake He03a32922017-10-31 08:06:45 -07001528#endif
Jingning Handfd72322017-08-09 14:04:12 -07001529 cost += txb_costs->nz_map_cost[coeff_ctx][is_nz];
Angie Chiang488f9212017-05-30 12:46:26 -07001530 }
Ola Hugosson13892102017-11-06 08:01:44 +01001531#endif
Angie Chiang488f9212017-05-30 12:46:26 -07001532 if (is_nz) {
Jingning Handfd72322017-08-09 14:04:12 -07001533 cost += get_sign_bit_cost(qc, scan_idx, txb_costs->dc_sign_cost,
Angie Chiang488f9212017-05-30 12:46:26 -07001534 txb_ctx->dc_sign_ctx);
1535
Ola Hugosson13892102017-11-06 08:01:44 +01001536#if !CONFIG_LV_MAP_MULTI
Dake He03a32922017-10-31 08:06:45 -07001537#if USE_CAUSAL_BASE_CTX
1538 int k;
1539 for (k = 0; k < NUM_BASE_LEVELS; ++k) {
1540 int ctx = coeff_ctx;
1541 int is_k = (abs_qc > (k + 1));
1542
1543 cost += txb_costs->base_cost[k][ctx][is_k];
1544 if (is_k == 0) break;
1545 }
1546#else
Angie Chiang488f9212017-05-30 12:46:26 -07001547 int ctx_ls[NUM_BASE_LEVELS] = { 0 };
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001548 get_base_ctx_set(txb_info->levels, scan[scan_idx], txb_info->bwl, ctx_ls);
Angie Chiang488f9212017-05-30 12:46:26 -07001549
1550 int i;
1551 for (i = 0; i < NUM_BASE_LEVELS; ++i) {
Jingning Handfd72322017-08-09 14:04:12 -07001552 cost += get_base_cost(abs_qc, ctx_ls[i],
1553 txb_costs->base_cost[i][ctx_ls[i]], i);
Angie Chiang488f9212017-05-30 12:46:26 -07001554 }
Dake He03a32922017-10-31 08:06:45 -07001555#endif
Ola Hugosson13892102017-11-06 08:01:44 +01001556#endif
Angie Chiang488f9212017-05-30 12:46:26 -07001557 if (abs_qc > NUM_BASE_LEVELS) {
Linfeng Zhang97fc4742017-11-07 12:57:25 -08001558 const int row = scan[scan_idx] >> txb_info->bwl;
1559 const int col = scan[scan_idx] - (row << txb_info->bwl);
1560 const int count = get_level_count(
1561 txb_info->levels, (1 << txb_info->bwl) + TX_PAD_HOR, row, col,
1562 NUM_BASE_LEVELS, br_ref_offset, BR_CONTEXT_POSITION_NUM);
1563 const int ctx =
1564 get_br_ctx(txb_info->levels, scan[scan_idx], txb_info->bwl, count);
Jingning Handfd72322017-08-09 14:04:12 -07001565 cost += get_br_cost(abs_qc, ctx, txb_costs->lps_cost[ctx]);
Angie Chiang488f9212017-05-30 12:46:26 -07001566 cost += get_golomb_cost(abs_qc);
1567 }
Angie Chiang488f9212017-05-30 12:46:26 -07001568 }
1569 return cost;
1570}
1571
Angie Chiang47e07072017-05-30 17:27:01 -07001572#if TEST_OPTIMIZE_TXB
Angie Chiang5e012fe2017-05-30 18:47:39 -07001573#define ALL_REF_OFFSET_NUM 17
Linfeng Zhang4afda452017-10-24 10:34:04 -07001574static const int all_ref_offset[ALL_REF_OFFSET_NUM][2] = {
Angie Chiang5e012fe2017-05-30 18:47:39 -07001575 { 0, 0 }, { -2, -1 }, { -2, 0 }, { -2, 1 }, { -1, -2 }, { -1, -1 },
1576 { -1, 0 }, { -1, 1 }, { 0, -2 }, { 0, -1 }, { 1, -2 }, { 1, -1 },
1577 { 1, 0 }, { 2, 0 }, { 0, 1 }, { 0, 2 }, { 1, 1 },
1578};
1579
Angie Chiang0b2795c2017-09-29 16:00:08 -07001580static int try_level_down_ref(int coeff_idx, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang5e012fe2017-05-30 18:47:39 -07001581 TxbInfo *txb_info,
1582 int (*cost_map)[COST_MAP_SIZE]) {
1583 if (cost_map) {
1584 for (int i = 0; i < COST_MAP_SIZE; ++i) av1_zero(cost_map[i]);
1585 }
1586 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1587 if (qc == 0) return 0;
1588 int row = coeff_idx >> txb_info->bwl;
1589 int col = coeff_idx - (row << txb_info->bwl);
1590 int org_cost = 0;
1591 for (int i = 0; i < ALL_REF_OFFSET_NUM; ++i) {
1592 int nb_row = row - all_ref_offset[i][0];
1593 int nb_col = col - all_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001594 int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001595 int nb_scan_idx = txb_info->scan_order->iscan[nb_coeff_idx];
1596 if (nb_scan_idx < txb_info->eob && nb_row >= 0 && nb_col >= 0 &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001597 nb_row < txb_info->height && nb_col < txb_info->width) {
Angie Chiang5e012fe2017-05-30 18:47:39 -07001598 tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
Ola Hugosson13892102017-11-06 08:01:44 +01001599#if CONFIG_LV_MAP_MULTI
1600 int cost =
1601 get_coeff_cost(nb_coeff, nb_scan_idx, is_eob, txb_info, txb_costs);
1602#else
Angie Chiang0b2795c2017-09-29 16:00:08 -07001603 int cost = get_coeff_cost(nb_coeff, nb_scan_idx, txb_info, txb_costs);
Ola Hugosson13892102017-11-06 08:01:44 +01001604#endif
Angie Chiang5e012fe2017-05-30 18:47:39 -07001605 if (cost_map)
1606 cost_map[nb_row - row + COST_MAP_OFFSET]
1607 [nb_col - col + COST_MAP_OFFSET] -= cost;
1608 org_cost += cost;
1609 }
1610 }
Linfeng Zhang1015a342017-10-24 16:20:41 -07001611 update_qcoeff(coeff_idx, get_lower_coeff(qc), txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001612 int new_cost = 0;
1613 for (int i = 0; i < ALL_REF_OFFSET_NUM; ++i) {
1614 int nb_row = row - all_ref_offset[i][0];
1615 int nb_col = col - all_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001616 int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001617 int nb_scan_idx = txb_info->scan_order->iscan[nb_coeff_idx];
1618 if (nb_scan_idx < txb_info->eob && nb_row >= 0 && nb_col >= 0 &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001619 nb_row < txb_info->height && nb_col < txb_info->width) {
Angie Chiang5e012fe2017-05-30 18:47:39 -07001620 tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
Ola Hugosson13892102017-11-06 08:01:44 +01001621#if CONFIG_LV_MAP_MULTI
1622 int cost =
1623 get_coeff_cost(nb_coeff, nb_scan_idx, is_eob, txb_info, txb_costs);
1624#else
Angie Chiang0b2795c2017-09-29 16:00:08 -07001625 int cost = get_coeff_cost(nb_coeff, nb_scan_idx, txb_info, txb_costs);
Ola Hugosson13892102017-11-06 08:01:44 +01001626#endif
Angie Chiang5e012fe2017-05-30 18:47:39 -07001627 if (cost_map)
1628 cost_map[nb_row - row + COST_MAP_OFFSET]
1629 [nb_col - col + COST_MAP_OFFSET] += cost;
1630 new_cost += cost;
1631 }
1632 }
Linfeng Zhang1015a342017-10-24 16:20:41 -07001633 update_qcoeff(coeff_idx, qc, txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001634 return new_cost - org_cost;
1635}
1636
1637static void test_level_down(int coeff_idx, const TxbCache *txb_cache,
Angie Chiang0b2795c2017-09-29 16:00:08 -07001638 const LV_MAP_COEFF_COST *txb_costs,
1639 TxbInfo *txb_info) {
Angie Chiang47e07072017-05-30 17:27:01 -07001640 int cost_map[COST_MAP_SIZE][COST_MAP_SIZE];
1641 int ref_cost_map[COST_MAP_SIZE][COST_MAP_SIZE];
1642 const int cost_diff =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001643 try_level_down(coeff_idx, txb_cache, txb_costs, txb_info, cost_map, 0);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001644 const int cost_diff_ref =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001645 try_level_down_ref(coeff_idx, txb_costs, txb_info, ref_cost_map);
Angie Chiang47e07072017-05-30 17:27:01 -07001646 if (cost_diff != cost_diff_ref) {
1647 printf("qc %d cost_diff %d cost_diff_ref %d\n", txb_info->qcoeff[coeff_idx],
1648 cost_diff, cost_diff_ref);
1649 for (int r = 0; r < COST_MAP_SIZE; ++r) {
1650 for (int c = 0; c < COST_MAP_SIZE; ++c) {
1651 printf("%d:%d ", cost_map[r][c], ref_cost_map[r][c]);
1652 }
1653 printf("\n");
1654 }
1655 }
1656}
1657#endif
1658
Angie Chiang488f9212017-05-30 12:46:26 -07001659// TODO(angiebird): make this static once it's called
Jingning Handfd72322017-08-09 14:04:12 -07001660int get_txb_cost(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs) {
Angie Chiang488f9212017-05-30 12:46:26 -07001661 int cost = 0;
1662 int txb_skip_ctx = txb_info->txb_ctx->txb_skip_ctx;
1663 const int16_t *scan = txb_info->scan_order->scan;
1664 if (txb_info->eob == 0) {
Jingning Handfd72322017-08-09 14:04:12 -07001665 cost = txb_costs->txb_skip_cost[txb_skip_ctx][1];
Angie Chiang488f9212017-05-30 12:46:26 -07001666 return cost;
1667 }
Jingning Handfd72322017-08-09 14:04:12 -07001668 cost = txb_costs->txb_skip_cost[txb_skip_ctx][0];
Angie Chiang488f9212017-05-30 12:46:26 -07001669 for (int c = 0; c < txb_info->eob; ++c) {
1670 tran_low_t qc = txb_info->qcoeff[scan[c]];
Ola Hugosson13892102017-11-06 08:01:44 +01001671#if CONFIG_LV_MAP_MULTI
1672 int coeff_cost =
1673 get_coeff_cost(qc, c, c == txb_info->eob - 1, txb_info, txb_costs);
1674#else
Jingning Handfd72322017-08-09 14:04:12 -07001675 int coeff_cost = get_coeff_cost(qc, c, txb_info, txb_costs);
Ola Hugosson13892102017-11-06 08:01:44 +01001676#endif
Angie Chiang488f9212017-05-30 12:46:26 -07001677 cost += coeff_cost;
1678 }
1679 return cost;
1680}
1681
Angie Chiang5e012fe2017-05-30 18:47:39 -07001682#if TEST_OPTIMIZE_TXB
Angie Chiang0b2795c2017-09-29 16:00:08 -07001683void test_try_change_eob(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang5e012fe2017-05-30 18:47:39 -07001684 TxbCache *txb_cache) {
1685 int eob = txb_info->eob;
1686 const int16_t *scan = txb_info->scan_order->scan;
1687 if (eob > 0) {
1688 int last_si = eob - 1;
1689 int last_ci = scan[last_si];
1690 int last_coeff = txb_info->qcoeff[last_ci];
1691 if (abs(last_coeff) == 1) {
1692 int new_eob;
1693 int cost_diff =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001694 try_change_eob(&new_eob, last_ci, txb_cache, txb_costs, txb_info, 0);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001695 int org_eob = txb_info->eob;
Angie Chiang0b2795c2017-09-29 16:00:08 -07001696 int cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001697
Linfeng Zhang1015a342017-10-24 16:20:41 -07001698 update_qcoeff(last_ci, get_lower_coeff(last_coeff), txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001699 set_eob(txb_info, new_eob);
Angie Chiang0b2795c2017-09-29 16:00:08 -07001700 int new_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001701 set_eob(txb_info, org_eob);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001702 update_qcoeff(last_ci, last_coeff, txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001703
1704 int ref_cost_diff = -cost + new_cost;
1705 if (cost_diff != ref_cost_diff)
1706 printf("org_eob %d new_eob %d cost_diff %d ref_cost_diff %d\n", org_eob,
1707 new_eob, cost_diff, ref_cost_diff);
1708 }
1709 }
1710}
1711#endif
1712
Angie Chiang47e07072017-05-30 17:27:01 -07001713void try_level_down_facade(LevelDownStats *stats, int scan_idx,
Jingning Handfd72322017-08-09 14:04:12 -07001714 const TxbCache *txb_cache,
1715 const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang25645b72017-09-24 14:28:49 -07001716 TxbInfo *txb_info, int fast_mode) {
Angie Chiang47e07072017-05-30 17:27:01 -07001717 const int16_t *scan = txb_info->scan_order->scan;
1718 const int coeff_idx = scan[scan_idx];
1719 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1720 stats->new_eob = -1;
1721 stats->update = 0;
1722 if (qc == 0) {
1723 return;
1724 }
1725
1726 const tran_low_t tqc = txb_info->tcoeff[coeff_idx];
1727 const int dqv = txb_info->dequant[coeff_idx != 0];
1728
1729 const tran_low_t dqc = qcoeff_to_dqcoeff(qc, dqv, txb_info->shift);
Jingning Han641c1e52017-10-13 09:42:49 -07001730
1731 if (scan_idx != txb_info->eob - 1)
1732 if (abs(dqc) < abs(tqc)) return;
1733
Angie Chiang47e07072017-05-30 17:27:01 -07001734 const int64_t dqc_dist = get_coeff_dist(tqc, dqc, txb_info->shift);
1735
1736 stats->low_qc = get_lower_coeff(qc);
1737 stats->low_dqc = qcoeff_to_dqcoeff(stats->low_qc, dqv, txb_info->shift);
1738 const int64_t low_dqc_dist =
1739 get_coeff_dist(tqc, stats->low_dqc, txb_info->shift);
1740
1741 stats->dist_diff = -dqc_dist + low_dqc_dist;
1742 stats->cost_diff = 0;
1743 stats->new_eob = txb_info->eob;
1744 if (scan_idx == txb_info->eob - 1 && abs(qc) == 1) {
1745 stats->cost_diff = try_change_eob(&stats->new_eob, coeff_idx, txb_cache,
Angie Chiang25645b72017-09-24 14:28:49 -07001746 txb_costs, txb_info, fast_mode);
Angie Chiang47e07072017-05-30 17:27:01 -07001747 } else {
Angie Chiang25645b72017-09-24 14:28:49 -07001748 stats->cost_diff = try_level_down(coeff_idx, txb_cache, txb_costs, txb_info,
1749 NULL, fast_mode);
Angie Chiang47e07072017-05-30 17:27:01 -07001750#if TEST_OPTIMIZE_TXB
Angie Chiang0b2795c2017-09-29 16:00:08 -07001751 test_level_down(coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chiang47e07072017-05-30 17:27:01 -07001752#endif
1753 }
Urvang Joshi70006e42017-06-14 16:08:55 -07001754 stats->rd_diff = RDCOST(txb_info->rdmult, stats->cost_diff, stats->dist_diff);
Angie Chiang47e07072017-05-30 17:27:01 -07001755 if (stats->rd_diff < 0) stats->update = 1;
1756 return;
1757}
Angie Chiang07c57f32017-05-30 18:18:33 -07001758
Jingning Han3422ac12017-10-25 20:37:53 -07001759#if 1
Dake Hea47cd6c2017-10-13 18:09:58 -07001760static int optimize_txb(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
1761 TxbCache *txb_cache, int dry_run, int fast_mode) {
1762 (void)fast_mode;
1763 (void)txb_cache;
1764 int update = 0;
Dake He03a32922017-10-31 08:06:45 -07001765 // return update; //TODO: training only.
Dake Hea47cd6c2017-10-13 18:09:58 -07001766 if (txb_info->eob == 0) return update;
1767 const int max_eob = tx_size_2d[txb_info->tx_size];
1768
1769#if TEST_OPTIMIZE_TXB
1770 int64_t sse;
1771 int64_t org_dist =
1772 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1773 (1 << (2 * txb_info->shift));
1774 int org_cost = get_txb_cost(txb_info, txb_probs);
1775#endif
1776
1777 tran_low_t *org_qcoeff = txb_info->qcoeff;
1778 tran_low_t *org_dqcoeff = txb_info->dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001779 uint8_t *const org_levels = txb_info->levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001780
1781 tran_low_t tmp_qcoeff[MAX_TX_SQUARE];
1782 tran_low_t tmp_dqcoeff[MAX_TX_SQUARE];
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001783 uint8_t tmp_levels_buf[TX_PAD_2D];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001784 uint8_t *const tmp_levels = set_levels(tmp_levels_buf, txb_info->width);
Dake Hea47cd6c2017-10-13 18:09:58 -07001785 const int org_eob = txb_info->eob;
1786 if (dry_run) {
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001787 const int stride = txb_info->width + TX_PAD_HOR;
1788 const int levels_size =
1789
1790 (stride * (txb_info->height + TX_PAD_VER) + TX_PAD_END);
Dake Hea47cd6c2017-10-13 18:09:58 -07001791 memcpy(tmp_qcoeff, org_qcoeff, sizeof(org_qcoeff[0]) * max_eob);
1792 memcpy(tmp_dqcoeff, org_dqcoeff, sizeof(org_dqcoeff[0]) * max_eob);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001793 memcpy(tmp_levels, org_levels - TX_PAD_TOP * stride,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001794 sizeof(org_levels[0]) * levels_size);
Dake Hea47cd6c2017-10-13 18:09:58 -07001795 txb_info->qcoeff = tmp_qcoeff;
1796 txb_info->dqcoeff = tmp_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001797 txb_info->levels = tmp_levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001798 }
1799
1800 const int16_t *scan = txb_info->scan_order->scan;
1801
1802 // forward optimize the nz_map`
1803 const int init_eob = txb_info->eob;
1804 const int seg_eob = txb_info->seg_eob;
Jingning Han35deaa72017-10-26 15:36:30 -07001805 int eob_cost = get_eob_cost(init_eob, seg_eob, txb_costs, txb_info->tx_type);
Dake Hea47cd6c2017-10-13 18:09:58 -07001806
1807 // backward optimize the level-k map
1808 int64_t accu_rate = eob_cost;
1809 int64_t accu_dist = 0;
1810 int64_t prev_eob_rd_cost = INT64_MAX;
1811 int64_t cur_eob_rd_cost = 0;
1812
1813 for (int si = init_eob - 1; si >= 0; --si) {
1814 const int coeff_idx = scan[si];
1815 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1816
1817 LevelDownStats stats;
Ola Hugosson13892102017-11-06 08:01:44 +01001818#if CONFIG_LV_MAP_MULTI
1819 get_dist_cost_stats(&stats, si, si == init_eob - 1, txb_costs, txb_info);
1820#else
Dake Hea47cd6c2017-10-13 18:09:58 -07001821 get_dist_cost_stats(&stats, si, txb_costs, txb_info);
Ola Hugosson13892102017-11-06 08:01:44 +01001822#endif
Dake Hea47cd6c2017-10-13 18:09:58 -07001823
1824 if (qc == 0) {
1825 accu_rate += stats.rate;
1826 } else {
1827 // check if it is better to make this the last significant coefficient
Jingning Han35deaa72017-10-26 15:36:30 -07001828 int cur_eob_rate =
1829 get_eob_cost(si + 1, seg_eob, txb_costs, txb_info->tx_type);
Dake Hea47cd6c2017-10-13 18:09:58 -07001830 cur_eob_rd_cost = RDCOST(txb_info->rdmult, cur_eob_rate, 0);
1831 prev_eob_rd_cost =
1832 RDCOST(txb_info->rdmult, accu_rate + stats.nz_rate, accu_dist);
1833 if (cur_eob_rd_cost <= prev_eob_rd_cost) {
1834 update = 1;
1835 for (int j = si + 1; j < txb_info->eob; j++) {
1836 const int coeff_pos_j = scan[j];
1837 update_coeff(coeff_pos_j, 0, txb_info);
1838 }
1839 txb_info->eob = si + 1;
1840
Ola Hugosson13892102017-11-06 08:01:44 +01001841 // rerun cost calculation due to change of eob
Dake Hea47cd6c2017-10-13 18:09:58 -07001842 accu_rate = cur_eob_rate;
1843 accu_dist = 0;
Ola Hugosson13892102017-11-06 08:01:44 +01001844#if CONFIG_LV_MAP_MULTI
1845 get_dist_cost_stats(&stats, si, 1, txb_costs, txb_info);
1846#else
Dake Hea47cd6c2017-10-13 18:09:58 -07001847 get_dist_cost_stats(&stats, si, txb_costs, txb_info);
Ola Hugosson13892102017-11-06 08:01:44 +01001848#endif
Dake Hea47cd6c2017-10-13 18:09:58 -07001849 }
1850
1851 int bUpdCoeff = 0;
1852 if (stats.rd_low < stats.rd) {
1853 if ((stats.low_qc != 0) || (si < txb_info->eob - 1)) {
1854 bUpdCoeff = 1;
1855 update = 1;
1856 }
1857 }
1858
1859 if (bUpdCoeff) {
1860 update_coeff(coeff_idx, stats.low_qc, txb_info);
1861 accu_rate += stats.rate_low;
1862 accu_dist += stats.dist_low;
1863 } else {
1864 accu_rate += stats.rate;
1865 accu_dist += stats.dist;
1866 }
1867 }
1868 } // for (si)
1869 int non_zero_blk_rate =
1870 txb_costs->txb_skip_cost[txb_info->txb_ctx->txb_skip_ctx][0];
1871 prev_eob_rd_cost =
1872 RDCOST(txb_info->rdmult, accu_rate + non_zero_blk_rate, accu_dist);
1873
1874 int zero_blk_rate =
1875 txb_costs->txb_skip_cost[txb_info->txb_ctx->txb_skip_ctx][1];
1876 int64_t zero_blk_rd_cost = RDCOST(txb_info->rdmult, zero_blk_rate, 0);
1877 if (zero_blk_rd_cost <= prev_eob_rd_cost) {
1878 update = 1;
1879 for (int j = 0; j < txb_info->eob; j++) {
1880 const int coeff_pos_j = scan[j];
1881 update_coeff(coeff_pos_j, 0, txb_info);
1882 }
1883 txb_info->eob = 0;
1884 }
1885
1886#if TEST_OPTIMIZE_TXB
1887 int cost_diff = 0;
1888 int64_t dist_diff = 0;
1889 int64_t rd_diff = 0;
1890 int64_t new_dist =
1891 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1892 (1 << (2 * txb_info->shift));
1893 int new_cost = get_txb_cost(txb_info, txb_probs);
1894 int64_t ref_dist_diff = new_dist - org_dist;
1895 int ref_cost_diff = new_cost - org_cost;
1896 if (cost_diff != ref_cost_diff || dist_diff != ref_dist_diff)
1897 printf(
1898 "overall rd_diff %ld\ncost_diff %d ref_cost_diff%d\ndist_diff %ld "
1899 "ref_dist_diff %ld\neob %d new_eob %d\n\n",
1900 rd_diff, cost_diff, ref_cost_diff, dist_diff, ref_dist_diff, org_eob,
1901 txb_info->eob);
1902#endif
1903 if (dry_run) {
1904 txb_info->qcoeff = org_qcoeff;
1905 txb_info->dqcoeff = org_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001906 txb_info->levels = org_levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001907 set_eob(txb_info, org_eob);
1908 }
1909 return update;
1910}
1911
1912#else
Jingning Handfd72322017-08-09 14:04:12 -07001913static int optimize_txb(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang25645b72017-09-24 14:28:49 -07001914 TxbCache *txb_cache, int dry_run, int fast_mode) {
Angie Chiang07c57f32017-05-30 18:18:33 -07001915 int update = 0;
1916 if (txb_info->eob == 0) return update;
1917 int cost_diff = 0;
1918 int64_t dist_diff = 0;
1919 int64_t rd_diff = 0;
1920 const int max_eob = tx_size_2d[txb_info->tx_size];
1921
1922#if TEST_OPTIMIZE_TXB
1923 int64_t sse;
1924 int64_t org_dist =
1925 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1926 (1 << (2 * txb_info->shift));
Angie Chiang0b2795c2017-09-29 16:00:08 -07001927 int org_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang07c57f32017-05-30 18:18:33 -07001928#endif
1929
1930 tran_low_t *org_qcoeff = txb_info->qcoeff;
1931 tran_low_t *org_dqcoeff = txb_info->dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001932 uint8_t *const org_levels = txb_info->levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07001933
1934 tran_low_t tmp_qcoeff[MAX_TX_SQUARE];
1935 tran_low_t tmp_dqcoeff[MAX_TX_SQUARE];
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001936 uint8_t tmp_levels_buf[TX_PAD_2D];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001937 uint8_t *const tmp_levels = set_levels(tmp_levels_buf, txb_info->width);
Angie Chiang07c57f32017-05-30 18:18:33 -07001938 const int org_eob = txb_info->eob;
1939 if (dry_run) {
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001940 const int stride = txb_info->width + TX_PAD_HOR;
1941 const int levels_size =
1942
1943 (stride * (txb_info->height + TX_PAD_VER) + TX_PAD_END);
Angie Chiang07c57f32017-05-30 18:18:33 -07001944 memcpy(tmp_qcoeff, org_qcoeff, sizeof(org_qcoeff[0]) * max_eob);
1945 memcpy(tmp_dqcoeff, org_dqcoeff, sizeof(org_dqcoeff[0]) * max_eob);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001946 memcpy(tmp_levels, org_levels - TX_PAD_TOP * stride,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001947 sizeof(org_levels[0]) * levels_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07001948 txb_info->qcoeff = tmp_qcoeff;
1949 txb_info->dqcoeff = tmp_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001950 txb_info->levels = tmp_levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07001951 }
1952
1953 const int16_t *scan = txb_info->scan_order->scan;
1954
1955 // forward optimize the nz_map
1956 const int cur_eob = txb_info->eob;
1957 for (int si = 0; si < cur_eob; ++si) {
1958 const int coeff_idx = scan[si];
1959 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1960 if (abs(qc) == 1) {
1961 LevelDownStats stats;
Angie Chiang25645b72017-09-24 14:28:49 -07001962 try_level_down_facade(&stats, si, txb_cache, txb_costs, txb_info,
1963 fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07001964 if (stats.update) {
1965 update = 1;
1966 cost_diff += stats.cost_diff;
1967 dist_diff += stats.dist_diff;
1968 rd_diff += stats.rd_diff;
1969 update_level_down(coeff_idx, txb_cache, txb_info);
1970 set_eob(txb_info, stats.new_eob);
1971 }
1972 }
1973 }
1974
1975 // backward optimize the level-k map
Angie Chiang530b3042017-08-17 15:08:58 -07001976 int eob_fix = 0;
Angie Chiang07c57f32017-05-30 18:18:33 -07001977 for (int si = txb_info->eob - 1; si >= 0; --si) {
Angie Chiang530b3042017-08-17 15:08:58 -07001978 const int coeff_idx = scan[si];
1979 if (eob_fix == 1 && txb_info->qcoeff[coeff_idx] == 1) {
1980 // when eob is fixed, there is not need to optimize again when
1981 // abs(qc) == 1
1982 continue;
1983 }
Angie Chiang07c57f32017-05-30 18:18:33 -07001984 LevelDownStats stats;
Angie Chiang25645b72017-09-24 14:28:49 -07001985 try_level_down_facade(&stats, si, txb_cache, txb_costs, txb_info,
1986 fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07001987 if (stats.update) {
1988#if TEST_OPTIMIZE_TXB
1989// printf("si %d low_qc %d cost_diff %d dist_diff %ld rd_diff %ld eob %d new_eob
1990// %d\n", si, stats.low_qc, stats.cost_diff, stats.dist_diff, stats.rd_diff,
1991// txb_info->eob, stats.new_eob);
1992#endif
1993 update = 1;
1994 cost_diff += stats.cost_diff;
1995 dist_diff += stats.dist_diff;
1996 rd_diff += stats.rd_diff;
1997 update_level_down(coeff_idx, txb_cache, txb_info);
1998 set_eob(txb_info, stats.new_eob);
1999 }
Angie Chiang530b3042017-08-17 15:08:58 -07002000 if (eob_fix == 0 && txb_info->qcoeff[coeff_idx] != 0) eob_fix = 1;
Angie Chiang07c57f32017-05-30 18:18:33 -07002001 if (si > txb_info->eob) si = txb_info->eob;
2002 }
2003#if TEST_OPTIMIZE_TXB
2004 int64_t new_dist =
2005 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
2006 (1 << (2 * txb_info->shift));
Angie Chiang0b2795c2017-09-29 16:00:08 -07002007 int new_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang07c57f32017-05-30 18:18:33 -07002008 int64_t ref_dist_diff = new_dist - org_dist;
2009 int ref_cost_diff = new_cost - org_cost;
2010 if (cost_diff != ref_cost_diff || dist_diff != ref_dist_diff)
2011 printf(
2012 "overall rd_diff %ld\ncost_diff %d ref_cost_diff%d\ndist_diff %ld "
2013 "ref_dist_diff %ld\neob %d new_eob %d\n\n",
2014 rd_diff, cost_diff, ref_cost_diff, dist_diff, ref_dist_diff, org_eob,
2015 txb_info->eob);
2016#endif
2017 if (dry_run) {
2018 txb_info->qcoeff = org_qcoeff;
2019 txb_info->dqcoeff = org_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07002020 txb_info->levels = org_levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07002021 set_eob(txb_info, org_eob);
2022 }
2023 return update;
2024}
Dake Hea47cd6c2017-10-13 18:09:58 -07002025#endif
Angie Chiang07c57f32017-05-30 18:18:33 -07002026
2027// These numbers are empirically obtained.
2028static const int plane_rd_mult[REF_TYPES][PLANE_TYPES] = {
Angie Chiang07c57f32017-05-30 18:18:33 -07002029 { 17, 13 }, { 16, 10 },
Angie Chiang07c57f32017-05-30 18:18:33 -07002030};
2031
Jingning Han7eab9ff2017-07-06 10:12:54 -07002032int av1_optimize_txb(const AV1_COMMON *cm, MACROBLOCK *x, int plane,
2033 int blk_row, int blk_col, int block, TX_SIZE tx_size,
Angie Chiang25645b72017-09-24 14:28:49 -07002034 TXB_CTX *txb_ctx, int fast_mode) {
Angie Chiang07c57f32017-05-30 18:18:33 -07002035 MACROBLOCKD *const xd = &x->e_mbd;
2036 const PLANE_TYPE plane_type = get_plane_type(plane);
Jingning Han48be0e12017-06-13 12:12:01 -07002037 const TX_SIZE txs_ctx = get_txsize_context(tx_size);
Jingning Han19b5c8f2017-07-06 15:10:12 -07002038 const TX_TYPE tx_type =
2039 av1_get_tx_type(plane_type, xd, blk_row, blk_col, block, tx_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07002040 const MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
2041 const struct macroblock_plane *p = &x->plane[plane];
2042 struct macroblockd_plane *pd = &xd->plane[plane];
2043 const int eob = p->eobs[block];
2044 tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2045 tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
2046 const tran_low_t *tcoeff = BLOCK_OFFSET(p->coeff, block);
Monty Montgomery125c0fc2017-10-26 00:44:35 -04002047 const int16_t *dequant = p->dequant_QTX;
Dake Hea47cd6c2017-10-13 18:09:58 -07002048 const int seg_eob = tx_size_2d[tx_size];
Angie Chiang07c57f32017-05-30 18:18:33 -07002049 const int bwl = b_width_log2_lookup[txsize_to_bsize[tx_size]] + 2;
Linfeng Zhang679d81e2017-10-31 15:27:42 -07002050 const int width = tx_size_wide[tx_size];
Jingning Hanb0f60ed2017-06-13 14:25:05 -07002051 const int height = tx_size_high[tx_size];
Angie Chiang07c57f32017-05-30 18:18:33 -07002052 const int is_inter = is_inter_block(mbmi);
Angie Chiangbd99b382017-06-20 15:11:16 -07002053 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Jingning Handfd72322017-08-09 14:04:12 -07002054 const LV_MAP_COEFF_COST txb_costs = x->coeff_costs[txs_ctx][plane_type];
Angie Chiang07c57f32017-05-30 18:18:33 -07002055
2056 const int shift = av1_get_tx_scale(tx_size);
2057 const int64_t rdmult =
2058 (x->rdmult * plane_rd_mult[is_inter][plane_type] + 2) >> 2;
Linfeng Zhang679d81e2017-10-31 15:27:42 -07002059 uint8_t levels_buf[TX_PAD_2D];
2060 uint8_t *const levels = set_levels(levels_buf, width);
Angie Chiang07c57f32017-05-30 18:18:33 -07002061
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002062 assert(width == (1 << bwl));
Linfeng Zhang1015a342017-10-24 16:20:41 -07002063 TxbInfo txb_info = {
2064 qcoeff, levels, dqcoeff, tcoeff, dequant, shift,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002065 tx_size, txs_ctx, tx_type, bwl, width, height,
Linfeng Zhang1015a342017-10-24 16:20:41 -07002066 eob, seg_eob, scan_order, txb_ctx, rdmult, &cm->coeff_ctx_table
2067 };
2068
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002069 av1_txb_init_levels(qcoeff, width, height, levels);
Urvang Joshi70006e42017-06-14 16:08:55 -07002070
Angie Chiang93af45f2017-10-23 18:19:59 -07002071 const int update = optimize_txb(&txb_info, &txb_costs, NULL, 0, fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07002072
Angie Chiang07c57f32017-05-30 18:18:33 -07002073 if (update) p->eobs[block] = txb_info.eob;
2074 return txb_info.eob;
2075}
Angie Chiang74e23072017-03-24 14:54:23 -07002076int av1_get_txb_entropy_context(const tran_low_t *qcoeff,
2077 const SCAN_ORDER *scan_order, int eob) {
2078 const int16_t *scan = scan_order->scan;
2079 int cul_level = 0;
2080 int c;
Jingning Han339cf932017-09-18 10:17:02 -07002081
2082 if (eob == 0) return 0;
Angie Chiang74e23072017-03-24 14:54:23 -07002083 for (c = 0; c < eob; ++c) {
2084 cul_level += abs(qcoeff[scan[c]]);
2085 }
2086
2087 cul_level = AOMMIN(COEFF_CONTEXT_MASK, cul_level);
2088 set_dc_sign(&cul_level, qcoeff[0]);
2089
2090 return cul_level;
2091}
2092
Jingning Han4fe5f672017-05-19 15:46:07 -07002093void av1_update_txb_context_b(int plane, int block, int blk_row, int blk_col,
2094 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
2095 void *arg) {
Jingning Han6171ae72017-05-18 20:15:06 -07002096 struct tokenize_b_args *const args = arg;
Angie Chiang36d616b2017-03-22 13:58:36 -07002097 const AV1_COMP *cpi = args->cpi;
2098 const AV1_COMMON *cm = &cpi->common;
Angie Chiang0397eda2017-03-15 16:57:14 -07002099 ThreadData *const td = args->td;
2100 MACROBLOCK *const x = &td->mb;
2101 MACROBLOCKD *const xd = &x->e_mbd;
Angie Chiang36d616b2017-03-22 13:58:36 -07002102 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiang0397eda2017-03-15 16:57:14 -07002103 struct macroblock_plane *p = &x->plane[plane];
2104 struct macroblockd_plane *pd = &xd->plane[plane];
Angie Chiang36d616b2017-03-22 13:58:36 -07002105 const uint16_t eob = p->eobs[block];
2106 const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2107 const PLANE_TYPE plane_type = pd->plane_type;
Jingning Han19b5c8f2017-07-06 15:10:12 -07002108 const TX_TYPE tx_type =
2109 av1_get_tx_type(plane_type, xd, blk_row, blk_col, block, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07002110 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Angie Chiang0397eda2017-03-15 16:57:14 -07002111 (void)plane_bsize;
Angie Chiang36d616b2017-03-22 13:58:36 -07002112
Angie Chiang74e23072017-03-24 14:54:23 -07002113 int cul_level = av1_get_txb_entropy_context(qcoeff, scan_order, eob);
Angie Chiang36d616b2017-03-22 13:58:36 -07002114 av1_set_contexts(xd, pd, plane, tx_size, cul_level, blk_col, blk_row);
Angie Chiang0397eda2017-03-15 16:57:14 -07002115}
2116
Jingning Han4fe5f672017-05-19 15:46:07 -07002117void av1_update_and_record_txb_context(int plane, int block, int blk_row,
2118 int blk_col, BLOCK_SIZE plane_bsize,
2119 TX_SIZE tx_size, void *arg) {
Jingning Han6171ae72017-05-18 20:15:06 -07002120 struct tokenize_b_args *const args = arg;
Angie Chiang0397eda2017-03-15 16:57:14 -07002121 const AV1_COMP *cpi = args->cpi;
2122 const AV1_COMMON *cm = &cpi->common;
2123 ThreadData *const td = args->td;
2124 MACROBLOCK *const x = &td->mb;
2125 MACROBLOCKD *const xd = &x->e_mbd;
2126 struct macroblock_plane *p = &x->plane[plane];
2127 struct macroblockd_plane *pd = &xd->plane[plane];
2128 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Linfeng Zhang848f7bc2017-10-31 15:26:07 -07002129 int eob = p->eobs[block], update_eob = -1;
Angie Chiang0397eda2017-03-15 16:57:14 -07002130 const PLANE_TYPE plane_type = pd->plane_type;
2131 const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2132 tran_low_t *tcoeff = BLOCK_OFFSET(x->mbmi_ext->tcoeff[plane], block);
2133 const int segment_id = mbmi->segment_id;
Jingning Han19b5c8f2017-07-06 15:10:12 -07002134 const TX_TYPE tx_type =
2135 av1_get_tx_type(plane_type, xd, blk_row, blk_col, block, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07002136 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Angie Chianga2d5c942017-03-22 13:37:51 -07002137 const int16_t *scan = scan_order->scan;
hui suc0cf71d2017-07-20 16:38:50 -07002138 const int seg_eob = av1_get_tx_eob(&cpi->common.seg, segment_id, tx_size);
Linfeng Zhang1015a342017-10-24 16:20:41 -07002139 int c;
Angie Chiang85901562017-03-17 12:03:27 -07002140 TXB_CTX txb_ctx;
2141 get_txb_ctx(plane_bsize, tx_size, plane, pd->above_context + blk_col,
2142 pd->left_context + blk_row, &txb_ctx);
Angie Chiang0397eda2017-03-15 16:57:14 -07002143 const int bwl = b_width_log2_lookup[txsize_to_bsize[tx_size]] + 2;
Linfeng Zhang679d81e2017-10-31 15:27:42 -07002144 const int width = tx_size_wide[tx_size];
Jingning Han341d79e2017-06-13 15:57:59 -07002145 const int height = tx_size_high[tx_size];
Linfeng Zhang679d81e2017-10-31 15:27:42 -07002146 uint8_t levels_buf[TX_PAD_2D];
2147 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -08002148 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Yunqing Wang0e141b52017-11-02 15:08:58 -07002149 const uint8_t allow_update_cdf = args->allow_update_cdf;
Angie Chiang0397eda2017-03-15 16:57:14 -07002150
Jingning Han48be0e12017-06-13 12:12:01 -07002151 TX_SIZE txsize_ctx = get_txsize_context(tx_size);
Jingning Han8f661602017-08-19 08:16:50 -07002152 FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
Jingning Han48be0e12017-06-13 12:12:01 -07002153
Angie Chiang0397eda2017-03-15 16:57:14 -07002154 memcpy(tcoeff, qcoeff, sizeof(*tcoeff) * seg_eob);
2155
Jingning Han48be0e12017-06-13 12:12:01 -07002156 ++td->counts->txb_skip[txsize_ctx][txb_ctx.txb_skip_ctx][eob == 0];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002157 if (allow_update_cdf)
2158 update_bin(ec_ctx->txb_skip_cdf[txsize_ctx][txb_ctx.txb_skip_ctx], eob == 0,
2159 2);
Angie Chiang85901562017-03-17 12:03:27 -07002160 x->mbmi_ext->txb_skip_ctx[plane][block] = txb_ctx.txb_skip_ctx;
Angie Chiang0397eda2017-03-15 16:57:14 -07002161
2162 x->mbmi_ext->eobs[plane][block] = eob;
2163
2164 if (eob == 0) {
2165 av1_set_contexts(xd, pd, plane, tx_size, 0, blk_col, blk_row);
2166 return;
2167 }
2168
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002169 av1_txb_init_levels(tcoeff, width, height, levels);
Linfeng Zhangce065ca2017-10-17 16:49:30 -07002170
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002171#if CONFIG_TXK_SEL
Jingning Han7eab9ff2017-07-06 10:12:54 -07002172 av1_update_tx_type_count(cm, xd, blk_row, blk_col, block, plane,
Yunqing Wang0e141b52017-11-02 15:08:58 -07002173 mbmi->sb_type, get_min_tx_size(tx_size), td->counts,
2174 allow_update_cdf);
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002175#endif
Angie Chiang0397eda2017-03-15 16:57:14 -07002176
Dake Hea47cd6c2017-10-13 18:09:58 -07002177 unsigned int(*nz_map_count)[SIG_COEF_CONTEXTS][2] =
2178 &(td->counts->nz_map[txsize_ctx][plane_type]);
Jingning Han35deaa72017-10-26 15:36:30 -07002179 av1_update_eob_context(eob, seg_eob, tx_size, tx_type, plane_type, ec_ctx,
Yunqing Wang0e141b52017-11-02 15:08:58 -07002180 td->counts, allow_update_cdf);
Dake He03a32922017-10-31 08:06:45 -07002181#if USE_CAUSAL_BASE_CTX
2182 int coeff_ctx = 0;
2183 update_eob = eob - 1;
2184#endif
Dake Hea47cd6c2017-10-13 18:09:58 -07002185 for (c = eob - 1; c >= 0; --c) {
2186 tran_low_t v = qcoeff[scan[c]];
2187 int is_nz = (v != 0);
Dake He03a32922017-10-31 08:06:45 -07002188
Ola Hugosson13892102017-11-06 08:01:44 +01002189#if CONFIG_LV_MAP_MULTI
2190 (void)is_nz;
2191 (void)nz_map_count;
2192 coeff_ctx =
2193 get_nz_map_ctx(levels, c, scan, bwl, height, tx_type, c == eob - 1);
2194 update_cdf(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][coeff_ctx],
2195 AOMMIN(abs(v), 3), 4);
2196
2197#elif USE_CAUSAL_BASE_CTX
Linfeng Zhangb6957c22017-10-25 13:17:28 -07002198 coeff_ctx = get_nz_map_ctx(levels, c, scan, bwl, height, tx_type);
Ola Hugosson13892102017-11-06 08:01:44 +01002199
Dake He03a32922017-10-31 08:06:45 -07002200 if (c < eob - 1) {
2201 ++(*nz_map_count)[coeff_ctx][is_nz];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002202 if (allow_update_cdf)
2203 update_cdf(ec_ctx->nz_map_cdf[txsize_ctx][plane_type][coeff_ctx], is_nz,
2204 2);
Dake He03a32922017-10-31 08:06:45 -07002205 }
2206
2207 if (is_nz) {
2208 int k;
2209 for (k = 0; k < NUM_BASE_LEVELS; ++k) {
2210 int ctx = coeff_ctx;
2211 int is_k = (abs(v) > (k + 1));
2212
2213 ++td->counts->coeff_base[txsize_ctx][plane_type][k][ctx][is_k];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002214 if (allow_update_cdf)
2215 update_bin(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][k][ctx],
2216 is_k, 2);
Dake He03a32922017-10-31 08:06:45 -07002217 if (is_k == 0) break;
2218 }
2219 }
2220#else
Linfeng Zhangb6957c22017-10-25 13:17:28 -07002221 int coeff_ctx = get_nz_map_ctx(levels, c, scan, bwl, height, tx_type);
Dake Hea47cd6c2017-10-13 18:09:58 -07002222
2223 if (c == eob - 1) continue;
2224
2225 ++(*nz_map_count)[coeff_ctx][is_nz];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002226 if (allow_update_cdf)
2227 update_cdf(ec_ctx->nz_map_cdf[txsize_ctx][plane_type][coeff_ctx], is_nz,
2228 2);
Dake He03a32922017-10-31 08:06:45 -07002229#endif
Dake Hea47cd6c2017-10-13 18:09:58 -07002230 }
Dake Hea47cd6c2017-10-13 18:09:58 -07002231
Dake He03a32922017-10-31 08:06:45 -07002232#if !USE_CAUSAL_BASE_CTX
Angie Chiang0397eda2017-03-15 16:57:14 -07002233 // Reverse process order to handle coefficient level and sign.
Linfeng Zhang1015a342017-10-24 16:20:41 -07002234 for (int i = 0; i < NUM_BASE_LEVELS; ++i) {
Linfeng Zhangf72e1382017-11-01 13:59:41 -07002235 av1_get_base_level_counts(levels, i, width, height, level_counts);
Angie Chiang0397eda2017-03-15 16:57:14 -07002236 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhang1015a342017-10-24 16:20:41 -07002237 const tran_low_t level = abs(tcoeff[scan[c]]);
Angie Chiang0397eda2017-03-15 16:57:14 -07002238 int ctx;
2239
2240 if (level <= i) continue;
2241
Linfeng Zhangf72e1382017-11-01 13:59:41 -07002242 ctx = get_base_ctx(levels, scan[c], bwl, i, level_counts[scan[c]]);
Angie Chiang0397eda2017-03-15 16:57:14 -07002243
2244 if (level == i + 1) {
Jingning Han48be0e12017-06-13 12:12:01 -07002245 ++td->counts->coeff_base[txsize_ctx][plane_type][i][ctx][1];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002246 if (allow_update_cdf)
2247 update_bin(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][i][ctx], 1,
2248 2);
Angie Chiang0397eda2017-03-15 16:57:14 -07002249 continue;
2250 }
Jingning Han48be0e12017-06-13 12:12:01 -07002251 ++td->counts->coeff_base[txsize_ctx][plane_type][i][ctx][0];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002252 if (allow_update_cdf)
2253 update_bin(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][i][ctx], 0,
2254 2);
Angie Chiang0397eda2017-03-15 16:57:14 -07002255 update_eob = AOMMAX(update_eob, c);
2256 }
2257 }
Dake He03a32922017-10-31 08:06:45 -07002258#endif
Angie Chiang0397eda2017-03-15 16:57:14 -07002259
Dake He43edb762017-10-26 10:29:46 -07002260 c = 0; // Update the context needed to code the DC sign (if applicable)
Linfeng Zhang1015a342017-10-24 16:20:41 -07002261 const int sign = (tcoeff[scan[c]] < 0) ? 1 : 0;
2262 if (tcoeff[scan[c]] != 0) {
Dake He43edb762017-10-26 10:29:46 -07002263 int dc_sign_ctx = txb_ctx.dc_sign_ctx;
2264
2265 ++td->counts->dc_sign[plane_type][dc_sign_ctx][sign];
2266#if LV_MAP_PROB
Yunqing Wang0e141b52017-11-02 15:08:58 -07002267 if (allow_update_cdf)
2268 update_bin(ec_ctx->dc_sign_cdf[plane_type][dc_sign_ctx], sign, 2);
Dake He43edb762017-10-26 10:29:46 -07002269#endif
2270 x->mbmi_ext->dc_sign_ctx[plane][block] = dc_sign_ctx;
2271 }
2272
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002273 if (update_eob >= 0) {
2274 av1_get_br_level_counts(levels, width, height, level_counts);
2275 for (c = update_eob; c >= 0; --c) {
2276 const tran_low_t level = abs(tcoeff[scan[c]]);
2277 int idx;
2278 int ctx;
Angie Chiang0397eda2017-03-15 16:57:14 -07002279
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002280 if (level <= NUM_BASE_LEVELS) continue;
Angie Chiang0397eda2017-03-15 16:57:14 -07002281
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002282 // level is above 1.
2283 ctx = get_br_ctx(levels, scan[c], bwl, level_counts[scan[c]]);
Jingning Han87b01b52017-08-31 12:07:20 -07002284
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002285 int base_range = level - 1 - NUM_BASE_LEVELS;
Ola Hugossone72a2092017-11-12 09:11:53 +01002286#if CONFIG_LV_MAP_MULTI
2287 for (idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
2288 int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
2289 // printf("br_update: %d %d %2d : %2d %d\n", txsize_ctx, plane, ctx,
2290 // base_range, k);
2291 update_cdf(ec_ctx->coeff_br_cdf[txsize_ctx][plane_type][ctx], k,
2292 BR_CDF_SIZE);
2293 if (k < BR_CDF_SIZE - 1) break;
2294 }
2295#else
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002296 int br_set_idx = base_range < COEFF_BASE_RANGE
2297 ? coeff_to_br_index[base_range]
2298 : BASE_RANGE_SETS;
Jingning Han87b01b52017-08-31 12:07:20 -07002299
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002300 for (idx = 0; idx < BASE_RANGE_SETS; ++idx) {
2301 if (idx == br_set_idx) {
2302 int br_base = br_index_to_coeff[br_set_idx];
2303 int br_offset = base_range - br_base;
2304 ++td->counts->coeff_br[txsize_ctx][plane_type][idx][ctx][1];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002305 if (allow_update_cdf)
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002306 update_bin(ec_ctx->coeff_br_cdf[txsize_ctx][plane_type][idx][ctx],
2307 1, 2);
2308 int extra_bits = (1 << br_extra_bits[idx]) - 1;
2309 for (int tok = 0; tok < extra_bits; ++tok) {
2310 if (br_offset == tok) {
2311 ++td->counts->coeff_lps[txsize_ctx][plane_type][ctx][1];
2312 if (allow_update_cdf)
2313 update_bin(ec_ctx->coeff_lps_cdf[txsize_ctx][plane_type][ctx],
2314 1, 2);
2315 break;
2316 }
2317 ++td->counts->coeff_lps[txsize_ctx][plane_type][ctx][0];
2318 if (allow_update_cdf)
2319 update_bin(ec_ctx->coeff_lps_cdf[txsize_ctx][plane_type][ctx], 0,
2320 2);
2321 }
2322 break;
Jingning Han87b01b52017-08-31 12:07:20 -07002323 }
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002324 ++td->counts->coeff_br[txsize_ctx][plane_type][idx][ctx][0];
2325 if (allow_update_cdf)
2326 update_bin(ec_ctx->coeff_br_cdf[txsize_ctx][plane_type][idx][ctx], 0,
2327 2);
Jingning Han87b01b52017-08-31 12:07:20 -07002328 }
Ola Hugossone72a2092017-11-12 09:11:53 +01002329#endif
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002330 // use 0-th order Golomb code to handle the residual level.
Jingning Han87b01b52017-08-31 12:07:20 -07002331 }
Angie Chiang0397eda2017-03-15 16:57:14 -07002332 }
Angie Chiang36d616b2017-03-22 13:58:36 -07002333
Angie Chiang63d190a2017-10-23 15:43:05 -07002334 int cul_level = av1_get_txb_entropy_context(tcoeff, scan_order, eob);
Angie Chiang0397eda2017-03-15 16:57:14 -07002335 av1_set_contexts(xd, pd, plane, tx_size, cul_level, blk_col, blk_row);
Angie Chiang0b205e62017-03-20 17:16:47 -07002336
2337#if CONFIG_ADAPT_SCAN
2338 // Since dqcoeff is not available here, we pass qcoeff into
2339 // av1_update_scan_count_facade(). The update behavior should be the same
2340 // because av1_update_scan_count_facade() only cares if coefficients are zero
2341 // or not.
2342 av1_update_scan_count_facade((AV1_COMMON *)cm, td->counts, tx_size, tx_type,
2343 qcoeff, eob);
2344#endif
Angie Chiang0397eda2017-03-15 16:57:14 -07002345}
2346
2347void av1_update_txb_context(const AV1_COMP *cpi, ThreadData *td,
2348 RUN_TYPE dry_run, BLOCK_SIZE bsize, int *rate,
Yunqing Wang0e141b52017-11-02 15:08:58 -07002349 int mi_row, int mi_col, uint8_t allow_update_cdf) {
Angie Chiang0397eda2017-03-15 16:57:14 -07002350 MACROBLOCK *const x = &td->mb;
2351 MACROBLOCKD *const xd = &x->e_mbd;
2352 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yunqing Wang0e141b52017-11-02 15:08:58 -07002353 struct tokenize_b_args arg = { cpi, td, NULL, 0, allow_update_cdf };
Angie Chiang0397eda2017-03-15 16:57:14 -07002354 (void)rate;
2355 (void)mi_row;
2356 (void)mi_col;
2357 if (mbmi->skip) {
Timothy B. Terriberrya2d5cde2017-05-10 18:33:50 -07002358 av1_reset_skip_context(xd, mi_row, mi_col, bsize);
Angie Chiang0397eda2017-03-15 16:57:14 -07002359 return;
2360 }
2361
2362 if (!dry_run) {
Jingning Han94652b82017-04-04 09:45:02 -07002363 av1_foreach_transformed_block(xd, bsize, mi_row, mi_col,
Jingning Han4fe5f672017-05-19 15:46:07 -07002364 av1_update_and_record_txb_context, &arg);
Angie Chiangc8af6112017-03-16 16:11:22 -07002365 } else if (dry_run == DRY_RUN_NORMAL) {
Jingning Han4fe5f672017-05-19 15:46:07 -07002366 av1_foreach_transformed_block(xd, bsize, mi_row, mi_col,
2367 av1_update_txb_context_b, &arg);
Angie Chiangc8af6112017-03-16 16:11:22 -07002368 } else {
2369 printf("DRY_RUN_COSTCOEFFS is not supported yet\n");
2370 assert(0);
Angie Chiang0397eda2017-03-15 16:57:14 -07002371 }
2372}
Angie Chiang800df032017-03-22 11:14:12 -07002373
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002374#if CONFIG_TXK_SEL
Angie Chiang808d8592017-04-06 18:36:55 -07002375int64_t av1_search_txk_type(const AV1_COMP *cpi, MACROBLOCK *x, int plane,
2376 int block, int blk_row, int blk_col,
2377 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
Angie Chiang65a39bb2017-04-11 16:50:04 -07002378 const ENTROPY_CONTEXT *a, const ENTROPY_CONTEXT *l,
2379 int use_fast_coef_costing, RD_STATS *rd_stats) {
Angie Chiang808d8592017-04-06 18:36:55 -07002380 const AV1_COMMON *cm = &cpi->common;
2381 MACROBLOCKD *xd = &x->e_mbd;
2382 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
2383 TX_TYPE txk_start = DCT_DCT;
2384 TX_TYPE txk_end = TX_TYPES - 1;
2385 TX_TYPE best_tx_type = txk_start;
2386 int64_t best_rd = INT64_MAX;
Jingning Han47558172017-07-05 16:33:19 -07002387 uint8_t best_eob = 0;
Angie Chiang65a39bb2017-04-11 16:50:04 -07002388 const int coeff_ctx = combine_entropy_contexts(*a, *l);
Jingning Hane3b81bc2017-06-23 11:43:52 -07002389 RD_STATS best_rd_stats;
Angie Chiang808d8592017-04-06 18:36:55 -07002390 TX_TYPE tx_type;
Jingning Hane3b81bc2017-06-23 11:43:52 -07002391
2392 av1_invalid_rd_stats(&best_rd_stats);
2393
Angie Chiang808d8592017-04-06 18:36:55 -07002394 for (tx_type = txk_start; tx_type <= txk_end; ++tx_type) {
Jingning Han19b5c8f2017-07-06 15:10:12 -07002395 if (plane == 0) mbmi->txk_type[(blk_row << 4) + blk_col] = tx_type;
2396 TX_TYPE ref_tx_type = av1_get_tx_type(get_plane_type(plane), xd, blk_row,
2397 blk_col, block, tx_size);
Angie Chiang00491e02017-04-11 17:55:10 -07002398 if (tx_type != ref_tx_type) {
hui su45b64752017-07-12 16:54:35 -07002399 // use av1_get_tx_type() to check if the tx_type is valid for the current
2400 // mode if it's not, we skip it here.
Angie Chiang00491e02017-04-11 17:55:10 -07002401 continue;
2402 }
Jingning Hane57d6322017-07-03 18:50:25 -07002403
Hui Suddbcde22017-09-18 17:22:02 -07002404 const int is_inter = is_inter_block(mbmi);
2405 const TxSetType tx_set_type =
2406 get_ext_tx_set_type(get_min_tx_size(tx_size), mbmi->sb_type, is_inter,
2407 cm->reduced_tx_set_used);
2408 if (!av1_ext_tx_used[tx_set_type][tx_type]) continue;
Jingning Hane57d6322017-07-03 18:50:25 -07002409
Angie Chiang808d8592017-04-06 18:36:55 -07002410 RD_STATS this_rd_stats;
2411 av1_invalid_rd_stats(&this_rd_stats);
Angie Chiang808d8592017-04-06 18:36:55 -07002412 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
2413 coeff_ctx, AV1_XFORM_QUANT_FP);
Jingning Han7eab9ff2017-07-06 10:12:54 -07002414 av1_optimize_b(cm, x, plane, blk_row, blk_col, block, plane_bsize, tx_size,
Angie Chiang25645b72017-09-24 14:28:49 -07002415 a, l, 1);
Angie Chiang808d8592017-04-06 18:36:55 -07002416 av1_dist_block(cpi, x, plane, plane_bsize, block, blk_row, blk_col, tx_size,
Angie Chiang2ed03a32017-04-16 18:00:06 -07002417 &this_rd_stats.dist, &this_rd_stats.sse,
2418 OUTPUT_HAS_PREDICTED_PIXELS);
Angie Chiangbd99b382017-06-20 15:11:16 -07002419 const SCAN_ORDER *scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Jingning Han7eab9ff2017-07-06 10:12:54 -07002420 this_rd_stats.rate =
2421 av1_cost_coeffs(cpi, x, plane, blk_row, blk_col, block, tx_size,
2422 scan_order, a, l, use_fast_coef_costing);
Urvang Joshi70006e42017-06-14 16:08:55 -07002423 int rd = RDCOST(x->rdmult, this_rd_stats.rate, this_rd_stats.dist);
Jingning Han19b5c8f2017-07-06 15:10:12 -07002424
Angie Chiang808d8592017-04-06 18:36:55 -07002425 if (rd < best_rd) {
2426 best_rd = rd;
Jingning Hane3b81bc2017-06-23 11:43:52 -07002427 best_rd_stats = this_rd_stats;
Angie Chiang808d8592017-04-06 18:36:55 -07002428 best_tx_type = tx_type;
Jingning Han47558172017-07-05 16:33:19 -07002429 best_eob = x->plane[plane].txb_entropy_ctx[block];
Angie Chiang808d8592017-04-06 18:36:55 -07002430 }
2431 }
Jingning Hane3b81bc2017-06-23 11:43:52 -07002432
2433 av1_merge_rd_stats(rd_stats, &best_rd_stats);
2434
Jingning Han19b5c8f2017-07-06 15:10:12 -07002435 if (best_eob == 0 && is_inter_block(mbmi)) best_tx_type = DCT_DCT;
2436
2437 if (plane == 0) mbmi->txk_type[(blk_row << 4) + blk_col] = best_tx_type;
Jingning Han47558172017-07-05 16:33:19 -07002438 x->plane[plane].txb_entropy_ctx[block] = best_eob;
2439
Angie Chiang2ed03a32017-04-16 18:00:06 -07002440 if (!is_inter_block(mbmi)) {
2441 // intra mode needs decoded result such that the next transform block
2442 // can use it for prediction.
Jingning Han47558172017-07-05 16:33:19 -07002443 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
2444 coeff_ctx, AV1_XFORM_QUANT_FP);
Jingning Han7eab9ff2017-07-06 10:12:54 -07002445 av1_optimize_b(cm, x, plane, blk_row, blk_col, block, plane_bsize, tx_size,
Angie Chiang25645b72017-09-24 14:28:49 -07002446 a, l, 1);
Jingning Han47558172017-07-05 16:33:19 -07002447
Angie Chiang2ed03a32017-04-16 18:00:06 -07002448 av1_inverse_transform_block_facade(xd, plane, block, blk_row, blk_col,
2449 x->plane[plane].eobs[block]);
2450 }
Angie Chiang808d8592017-04-06 18:36:55 -07002451 return best_rd;
2452}
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002453#endif // CONFIG_TXK_SEL