blob: 19f2b48ab5be34a900ce43f2363c2272b0842987 [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;
Dominic Symes917d6c02017-10-11 18:00:52 +020061 int size = ((cm->mi_rows >> cm->mib_size_log2) + 1) *
62 ((cm->mi_cols >> cm->mib_size_log2) + 1);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070063
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) {
Dominic Symes917d6c02017-10-11 18:00:52 +020084 int mib_size_log2 = cpi->common.mib_size_log2;
85 int stride = (cpi->common.mi_cols >> mib_size_log2) + 1;
86 int offset = (mi_row >> mib_size_log2) * stride + (mi_col >> mib_size_log2);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070087 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) {
Monty Montgomery4a05a582017-11-01 21:21:07 -0400129#if CONFIG_DAALA_TX
130 int depth_shift = (TX_COEFF_DEPTH - 11) * 2;
131 int depth_round = depth_shift > 1 ? (1 << (depth_shift - 1)) : 0;
132 const int64_t diff = tcoeff - dqcoeff;
133 const int64_t error = diff * diff + depth_round >> depth_shift;
134 (void)shift;
135#else
Dake Hea47cd6c2017-10-13 18:09:58 -0700136 const int64_t diff = (tcoeff - dqcoeff) * (1 << shift);
137 const int64_t error = diff * diff;
Monty Montgomery4a05a582017-11-01 21:21:07 -0400138#endif
Dake Hea47cd6c2017-10-13 18:09:58 -0700139 return error;
140}
141
Jingning Han35deaa72017-10-26 15:36:30 -0700142void av1_update_eob_context(int eob, int seg_eob, TX_SIZE tx_size,
143 TX_TYPE tx_type, PLANE_TYPE plane,
Yunqing Wang0e141b52017-11-02 15:08:58 -0700144 FRAME_CONTEXT *ec_ctx, FRAME_COUNTS *counts,
145 uint8_t allow_update_cdf) {
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800146 int eob_extra, dummy;
147 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
148 const int max_eob_pt = get_eob_pos_token(seg_eob, &dummy);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -0800149 TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Dake Hea47cd6c2017-10-13 18:09:58 -0700150
151 for (int i = 1; i < max_eob_pt; i++) {
Jingning Han35deaa72017-10-26 15:36:30 -0700152 int eob_pos_ctx = av1_get_eob_pos_ctx(tx_type, i);
153 counts->eob_flag[txs_ctx][plane][eob_pos_ctx][eob_pt == i]++;
Yunqing Wang0e141b52017-11-02 15:08:58 -0700154 if (allow_update_cdf)
155 update_cdf(ec_ctx->eob_flag_cdf[txs_ctx][plane][eob_pos_ctx], eob_pt == i,
156 2);
Dake Hea47cd6c2017-10-13 18:09:58 -0700157 if (eob_pt == i) {
158 break;
159 }
160 }
Jingning Han00803a72017-10-25 16:04:34 -0700161
Angie Chiang7ab884e2017-10-18 15:57:12 -0700162 if (k_eob_offset_bits[eob_pt] > 0) {
163 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
164 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Jingning Han35deaa72017-10-26 15:36:30 -0700165 counts->eob_extra[txs_ctx][plane][eob_pt][bit]++;
Yunqing Wang0e141b52017-11-02 15:08:58 -0700166 if (allow_update_cdf)
167 update_cdf(ec_ctx->eob_extra_cdf[txs_ctx][plane][eob_pt], bit, 2);
Angie Chiang7ab884e2017-10-18 15:57:12 -0700168 }
Dake Hea47cd6c2017-10-13 18:09:58 -0700169}
170
171static int get_eob_cost(int eob, int seg_eob,
Jingning Han35deaa72017-10-26 15:36:30 -0700172 const LV_MAP_COEFF_COST *txb_costs, TX_TYPE tx_type) {
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800173 int eob_extra, dummy;
174 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
175 const int max_eob_pt = get_eob_pos_token(seg_eob, &dummy);
Dake Hea47cd6c2017-10-13 18:09:58 -0700176 int eob_cost = 0;
177
Dake Hea47cd6c2017-10-13 18:09:58 -0700178 for (int i = 1; i < max_eob_pt; i++) {
Jingning Han35deaa72017-10-26 15:36:30 -0700179 int eob_pos_ctx = av1_get_eob_pos_ctx(tx_type, i);
Dake Hea47cd6c2017-10-13 18:09:58 -0700180 eob_cost += txb_costs->eob_cost[eob_pos_ctx][eob_pt == i];
181 if (eob_pt == i) {
182 break;
183 }
184 }
185 if (k_eob_offset_bits[eob_pt] > 0) {
Angie Chiang7ab884e2017-10-18 15:57:12 -0700186 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
187 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
188 eob_cost += txb_costs->eob_extra_cost[eob_pt][bit];
189 for (int i = 1; i < k_eob_offset_bits[eob_pt]; i++) {
190 eob_shift = k_eob_offset_bits[eob_pt] - 1 - i;
191 bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700192 eob_cost += av1_cost_bit(128, bit);
193 }
194 }
195 return eob_cost;
196}
197
Linfeng Zhang1015a342017-10-24 16:20:41 -0700198static int get_coeff_cost(const tran_low_t qc, const int scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +0100199#if CONFIG_LV_MAP_MULTI
200 const int is_eob,
201#endif
Linfeng Zhang1015a342017-10-24 16:20:41 -0700202 const TxbInfo *const txb_info,
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -0800203 const LV_MAP_COEFF_COST *const txb_costs,
204 const int coeff_ctx);
Dake Hea47cd6c2017-10-13 18:09:58 -0700205
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800206static void get_dist_cost_stats(LevelDownStats *const stats, const int scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +0100207#if CONFIG_LV_MAP_MULTI
208 const int is_eob,
209#endif
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800210 const LV_MAP_COEFF_COST *const txb_costs,
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -0800211 const TxbInfo *const txb_info) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800212 const int16_t *const scan = txb_info->scan_order->scan;
Dake Hea47cd6c2017-10-13 18:09:58 -0700213 const int coeff_idx = scan[scan_idx];
214 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
Linfeng Zhang1015a342017-10-24 16:20:41 -0700215 const uint8_t *const levels = txb_info->levels;
Dake Hea47cd6c2017-10-13 18:09:58 -0700216 stats->new_eob = -1;
217 stats->update = 0;
218
219 const tran_low_t tqc = txb_info->tcoeff[coeff_idx];
220 const int dqv = txb_info->dequant[coeff_idx != 0];
221
222 const tran_low_t dqc = qcoeff_to_dqcoeff(qc, dqv, txb_info->shift);
223 const int64_t dqc_dist = get_coeff_dist(tqc, dqc, txb_info->shift);
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -0800224 const int coeff_ctx = get_nz_map_ctx(levels, coeff_idx, txb_info->bwl,
225#if CONFIG_LV_MAP_MULTI
226 txb_info->height, scan_idx, is_eob,
227#endif
228 txb_info->tx_size, txb_info->tx_type);
Linfeng Zhang960e7002017-12-11 13:46:40 -0800229 const int qc_cost = get_coeff_cost(qc, scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +0100230#if CONFIG_LV_MAP_MULTI
Linfeng Zhang960e7002017-12-11 13:46:40 -0800231 is_eob,
Ola Hugosson13892102017-11-06 08:01:44 +0100232#endif
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -0800233 txb_info, txb_costs, coeff_ctx);
Dake Hea47cd6c2017-10-13 18:09:58 -0700234
235 // distortion difference when coefficient is quantized to 0
236 const tran_low_t dqc0 = qcoeff_to_dqcoeff(0, dqv, txb_info->shift);
237 stats->dist0 = get_coeff_dist(tqc, dqc0, txb_info->shift);
238 stats->dist = dqc_dist - stats->dist0;
239 stats->rate = qc_cost;
240
241 if (qc == 0) {
242 return;
243 }
244 stats->rd = RDCOST(txb_info->rdmult, stats->rate, stats->dist);
245
246 stats->low_qc = get_lower_coeff(qc);
247 stats->low_dqc = qcoeff_to_dqcoeff(stats->low_qc, dqv, txb_info->shift);
248 const int64_t low_dqc_dist =
249 get_coeff_dist(tqc, stats->low_dqc, txb_info->shift);
Linfeng Zhang960e7002017-12-11 13:46:40 -0800250 const int low_qc_cost = get_coeff_cost(stats->low_qc, scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +0100251#if CONFIG_LV_MAP_MULTI
Linfeng Zhang960e7002017-12-11 13:46:40 -0800252 is_eob,
Ola Hugosson13892102017-11-06 08:01:44 +0100253#endif
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -0800254 txb_info, txb_costs, coeff_ctx);
Dake Hea47cd6c2017-10-13 18:09:58 -0700255 stats->dist_low = low_dqc_dist - stats->dist0;
256 stats->rate_low = low_qc_cost;
257 stats->rd_low = RDCOST(txb_info->rdmult, stats->rate_low, stats->dist_low);
258
Ola Hugosson13892102017-11-06 08:01:44 +0100259#if CONFIG_LV_MAP_MULTI
Ola Hugossone5a9b382017-11-16 17:02:28 +0100260 (void)levels;
Ola Hugosson13892102017-11-06 08:01:44 +0100261 if ((stats->rd_low < stats->rd) && (stats->low_qc == 0)) {
Ola Hugossone5a9b382017-11-16 17:02:28 +0100262 stats->nz_rate = low_qc_cost;
Ola Hugosson13892102017-11-06 08:01:44 +0100263 } else {
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -0800264 const int coeff_ctx_temp =
265 get_nz_map_ctx(levels, coeff_idx, txb_info->bwl,
266#if CONFIG_LV_MAP_MULTI
267 txb_info->height, scan_idx, 1,
268#endif
269 txb_info->tx_size, txb_info->tx_type);
Linfeng Zhang960e7002017-12-11 13:46:40 -0800270 const int qc_eob_cost =
271 get_coeff_cost((stats->rd_low < stats->rd) ? stats->low_qc : qc,
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -0800272 scan_idx, 1, txb_info, txb_costs, coeff_ctx_temp);
Linfeng Zhang960e7002017-12-11 13:46:40 -0800273 stats->nz_rate =
274 ((stats->rd_low < stats->rd) ? low_qc_cost : qc_cost) - qc_eob_cost;
Ola Hugosson13892102017-11-06 08:01:44 +0100275 }
276#else
Linfeng Zhang960e7002017-12-11 13:46:40 -0800277 const int is_nz = (stats->rd_low < stats->rd && stats->low_qc == 0) ? 0 : 1;
278 stats->nz_rate = txb_costs->nz_map_cost[coeff_ctx][is_nz];
Ola Hugosson13892102017-11-06 08:01:44 +0100279#endif
Dake Hea47cd6c2017-10-13 18:09:58 -0700280}
281
Linfeng Zhang1015a342017-10-24 16:20:41 -0700282static INLINE void update_qcoeff(const int coeff_idx, const tran_low_t qc,
283 const TxbInfo *const txb_info) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700284 txb_info->qcoeff[coeff_idx] = qc;
Linfeng Zhangd5647372017-12-05 17:06:07 -0800285 txb_info->levels[get_padded_idx(coeff_idx, txb_info->bwl)] =
Jingning Han5cb408e2017-11-17 14:43:39 -0800286 (uint8_t)clamp(abs(qc), 0, INT8_MAX);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700287}
288
289static INLINE void update_coeff(const int coeff_idx, const tran_low_t qc,
290 const TxbInfo *const txb_info) {
291 update_qcoeff(coeff_idx, qc, txb_info);
Dake Hea47cd6c2017-10-13 18:09:58 -0700292 const int dqv = txb_info->dequant[coeff_idx != 0];
293 txb_info->dqcoeff[coeff_idx] = qcoeff_to_dqcoeff(qc, dqv, txb_info->shift);
294}
295
Linfeng Zhang1015a342017-10-24 16:20:41 -0700296static INLINE void av1_txb_init_levels(const tran_low_t *const coeff,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700297 const int width, const int height,
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700298 uint8_t *const levels) {
299 const int stride = width + TX_PAD_HOR;
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700300 uint8_t *ls = levels;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700301
302 memset(levels - TX_PAD_TOP * stride, 0,
303 sizeof(*levels) * TX_PAD_TOP * stride);
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700304 memset(levels + stride * height, 0,
305 sizeof(*levels) * (TX_PAD_BOTTOM * stride + TX_PAD_END));
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700306
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700307 for (int i = 0; i < height; i++) {
308 for (int j = 0; j < width; j++) {
Jingning Han5cb408e2017-11-17 14:43:39 -0800309 *ls++ = (uint8_t)clamp(abs(coeff[i * width + j]), 0, INT8_MAX);
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700310 }
311 for (int j = 0; j < TX_PAD_HOR; j++) {
312 *ls++ = 0;
313 }
Linfeng Zhang1015a342017-10-24 16:20:41 -0700314 }
315}
316
Angie Chiang80b82262017-02-24 11:39:47 -0800317void av1_write_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCKD *xd,
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500318 aom_writer *w, int blk_row, int blk_col, int plane,
319 TX_SIZE tx_size, const tran_low_t *tcoeff,
Jingning Han7eab9ff2017-07-06 10:12:54 -0700320 uint16_t eob, TXB_CTX *txb_ctx) {
Angie Chiang80b82262017-02-24 11:39:47 -0800321 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiangcea11f22017-02-24 12:30:40 -0800322 const PLANE_TYPE plane_type = get_plane_type(plane);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -0800323 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Jingning Han19b5c8f2017-07-06 15:10:12 -0700324 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500325 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -0700326 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800327 const int16_t *const scan = scan_order->scan;
Urvang Joshi80893152017-10-27 11:51:14 -0700328 const int seg_eob = av1_get_max_eob(tx_size);
Angie Chiang80b82262017-02-24 11:39:47 -0800329 int c;
Angie Chianga9ba58e2017-12-01 19:22:43 -0800330 const int bwl = get_txb_bwl(tx_size);
331 const int width = get_txb_wide(tx_size);
332 const int height = get_txb_high(tx_size);
Linfeng Zhang848f7bc2017-10-31 15:26:07 -0700333 int update_eob = -1;
Jingning Han41c7f442017-09-05 14:54:00 -0700334 FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700335 uint8_t levels_buf[TX_PAD_2D];
336 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -0800337 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Angie Chiang80b82262017-02-24 11:39:47 -0800338
Jingning Han7eab9ff2017-07-06 10:12:54 -0700339 (void)blk_row;
340 (void)blk_col;
Jingning Han94cea4a2017-09-30 14:13:23 -0700341 aom_write_bin(w, eob == 0,
342 ec_ctx->txb_skip_cdf[txs_ctx][txb_ctx->txb_skip_ctx], 2);
Angie Chiang5f0cb5e2017-12-11 16:07:50 -0800343#if CONFIG_TXK_SEL
Angie Chianga3f7d2e2017-12-07 19:51:14 -0800344 if (plane == 0 && eob == 0) {
345 assert(tx_type == DCT_DCT);
346 }
Angie Chiang5f0cb5e2017-12-11 16:07:50 -0800347#endif
Angie Chiang80b82262017-02-24 11:39:47 -0800348 if (eob == 0) return;
Linfeng Zhangce065ca2017-10-17 16:49:30 -0700349
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700350 av1_txb_init_levels(tcoeff, width, height, levels);
Linfeng Zhangce065ca2017-10-17 16:49:30 -0700351
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700352#if CONFIG_TXK_SEL
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500353 av1_write_tx_type(cm, xd, blk_row, blk_col, plane, get_min_tx_size(tx_size),
354 w);
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700355#endif
Angie Chiang80b82262017-02-24 11:39:47 -0800356
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800357 int eob_extra, dummy;
358 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
359 const int max_eob_pt = get_eob_pos_token(seg_eob, &dummy);
Dake Hea47cd6c2017-10-13 18:09:58 -0700360
Dake Hea47cd6c2017-10-13 18:09:58 -0700361 for (int i = 1; i < max_eob_pt; i++) {
Jingning Han35deaa72017-10-26 15:36:30 -0700362 int eob_pos_ctx = av1_get_eob_pos_ctx(tx_type, i);
Dake Hea47cd6c2017-10-13 18:09:58 -0700363
364 aom_write_bin(w, eob_pt == i,
365 ec_ctx->eob_flag_cdf[txs_ctx][plane_type][eob_pos_ctx], 2);
366 // aom_write_symbol(w, eob_pt == i,
367 // ec_ctx->eob_flag_cdf[AOMMIN(txs_ctx,3)][plane_type][eob_pos_ctx], 2);
368 if (eob_pt == i) {
369 break;
370 }
371 }
372
373 if (k_eob_offset_bits[eob_pt] > 0) {
Angie Chiang7ab884e2017-10-18 15:57:12 -0700374 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
375 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
376 aom_write_bin(w, bit, ec_ctx->eob_extra_cdf[txs_ctx][plane_type][eob_pt],
377 2);
378 for (int i = 1; i < k_eob_offset_bits[eob_pt]; i++) {
379 eob_shift = k_eob_offset_bits[eob_pt] - 1 - i;
380 bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700381 aom_write_bit(w, bit);
Dake Hea47cd6c2017-10-13 18:09:58 -0700382 }
383 }
Dake He03a32922017-10-31 08:06:45 -0700384
Dake He03a32922017-10-31 08:06:45 -0700385 int coeff_ctx = 0;
386 for (int i = 0; i < eob; ++i) {
387 c = eob - 1 - i;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800388 const int pos = scan[c];
Dake He03a32922017-10-31 08:06:45 -0700389
Ola Hugosson13892102017-11-06 08:01:44 +0100390#if CONFIG_LV_MAP_MULTI
Linfeng Zhangf6d730a2017-12-06 14:49:44 -0800391 coeff_ctx = get_nz_map_ctx(levels, pos, bwl, height, c, c == eob - 1,
392 tx_size, tx_type);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800393 const tran_low_t v = tcoeff[pos];
Dake He3fe369c2017-11-16 17:56:44 -0800394#if USE_BASE_EOB_ALPHABET
395 if (c == eob - 1) {
396 aom_write_symbol(
397 w, AOMMIN(abs(v), 3) - 1,
398 ec_ctx->coeff_base_eob_cdf[txs_ctx][plane_type]
399 [coeff_ctx - SIG_COEF_CONTEXTS +
400 SIG_COEF_CONTEXTS_EOB],
401 3);
402 } else {
403 aom_write_symbol(w, AOMMIN(abs(v), 3),
404 ec_ctx->coeff_base_cdf[txs_ctx][plane_type][coeff_ctx],
405 4);
406 }
407#else
Thomas Davies736ddef2017-11-09 09:46:08 +0000408 aom_write_symbol(w, AOMMIN(abs(v), 3),
409 ec_ctx->coeff_base_cdf[txs_ctx][plane_type][coeff_ctx], 4);
Dake He3fe369c2017-11-16 17:56:44 -0800410#endif
Ola Hugosson13892102017-11-06 08:01:44 +0100411#else
Linfeng Zhangf6d730a2017-12-06 14:49:44 -0800412 coeff_ctx = get_nz_map_ctx(levels, pos, bwl, tx_size, tx_type);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800413 const tran_low_t v = tcoeff[pos];
414 const int is_nz = (v != 0);
Dake He03a32922017-10-31 08:06:45 -0700415
416 if (c < eob - 1) {
417 aom_write_bin(w, is_nz,
418 ec_ctx->nz_map_cdf[txs_ctx][plane_type][coeff_ctx], 2);
419 }
420 if (is_nz) {
421 const int level = abs(v);
422 int k;
423 for (k = 0; k < NUM_BASE_LEVELS; ++k) {
424 int is_k = (level > (k + 1));
425 int ctx = coeff_ctx;
426 aom_write_bin(w, is_k,
427 ec_ctx->coeff_base_cdf[txs_ctx][plane_type][k][ctx], 2);
428 if (is_k == 0) break;
429 }
430 }
Ola Hugosson13892102017-11-06 08:01:44 +0100431#endif
Dake He03a32922017-10-31 08:06:45 -0700432 }
433 update_eob = eob - 1;
Angie Chiang80b82262017-02-24 11:39:47 -0800434
Dake He43edb762017-10-26 10:29:46 -0700435 // Loop to code all signs in the transform block,
436 // starting with the sign of DC (if applicable)
437 for (c = 0; c < eob; ++c) {
Linfeng Zhang1015a342017-10-24 16:20:41 -0700438 const tran_low_t v = tcoeff[scan[c]];
439 const tran_low_t level = abs(v);
440 const int sign = (v < 0) ? 1 : 0;
Dake He43edb762017-10-26 10:29:46 -0700441 if (level == 0) continue;
442
443 if (c == 0) {
444#if LV_MAP_PROB
445 aom_write_bin(w, sign,
446 ec_ctx->dc_sign_cdf[plane_type][txb_ctx->dc_sign_ctx], 2);
447#else
448 aom_write(w, sign, ec_ctx->dc_sign[plane_type][txb_ctx->dc_sign_ctx]);
449#endif
450 } else {
451 aom_write_bit(w, sign);
452 }
453 }
454
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800455 if (update_eob >= 0) {
Dake He7d01ab52017-11-24 17:53:28 -0800456#if !CONFIG_LV_MAP_MULTI
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800457 av1_get_br_level_counts(levels, width, height, level_counts);
Dake He7d01ab52017-11-24 17:53:28 -0800458#endif
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800459 for (c = update_eob; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800460 const int pos = scan[c];
461 const tran_low_t level = abs(tcoeff[pos]);
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800462 int idx;
463 int ctx;
Angie Chiang80b82262017-02-24 11:39:47 -0800464
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800465 if (level <= NUM_BASE_LEVELS) continue;
Angie Chiang80b82262017-02-24 11:39:47 -0800466
Dake He7d01ab52017-11-24 17:53:28 -0800467// level is above 1.
468#if !CONFIG_LV_MAP_MULTI
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800469 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -0800470#endif
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800471 const int base_range = level - 1 - NUM_BASE_LEVELS;
Ola Hugossone72a2092017-11-12 09:11:53 +0100472#if CONFIG_LV_MAP_MULTI
Dake He7d01ab52017-11-24 17:53:28 -0800473#if USE_CAUSAL_BR_CTX
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800474 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos], tx_type);
Dake He7d01ab52017-11-24 17:53:28 -0800475
476#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800477 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -0800478#endif
Ola Hugossone72a2092017-11-12 09:11:53 +0100479 for (idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800480 const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
Dake He7d01ab52017-11-24 17:53:28 -0800481 aom_write_symbol(
482 w, k,
483 ec_ctx->coeff_br_cdf[AOMMIN(txs_ctx, TX_16X16)][plane_type][ctx],
484 BR_CDF_SIZE);
Ola Hugossone72a2092017-11-12 09:11:53 +0100485 if (k < BR_CDF_SIZE - 1) break;
486 }
487 if (base_range < COEFF_BASE_RANGE) continue;
488#else
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800489 int br_set_idx = 0;
490 int br_base = 0;
491 int br_offset = 0;
Jingning Han87b01b52017-08-31 12:07:20 -0700492
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800493 if (base_range >= COEFF_BASE_RANGE)
494 br_set_idx = BASE_RANGE_SETS;
495 else
496 br_set_idx = coeff_to_br_index[base_range];
Jingning Han87b01b52017-08-31 12:07:20 -0700497
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800498 for (idx = 0; idx < BASE_RANGE_SETS; ++idx) {
499 aom_write_bin(w, idx == br_set_idx,
500 ec_ctx->coeff_br_cdf[txs_ctx][plane_type][idx][ctx], 2);
501 if (idx == br_set_idx) {
502 br_base = br_index_to_coeff[br_set_idx];
503 br_offset = base_range - br_base;
504 int extra_bits = (1 << br_extra_bits[idx]) - 1;
505 for (int tok = 0; tok < extra_bits; ++tok) {
506 if (tok == br_offset) {
507 aom_write_bin(w, 1,
508 ec_ctx->coeff_lps_cdf[txs_ctx][plane_type][ctx], 2);
509 break;
510 }
511 aom_write_bin(w, 0, ec_ctx->coeff_lps_cdf[txs_ctx][plane_type][ctx],
Jingning Han94cea4a2017-09-30 14:13:23 -0700512 2);
Jingning Han87b01b52017-08-31 12:07:20 -0700513 }
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800514 // aom_write_literal(w, br_offset, br_extra_bits[idx]);
515 break;
Jingning Han87b01b52017-08-31 12:07:20 -0700516 }
Jingning Han87b01b52017-08-31 12:07:20 -0700517 }
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800518
519 if (br_set_idx < BASE_RANGE_SETS) continue;
Ola Hugossone72a2092017-11-12 09:11:53 +0100520#endif
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800521 // use 0-th order Golomb code to handle the residual level.
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800522 write_golomb(w,
523 abs(tcoeff[pos]) - COEFF_BASE_RANGE - 1 - NUM_BASE_LEVELS);
Jingning Han87b01b52017-08-31 12:07:20 -0700524 }
Angie Chiang80b82262017-02-24 11:39:47 -0800525 }
Jingning Han0bd3bf62017-11-28 17:11:51 -0800526
527#if CONFIG_ADAPT_SCAN
528 const int mi_row = -xd->mb_to_top_edge >> (3 + MI_SIZE_LOG2);
529 av1_update_scan_count_facade(cm, xd, mi_row, tx_size, tx_type, tcoeff, eob);
530#endif
Angie Chiang80b82262017-02-24 11:39:47 -0800531}
Angie Chiang47c72182017-02-27 14:30:38 -0800532
Angie Chiang140b3332017-12-12 17:29:25 -0800533typedef struct encode_txb_args {
534 const AV1_COMMON *cm;
535 MACROBLOCK *x;
536 aom_writer *w;
537} ENCODE_TXB_ARGS;
538
539static void av1_write_coeffs_txb_wrap(int plane, int block, int blk_row,
540 int blk_col, BLOCK_SIZE plane_bsize,
541 TX_SIZE tx_size, void *arg) {
542 (void)plane_bsize;
543 ENCODE_TXB_ARGS *enc_args = (ENCODE_TXB_ARGS *)arg;
544 const AV1_COMMON *cm = enc_args->cm;
545 MACROBLOCK *x = enc_args->x;
Angie Chiangc8af6112017-03-16 16:11:22 -0700546 MACROBLOCKD *xd = &x->e_mbd;
Angie Chiang140b3332017-12-12 17:29:25 -0800547 aom_writer *w = enc_args->w;
548 tran_low_t *tcoeff = BLOCK_OFFSET(x->mbmi_ext->tcoeff[plane], block);
549 uint16_t eob = x->mbmi_ext->eobs[plane][block];
550 TXB_CTX txb_ctx = { x->mbmi_ext->txb_skip_ctx[plane][block],
551 x->mbmi_ext->dc_sign_ctx[plane][block] };
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500552 av1_write_coeffs_txb(cm, xd, w, blk_row, blk_col, plane, tx_size, tcoeff, eob,
553 &txb_ctx);
Angie Chiang140b3332017-12-12 17:29:25 -0800554}
555
556void av1_write_coeffs_mb(const AV1_COMMON *const cm, MACROBLOCK *x,
557 aom_writer *w, int plane, BLOCK_SIZE bsize) {
558 ENCODE_TXB_ARGS enc_args = { cm, x, w };
559 MACROBLOCKD *xd = &x->e_mbd;
560 av1_foreach_transformed_block_in_plane(xd, bsize, plane,
561 av1_write_coeffs_txb_wrap, &enc_args);
Angie Chiangc8af6112017-03-16 16:11:22 -0700562}
563
Angie Chiang488f9212017-05-30 12:46:26 -0700564static INLINE int get_br_cost(tran_low_t abs_qc, int ctx,
Angie Chiang26d3e452017-09-29 17:40:02 -0700565 const int *coeff_lps) {
Angie Chiang488f9212017-05-30 12:46:26 -0700566 const tran_low_t min_level = 1 + NUM_BASE_LEVELS;
567 const tran_low_t max_level = 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE;
Jingning Handfd72322017-08-09 14:04:12 -0700568 (void)ctx;
Angie Chiang488f9212017-05-30 12:46:26 -0700569 if (abs_qc >= min_level) {
Angie Chiang488f9212017-05-30 12:46:26 -0700570 if (abs_qc >= max_level)
Jingning Han772dee32017-09-15 08:53:18 -0700571 return coeff_lps[COEFF_BASE_RANGE]; // COEFF_BASE_RANGE * cost0;
Angie Chiang488f9212017-05-30 12:46:26 -0700572 else
Jingning Han772dee32017-09-15 08:53:18 -0700573 return coeff_lps[(abs_qc - min_level)]; // * cost0 + cost1;
Angie Chiang488f9212017-05-30 12:46:26 -0700574 } else {
575 return 0;
576 }
577}
578
579static INLINE int get_base_cost(tran_low_t abs_qc, int ctx,
Jingning Handfd72322017-08-09 14:04:12 -0700580 const int coeff_base[2], int base_idx) {
Angie Chiang488f9212017-05-30 12:46:26 -0700581 const int level = base_idx + 1;
Jingning Handfd72322017-08-09 14:04:12 -0700582 (void)ctx;
Angie Chiang488f9212017-05-30 12:46:26 -0700583 if (abs_qc < level)
584 return 0;
585 else
Jingning Handfd72322017-08-09 14:04:12 -0700586 return coeff_base[abs_qc == level];
Angie Chiang488f9212017-05-30 12:46:26 -0700587}
588
Angie Chiang3627de22017-08-18 20:15:59 -0700589int av1_cost_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCK *x, int plane,
Jingning Han7eab9ff2017-07-06 10:12:54 -0700590 int blk_row, int blk_col, int block, TX_SIZE tx_size,
591 TXB_CTX *txb_ctx) {
Angie Chiang47c72182017-02-27 14:30:38 -0800592 MACROBLOCKD *const xd = &x->e_mbd;
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -0800593 TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Angie Chiang47c72182017-02-27 14:30:38 -0800594 const PLANE_TYPE plane_type = get_plane_type(plane);
Jingning Han19b5c8f2017-07-06 15:10:12 -0700595 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500596 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiang47c72182017-02-27 14:30:38 -0800597 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
598 const struct macroblock_plane *p = &x->plane[plane];
599 const int eob = p->eobs[block];
600 const tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
601 int c, cost;
Angie Chiang47c72182017-02-27 14:30:38 -0800602 int txb_skip_ctx = txb_ctx->txb_skip_ctx;
Angie Chiang47c72182017-02-27 14:30:38 -0800603
Angie Chianga9ba58e2017-12-01 19:22:43 -0800604 const int bwl = get_txb_bwl(tx_size);
605 const int width = get_txb_wide(tx_size);
606 const int height = get_txb_high(tx_size);
Jingning Han341d79e2017-06-13 15:57:59 -0700607
Angie Chiangbd99b382017-06-20 15:11:16 -0700608 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800609 const int16_t *const scan = scan_order->scan;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700610 uint8_t levels_buf[TX_PAD_2D];
611 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -0800612 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Angie Chiang47c72182017-02-27 14:30:38 -0800613
Jingning Handfd72322017-08-09 14:04:12 -0700614 LV_MAP_COEFF_COST *coeff_costs = &x->coeff_costs[txs_ctx][plane_type];
615
Angie Chiang47c72182017-02-27 14:30:38 -0800616 cost = 0;
617
618 if (eob == 0) {
Jingning Handfd72322017-08-09 14:04:12 -0700619 cost = coeff_costs->txb_skip_cost[txb_skip_ctx][1];
Angie Chiang47c72182017-02-27 14:30:38 -0800620 return cost;
621 }
Jingning Handfd72322017-08-09 14:04:12 -0700622 cost = coeff_costs->txb_skip_cost[txb_skip_ctx][0];
Angie Chiang47c72182017-02-27 14:30:38 -0800623
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700624 av1_txb_init_levels(qcoeff, width, height, levels);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700625
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700626#if CONFIG_TXK_SEL
Yue Chenb23d00a2017-07-28 17:01:21 -0700627 cost += av1_tx_type_cost(cm, x, xd, mbmi->sb_type, plane, tx_size, tx_type);
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700628#endif
Angie Chiang05917872017-04-15 12:28:56 -0700629
Urvang Joshi80893152017-10-27 11:51:14 -0700630 const int seg_eob = av1_get_max_eob(tx_size);
Jingning Han35deaa72017-10-26 15:36:30 -0700631 int eob_cost = get_eob_cost(eob, seg_eob, coeff_costs, tx_type);
Dake He7d01ab52017-11-24 17:53:28 -0800632#if !CONFIG_LV_MAP_MULTI
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800633 av1_get_br_level_counts(levels, width, height, level_counts);
Dake He7d01ab52017-11-24 17:53:28 -0800634#endif
Dake Hea47cd6c2017-10-13 18:09:58 -0700635 cost += eob_cost;
Dake He03a32922017-10-31 08:06:45 -0700636 int coeff_ctx = 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700637 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800638 const int pos = scan[c];
639 const tran_low_t v = qcoeff[pos];
640 const int is_nz = (v != 0);
641 const int level = abs(v);
Ola Hugosson13892102017-11-06 08:01:44 +0100642#if CONFIG_LV_MAP_MULTI
Linfeng Zhangf6d730a2017-12-06 14:49:44 -0800643 coeff_ctx = get_nz_map_ctx(levels, pos, bwl, height, c, c == eob - 1,
644 tx_size, tx_type);
Dake He3fe369c2017-11-16 17:56:44 -0800645#if USE_BASE_EOB_ALPHABET
646 if (c == eob - 1) {
647 cost += coeff_costs
648 ->base_eob_cost[coeff_ctx - SIG_COEF_CONTEXTS +
649 SIG_COEF_CONTEXTS_EOB][AOMMIN(level, 3) - 1];
650 } else {
651 cost += coeff_costs->base_cost[coeff_ctx][AOMMIN(level, 3)];
652 }
653#else
Ola Hugosson13892102017-11-06 08:01:44 +0100654 cost += coeff_costs->base_cost[coeff_ctx][AOMMIN(level, 3)];
Dake He3fe369c2017-11-16 17:56:44 -0800655#endif
Linfeng Zhang1757fb62017-12-11 10:47:59 -0800656#else // CONFIG_LV_MAP_MULTI
Linfeng Zhangf6d730a2017-12-06 14:49:44 -0800657 coeff_ctx = get_nz_map_ctx(levels, pos, bwl, tx_size, tx_type);
Dake Hea47cd6c2017-10-13 18:09:58 -0700658
659 if (c < eob - 1) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700660 cost += coeff_costs->nz_map_cost[coeff_ctx][is_nz];
661 }
Ola Hugosson13892102017-11-06 08:01:44 +0100662#endif // CONFIG_LV_MAP_MULTI
Dake Hea47cd6c2017-10-13 18:09:58 -0700663
664 if (is_nz) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700665 int sign = (v < 0) ? 1 : 0;
666
667 // sign bit cost
668 if (c == 0) {
669 int dc_sign_ctx = txb_ctx->dc_sign_ctx;
670 cost += coeff_costs->dc_sign_cost[dc_sign_ctx][sign];
671 } else {
672 cost += av1_cost_bit(128, sign);
673 }
Ola Hugosson13892102017-11-06 08:01:44 +0100674#if !CONFIG_LV_MAP_MULTI
Dake He03a32922017-10-31 08:06:45 -0700675 int k;
676 for (k = 0; k < NUM_BASE_LEVELS; ++k) {
677 int is_k = (level > (k + 1));
678 int ctx = coeff_ctx;
679 // get_base_ctx_from_b(c, k, b0, b1, b2);
680 cost += coeff_costs->base_cost[k][ctx][is_k];
681 if (is_k == 0) break;
682 }
Ola Hugosson13892102017-11-06 08:01:44 +0100683#endif // CONFIG_LV_MAP_MULTI
Dake Hea47cd6c2017-10-13 18:09:58 -0700684 if (level > NUM_BASE_LEVELS) {
685 int ctx;
Dake He7d01ab52017-11-24 17:53:28 -0800686#if CONFIG_LV_MAP_MULTI && USE_CAUSAL_BR_CTX
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800687 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos], tx_type);
Dake He7d01ab52017-11-24 17:53:28 -0800688#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800689 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -0800690#endif
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800691 const int base_range = level - 1 - NUM_BASE_LEVELS;
Dake Hea47cd6c2017-10-13 18:09:58 -0700692 if (base_range < COEFF_BASE_RANGE) {
693 cost += coeff_costs->lps_cost[ctx][base_range];
694 } else {
695 cost += coeff_costs->lps_cost[ctx][COEFF_BASE_RANGE];
696 }
697
Dake Hea47cd6c2017-10-13 18:09:58 -0700698 if (level >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
699 // residual cost
700 int r = level - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
701 int ri = r;
702 int length = 0;
703
704 while (ri) {
705 ri >>= 1;
706 ++length;
707 }
708
709 for (ri = 0; ri < length - 1; ++ri) cost += av1_cost_bit(128, 0);
710
711 for (ri = length - 1; ri >= 0; --ri)
712 cost += av1_cost_bit(128, (r >> ri) & 0x01);
713 }
714 }
715 }
716 }
Angie Chiang47c72182017-02-27 14:30:38 -0800717 return cost;
718}
Angie Chiang0397eda2017-03-15 16:57:14 -0700719
Angie Chiang2affb3b2017-05-30 15:23:51 -0700720static INLINE int has_base(tran_low_t qc, int base_idx) {
721 const int level = base_idx + 1;
722 return abs(qc) >= level;
723}
724
Angie Chiang2affb3b2017-05-30 15:23:51 -0700725static INLINE int has_br(tran_low_t qc) {
726 return abs(qc) >= 1 + NUM_BASE_LEVELS;
727}
728
Angie Chiang488f9212017-05-30 12:46:26 -0700729static INLINE int get_sign_bit_cost(tran_low_t qc, int coeff_idx,
Jingning Handfd72322017-08-09 14:04:12 -0700730 const int (*dc_sign_cost)[2],
Angie Chiang488f9212017-05-30 12:46:26 -0700731 int dc_sign_ctx) {
732 const int sign = (qc < 0) ? 1 : 0;
733 // sign bit cost
734 if (coeff_idx == 0) {
Jingning Handfd72322017-08-09 14:04:12 -0700735 return dc_sign_cost[dc_sign_ctx][sign];
Angie Chiang488f9212017-05-30 12:46:26 -0700736 } else {
737 return av1_cost_bit(128, sign);
738 }
739}
740static INLINE int get_golomb_cost(int abs_qc) {
741 if (abs_qc >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
742 // residual cost
743 int r = abs_qc - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
744 int ri = r;
745 int length = 0;
746
747 while (ri) {
748 ri >>= 1;
749 ++length;
750 }
751
752 return av1_cost_literal(2 * length - 1);
753 } else {
754 return 0;
755 }
756}
757
Angie Chiang2affb3b2017-05-30 15:23:51 -0700758void gen_txb_cache(TxbCache *txb_cache, TxbInfo *txb_info) {
Angie Chiang481c01f2017-08-15 16:24:30 -0700759 // gen_nz_count_arr
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800760 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang481c01f2017-08-15 16:24:30 -0700761 const int bwl = txb_info->bwl;
762 const int height = txb_info->height;
Linfeng Zhang72e0b3f2017-10-18 13:32:12 -0700763 const tran_low_t *const qcoeff = txb_info->qcoeff;
Linfeng Zhangb6957c22017-10-25 13:17:28 -0700764 const uint8_t *const levels = txb_info->levels;
Angie Chiangdef11252017-08-18 14:37:32 -0700765 const BASE_CTX_TABLE *base_ctx_table =
766 txb_info->coeff_ctx_table->base_ctx_table;
Angie Chiang481c01f2017-08-15 16:24:30 -0700767 for (int c = 0; c < txb_info->eob; ++c) {
768 const int coeff_idx = scan[c]; // raster order
769 const int row = coeff_idx >> bwl;
770 const int col = coeff_idx - (row << bwl);
Jingning Han3422ac12017-10-25 20:37:53 -0700771
Linfeng Zhangf91f3ca2017-12-05 11:22:41 -0800772 txb_cache->nz_count_arr[coeff_idx] =
Linfeng Zhangd5647372017-12-05 17:06:07 -0800773 get_nz_count(levels + get_padded_idx(coeff_idx, bwl), bwl,
Linfeng Zhangf91f3ca2017-12-05 11:22:41 -0800774 tx_type_to_class[txb_info->tx_type]);
Dake Hea47cd6c2017-10-13 18:09:58 -0700775
Yaowu Xu102ef812017-12-12 11:31:03 -0800776 txb_cache->nz_ctx_arr[coeff_idx] =
777 get_nz_map_ctx_from_stats(0, coeff_idx, bwl, txb_info->tx_size,
778 tx_type_to_class[txb_info->tx_type]);
Angie Chiang481c01f2017-08-15 16:24:30 -0700779
780 // gen_base_count_mag_arr
781 if (!has_base(qcoeff[coeff_idx], 0)) continue;
782 int *base_mag = txb_cache->base_mag_arr[coeff_idx];
Angie Chiang9cde59f2017-08-16 15:24:55 -0700783 int count[NUM_BASE_LEVELS];
784 get_base_count_mag(base_mag, count, qcoeff, bwl, height, row, col);
Angie Chiang481c01f2017-08-15 16:24:30 -0700785
786 for (int i = 0; i < NUM_BASE_LEVELS; ++i) {
Angie Chiang9cde59f2017-08-16 15:24:55 -0700787 if (!has_base(qcoeff[coeff_idx], i)) break;
788 txb_cache->base_count_arr[i][coeff_idx] = count[i];
Angie Chiang481c01f2017-08-15 16:24:30 -0700789 const int level = i + 1;
Angie Chiang9cde59f2017-08-16 15:24:55 -0700790 txb_cache->base_ctx_arr[i][coeff_idx] =
Angie Chiangdef11252017-08-18 14:37:32 -0700791 base_ctx_table[row != 0][col != 0][base_mag[0] > level][count[i]];
Angie Chiang481c01f2017-08-15 16:24:30 -0700792 }
793
794 // gen_br_count_mag_arr
795 if (!has_br(qcoeff[coeff_idx])) continue;
796 int *br_count = txb_cache->br_count_arr + coeff_idx;
797 int *br_mag = txb_cache->br_mag_arr[coeff_idx];
Angie Chiangea8183b2017-08-17 14:36:35 -0700798 *br_count = get_br_count_mag(br_mag, qcoeff, bwl, height, row, col,
799 NUM_BASE_LEVELS);
Angie Chiang481c01f2017-08-15 16:24:30 -0700800 txb_cache->br_ctx_arr[coeff_idx] =
801 get_br_ctx_from_count_mag(row, col, *br_count, br_mag[0]);
802 }
Angie Chiang2affb3b2017-05-30 15:23:51 -0700803}
804
Jingning Handfd72322017-08-09 14:04:12 -0700805static INLINE const int *get_level_prob(int level, int coeff_idx,
806 const TxbCache *txb_cache,
807 const LV_MAP_COEFF_COST *txb_costs) {
Ola Hugosson13892102017-11-06 08:01:44 +0100808#if CONFIG_LV_MAP_MULTI
809 if (level < 1 + NUM_BASE_LEVELS) {
810 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
811 return &txb_costs->base_cost[ctx][level];
812#else
Angie Chiang7afbba42017-05-30 15:59:15 -0700813 if (level == 0) {
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700814 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700815 return txb_costs->nz_map_cost[ctx];
Angie Chiang7afbba42017-05-30 15:59:15 -0700816 } else if (level >= 1 && level < 1 + NUM_BASE_LEVELS) {
817 const int idx = level - 1;
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700818 const int ctx = txb_cache->base_ctx_arr[idx][coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700819 return txb_costs->base_cost[idx][ctx];
Ola Hugosson13892102017-11-06 08:01:44 +0100820#endif
Angie Chiang7afbba42017-05-30 15:59:15 -0700821 } else if (level >= 1 + NUM_BASE_LEVELS &&
822 level < 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700823 const int ctx = txb_cache->br_ctx_arr[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700824 return txb_costs->lps_cost[ctx];
Angie Chiang7afbba42017-05-30 15:59:15 -0700825 } else if (level >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Ola Hugosson13892102017-11-06 08:01:44 +0100826 // printf("get_level_prob does not support golomb\n");
Angie Chiang7afbba42017-05-30 15:59:15 -0700827 assert(0);
828 return 0;
829 } else {
830 assert(0);
831 return 0;
832 }
833}
834
Angie Chiangd19969e2017-05-30 18:02:33 -0700835static INLINE void update_mag_arr(int *mag_arr, int abs_qc) {
836 if (mag_arr[0] == abs_qc) {
837 mag_arr[1] -= 1;
838 assert(mag_arr[1] >= 0);
839 }
840}
841
Angie Chianga530ef42017-05-30 16:32:36 -0700842static INLINE int get_mag_from_mag_arr(const int *mag_arr) {
843 int mag;
844 if (mag_arr[1] > 0) {
845 mag = mag_arr[0];
846 } else if (mag_arr[0] > 0) {
847 mag = mag_arr[0] - 1;
848 } else {
849 // no neighbor
850 assert(mag_arr[0] == 0 && mag_arr[1] == 0);
851 mag = 0;
852 }
853 return mag;
854}
855
856static int neighbor_level_down_update(int *new_count, int *new_mag, int count,
857 const int *mag, int coeff_idx,
858 tran_low_t abs_nb_coeff, int nb_coeff_idx,
859 int level, const TxbInfo *txb_info) {
860 *new_count = count;
861 *new_mag = get_mag_from_mag_arr(mag);
862
863 int update = 0;
864 // check if br_count changes
865 if (abs_nb_coeff == level) {
866 update = 1;
867 *new_count -= 1;
868 assert(*new_count >= 0);
869 }
870 const int row = coeff_idx >> txb_info->bwl;
871 const int col = coeff_idx - (row << txb_info->bwl);
872 const int nb_row = nb_coeff_idx >> txb_info->bwl;
873 const int nb_col = nb_coeff_idx - (nb_row << txb_info->bwl);
874
875 // check if mag changes
876 if (nb_row >= row && nb_col >= col) {
877 if (abs_nb_coeff == mag[0]) {
878 assert(mag[1] > 0);
879 if (mag[1] == 1) {
880 // the nb is the only qc with max mag
881 *new_mag -= 1;
882 assert(*new_mag >= 0);
883 update = 1;
884 }
885 }
886 }
887 return update;
888}
889
890static int try_neighbor_level_down_br(int coeff_idx, int nb_coeff_idx,
891 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700892 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -0700893 const TxbInfo *txb_info) {
894 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
895 const tran_low_t abs_qc = abs(qc);
896 const int level = NUM_BASE_LEVELS + 1;
897 if (abs_qc < level) return 0;
898
899 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
900 const tran_low_t abs_nb_coeff = abs(nb_coeff);
901 const int count = txb_cache->br_count_arr[coeff_idx];
902 const int *mag = txb_cache->br_mag_arr[coeff_idx];
903 int new_count;
904 int new_mag;
905 const int update =
906 neighbor_level_down_update(&new_count, &new_mag, count, mag, coeff_idx,
907 abs_nb_coeff, nb_coeff_idx, level, txb_info);
908 if (update) {
909 const int row = coeff_idx >> txb_info->bwl;
910 const int col = coeff_idx - (row << txb_info->bwl);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700911 const int ctx = txb_cache->br_ctx_arr[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700912 const int org_cost = get_br_cost(abs_qc, ctx, txb_costs->lps_cost[ctx]);
Angie Chianga530ef42017-05-30 16:32:36 -0700913
914 const int new_ctx = get_br_ctx_from_count_mag(row, col, new_count, new_mag);
Jingning Handfd72322017-08-09 14:04:12 -0700915 const int new_cost =
916 get_br_cost(abs_qc, new_ctx, txb_costs->lps_cost[new_ctx]);
Angie Chianga530ef42017-05-30 16:32:36 -0700917 const int cost_diff = -org_cost + new_cost;
918 return cost_diff;
919 } else {
920 return 0;
921 }
922}
923
924static int try_neighbor_level_down_base(int coeff_idx, int nb_coeff_idx,
925 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700926 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -0700927 const TxbInfo *txb_info) {
Ola Hugosson13892102017-11-06 08:01:44 +0100928#if CONFIG_LV_MAP_MULTI
929 // TODO(olah): not implemented yet
930 (void)coeff_idx;
931 (void)nb_coeff_idx;
932 (void)txb_cache;
933 (void)txb_costs;
934 (void)txb_info;
935 return 0;
936#else
Angie Chianga530ef42017-05-30 16:32:36 -0700937 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
938 const tran_low_t abs_qc = abs(qc);
Angie Chiangdef11252017-08-18 14:37:32 -0700939 const BASE_CTX_TABLE *base_ctx_table =
940 txb_info->coeff_ctx_table->base_ctx_table;
Angie Chianga530ef42017-05-30 16:32:36 -0700941
942 int cost_diff = 0;
943 for (int base_idx = 0; base_idx < NUM_BASE_LEVELS; ++base_idx) {
944 const int level = base_idx + 1;
945 if (abs_qc < level) continue;
946
947 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
948 const tran_low_t abs_nb_coeff = abs(nb_coeff);
949
950 const int count = txb_cache->base_count_arr[base_idx][coeff_idx];
951 const int *mag = txb_cache->base_mag_arr[coeff_idx];
952 int new_count;
953 int new_mag;
954 const int update =
955 neighbor_level_down_update(&new_count, &new_mag, count, mag, coeff_idx,
956 abs_nb_coeff, nb_coeff_idx, level, txb_info);
957 if (update) {
958 const int row = coeff_idx >> txb_info->bwl;
959 const int col = coeff_idx - (row << txb_info->bwl);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700960 const int ctx = txb_cache->base_ctx_arr[base_idx][coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700961 const int org_cost = get_base_cost(
962 abs_qc, ctx, txb_costs->base_cost[base_idx][ctx], base_idx);
Angie Chianga530ef42017-05-30 16:32:36 -0700963
964 const int new_ctx =
Angie Chiangdef11252017-08-18 14:37:32 -0700965 base_ctx_table[row != 0][col != 0][new_mag > level][new_count];
Jingning Handfd72322017-08-09 14:04:12 -0700966 const int new_cost = get_base_cost(
967 abs_qc, new_ctx, txb_costs->base_cost[base_idx][new_ctx], base_idx);
Angie Chianga530ef42017-05-30 16:32:36 -0700968 cost_diff += -org_cost + new_cost;
969 }
970 }
971 return cost_diff;
Ola Hugosson13892102017-11-06 08:01:44 +0100972#endif
Angie Chianga530ef42017-05-30 16:32:36 -0700973}
974
975static int try_neighbor_level_down_nz(int coeff_idx, int nb_coeff_idx,
976 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700977 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -0700978 TxbInfo *txb_info) {
979 // assume eob doesn't change
980 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
981 const tran_low_t abs_qc = abs(qc);
982 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
983 const tran_low_t abs_nb_coeff = abs(nb_coeff);
984 if (abs_nb_coeff != 1) return 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800985 const int16_t *const iscan = txb_info->scan_order->iscan;
Angie Chianga530ef42017-05-30 16:32:36 -0700986 const int scan_idx = iscan[coeff_idx];
987 if (scan_idx == txb_info->seg_eob) return 0;
988 const int nb_scan_idx = iscan[nb_coeff_idx];
989 if (nb_scan_idx < scan_idx) {
990 const int count = txb_cache->nz_count_arr[coeff_idx];
Linfeng Zhang8ac45572017-11-29 11:39:51 -0800991 (void)count;
Angie Chianga530ef42017-05-30 16:32:36 -0700992 assert(count > 0);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700993 update_qcoeff(nb_coeff_idx, get_lower_coeff(nb_coeff), txb_info);
Linfeng Zhang8ac45572017-11-29 11:39:51 -0800994 const int new_ctx = get_nz_map_ctx_from_stats(
Yaowu Xu102ef812017-12-12 11:31:03 -0800995 0, coeff_idx, txb_info->bwl, txb_info->tx_size,
996 tx_type_to_class[txb_info->tx_type]);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700997 update_qcoeff(nb_coeff_idx, nb_coeff, txb_info);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700998 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
Ola Hugosson13892102017-11-06 08:01:44 +0100999#if CONFIG_LV_MAP_MULTI
1000 const int org_cost = txb_costs->base_cost[ctx][AOMMIN(abs_qc, 3)];
1001 const int new_cost = txb_costs->base_cost[new_ctx][AOMMIN(abs_qc, 3)];
1002#else
Angie Chianga530ef42017-05-30 16:32:36 -07001003 const int is_nz = abs_qc > 0;
Jingning Handfd72322017-08-09 14:04:12 -07001004 const int org_cost = txb_costs->nz_map_cost[ctx][is_nz];
1005 const int new_cost = txb_costs->nz_map_cost[new_ctx][is_nz];
Ola Hugosson13892102017-11-06 08:01:44 +01001006#endif
Angie Chianga530ef42017-05-30 16:32:36 -07001007 const int cost_diff = new_cost - org_cost;
1008 return cost_diff;
1009 } else {
1010 return 0;
1011 }
1012}
1013
1014static int try_self_level_down(tran_low_t *low_coeff, int coeff_idx,
1015 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001016 const LV_MAP_COEFF_COST *txb_costs,
1017 TxbInfo *txb_info) {
Angie Chiang7afbba42017-05-30 15:59:15 -07001018 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1019 if (qc == 0) {
1020 *low_coeff = 0;
1021 return 0;
1022 }
1023 const tran_low_t abs_qc = abs(qc);
1024 *low_coeff = get_lower_coeff(qc);
1025 int cost_diff;
1026 if (*low_coeff == 0) {
1027 const int scan_idx = txb_info->scan_order->iscan[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -07001028 const int *level_cost =
1029 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1030 const int *low_level_cost =
1031 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
Jingning Han3422ac12017-10-25 20:37:53 -07001032
Dake Hea47cd6c2017-10-13 18:09:58 -07001033 if (scan_idx < txb_info->eob - 1) {
Angie Chiang7afbba42017-05-30 15:59:15 -07001034 // When level-0, we code the binary of abs_qc > level
1035 // but when level-k k > 0 we code the binary of abs_qc == level
1036 // That's why wee need this special treatment for level-0 map
1037 // TODO(angiebird): make leve-0 consistent to other levels
Jingning Handfd72322017-08-09 14:04:12 -07001038 cost_diff = -level_cost[1] + low_level_cost[0] - low_level_cost[1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001039 } else {
Jingning Handfd72322017-08-09 14:04:12 -07001040 cost_diff = -level_cost[1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001041 }
1042
Angie Chiang7afbba42017-05-30 15:59:15 -07001043 const int sign_cost = get_sign_bit_cost(
Jingning Handfd72322017-08-09 14:04:12 -07001044 qc, coeff_idx, txb_costs->dc_sign_cost, txb_info->txb_ctx->dc_sign_ctx);
Angie Chiang7afbba42017-05-30 15:59:15 -07001045 cost_diff -= sign_cost;
Jingning Han772dee32017-09-15 08:53:18 -07001046 } else if (abs_qc <= NUM_BASE_LEVELS) {
1047 const int *level_cost =
1048 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1049 const int *low_level_cost =
1050 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1051 cost_diff = -level_cost[1] + low_level_cost[1] - low_level_cost[0];
1052 } else if (abs_qc == NUM_BASE_LEVELS + 1) {
1053 const int *level_cost =
1054 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1055 const int *low_level_cost =
1056 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1057 cost_diff = -level_cost[0] + low_level_cost[1] - low_level_cost[0];
Angie Chiang7afbba42017-05-30 15:59:15 -07001058 } else if (abs_qc < 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Jingning Handfd72322017-08-09 14:04:12 -07001059 const int *level_cost =
1060 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1061 const int *low_level_cost =
1062 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1063
Jingning Han772dee32017-09-15 08:53:18 -07001064 cost_diff = -level_cost[abs_qc - 1 - NUM_BASE_LEVELS] +
1065 low_level_cost[abs(*low_coeff) - 1 - NUM_BASE_LEVELS];
Angie Chiang7afbba42017-05-30 15:59:15 -07001066 } else if (abs_qc == 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Jingning Handfd72322017-08-09 14:04:12 -07001067 const int *low_level_cost =
1068 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
Jingning Han772dee32017-09-15 08:53:18 -07001069 cost_diff = -get_golomb_cost(abs_qc) - low_level_cost[COEFF_BASE_RANGE] +
1070 low_level_cost[COEFF_BASE_RANGE - 1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001071 } else {
1072 assert(abs_qc > 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE);
1073 const tran_low_t abs_low_coeff = abs(*low_coeff);
1074 cost_diff = -get_golomb_cost(abs_qc) + get_golomb_cost(abs_low_coeff);
1075 }
1076 return cost_diff;
1077}
1078
Angie Chianga530ef42017-05-30 16:32:36 -07001079#define COST_MAP_SIZE 5
1080#define COST_MAP_OFFSET 2
1081
1082static INLINE int check_nz_neighbor(tran_low_t qc) { return abs(qc) == 1; }
1083
1084static INLINE int check_base_neighbor(tran_low_t qc) {
1085 return abs(qc) <= 1 + NUM_BASE_LEVELS;
1086}
1087
1088static INLINE int check_br_neighbor(tran_low_t qc) {
1089 return abs(qc) > BR_MAG_OFFSET;
1090}
1091
Angie Chiang87278292017-10-18 09:59:47 -07001092#define FAST_OPTIMIZE_TXB 1
Angie Chiange80957f2017-09-05 10:48:00 -07001093
1094#if FAST_OPTIMIZE_TXB
1095#define ALNB_REF_OFFSET_NUM 2
Linfeng Zhang4afda452017-10-24 10:34:04 -07001096static const int alnb_ref_offset[ALNB_REF_OFFSET_NUM][2] = {
Angie Chiange80957f2017-09-05 10:48:00 -07001097 { -1, 0 }, { 0, -1 },
1098};
1099#define NB_REF_OFFSET_NUM 4
Linfeng Zhang4afda452017-10-24 10:34:04 -07001100static const int nb_ref_offset[NB_REF_OFFSET_NUM][2] = {
Angie Chiange80957f2017-09-05 10:48:00 -07001101 { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 },
1102};
1103#endif // FAST_OPTIMIZE_TXB
1104
Angie Chianga530ef42017-05-30 16:32:36 -07001105// TODO(angiebird): add static to this function once it's called
1106int try_level_down(int coeff_idx, const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001107 const LV_MAP_COEFF_COST *txb_costs, TxbInfo *txb_info,
Angie Chiang25645b72017-09-24 14:28:49 -07001108 int (*cost_map)[COST_MAP_SIZE], int fast_mode) {
1109#if !FAST_OPTIMIZE_TXB
1110 (void)fast_mode;
1111#endif
Angie Chianga530ef42017-05-30 16:32:36 -07001112 if (cost_map) {
1113 for (int i = 0; i < COST_MAP_SIZE; ++i) av1_zero(cost_map[i]);
1114 }
1115
1116 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1117 tran_low_t low_coeff;
1118 if (qc == 0) return 0;
1119 int accu_cost_diff = 0;
1120
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001121 const int16_t *const iscan = txb_info->scan_order->iscan;
Angie Chianga530ef42017-05-30 16:32:36 -07001122 const int eob = txb_info->eob;
1123 const int scan_idx = iscan[coeff_idx];
1124 if (scan_idx < eob) {
1125 const int cost_diff = try_self_level_down(&low_coeff, coeff_idx, txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001126 txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001127 if (cost_map)
1128 cost_map[0 + COST_MAP_OFFSET][0 + COST_MAP_OFFSET] = cost_diff;
1129 accu_cost_diff += cost_diff;
1130 }
1131
1132 const int row = coeff_idx >> txb_info->bwl;
1133 const int col = coeff_idx - (row << txb_info->bwl);
1134 if (check_nz_neighbor(qc)) {
Angie Chiange80957f2017-09-05 10:48:00 -07001135#if FAST_OPTIMIZE_TXB
Linfeng Zhang4afda452017-10-24 10:34:04 -07001136 const int(*ref_offset)[2];
Angie Chiang25645b72017-09-24 14:28:49 -07001137 int ref_num;
1138 if (fast_mode) {
1139 ref_offset = alnb_ref_offset;
1140 ref_num = ALNB_REF_OFFSET_NUM;
1141 } else {
1142 ref_offset = sig_ref_offset;
1143 ref_num = SIG_REF_OFFSET_NUM;
1144 }
Angie Chiange80957f2017-09-05 10:48:00 -07001145#else
Linfeng Zhang4afda452017-10-24 10:34:04 -07001146 const int(*ref_offset)[2] = sig_ref_offset;
Angie Chiange80957f2017-09-05 10:48:00 -07001147 const int ref_num = SIG_REF_OFFSET_NUM;
1148#endif
1149 for (int i = 0; i < ref_num; ++i) {
1150 const int nb_row = row - ref_offset[i][0];
1151 const int nb_col = col - ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001152 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han4cbb3632017-06-13 12:50:33 -07001153
Angie Chiang0c89dca2017-08-17 16:36:18 -07001154 if (nb_row < 0 || nb_col < 0 || nb_row >= txb_info->height ||
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001155 nb_col >= txb_info->width)
Jingning Han3455e762017-06-13 21:15:44 -07001156 continue;
1157
Angie Chianga530ef42017-05-30 16:32:36 -07001158 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001159 if (nb_scan_idx < eob) {
Angie Chianga530ef42017-05-30 16:32:36 -07001160 const int cost_diff = try_neighbor_level_down_nz(
Jingning Handfd72322017-08-09 14:04:12 -07001161 nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001162 if (cost_map)
1163 cost_map[nb_row - row + COST_MAP_OFFSET]
1164 [nb_col - col + COST_MAP_OFFSET] += cost_diff;
1165 accu_cost_diff += cost_diff;
1166 }
1167 }
1168 }
1169
1170 if (check_base_neighbor(qc)) {
Angie Chiange80957f2017-09-05 10:48:00 -07001171#if FAST_OPTIMIZE_TXB
Linfeng Zhang4afda452017-10-24 10:34:04 -07001172 const int(*ref_offset)[2];
Angie Chiang25645b72017-09-24 14:28:49 -07001173 int ref_num;
1174 if (fast_mode) {
1175 ref_offset = nb_ref_offset;
1176 ref_num = NB_REF_OFFSET_NUM;
1177 } else {
1178 ref_offset = base_ref_offset;
1179 ref_num = BASE_CONTEXT_POSITION_NUM;
1180 }
Angie Chiange80957f2017-09-05 10:48:00 -07001181#else
Linfeng Zhangce065ca2017-10-17 16:49:30 -07001182 const int(*ref_offset)[2] = base_ref_offset;
Angie Chiang25645b72017-09-24 14:28:49 -07001183 int ref_num = BASE_CONTEXT_POSITION_NUM;
Angie Chiange80957f2017-09-05 10:48:00 -07001184#endif
1185 for (int i = 0; i < ref_num; ++i) {
1186 const int nb_row = row - ref_offset[i][0];
1187 const int nb_col = col - ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001188 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001189
Angie Chiang0c89dca2017-08-17 16:36:18 -07001190 if (nb_row < 0 || nb_col < 0 || nb_row >= txb_info->height ||
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001191 nb_col >= txb_info->width)
Jingning Han3455e762017-06-13 21:15:44 -07001192 continue;
1193
Angie Chianga530ef42017-05-30 16:32:36 -07001194 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001195 if (nb_scan_idx < eob) {
Angie Chianga530ef42017-05-30 16:32:36 -07001196 const int cost_diff = try_neighbor_level_down_base(
Jingning Handfd72322017-08-09 14:04:12 -07001197 nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001198 if (cost_map)
1199 cost_map[nb_row - row + COST_MAP_OFFSET]
1200 [nb_col - col + COST_MAP_OFFSET] += cost_diff;
1201 accu_cost_diff += cost_diff;
1202 }
1203 }
1204 }
1205
1206 if (check_br_neighbor(qc)) {
Angie Chiange80957f2017-09-05 10:48:00 -07001207#if FAST_OPTIMIZE_TXB
Linfeng Zhang4afda452017-10-24 10:34:04 -07001208 const int(*ref_offset)[2];
Angie Chiang25645b72017-09-24 14:28:49 -07001209 int ref_num;
1210 if (fast_mode) {
1211 ref_offset = nb_ref_offset;
1212 ref_num = NB_REF_OFFSET_NUM;
1213 } else {
1214 ref_offset = br_ref_offset;
1215 ref_num = BR_CONTEXT_POSITION_NUM;
1216 }
Angie Chiange80957f2017-09-05 10:48:00 -07001217#else
Linfeng Zhangce065ca2017-10-17 16:49:30 -07001218 const int(*ref_offset)[2] = br_ref_offset;
Angie Chiange80957f2017-09-05 10:48:00 -07001219 const int ref_num = BR_CONTEXT_POSITION_NUM;
1220#endif
1221 for (int i = 0; i < ref_num; ++i) {
1222 const int nb_row = row - ref_offset[i][0];
1223 const int nb_col = col - ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001224 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001225
Angie Chiang0c89dca2017-08-17 16:36:18 -07001226 if (nb_row < 0 || nb_col < 0 || nb_row >= txb_info->height ||
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001227 nb_col >= txb_info->width)
Jingning Han3455e762017-06-13 21:15:44 -07001228 continue;
1229
Angie Chianga530ef42017-05-30 16:32:36 -07001230 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001231 if (nb_scan_idx < eob) {
Angie Chianga530ef42017-05-30 16:32:36 -07001232 const int cost_diff = try_neighbor_level_down_br(
Jingning Handfd72322017-08-09 14:04:12 -07001233 nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001234 if (cost_map)
1235 cost_map[nb_row - row + COST_MAP_OFFSET]
1236 [nb_col - col + COST_MAP_OFFSET] += cost_diff;
1237 accu_cost_diff += cost_diff;
1238 }
1239 }
1240 }
1241
1242 return accu_cost_diff;
1243}
1244
Angie Chiangc77799b2017-05-30 17:08:17 -07001245static int get_low_coeff_cost(int coeff_idx, const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001246 const LV_MAP_COEFF_COST *txb_costs,
Angie Chiangc77799b2017-05-30 17:08:17 -07001247 const TxbInfo *txb_info) {
1248 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1249 const int abs_qc = abs(qc);
1250 assert(abs_qc <= 1);
1251 int cost = 0;
Jingning Han3422ac12017-10-25 20:37:53 -07001252
Ola Hugosson13892102017-11-06 08:01:44 +01001253#if CONFIG_LV_MAP_MULTI
1254 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
1255 cost += txb_costs->base_cost[ctx][AOMMIN(abs_qc, 3)];
1256 if (qc != 0) {
1257 cost += get_sign_bit_cost(qc, coeff_idx, txb_costs->dc_sign_cost,
1258 txb_info->txb_ctx->dc_sign_ctx);
1259 }
1260#else
1261 const int scan_idx = txb_info->scan_order->iscan[coeff_idx];
Dake Hea47cd6c2017-10-13 18:09:58 -07001262 if (scan_idx < txb_info->eob - 1) {
Jingning Handfd72322017-08-09 14:04:12 -07001263 const int *level_cost = get_level_prob(0, coeff_idx, txb_cache, txb_costs);
1264 cost += level_cost[qc != 0];
Angie Chiangc77799b2017-05-30 17:08:17 -07001265 }
1266
1267 if (qc != 0) {
1268 const int base_idx = 0;
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001269 const int ctx = txb_cache->base_ctx_arr[base_idx][coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -07001270 cost += get_base_cost(abs_qc, ctx, txb_costs->base_cost[base_idx][ctx],
1271 base_idx);
Jingning Handfd72322017-08-09 14:04:12 -07001272 cost += get_sign_bit_cost(qc, coeff_idx, txb_costs->dc_sign_cost,
Angie Chiangc77799b2017-05-30 17:08:17 -07001273 txb_info->txb_ctx->dc_sign_ctx);
1274 }
Ola Hugosson13892102017-11-06 08:01:44 +01001275#endif
Angie Chiangc77799b2017-05-30 17:08:17 -07001276 return cost;
1277}
1278
1279static INLINE void set_eob(TxbInfo *txb_info, int eob) {
1280 txb_info->eob = eob;
Urvang Joshi80893152017-10-27 11:51:14 -07001281 txb_info->seg_eob = av1_get_max_eob(txb_info->tx_size);
Angie Chiangc77799b2017-05-30 17:08:17 -07001282}
1283
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001284static INLINE int get_eob_ctx(const int coeff_idx, // raster order
1285 const TX_SIZE txs_ctx) {
1286 if (txs_ctx == TX_4X4) return av1_coeff_band_4x4[coeff_idx];
1287 if (txs_ctx == TX_8X8) return av1_coeff_band_8x8[coeff_idx];
1288 if (txs_ctx == TX_16X16) return av1_coeff_band_16x16[coeff_idx];
1289 if (txs_ctx == TX_32X32) return av1_coeff_band_32x32[coeff_idx];
1290
1291#if CONFIG_TX64X64
1292 // Since TX64X64 use 32x32 coeff buffer, so it share the same coeff_band with
1293 // TX32X32
1294 if (txs_ctx == TX_64X64) return av1_coeff_band_32x32[coeff_idx];
1295#endif // CONFIG_TX64X64
1296
1297 assert(0 && "Invalid value of txs_ctx");
1298 return 0;
1299}
1300
Angie Chiangc77799b2017-05-30 17:08:17 -07001301// TODO(angiebird): add static to this function once it's called
1302int try_change_eob(int *new_eob, int coeff_idx, const TxbCache *txb_cache,
Angie Chiang25645b72017-09-24 14:28:49 -07001303 const LV_MAP_COEFF_COST *txb_costs, TxbInfo *txb_info,
1304 int fast_mode) {
Angie Chiangc77799b2017-05-30 17:08:17 -07001305 assert(txb_info->eob > 0);
1306 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1307 const int abs_qc = abs(qc);
1308 if (abs_qc != 1) {
1309 *new_eob = -1;
1310 return 0;
1311 }
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001312 const int16_t *const iscan = txb_info->scan_order->iscan;
1313 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiangc77799b2017-05-30 17:08:17 -07001314 const int scan_idx = iscan[coeff_idx];
1315 *new_eob = 0;
1316 int cost_diff = 0;
Jingning Handfd72322017-08-09 14:04:12 -07001317 cost_diff -= get_low_coeff_cost(coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chiangc77799b2017-05-30 17:08:17 -07001318 for (int si = scan_idx - 1; si >= 0; --si) {
1319 const int ci = scan[si];
1320 if (txb_info->qcoeff[ci] != 0) {
1321 *new_eob = si + 1;
1322 break;
1323 } else {
Jingning Handfd72322017-08-09 14:04:12 -07001324 cost_diff -= get_low_coeff_cost(ci, txb_cache, txb_costs, txb_info);
Angie Chiangc77799b2017-05-30 17:08:17 -07001325 }
1326 }
1327
1328 const int org_eob = txb_info->eob;
1329 set_eob(txb_info, *new_eob);
Angie Chiang25645b72017-09-24 14:28:49 -07001330 cost_diff += try_level_down(coeff_idx, txb_cache, txb_costs, txb_info, NULL,
1331 fast_mode);
Angie Chiangc77799b2017-05-30 17:08:17 -07001332 set_eob(txb_info, org_eob);
1333
1334 if (*new_eob > 0) {
1335 // Note that get_eob_ctx does NOT actually account for qcoeff, so we don't
1336 // need to lower down the qcoeff here
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001337 const int eob_ctx = get_eob_ctx(scan[*new_eob - 1], txb_info->txs_ctx);
Jingning Handfd72322017-08-09 14:04:12 -07001338 cost_diff -= txb_costs->eob_cost[eob_ctx][0];
1339 cost_diff += txb_costs->eob_cost[eob_ctx][1];
Angie Chiangc77799b2017-05-30 17:08:17 -07001340 } else {
1341 const int txb_skip_ctx = txb_info->txb_ctx->txb_skip_ctx;
Jingning Handfd72322017-08-09 14:04:12 -07001342 cost_diff -= txb_costs->txb_skip_cost[txb_skip_ctx][0];
1343 cost_diff += txb_costs->txb_skip_cost[txb_skip_ctx][1];
Angie Chiangc77799b2017-05-30 17:08:17 -07001344 }
1345 return cost_diff;
1346}
Angie Chiang47e07072017-05-30 17:27:01 -07001347
Angie Chiangd19969e2017-05-30 18:02:33 -07001348// TODO(angiebird): add static to this function it's called
Linfeng Zhang1015a342017-10-24 16:20:41 -07001349void update_level_down(const int coeff_idx, TxbCache *const txb_cache,
1350 TxbInfo *const txb_info) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001351 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1352 const int abs_qc = abs(qc);
1353 if (qc == 0) return;
1354 const tran_low_t low_coeff = get_lower_coeff(qc);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001355 update_coeff(coeff_idx, low_coeff, txb_info);
Angie Chiangd19969e2017-05-30 18:02:33 -07001356
1357 const int row = coeff_idx >> txb_info->bwl;
1358 const int col = coeff_idx - (row << txb_info->bwl);
1359 const int eob = txb_info->eob;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001360 const int16_t *const iscan = txb_info->scan_order->iscan;
Angie Chiangd19969e2017-05-30 18:02:33 -07001361 for (int i = 0; i < SIG_REF_OFFSET_NUM; ++i) {
1362 const int nb_row = row - sig_ref_offset[i][0];
1363 const int nb_col = col - sig_ref_offset[i][1];
Jingning Han3455e762017-06-13 21:15:44 -07001364
1365 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001366 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001367 continue;
1368
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001369 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiangd19969e2017-05-30 18:02:33 -07001370 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001371 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001372 const int scan_idx = iscan[coeff_idx];
1373 if (scan_idx < nb_scan_idx) {
1374 const int level = 1;
1375 if (abs_qc == level) {
1376 txb_cache->nz_count_arr[nb_coeff_idx] -= 1;
1377 assert(txb_cache->nz_count_arr[nb_coeff_idx] >= 0);
1378 }
Yaowu Xu102ef812017-12-12 11:31:03 -08001379 txb_cache->nz_ctx_arr[nb_coeff_idx] = get_nz_map_ctx_from_stats(
1380 0, nb_coeff_idx, txb_info->bwl, txb_info->tx_size,
1381 tx_type_to_class[txb_info->tx_type]);
Angie Chiangd19969e2017-05-30 18:02:33 -07001382 }
1383 }
1384 }
1385
Angie Chiangdef11252017-08-18 14:37:32 -07001386 const BASE_CTX_TABLE *base_ctx_table =
1387 txb_info->coeff_ctx_table->base_ctx_table;
Angie Chiangd19969e2017-05-30 18:02:33 -07001388 for (int i = 0; i < BASE_CONTEXT_POSITION_NUM; ++i) {
1389 const int nb_row = row - base_ref_offset[i][0];
1390 const int nb_col = col - base_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001391 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001392
1393 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001394 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001395 continue;
1396
Angie Chiangd19969e2017-05-30 18:02:33 -07001397 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
1398 if (!has_base(nb_coeff, 0)) continue;
1399 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001400 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001401 if (row >= nb_row && col >= nb_col)
1402 update_mag_arr(txb_cache->base_mag_arr[nb_coeff_idx], abs_qc);
1403 const int mag =
1404 get_mag_from_mag_arr(txb_cache->base_mag_arr[nb_coeff_idx]);
1405 for (int base_idx = 0; base_idx < NUM_BASE_LEVELS; ++base_idx) {
1406 if (!has_base(nb_coeff, base_idx)) continue;
1407 const int level = base_idx + 1;
1408 if (abs_qc == level) {
1409 txb_cache->base_count_arr[base_idx][nb_coeff_idx] -= 1;
1410 assert(txb_cache->base_count_arr[base_idx][nb_coeff_idx] >= 0);
1411 }
1412 const int count = txb_cache->base_count_arr[base_idx][nb_coeff_idx];
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001413 txb_cache->base_ctx_arr[base_idx][nb_coeff_idx] =
Angie Chiangdef11252017-08-18 14:37:32 -07001414 base_ctx_table[nb_row != 0][nb_col != 0][mag > level][count];
Angie Chiangd19969e2017-05-30 18:02:33 -07001415 }
1416 }
1417 }
1418
1419 for (int i = 0; i < BR_CONTEXT_POSITION_NUM; ++i) {
1420 const int nb_row = row - br_ref_offset[i][0];
1421 const int nb_col = col - br_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001422 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001423
1424 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001425 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001426 continue;
1427
Angie Chiangd19969e2017-05-30 18:02:33 -07001428 const int nb_scan_idx = iscan[nb_coeff_idx];
1429 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
1430 if (!has_br(nb_coeff)) continue;
Jingning Han3455e762017-06-13 21:15:44 -07001431 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001432 const int level = 1 + NUM_BASE_LEVELS;
1433 if (abs_qc == level) {
1434 txb_cache->br_count_arr[nb_coeff_idx] -= 1;
1435 assert(txb_cache->br_count_arr[nb_coeff_idx] >= 0);
1436 }
1437 if (row >= nb_row && col >= nb_col)
1438 update_mag_arr(txb_cache->br_mag_arr[nb_coeff_idx], abs_qc);
1439 const int count = txb_cache->br_count_arr[nb_coeff_idx];
1440 const int mag = get_mag_from_mag_arr(txb_cache->br_mag_arr[nb_coeff_idx]);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001441 txb_cache->br_ctx_arr[nb_coeff_idx] =
Angie Chiangd19969e2017-05-30 18:02:33 -07001442 get_br_ctx_from_count_mag(nb_row, nb_col, count, mag);
Angie Chiangd19969e2017-05-30 18:02:33 -07001443 }
1444 }
1445}
1446
Linfeng Zhang1015a342017-10-24 16:20:41 -07001447static int get_coeff_cost(const tran_low_t qc, const int scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +01001448#if CONFIG_LV_MAP_MULTI
1449 const int is_eob,
1450#endif
Linfeng Zhang1015a342017-10-24 16:20:41 -07001451 const TxbInfo *const txb_info,
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001452 const LV_MAP_COEFF_COST *const txb_costs,
1453 const int coeff_ctx) {
Angie Chiang488f9212017-05-30 12:46:26 -07001454 const TXB_CTX *txb_ctx = txb_info->txb_ctx;
1455 const int is_nz = (qc != 0);
1456 const tran_low_t abs_qc = abs(qc);
1457 int cost = 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001458 const int16_t *const scan = txb_info->scan_order->scan;
1459 const int pos = scan[scan_idx];
Dake He03a32922017-10-31 08:06:45 -07001460
Ola Hugosson13892102017-11-06 08:01:44 +01001461#if CONFIG_LV_MAP_MULTI
Dake He3fe369c2017-11-16 17:56:44 -08001462#if USE_BASE_EOB_ALPHABET
1463 if (is_eob) {
1464 cost +=
1465 txb_costs->base_eob_cost[coeff_ctx - SIG_COEF_CONTEXTS +
1466 SIG_COEF_CONTEXTS_EOB][AOMMIN(abs_qc, 3) - 1];
1467 } else {
1468 cost += txb_costs->base_cost[coeff_ctx][AOMMIN(abs_qc, 3)];
1469 }
1470
1471#else
Ola Hugosson13892102017-11-06 08:01:44 +01001472 cost += txb_costs->base_cost[coeff_ctx][AOMMIN(abs_qc, 3)];
Dake He3fe369c2017-11-16 17:56:44 -08001473#endif
Ola Hugosson13892102017-11-06 08:01:44 +01001474#else
Dake Hea47cd6c2017-10-13 18:09:58 -07001475 if (scan_idx < txb_info->eob - 1) {
Jingning Handfd72322017-08-09 14:04:12 -07001476 cost += txb_costs->nz_map_cost[coeff_ctx][is_nz];
Angie Chiang488f9212017-05-30 12:46:26 -07001477 }
Ola Hugosson13892102017-11-06 08:01:44 +01001478#endif
Angie Chiang488f9212017-05-30 12:46:26 -07001479 if (is_nz) {
Jingning Handfd72322017-08-09 14:04:12 -07001480 cost += get_sign_bit_cost(qc, scan_idx, txb_costs->dc_sign_cost,
Angie Chiang488f9212017-05-30 12:46:26 -07001481 txb_ctx->dc_sign_ctx);
1482
Ola Hugosson13892102017-11-06 08:01:44 +01001483#if !CONFIG_LV_MAP_MULTI
Dake He03a32922017-10-31 08:06:45 -07001484 int k;
1485 for (k = 0; k < NUM_BASE_LEVELS; ++k) {
1486 int ctx = coeff_ctx;
1487 int is_k = (abs_qc > (k + 1));
1488
1489 cost += txb_costs->base_cost[k][ctx][is_k];
1490 if (is_k == 0) break;
1491 }
Ola Hugosson13892102017-11-06 08:01:44 +01001492#endif
Angie Chiang488f9212017-05-30 12:46:26 -07001493 if (abs_qc > NUM_BASE_LEVELS) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001494 const int row = pos >> txb_info->bwl;
1495 const int col = pos - (row << txb_info->bwl);
Dake He7d01ab52017-11-24 17:53:28 -08001496
1497#if CONFIG_LV_MAP_MULTI && USE_CAUSAL_BR_CTX
1498 (void)col;
1499 const int count = 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001500 const int ctx = get_br_ctx(txb_info->levels, pos, txb_info->bwl, count,
1501 txb_info->tx_type);
Dake He7d01ab52017-11-24 17:53:28 -08001502#else
Linfeng Zhang97fc4742017-11-07 12:57:25 -08001503 const int count = get_level_count(
1504 txb_info->levels, (1 << txb_info->bwl) + TX_PAD_HOR, row, col,
1505 NUM_BASE_LEVELS, br_ref_offset, BR_CONTEXT_POSITION_NUM);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001506 const int ctx = get_br_ctx(txb_info->levels, pos, txb_info->bwl, count);
Dake He7d01ab52017-11-24 17:53:28 -08001507#endif
Jingning Handfd72322017-08-09 14:04:12 -07001508 cost += get_br_cost(abs_qc, ctx, txb_costs->lps_cost[ctx]);
Angie Chiang488f9212017-05-30 12:46:26 -07001509 cost += get_golomb_cost(abs_qc);
1510 }
Angie Chiang488f9212017-05-30 12:46:26 -07001511 }
1512 return cost;
1513}
1514
Angie Chiang47e07072017-05-30 17:27:01 -07001515#if TEST_OPTIMIZE_TXB
Angie Chiang5e012fe2017-05-30 18:47:39 -07001516#define ALL_REF_OFFSET_NUM 17
Linfeng Zhang4afda452017-10-24 10:34:04 -07001517static const int all_ref_offset[ALL_REF_OFFSET_NUM][2] = {
Angie Chiang5e012fe2017-05-30 18:47:39 -07001518 { 0, 0 }, { -2, -1 }, { -2, 0 }, { -2, 1 }, { -1, -2 }, { -1, -1 },
1519 { -1, 0 }, { -1, 1 }, { 0, -2 }, { 0, -1 }, { 1, -2 }, { 1, -1 },
1520 { 1, 0 }, { 2, 0 }, { 0, 1 }, { 0, 2 }, { 1, 1 },
1521};
1522
Angie Chiang0b2795c2017-09-29 16:00:08 -07001523static int try_level_down_ref(int coeff_idx, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang5e012fe2017-05-30 18:47:39 -07001524 TxbInfo *txb_info,
1525 int (*cost_map)[COST_MAP_SIZE]) {
1526 if (cost_map) {
1527 for (int i = 0; i < COST_MAP_SIZE; ++i) av1_zero(cost_map[i]);
1528 }
1529 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1530 if (qc == 0) return 0;
1531 int row = coeff_idx >> txb_info->bwl;
1532 int col = coeff_idx - (row << txb_info->bwl);
1533 int org_cost = 0;
1534 for (int i = 0; i < ALL_REF_OFFSET_NUM; ++i) {
1535 int nb_row = row - all_ref_offset[i][0];
1536 int nb_col = col - all_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001537 int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001538 int nb_scan_idx = txb_info->scan_order->iscan[nb_coeff_idx];
1539 if (nb_scan_idx < txb_info->eob && nb_row >= 0 && nb_col >= 0 &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001540 nb_row < txb_info->height && nb_col < txb_info->width) {
Linfeng Zhang960e7002017-12-11 13:46:40 -08001541 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001542 const int coeff_ctx =
1543 get_nz_map_ctx(txb_info->levels, nb_coeff_idx, txb_info->bwl,
1544#if CONFIG_LV_MAP_MULTI
1545 txb_info->height, nb_scan_idx, is_eob,
1546#endif
1547 txb_info->tx_size, txb_info->tx_type);
Linfeng Zhang960e7002017-12-11 13:46:40 -08001548 const int cost = get_coeff_cost(nb_coeff, nb_scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +01001549#if CONFIG_LV_MAP_MULTI
Linfeng Zhang960e7002017-12-11 13:46:40 -08001550 is_eob,
Ola Hugosson13892102017-11-06 08:01:44 +01001551#endif
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001552 txb_info, txb_costs, coeff_ctx);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001553 if (cost_map)
1554 cost_map[nb_row - row + COST_MAP_OFFSET]
1555 [nb_col - col + COST_MAP_OFFSET] -= cost;
1556 org_cost += cost;
1557 }
1558 }
Linfeng Zhang1015a342017-10-24 16:20:41 -07001559 update_qcoeff(coeff_idx, get_lower_coeff(qc), txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001560 int new_cost = 0;
1561 for (int i = 0; i < ALL_REF_OFFSET_NUM; ++i) {
1562 int nb_row = row - all_ref_offset[i][0];
1563 int nb_col = col - all_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001564 int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001565 int nb_scan_idx = txb_info->scan_order->iscan[nb_coeff_idx];
1566 if (nb_scan_idx < txb_info->eob && nb_row >= 0 && nb_col >= 0 &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001567 nb_row < txb_info->height && nb_col < txb_info->width) {
Linfeng Zhang960e7002017-12-11 13:46:40 -08001568 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001569 const int coeff_ctx =
1570 get_nz_map_ctx(txb_info->levels, nb_coeff_idx, txb_info->bwl,
1571#if CONFIG_LV_MAP_MULTI
1572 txb_info->height, nb_scan_idx, is_eob,
1573#endif
1574 txb_info->tx_size, txb_info->tx_type);
Linfeng Zhang960e7002017-12-11 13:46:40 -08001575 const int cost = get_coeff_cost(nb_coeff, nb_scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +01001576#if CONFIG_LV_MAP_MULTI
Linfeng Zhang960e7002017-12-11 13:46:40 -08001577 is_eob,
Ola Hugosson13892102017-11-06 08:01:44 +01001578#endif
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001579 txb_info, txb_costs, coeff_ctx);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001580 if (cost_map)
1581 cost_map[nb_row - row + COST_MAP_OFFSET]
1582 [nb_col - col + COST_MAP_OFFSET] += cost;
1583 new_cost += cost;
1584 }
1585 }
Linfeng Zhang1015a342017-10-24 16:20:41 -07001586 update_qcoeff(coeff_idx, qc, txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001587 return new_cost - org_cost;
1588}
1589
1590static void test_level_down(int coeff_idx, const TxbCache *txb_cache,
Angie Chiang0b2795c2017-09-29 16:00:08 -07001591 const LV_MAP_COEFF_COST *txb_costs,
1592 TxbInfo *txb_info) {
Angie Chiang47e07072017-05-30 17:27:01 -07001593 int cost_map[COST_MAP_SIZE][COST_MAP_SIZE];
1594 int ref_cost_map[COST_MAP_SIZE][COST_MAP_SIZE];
1595 const int cost_diff =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001596 try_level_down(coeff_idx, txb_cache, txb_costs, txb_info, cost_map, 0);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001597 const int cost_diff_ref =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001598 try_level_down_ref(coeff_idx, txb_costs, txb_info, ref_cost_map);
Angie Chiang47e07072017-05-30 17:27:01 -07001599 if (cost_diff != cost_diff_ref) {
1600 printf("qc %d cost_diff %d cost_diff_ref %d\n", txb_info->qcoeff[coeff_idx],
1601 cost_diff, cost_diff_ref);
1602 for (int r = 0; r < COST_MAP_SIZE; ++r) {
1603 for (int c = 0; c < COST_MAP_SIZE; ++c) {
1604 printf("%d:%d ", cost_map[r][c], ref_cost_map[r][c]);
1605 }
1606 printf("\n");
1607 }
1608 }
1609}
1610#endif
1611
Angie Chiang488f9212017-05-30 12:46:26 -07001612// TODO(angiebird): make this static once it's called
Jingning Handfd72322017-08-09 14:04:12 -07001613int get_txb_cost(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs) {
Angie Chiang488f9212017-05-30 12:46:26 -07001614 int cost = 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001615 const int txb_skip_ctx = txb_info->txb_ctx->txb_skip_ctx;
1616 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang488f9212017-05-30 12:46:26 -07001617 if (txb_info->eob == 0) {
Jingning Handfd72322017-08-09 14:04:12 -07001618 cost = txb_costs->txb_skip_cost[txb_skip_ctx][1];
Angie Chiang488f9212017-05-30 12:46:26 -07001619 return cost;
1620 }
Jingning Handfd72322017-08-09 14:04:12 -07001621 cost = txb_costs->txb_skip_cost[txb_skip_ctx][0];
Angie Chiang488f9212017-05-30 12:46:26 -07001622 for (int c = 0; c < txb_info->eob; ++c) {
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001623 const int pos = scan[c];
1624 const tran_low_t qc = txb_info->qcoeff[pos];
1625 const int coeff_ctx =
1626 get_nz_map_ctx(txb_info->levels, pos, txb_info->bwl,
1627#if CONFIG_LV_MAP_MULTI
1628 txb_info->height, c, c == txb_info->eob - 1,
1629#endif
1630 txb_info->tx_size, txb_info->tx_type);
Linfeng Zhang960e7002017-12-11 13:46:40 -08001631 const int coeff_cost = get_coeff_cost(qc, c,
Ola Hugosson13892102017-11-06 08:01:44 +01001632#if CONFIG_LV_MAP_MULTI
Linfeng Zhang960e7002017-12-11 13:46:40 -08001633 c == txb_info->eob - 1,
Ola Hugosson13892102017-11-06 08:01:44 +01001634#endif
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001635 txb_info, txb_costs, coeff_ctx);
Angie Chiang488f9212017-05-30 12:46:26 -07001636 cost += coeff_cost;
1637 }
1638 return cost;
1639}
1640
Angie Chiang5e012fe2017-05-30 18:47:39 -07001641#if TEST_OPTIMIZE_TXB
Angie Chiang0b2795c2017-09-29 16:00:08 -07001642void test_try_change_eob(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang5e012fe2017-05-30 18:47:39 -07001643 TxbCache *txb_cache) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001644 const int eob = txb_info->eob;
1645 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001646 if (eob > 0) {
1647 int last_si = eob - 1;
1648 int last_ci = scan[last_si];
1649 int last_coeff = txb_info->qcoeff[last_ci];
1650 if (abs(last_coeff) == 1) {
1651 int new_eob;
1652 int cost_diff =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001653 try_change_eob(&new_eob, last_ci, txb_cache, txb_costs, txb_info, 0);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001654 int org_eob = txb_info->eob;
Angie Chiang0b2795c2017-09-29 16:00:08 -07001655 int cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001656
Linfeng Zhang1015a342017-10-24 16:20:41 -07001657 update_qcoeff(last_ci, get_lower_coeff(last_coeff), txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001658 set_eob(txb_info, new_eob);
Angie Chiang0b2795c2017-09-29 16:00:08 -07001659 int new_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001660 set_eob(txb_info, org_eob);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001661 update_qcoeff(last_ci, last_coeff, txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001662
1663 int ref_cost_diff = -cost + new_cost;
1664 if (cost_diff != ref_cost_diff)
1665 printf("org_eob %d new_eob %d cost_diff %d ref_cost_diff %d\n", org_eob,
1666 new_eob, cost_diff, ref_cost_diff);
1667 }
1668 }
1669}
1670#endif
1671
Angie Chiang47e07072017-05-30 17:27:01 -07001672void try_level_down_facade(LevelDownStats *stats, int scan_idx,
Jingning Handfd72322017-08-09 14:04:12 -07001673 const TxbCache *txb_cache,
1674 const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang25645b72017-09-24 14:28:49 -07001675 TxbInfo *txb_info, int fast_mode) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001676 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang47e07072017-05-30 17:27:01 -07001677 const int coeff_idx = scan[scan_idx];
1678 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1679 stats->new_eob = -1;
1680 stats->update = 0;
1681 if (qc == 0) {
1682 return;
1683 }
1684
1685 const tran_low_t tqc = txb_info->tcoeff[coeff_idx];
1686 const int dqv = txb_info->dequant[coeff_idx != 0];
1687
1688 const tran_low_t dqc = qcoeff_to_dqcoeff(qc, dqv, txb_info->shift);
Jingning Han641c1e52017-10-13 09:42:49 -07001689
1690 if (scan_idx != txb_info->eob - 1)
1691 if (abs(dqc) < abs(tqc)) return;
1692
Angie Chiang47e07072017-05-30 17:27:01 -07001693 const int64_t dqc_dist = get_coeff_dist(tqc, dqc, txb_info->shift);
1694
1695 stats->low_qc = get_lower_coeff(qc);
1696 stats->low_dqc = qcoeff_to_dqcoeff(stats->low_qc, dqv, txb_info->shift);
1697 const int64_t low_dqc_dist =
1698 get_coeff_dist(tqc, stats->low_dqc, txb_info->shift);
1699
1700 stats->dist_diff = -dqc_dist + low_dqc_dist;
1701 stats->cost_diff = 0;
1702 stats->new_eob = txb_info->eob;
1703 if (scan_idx == txb_info->eob - 1 && abs(qc) == 1) {
1704 stats->cost_diff = try_change_eob(&stats->new_eob, coeff_idx, txb_cache,
Angie Chiang25645b72017-09-24 14:28:49 -07001705 txb_costs, txb_info, fast_mode);
Angie Chiang47e07072017-05-30 17:27:01 -07001706 } else {
Angie Chiang25645b72017-09-24 14:28:49 -07001707 stats->cost_diff = try_level_down(coeff_idx, txb_cache, txb_costs, txb_info,
1708 NULL, fast_mode);
Angie Chiang47e07072017-05-30 17:27:01 -07001709#if TEST_OPTIMIZE_TXB
Angie Chiang0b2795c2017-09-29 16:00:08 -07001710 test_level_down(coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chiang47e07072017-05-30 17:27:01 -07001711#endif
1712 }
Urvang Joshi70006e42017-06-14 16:08:55 -07001713 stats->rd_diff = RDCOST(txb_info->rdmult, stats->cost_diff, stats->dist_diff);
Angie Chiang47e07072017-05-30 17:27:01 -07001714 if (stats->rd_diff < 0) stats->update = 1;
1715 return;
1716}
Angie Chiang07c57f32017-05-30 18:18:33 -07001717
Jingning Han3422ac12017-10-25 20:37:53 -07001718#if 1
Dake Hea47cd6c2017-10-13 18:09:58 -07001719static int optimize_txb(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
1720 TxbCache *txb_cache, int dry_run, int fast_mode) {
1721 (void)fast_mode;
1722 (void)txb_cache;
1723 int update = 0;
Dake He59881772017-11-24 07:00:02 -08001724 // return update; // TODO(DKHE): training only.
Dake Hea47cd6c2017-10-13 18:09:58 -07001725 if (txb_info->eob == 0) return update;
Urvang Joshi80893152017-10-27 11:51:14 -07001726 const int max_eob = av1_get_max_eob(txb_info->tx_size);
Dake Hea47cd6c2017-10-13 18:09:58 -07001727
1728#if TEST_OPTIMIZE_TXB
1729 int64_t sse;
1730 int64_t org_dist =
1731 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1732 (1 << (2 * txb_info->shift));
1733 int org_cost = get_txb_cost(txb_info, txb_probs);
1734#endif
1735
1736 tran_low_t *org_qcoeff = txb_info->qcoeff;
1737 tran_low_t *org_dqcoeff = txb_info->dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001738 uint8_t *const org_levels = txb_info->levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001739
1740 tran_low_t tmp_qcoeff[MAX_TX_SQUARE];
1741 tran_low_t tmp_dqcoeff[MAX_TX_SQUARE];
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001742 uint8_t tmp_levels_buf[TX_PAD_2D];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001743 uint8_t *const tmp_levels = set_levels(tmp_levels_buf, txb_info->width);
Dake Hea47cd6c2017-10-13 18:09:58 -07001744 const int org_eob = txb_info->eob;
1745 if (dry_run) {
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001746 const int stride = txb_info->width + TX_PAD_HOR;
1747 const int levels_size =
1748
1749 (stride * (txb_info->height + TX_PAD_VER) + TX_PAD_END);
Dake Hea47cd6c2017-10-13 18:09:58 -07001750 memcpy(tmp_qcoeff, org_qcoeff, sizeof(org_qcoeff[0]) * max_eob);
1751 memcpy(tmp_dqcoeff, org_dqcoeff, sizeof(org_dqcoeff[0]) * max_eob);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001752 memcpy(tmp_levels, org_levels - TX_PAD_TOP * stride,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001753 sizeof(org_levels[0]) * levels_size);
Dake Hea47cd6c2017-10-13 18:09:58 -07001754 txb_info->qcoeff = tmp_qcoeff;
1755 txb_info->dqcoeff = tmp_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001756 txb_info->levels = tmp_levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001757 }
1758
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001759 const int16_t *const scan = txb_info->scan_order->scan;
Dake Hea47cd6c2017-10-13 18:09:58 -07001760
1761 // forward optimize the nz_map`
1762 const int init_eob = txb_info->eob;
1763 const int seg_eob = txb_info->seg_eob;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001764 const int eob_cost =
1765 get_eob_cost(init_eob, seg_eob, txb_costs, txb_info->tx_type);
Dake Hea47cd6c2017-10-13 18:09:58 -07001766
1767 // backward optimize the level-k map
1768 int64_t accu_rate = eob_cost;
1769 int64_t accu_dist = 0;
1770 int64_t prev_eob_rd_cost = INT64_MAX;
1771 int64_t cur_eob_rd_cost = 0;
1772
1773 for (int si = init_eob - 1; si >= 0; --si) {
1774 const int coeff_idx = scan[si];
1775 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1776
1777 LevelDownStats stats;
Linfeng Zhang960e7002017-12-11 13:46:40 -08001778 get_dist_cost_stats(&stats, si,
Ola Hugosson13892102017-11-06 08:01:44 +01001779#if CONFIG_LV_MAP_MULTI
Linfeng Zhang960e7002017-12-11 13:46:40 -08001780 si == init_eob - 1,
Ola Hugosson13892102017-11-06 08:01:44 +01001781#endif
Linfeng Zhang960e7002017-12-11 13:46:40 -08001782 txb_costs, txb_info);
Dake Hea47cd6c2017-10-13 18:09:58 -07001783
1784 if (qc == 0) {
1785 accu_rate += stats.rate;
1786 } else {
1787 // check if it is better to make this the last significant coefficient
Jingning Han35deaa72017-10-26 15:36:30 -07001788 int cur_eob_rate =
1789 get_eob_cost(si + 1, seg_eob, txb_costs, txb_info->tx_type);
Dake Hea47cd6c2017-10-13 18:09:58 -07001790 cur_eob_rd_cost = RDCOST(txb_info->rdmult, cur_eob_rate, 0);
1791 prev_eob_rd_cost =
1792 RDCOST(txb_info->rdmult, accu_rate + stats.nz_rate, accu_dist);
1793 if (cur_eob_rd_cost <= prev_eob_rd_cost) {
1794 update = 1;
1795 for (int j = si + 1; j < txb_info->eob; j++) {
1796 const int coeff_pos_j = scan[j];
1797 update_coeff(coeff_pos_j, 0, txb_info);
1798 }
1799 txb_info->eob = si + 1;
1800
Ola Hugosson13892102017-11-06 08:01:44 +01001801 // rerun cost calculation due to change of eob
Dake Hea47cd6c2017-10-13 18:09:58 -07001802 accu_rate = cur_eob_rate;
1803 accu_dist = 0;
Linfeng Zhang960e7002017-12-11 13:46:40 -08001804 get_dist_cost_stats(&stats, si,
Ola Hugosson13892102017-11-06 08:01:44 +01001805#if CONFIG_LV_MAP_MULTI
Linfeng Zhang960e7002017-12-11 13:46:40 -08001806 1,
Ola Hugosson13892102017-11-06 08:01:44 +01001807#endif
Linfeng Zhang960e7002017-12-11 13:46:40 -08001808 txb_costs, txb_info);
Dake Hea47cd6c2017-10-13 18:09:58 -07001809 }
1810
1811 int bUpdCoeff = 0;
1812 if (stats.rd_low < stats.rd) {
1813 if ((stats.low_qc != 0) || (si < txb_info->eob - 1)) {
1814 bUpdCoeff = 1;
1815 update = 1;
1816 }
1817 }
1818
1819 if (bUpdCoeff) {
1820 update_coeff(coeff_idx, stats.low_qc, txb_info);
1821 accu_rate += stats.rate_low;
1822 accu_dist += stats.dist_low;
1823 } else {
1824 accu_rate += stats.rate;
1825 accu_dist += stats.dist;
1826 }
1827 }
1828 } // for (si)
1829 int non_zero_blk_rate =
1830 txb_costs->txb_skip_cost[txb_info->txb_ctx->txb_skip_ctx][0];
1831 prev_eob_rd_cost =
1832 RDCOST(txb_info->rdmult, accu_rate + non_zero_blk_rate, accu_dist);
1833
1834 int zero_blk_rate =
1835 txb_costs->txb_skip_cost[txb_info->txb_ctx->txb_skip_ctx][1];
1836 int64_t zero_blk_rd_cost = RDCOST(txb_info->rdmult, zero_blk_rate, 0);
1837 if (zero_blk_rd_cost <= prev_eob_rd_cost) {
1838 update = 1;
1839 for (int j = 0; j < txb_info->eob; j++) {
1840 const int coeff_pos_j = scan[j];
1841 update_coeff(coeff_pos_j, 0, txb_info);
1842 }
1843 txb_info->eob = 0;
1844 }
1845
1846#if TEST_OPTIMIZE_TXB
1847 int cost_diff = 0;
1848 int64_t dist_diff = 0;
1849 int64_t rd_diff = 0;
1850 int64_t new_dist =
1851 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1852 (1 << (2 * txb_info->shift));
1853 int new_cost = get_txb_cost(txb_info, txb_probs);
1854 int64_t ref_dist_diff = new_dist - org_dist;
1855 int ref_cost_diff = new_cost - org_cost;
1856 if (cost_diff != ref_cost_diff || dist_diff != ref_dist_diff)
1857 printf(
1858 "overall rd_diff %ld\ncost_diff %d ref_cost_diff%d\ndist_diff %ld "
1859 "ref_dist_diff %ld\neob %d new_eob %d\n\n",
1860 rd_diff, cost_diff, ref_cost_diff, dist_diff, ref_dist_diff, org_eob,
1861 txb_info->eob);
1862#endif
1863 if (dry_run) {
1864 txb_info->qcoeff = org_qcoeff;
1865 txb_info->dqcoeff = org_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001866 txb_info->levels = org_levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001867 set_eob(txb_info, org_eob);
1868 }
1869 return update;
1870}
1871
1872#else
Jingning Handfd72322017-08-09 14:04:12 -07001873static int optimize_txb(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang25645b72017-09-24 14:28:49 -07001874 TxbCache *txb_cache, int dry_run, int fast_mode) {
Angie Chiang07c57f32017-05-30 18:18:33 -07001875 int update = 0;
1876 if (txb_info->eob == 0) return update;
1877 int cost_diff = 0;
1878 int64_t dist_diff = 0;
1879 int64_t rd_diff = 0;
Urvang Joshi80893152017-10-27 11:51:14 -07001880 const int max_eob = av1_get_max_eob(txb_info->tx_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07001881
1882#if TEST_OPTIMIZE_TXB
1883 int64_t sse;
1884 int64_t org_dist =
1885 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1886 (1 << (2 * txb_info->shift));
Angie Chiang0b2795c2017-09-29 16:00:08 -07001887 int org_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang07c57f32017-05-30 18:18:33 -07001888#endif
1889
1890 tran_low_t *org_qcoeff = txb_info->qcoeff;
1891 tran_low_t *org_dqcoeff = txb_info->dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001892 uint8_t *const org_levels = txb_info->levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07001893
1894 tran_low_t tmp_qcoeff[MAX_TX_SQUARE];
1895 tran_low_t tmp_dqcoeff[MAX_TX_SQUARE];
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001896 uint8_t tmp_levels_buf[TX_PAD_2D];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001897 uint8_t *const tmp_levels = set_levels(tmp_levels_buf, txb_info->width);
Angie Chiang07c57f32017-05-30 18:18:33 -07001898 const int org_eob = txb_info->eob;
1899 if (dry_run) {
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001900 const int stride = txb_info->width + TX_PAD_HOR;
1901 const int levels_size =
1902
1903 (stride * (txb_info->height + TX_PAD_VER) + TX_PAD_END);
Angie Chiang07c57f32017-05-30 18:18:33 -07001904 memcpy(tmp_qcoeff, org_qcoeff, sizeof(org_qcoeff[0]) * max_eob);
1905 memcpy(tmp_dqcoeff, org_dqcoeff, sizeof(org_dqcoeff[0]) * max_eob);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001906 memcpy(tmp_levels, org_levels - TX_PAD_TOP * stride,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001907 sizeof(org_levels[0]) * levels_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07001908 txb_info->qcoeff = tmp_qcoeff;
1909 txb_info->dqcoeff = tmp_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001910 txb_info->levels = tmp_levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07001911 }
1912
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001913 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang07c57f32017-05-30 18:18:33 -07001914
1915 // forward optimize the nz_map
1916 const int cur_eob = txb_info->eob;
1917 for (int si = 0; si < cur_eob; ++si) {
1918 const int coeff_idx = scan[si];
1919 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1920 if (abs(qc) == 1) {
1921 LevelDownStats stats;
Angie Chiang25645b72017-09-24 14:28:49 -07001922 try_level_down_facade(&stats, si, txb_cache, txb_costs, txb_info,
1923 fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07001924 if (stats.update) {
1925 update = 1;
1926 cost_diff += stats.cost_diff;
1927 dist_diff += stats.dist_diff;
1928 rd_diff += stats.rd_diff;
1929 update_level_down(coeff_idx, txb_cache, txb_info);
1930 set_eob(txb_info, stats.new_eob);
1931 }
1932 }
1933 }
1934
1935 // backward optimize the level-k map
Angie Chiang530b3042017-08-17 15:08:58 -07001936 int eob_fix = 0;
Angie Chiang07c57f32017-05-30 18:18:33 -07001937 for (int si = txb_info->eob - 1; si >= 0; --si) {
Angie Chiang530b3042017-08-17 15:08:58 -07001938 const int coeff_idx = scan[si];
1939 if (eob_fix == 1 && txb_info->qcoeff[coeff_idx] == 1) {
1940 // when eob is fixed, there is not need to optimize again when
1941 // abs(qc) == 1
1942 continue;
1943 }
Angie Chiang07c57f32017-05-30 18:18:33 -07001944 LevelDownStats stats;
Angie Chiang25645b72017-09-24 14:28:49 -07001945 try_level_down_facade(&stats, si, txb_cache, txb_costs, txb_info,
1946 fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07001947 if (stats.update) {
1948#if TEST_OPTIMIZE_TXB
1949// printf("si %d low_qc %d cost_diff %d dist_diff %ld rd_diff %ld eob %d new_eob
1950// %d\n", si, stats.low_qc, stats.cost_diff, stats.dist_diff, stats.rd_diff,
1951// txb_info->eob, stats.new_eob);
1952#endif
1953 update = 1;
1954 cost_diff += stats.cost_diff;
1955 dist_diff += stats.dist_diff;
1956 rd_diff += stats.rd_diff;
1957 update_level_down(coeff_idx, txb_cache, txb_info);
1958 set_eob(txb_info, stats.new_eob);
1959 }
Angie Chiang530b3042017-08-17 15:08:58 -07001960 if (eob_fix == 0 && txb_info->qcoeff[coeff_idx] != 0) eob_fix = 1;
Angie Chiang07c57f32017-05-30 18:18:33 -07001961 if (si > txb_info->eob) si = txb_info->eob;
1962 }
1963#if TEST_OPTIMIZE_TXB
1964 int64_t new_dist =
1965 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1966 (1 << (2 * txb_info->shift));
Angie Chiang0b2795c2017-09-29 16:00:08 -07001967 int new_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang07c57f32017-05-30 18:18:33 -07001968 int64_t ref_dist_diff = new_dist - org_dist;
1969 int ref_cost_diff = new_cost - org_cost;
1970 if (cost_diff != ref_cost_diff || dist_diff != ref_dist_diff)
1971 printf(
1972 "overall rd_diff %ld\ncost_diff %d ref_cost_diff%d\ndist_diff %ld "
1973 "ref_dist_diff %ld\neob %d new_eob %d\n\n",
1974 rd_diff, cost_diff, ref_cost_diff, dist_diff, ref_dist_diff, org_eob,
1975 txb_info->eob);
1976#endif
1977 if (dry_run) {
1978 txb_info->qcoeff = org_qcoeff;
1979 txb_info->dqcoeff = org_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001980 txb_info->levels = org_levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07001981 set_eob(txb_info, org_eob);
1982 }
1983 return update;
1984}
Dake Hea47cd6c2017-10-13 18:09:58 -07001985#endif
Angie Chiang07c57f32017-05-30 18:18:33 -07001986
1987// These numbers are empirically obtained.
1988static const int plane_rd_mult[REF_TYPES][PLANE_TYPES] = {
Angie Chiang07c57f32017-05-30 18:18:33 -07001989 { 17, 13 }, { 16, 10 },
Angie Chiang07c57f32017-05-30 18:18:33 -07001990};
1991
Jingning Han7eab9ff2017-07-06 10:12:54 -07001992int av1_optimize_txb(const AV1_COMMON *cm, MACROBLOCK *x, int plane,
1993 int blk_row, int blk_col, int block, TX_SIZE tx_size,
Angie Chiang25645b72017-09-24 14:28:49 -07001994 TXB_CTX *txb_ctx, int fast_mode) {
Angie Chiang07c57f32017-05-30 18:18:33 -07001995 MACROBLOCKD *const xd = &x->e_mbd;
1996 const PLANE_TYPE plane_type = get_plane_type(plane);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -08001997 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Jingning Han19b5c8f2017-07-06 15:10:12 -07001998 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -05001999 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07002000 const MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
2001 const struct macroblock_plane *p = &x->plane[plane];
2002 struct macroblockd_plane *pd = &xd->plane[plane];
2003 const int eob = p->eobs[block];
2004 tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2005 tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
2006 const tran_low_t *tcoeff = BLOCK_OFFSET(p->coeff, block);
Monty Montgomery125c0fc2017-10-26 00:44:35 -04002007 const int16_t *dequant = p->dequant_QTX;
Urvang Joshi80893152017-10-27 11:51:14 -07002008 const int seg_eob = av1_get_max_eob(tx_size);
Angie Chianga9ba58e2017-12-01 19:22:43 -08002009 const int bwl = get_txb_bwl(tx_size);
2010 const int width = get_txb_wide(tx_size);
2011 const int height = get_txb_high(tx_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07002012 const int is_inter = is_inter_block(mbmi);
Angie Chiangbd99b382017-06-20 15:11:16 -07002013 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Jingning Handfd72322017-08-09 14:04:12 -07002014 const LV_MAP_COEFF_COST txb_costs = x->coeff_costs[txs_ctx][plane_type];
Angie Chiang07c57f32017-05-30 18:18:33 -07002015
2016 const int shift = av1_get_tx_scale(tx_size);
2017 const int64_t rdmult =
Jingning Hanb433f4c2017-11-17 15:43:59 -08002018 ((x->rdmult * plane_rd_mult[is_inter][plane_type] << (2 * (xd->bd - 8))) +
2019 2) >>
2020 2;
Linfeng Zhang679d81e2017-10-31 15:27:42 -07002021 uint8_t levels_buf[TX_PAD_2D];
2022 uint8_t *const levels = set_levels(levels_buf, width);
Angie Chiang07c57f32017-05-30 18:18:33 -07002023
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002024 assert(width == (1 << bwl));
Linfeng Zhang1015a342017-10-24 16:20:41 -07002025 TxbInfo txb_info = {
2026 qcoeff, levels, dqcoeff, tcoeff, dequant, shift,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002027 tx_size, txs_ctx, tx_type, bwl, width, height,
Linfeng Zhang1015a342017-10-24 16:20:41 -07002028 eob, seg_eob, scan_order, txb_ctx, rdmult, &cm->coeff_ctx_table
2029 };
2030
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002031 av1_txb_init_levels(qcoeff, width, height, levels);
Urvang Joshi70006e42017-06-14 16:08:55 -07002032
Angie Chiang93af45f2017-10-23 18:19:59 -07002033 const int update = optimize_txb(&txb_info, &txb_costs, NULL, 0, fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07002034
Jingning Hand7e99112017-12-13 09:47:45 -08002035 if (update) {
2036 p->eobs[block] = txb_info.eob;
2037 p->txb_entropy_ctx[block] =
2038 av1_get_txb_entropy_context(qcoeff, scan_order, txb_info.eob);
2039 }
Angie Chiang07c57f32017-05-30 18:18:33 -07002040 return txb_info.eob;
2041}
Jingning Hand7e99112017-12-13 09:47:45 -08002042
Angie Chiang74e23072017-03-24 14:54:23 -07002043int av1_get_txb_entropy_context(const tran_low_t *qcoeff,
2044 const SCAN_ORDER *scan_order, int eob) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002045 const int16_t *const scan = scan_order->scan;
Angie Chiang74e23072017-03-24 14:54:23 -07002046 int cul_level = 0;
2047 int c;
Jingning Han339cf932017-09-18 10:17:02 -07002048
2049 if (eob == 0) return 0;
Angie Chiang74e23072017-03-24 14:54:23 -07002050 for (c = 0; c < eob; ++c) {
2051 cul_level += abs(qcoeff[scan[c]]);
2052 }
2053
2054 cul_level = AOMMIN(COEFF_CONTEXT_MASK, cul_level);
2055 set_dc_sign(&cul_level, qcoeff[0]);
2056
2057 return cul_level;
2058}
2059
Jingning Han4fe5f672017-05-19 15:46:07 -07002060void av1_update_txb_context_b(int plane, int block, int blk_row, int blk_col,
2061 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
2062 void *arg) {
Jingning Han6171ae72017-05-18 20:15:06 -07002063 struct tokenize_b_args *const args = arg;
Angie Chiang36d616b2017-03-22 13:58:36 -07002064 const AV1_COMP *cpi = args->cpi;
2065 const AV1_COMMON *cm = &cpi->common;
Angie Chiang0397eda2017-03-15 16:57:14 -07002066 ThreadData *const td = args->td;
2067 MACROBLOCK *const x = &td->mb;
2068 MACROBLOCKD *const xd = &x->e_mbd;
Angie Chiang36d616b2017-03-22 13:58:36 -07002069 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiang0397eda2017-03-15 16:57:14 -07002070 struct macroblock_plane *p = &x->plane[plane];
2071 struct macroblockd_plane *pd = &xd->plane[plane];
Angie Chiang36d616b2017-03-22 13:58:36 -07002072 const uint16_t eob = p->eobs[block];
2073 const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2074 const PLANE_TYPE plane_type = pd->plane_type;
Jingning Han19b5c8f2017-07-06 15:10:12 -07002075 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002076 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07002077 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Angie Chiang0397eda2017-03-15 16:57:14 -07002078 (void)plane_bsize;
Angie Chiang36d616b2017-03-22 13:58:36 -07002079
Angie Chiang74e23072017-03-24 14:54:23 -07002080 int cul_level = av1_get_txb_entropy_context(qcoeff, scan_order, eob);
Angie Chiang36d616b2017-03-22 13:58:36 -07002081 av1_set_contexts(xd, pd, plane, tx_size, cul_level, blk_col, blk_row);
Angie Chiang0397eda2017-03-15 16:57:14 -07002082}
2083
Jingning Han4fe5f672017-05-19 15:46:07 -07002084void av1_update_and_record_txb_context(int plane, int block, int blk_row,
2085 int blk_col, BLOCK_SIZE plane_bsize,
2086 TX_SIZE tx_size, void *arg) {
Jingning Han6171ae72017-05-18 20:15:06 -07002087 struct tokenize_b_args *const args = arg;
Angie Chiang0397eda2017-03-15 16:57:14 -07002088 const AV1_COMP *cpi = args->cpi;
2089 const AV1_COMMON *cm = &cpi->common;
2090 ThreadData *const td = args->td;
2091 MACROBLOCK *const x = &td->mb;
2092 MACROBLOCKD *const xd = &x->e_mbd;
2093 struct macroblock_plane *p = &x->plane[plane];
2094 struct macroblockd_plane *pd = &xd->plane[plane];
2095 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Linfeng Zhang848f7bc2017-10-31 15:26:07 -07002096 int eob = p->eobs[block], update_eob = -1;
Angie Chiang0397eda2017-03-15 16:57:14 -07002097 const PLANE_TYPE plane_type = pd->plane_type;
2098 const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2099 tran_low_t *tcoeff = BLOCK_OFFSET(x->mbmi_ext->tcoeff[plane], block);
2100 const int segment_id = mbmi->segment_id;
Jingning Han19b5c8f2017-07-06 15:10:12 -07002101 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002102 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07002103 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002104 const int16_t *const scan = scan_order->scan;
hui suc0cf71d2017-07-20 16:38:50 -07002105 const int seg_eob = av1_get_tx_eob(&cpi->common.seg, segment_id, tx_size);
Linfeng Zhang1015a342017-10-24 16:20:41 -07002106 int c;
Angie Chiang85901562017-03-17 12:03:27 -07002107 TXB_CTX txb_ctx;
2108 get_txb_ctx(plane_bsize, tx_size, plane, pd->above_context + blk_col,
2109 pd->left_context + blk_row, &txb_ctx);
Angie Chianga9ba58e2017-12-01 19:22:43 -08002110 const int bwl = get_txb_bwl(tx_size);
2111 const int width = get_txb_wide(tx_size);
2112 const int height = get_txb_high(tx_size);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07002113 uint8_t levels_buf[TX_PAD_2D];
2114 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -08002115 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Yunqing Wang0e141b52017-11-02 15:08:58 -07002116 const uint8_t allow_update_cdf = args->allow_update_cdf;
Angie Chiang0397eda2017-03-15 16:57:14 -07002117
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -08002118 TX_SIZE txsize_ctx = get_txsize_entropy_ctx(tx_size);
Jingning Han8f661602017-08-19 08:16:50 -07002119 FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
Jingning Han48be0e12017-06-13 12:12:01 -07002120
Angie Chiang0397eda2017-03-15 16:57:14 -07002121 memcpy(tcoeff, qcoeff, sizeof(*tcoeff) * seg_eob);
2122
Jingning Han48be0e12017-06-13 12:12:01 -07002123 ++td->counts->txb_skip[txsize_ctx][txb_ctx.txb_skip_ctx][eob == 0];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002124 if (allow_update_cdf)
2125 update_bin(ec_ctx->txb_skip_cdf[txsize_ctx][txb_ctx.txb_skip_ctx], eob == 0,
2126 2);
Angie Chiang85901562017-03-17 12:03:27 -07002127 x->mbmi_ext->txb_skip_ctx[plane][block] = txb_ctx.txb_skip_ctx;
Angie Chiang0397eda2017-03-15 16:57:14 -07002128
2129 x->mbmi_ext->eobs[plane][block] = eob;
2130
2131 if (eob == 0) {
2132 av1_set_contexts(xd, pd, plane, tx_size, 0, blk_col, blk_row);
2133 return;
2134 }
2135
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002136 av1_txb_init_levels(tcoeff, width, height, levels);
Linfeng Zhangce065ca2017-10-17 16:49:30 -07002137
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002138#if CONFIG_TXK_SEL
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002139 av1_update_tx_type_count(cm, xd, blk_row, blk_col, plane, mbmi->sb_type,
2140 get_min_tx_size(tx_size), td->counts,
Yunqing Wang0e141b52017-11-02 15:08:58 -07002141 allow_update_cdf);
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002142#endif
Angie Chiang0397eda2017-03-15 16:57:14 -07002143
Dake Hea47cd6c2017-10-13 18:09:58 -07002144 unsigned int(*nz_map_count)[SIG_COEF_CONTEXTS][2] =
2145 &(td->counts->nz_map[txsize_ctx][plane_type]);
Jingning Han35deaa72017-10-26 15:36:30 -07002146 av1_update_eob_context(eob, seg_eob, tx_size, tx_type, plane_type, ec_ctx,
Yunqing Wang0e141b52017-11-02 15:08:58 -07002147 td->counts, allow_update_cdf);
Dake He03a32922017-10-31 08:06:45 -07002148 int coeff_ctx = 0;
2149 update_eob = eob - 1;
Dake Hea47cd6c2017-10-13 18:09:58 -07002150 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002151 const int pos = scan[c];
2152 const tran_low_t v = qcoeff[pos];
2153 const int is_nz = (v != 0);
Dake He03a32922017-10-31 08:06:45 -07002154
Ola Hugosson13892102017-11-06 08:01:44 +01002155#if CONFIG_LV_MAP_MULTI
2156 (void)is_nz;
2157 (void)nz_map_count;
Linfeng Zhangf6d730a2017-12-06 14:49:44 -08002158 coeff_ctx = get_nz_map_ctx(levels, pos, bwl, height, c, c == eob - 1,
2159 tx_size, tx_type);
Dake He3fe369c2017-11-16 17:56:44 -08002160#if USE_BASE_EOB_ALPHABET
2161 if (c == eob - 1) {
2162 update_cdf(ec_ctx->coeff_base_eob_cdf[txsize_ctx][plane_type]
2163 [coeff_ctx - SIG_COEF_CONTEXTS +
2164 SIG_COEF_CONTEXTS_EOB],
2165 AOMMIN(abs(v), 3) - 1, 3);
2166 } else {
2167 update_cdf(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][coeff_ctx],
2168 AOMMIN(abs(v), 3), 4);
2169 }
Dake He59881772017-11-24 07:00:02 -08002170 {
2171 if (c < eob - 1) {
2172 ++(*nz_map_count)[coeff_ctx][is_nz];
2173 }
2174 if (is_nz) {
2175 for (int k = 0; k < NUM_BASE_LEVELS; ++k) {
2176 int is_k = (abs(v) > (k + 1));
2177 ++td->counts->coeff_base[txsize_ctx][plane_type][k][coeff_ctx][is_k];
2178 if (is_k == 0) break;
2179 }
2180 }
2181 }
2182
Dake He3fe369c2017-11-16 17:56:44 -08002183#else
Ola Hugosson13892102017-11-06 08:01:44 +01002184 update_cdf(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][coeff_ctx],
2185 AOMMIN(abs(v), 3), 4);
Dake He3fe369c2017-11-16 17:56:44 -08002186#endif
Linfeng Zhang1757fb62017-12-11 10:47:59 -08002187#else
Linfeng Zhangf6d730a2017-12-06 14:49:44 -08002188 coeff_ctx = get_nz_map_ctx(levels, pos, bwl, tx_size, tx_type);
Ola Hugosson13892102017-11-06 08:01:44 +01002189
Dake He03a32922017-10-31 08:06:45 -07002190 if (c < eob - 1) {
2191 ++(*nz_map_count)[coeff_ctx][is_nz];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002192 if (allow_update_cdf)
2193 update_cdf(ec_ctx->nz_map_cdf[txsize_ctx][plane_type][coeff_ctx], is_nz,
2194 2);
Dake He03a32922017-10-31 08:06:45 -07002195 }
2196
2197 if (is_nz) {
2198 int k;
2199 for (k = 0; k < NUM_BASE_LEVELS; ++k) {
2200 int ctx = coeff_ctx;
2201 int is_k = (abs(v) > (k + 1));
2202
2203 ++td->counts->coeff_base[txsize_ctx][plane_type][k][ctx][is_k];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002204 if (allow_update_cdf)
2205 update_bin(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][k][ctx],
2206 is_k, 2);
Dake He03a32922017-10-31 08:06:45 -07002207 if (is_k == 0) break;
2208 }
2209 }
Dake He03a32922017-10-31 08:06:45 -07002210#endif
Dake Hea47cd6c2017-10-13 18:09:58 -07002211 }
Dake Hea47cd6c2017-10-13 18:09:58 -07002212
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002213 // Update the context needed to code the DC sign (if applicable)
2214 const int sign = (tcoeff[0] < 0) ? 1 : 0;
2215 if (tcoeff[0] != 0) {
Dake He43edb762017-10-26 10:29:46 -07002216 int dc_sign_ctx = txb_ctx.dc_sign_ctx;
2217
2218 ++td->counts->dc_sign[plane_type][dc_sign_ctx][sign];
2219#if LV_MAP_PROB
Yunqing Wang0e141b52017-11-02 15:08:58 -07002220 if (allow_update_cdf)
2221 update_bin(ec_ctx->dc_sign_cdf[plane_type][dc_sign_ctx], sign, 2);
Dake He43edb762017-10-26 10:29:46 -07002222#endif
2223 x->mbmi_ext->dc_sign_ctx[plane][block] = dc_sign_ctx;
2224 }
2225
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002226 if (update_eob >= 0) {
Dake He7d01ab52017-11-24 17:53:28 -08002227#if !CONFIG_LV_MAP_MULTI
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002228 av1_get_br_level_counts(levels, width, height, level_counts);
Dake He7d01ab52017-11-24 17:53:28 -08002229#endif
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002230 for (c = update_eob; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002231 const int pos = scan[c];
2232 const tran_low_t level = abs(tcoeff[pos]);
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002233 int idx;
2234 int ctx;
Angie Chiang0397eda2017-03-15 16:57:14 -07002235
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002236 if (level <= NUM_BASE_LEVELS) continue;
Angie Chiang0397eda2017-03-15 16:57:14 -07002237
Dake He7d01ab52017-11-24 17:53:28 -08002238// level is above 1.
2239#if !CONFIG_LV_MAP_MULTI
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002240 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -08002241#endif
Jingning Han87b01b52017-08-31 12:07:20 -07002242
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002243 const int base_range = level - 1 - NUM_BASE_LEVELS;
Ola Hugossone72a2092017-11-12 09:11:53 +01002244#if CONFIG_LV_MAP_MULTI
Dake He7d01ab52017-11-24 17:53:28 -08002245#if USE_CAUSAL_BR_CTX
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002246 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos], tx_type);
Dake He7d01ab52017-11-24 17:53:28 -08002247#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002248 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -08002249#endif
Ola Hugossone72a2092017-11-12 09:11:53 +01002250 for (idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002251 const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
Dake He7d01ab52017-11-24 17:53:28 -08002252 update_cdf(
2253 ec_ctx->coeff_br_cdf[AOMMIN(txsize_ctx, TX_16X16)][plane_type][ctx],
2254 k, BR_CDF_SIZE);
2255 for (int lps = 0; lps < BR_CDF_SIZE - 1; lps++) {
2256 ++td->counts->coeff_lps[AOMMIN(txsize_ctx, TX_16X16)][plane_type][lps]
2257 [ctx][lps == k];
Dake He59881772017-11-24 07:00:02 -08002258 if (lps == k) break;
2259 }
2260
Ola Hugossone72a2092017-11-12 09:11:53 +01002261 if (k < BR_CDF_SIZE - 1) break;
2262 }
2263#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002264 const int br_set_idx = base_range < COEFF_BASE_RANGE
2265 ? coeff_to_br_index[base_range]
2266 : BASE_RANGE_SETS;
Jingning Han87b01b52017-08-31 12:07:20 -07002267
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002268 for (idx = 0; idx < BASE_RANGE_SETS; ++idx) {
2269 if (idx == br_set_idx) {
2270 int br_base = br_index_to_coeff[br_set_idx];
2271 int br_offset = base_range - br_base;
2272 ++td->counts->coeff_br[txsize_ctx][plane_type][idx][ctx][1];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002273 if (allow_update_cdf)
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002274 update_bin(ec_ctx->coeff_br_cdf[txsize_ctx][plane_type][idx][ctx],
2275 1, 2);
2276 int extra_bits = (1 << br_extra_bits[idx]) - 1;
2277 for (int tok = 0; tok < extra_bits; ++tok) {
2278 if (br_offset == tok) {
2279 ++td->counts->coeff_lps[txsize_ctx][plane_type][ctx][1];
2280 if (allow_update_cdf)
2281 update_bin(ec_ctx->coeff_lps_cdf[txsize_ctx][plane_type][ctx],
2282 1, 2);
2283 break;
2284 }
2285 ++td->counts->coeff_lps[txsize_ctx][plane_type][ctx][0];
2286 if (allow_update_cdf)
2287 update_bin(ec_ctx->coeff_lps_cdf[txsize_ctx][plane_type][ctx], 0,
2288 2);
2289 }
2290 break;
Jingning Han87b01b52017-08-31 12:07:20 -07002291 }
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002292 ++td->counts->coeff_br[txsize_ctx][plane_type][idx][ctx][0];
2293 if (allow_update_cdf)
2294 update_bin(ec_ctx->coeff_br_cdf[txsize_ctx][plane_type][idx][ctx], 0,
2295 2);
Jingning Han87b01b52017-08-31 12:07:20 -07002296 }
Ola Hugossone72a2092017-11-12 09:11:53 +01002297#endif
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002298 // use 0-th order Golomb code to handle the residual level.
Jingning Han87b01b52017-08-31 12:07:20 -07002299 }
Angie Chiang0397eda2017-03-15 16:57:14 -07002300 }
Angie Chiang36d616b2017-03-22 13:58:36 -07002301
Angie Chiang63d190a2017-10-23 15:43:05 -07002302 int cul_level = av1_get_txb_entropy_context(tcoeff, scan_order, eob);
Angie Chiang0397eda2017-03-15 16:57:14 -07002303 av1_set_contexts(xd, pd, plane, tx_size, cul_level, blk_col, blk_row);
Angie Chiang0b205e62017-03-20 17:16:47 -07002304
2305#if CONFIG_ADAPT_SCAN
2306 // Since dqcoeff is not available here, we pass qcoeff into
2307 // av1_update_scan_count_facade(). The update behavior should be the same
2308 // because av1_update_scan_count_facade() only cares if coefficients are zero
2309 // or not.
Jingning Han025c6c42017-11-22 12:06:03 -08002310 const int mi_row = -xd->mb_to_top_edge >> (3 + MI_SIZE_LOG2);
Jingning Han0bd3bf62017-11-28 17:11:51 -08002311 av1_update_scan_count_facade((AV1_COMMON *)cm, xd, mi_row, tx_size, tx_type,
2312 qcoeff, eob);
Angie Chiang0b205e62017-03-20 17:16:47 -07002313#endif
Angie Chiang0397eda2017-03-15 16:57:14 -07002314}
2315
2316void av1_update_txb_context(const AV1_COMP *cpi, ThreadData *td,
2317 RUN_TYPE dry_run, BLOCK_SIZE bsize, int *rate,
Yunqing Wang0e141b52017-11-02 15:08:58 -07002318 int mi_row, int mi_col, uint8_t allow_update_cdf) {
Angie Chiang0397eda2017-03-15 16:57:14 -07002319 MACROBLOCK *const x = &td->mb;
2320 MACROBLOCKD *const xd = &x->e_mbd;
2321 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yunqing Wang0e141b52017-11-02 15:08:58 -07002322 struct tokenize_b_args arg = { cpi, td, NULL, 0, allow_update_cdf };
Angie Chiang0397eda2017-03-15 16:57:14 -07002323 (void)rate;
2324 (void)mi_row;
2325 (void)mi_col;
2326 if (mbmi->skip) {
Timothy B. Terriberrya2d5cde2017-05-10 18:33:50 -07002327 av1_reset_skip_context(xd, mi_row, mi_col, bsize);
Angie Chiang0397eda2017-03-15 16:57:14 -07002328 return;
2329 }
2330
2331 if (!dry_run) {
Jingning Han94652b82017-04-04 09:45:02 -07002332 av1_foreach_transformed_block(xd, bsize, mi_row, mi_col,
Jingning Han4fe5f672017-05-19 15:46:07 -07002333 av1_update_and_record_txb_context, &arg);
Angie Chiangc8af6112017-03-16 16:11:22 -07002334 } else if (dry_run == DRY_RUN_NORMAL) {
Jingning Han4fe5f672017-05-19 15:46:07 -07002335 av1_foreach_transformed_block(xd, bsize, mi_row, mi_col,
2336 av1_update_txb_context_b, &arg);
Angie Chiangc8af6112017-03-16 16:11:22 -07002337 } else {
2338 printf("DRY_RUN_COSTCOEFFS is not supported yet\n");
2339 assert(0);
Angie Chiang0397eda2017-03-15 16:57:14 -07002340 }
2341}
Angie Chiang800df032017-03-22 11:14:12 -07002342
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002343#if CONFIG_TXK_SEL
Angie Chiang808d8592017-04-06 18:36:55 -07002344int64_t av1_search_txk_type(const AV1_COMP *cpi, MACROBLOCK *x, int plane,
2345 int block, int blk_row, int blk_col,
2346 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
Angie Chiang65a39bb2017-04-11 16:50:04 -07002347 const ENTROPY_CONTEXT *a, const ENTROPY_CONTEXT *l,
2348 int use_fast_coef_costing, RD_STATS *rd_stats) {
Angie Chiang808d8592017-04-06 18:36:55 -07002349 const AV1_COMMON *cm = &cpi->common;
2350 MACROBLOCKD *xd = &x->e_mbd;
2351 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
2352 TX_TYPE txk_start = DCT_DCT;
2353 TX_TYPE txk_end = TX_TYPES - 1;
2354 TX_TYPE best_tx_type = txk_start;
2355 int64_t best_rd = INT64_MAX;
Jingning Han47558172017-07-05 16:33:19 -07002356 uint8_t best_eob = 0;
Jingning Hane3b81bc2017-06-23 11:43:52 -07002357 RD_STATS best_rd_stats;
Angie Chiang808d8592017-04-06 18:36:55 -07002358 TX_TYPE tx_type;
Jingning Hane3b81bc2017-06-23 11:43:52 -07002359
2360 av1_invalid_rd_stats(&best_rd_stats);
2361
Angie Chiang808d8592017-04-06 18:36:55 -07002362 for (tx_type = txk_start; tx_type <= txk_end; ++tx_type) {
Angie Chiangbce07f12017-12-01 16:34:31 -08002363 if (plane == 0)
2364 mbmi->txk_type[(blk_row << MAX_MIB_SIZE_LOG2) + blk_col] = tx_type;
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002365 TX_TYPE ref_tx_type =
2366 av1_get_tx_type(get_plane_type(plane), xd, blk_row, blk_col, tx_size);
Angie Chiang00491e02017-04-11 17:55:10 -07002367 if (tx_type != ref_tx_type) {
hui su45b64752017-07-12 16:54:35 -07002368 // use av1_get_tx_type() to check if the tx_type is valid for the current
2369 // mode if it's not, we skip it here.
Angie Chiang00491e02017-04-11 17:55:10 -07002370 continue;
2371 }
Jingning Hane57d6322017-07-03 18:50:25 -07002372
Hui Suddbcde22017-09-18 17:22:02 -07002373 const int is_inter = is_inter_block(mbmi);
Angie Chiang53bf1e92017-11-29 16:53:07 -08002374 const TxSetType tx_set_type = get_ext_tx_set_type(
2375 tx_size, mbmi->sb_type, is_inter, cm->reduced_tx_set_used);
Hui Suddbcde22017-09-18 17:22:02 -07002376 if (!av1_ext_tx_used[tx_set_type][tx_type]) continue;
Jingning Hane57d6322017-07-03 18:50:25 -07002377
Angie Chiang808d8592017-04-06 18:36:55 -07002378 RD_STATS this_rd_stats;
2379 av1_invalid_rd_stats(&this_rd_stats);
Angie Chiangdaccae32017-12-04 09:34:44 -08002380#if DISABLE_TRELLISQ_SEARCH
2381 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Sarah Parkere8d0d4c2017-12-06 15:11:37 -08002382 AV1_XFORM_QUANT_B);
Angie Chiangdaccae32017-12-04 09:34:44 -08002383#else
Angie Chiang808d8592017-04-06 18:36:55 -07002384 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Sarah Parkere8d0d4c2017-12-06 15:11:37 -08002385 AV1_XFORM_QUANT_FP);
Jingning Han7eab9ff2017-07-06 10:12:54 -07002386 av1_optimize_b(cm, x, plane, blk_row, blk_col, block, plane_bsize, tx_size,
Angie Chiang25645b72017-09-24 14:28:49 -07002387 a, l, 1);
Angie Chiangdaccae32017-12-04 09:34:44 -08002388#endif
Angie Chiang808d8592017-04-06 18:36:55 -07002389 av1_dist_block(cpi, x, plane, plane_bsize, block, blk_row, blk_col, tx_size,
Angie Chiang2ed03a32017-04-16 18:00:06 -07002390 &this_rd_stats.dist, &this_rd_stats.sse,
2391 OUTPUT_HAS_PREDICTED_PIXELS);
Angie Chiangbd99b382017-06-20 15:11:16 -07002392 const SCAN_ORDER *scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Jingning Han7eab9ff2017-07-06 10:12:54 -07002393 this_rd_stats.rate =
2394 av1_cost_coeffs(cpi, x, plane, blk_row, blk_col, block, tx_size,
2395 scan_order, a, l, use_fast_coef_costing);
Urvang Joshi70006e42017-06-14 16:08:55 -07002396 int rd = RDCOST(x->rdmult, this_rd_stats.rate, this_rd_stats.dist);
Jingning Han19b5c8f2017-07-06 15:10:12 -07002397
Angie Chiang808d8592017-04-06 18:36:55 -07002398 if (rd < best_rd) {
2399 best_rd = rd;
Jingning Hane3b81bc2017-06-23 11:43:52 -07002400 best_rd_stats = this_rd_stats;
Angie Chiang808d8592017-04-06 18:36:55 -07002401 best_tx_type = tx_type;
Jingning Han47558172017-07-05 16:33:19 -07002402 best_eob = x->plane[plane].txb_entropy_ctx[block];
Angie Chiang808d8592017-04-06 18:36:55 -07002403 }
2404 }
Jingning Hane3b81bc2017-06-23 11:43:52 -07002405
2406 av1_merge_rd_stats(rd_stats, &best_rd_stats);
2407
Angie Chianga3f7d2e2017-12-07 19:51:14 -08002408 if (best_eob == 0) best_tx_type = DCT_DCT;
Jingning Han19b5c8f2017-07-06 15:10:12 -07002409
Angie Chiangbce07f12017-12-01 16:34:31 -08002410 if (plane == 0)
2411 mbmi->txk_type[(blk_row << MAX_MIB_SIZE_LOG2) + blk_col] = best_tx_type;
Jingning Han47558172017-07-05 16:33:19 -07002412 x->plane[plane].txb_entropy_ctx[block] = best_eob;
2413
Angie Chiang2ed03a32017-04-16 18:00:06 -07002414 if (!is_inter_block(mbmi)) {
Angie Chiangdaccae32017-12-04 09:34:44 -08002415// intra mode needs decoded result such that the next transform block
2416// can use it for prediction.
2417#if DISABLE_TRELLISQ_SEARCH
2418 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Sarah Parkere8d0d4c2017-12-06 15:11:37 -08002419 AV1_XFORM_QUANT_B);
Angie Chiangdaccae32017-12-04 09:34:44 -08002420#else
Jingning Han47558172017-07-05 16:33:19 -07002421 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Sarah Parkere8d0d4c2017-12-06 15:11:37 -08002422 AV1_XFORM_QUANT_FP);
Jingning Han7eab9ff2017-07-06 10:12:54 -07002423 av1_optimize_b(cm, x, plane, blk_row, blk_col, block, plane_bsize, tx_size,
Angie Chiang25645b72017-09-24 14:28:49 -07002424 a, l, 1);
Angie Chiangdaccae32017-12-04 09:34:44 -08002425#endif
Jingning Han47558172017-07-05 16:33:19 -07002426
Angie Chiang2ed03a32017-04-16 18:00:06 -07002427 av1_inverse_transform_block_facade(xd, plane, block, blk_row, blk_col,
Frederic Barbier33b39f02017-11-21 11:11:24 +01002428 x->plane[plane].eobs[block],
2429 cm->reduced_tx_set_used);
Angie Chiang2ed03a32017-04-16 18:00:06 -07002430 }
Angie Chiang808d8592017-04-06 18:36:55 -07002431 return best_rd;
2432}
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002433#endif // CONFIG_TXK_SEL