blob: 910a90f26102f59d689f34932fafbfab64dd4cc2 [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;
Montybca9e9e2017-12-14 06:23:29 -0600133 const int64_t error = (diff * diff + depth_round) >> depth_shift;
Monty Montgomery4a05a582017-11-01 21:21:07 -0400134 (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
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800317static void av1_get_nz_map_contexts(const uint8_t *const levels,
318 const int16_t *const scan,
319 const uint16_t eob, const TX_SIZE tx_size,
320 const TX_TYPE tx_type,
321 int8_t *const coeff_contexts) {
322 const int bwl = get_txb_bwl(tx_size);
323#if CONFIG_LV_MAP_MULTI
324 const int height = get_txb_high(tx_size);
325#endif
326 for (int i = 0; i < eob; ++i) {
327 const int pos = scan[i];
328 coeff_contexts[pos] = get_nz_map_ctx(levels, pos, bwl,
329#if CONFIG_LV_MAP_MULTI
330 height, i, i == eob - 1,
331#endif
332 tx_size, tx_type);
333 }
334}
335
Angie Chiang80b82262017-02-24 11:39:47 -0800336void av1_write_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCKD *xd,
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500337 aom_writer *w, int blk_row, int blk_col, int plane,
338 TX_SIZE tx_size, const tran_low_t *tcoeff,
Jingning Han7eab9ff2017-07-06 10:12:54 -0700339 uint16_t eob, TXB_CTX *txb_ctx) {
Angie Chiang80b82262017-02-24 11:39:47 -0800340 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiangcea11f22017-02-24 12:30:40 -0800341 const PLANE_TYPE plane_type = get_plane_type(plane);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -0800342 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Jingning Han19b5c8f2017-07-06 15:10:12 -0700343 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500344 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -0700345 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800346 const int16_t *const scan = scan_order->scan;
Urvang Joshi80893152017-10-27 11:51:14 -0700347 const int seg_eob = av1_get_max_eob(tx_size);
Angie Chiang80b82262017-02-24 11:39:47 -0800348 int c;
Angie Chianga9ba58e2017-12-01 19:22:43 -0800349 const int bwl = get_txb_bwl(tx_size);
350 const int width = get_txb_wide(tx_size);
351 const int height = get_txb_high(tx_size);
Linfeng Zhang848f7bc2017-10-31 15:26:07 -0700352 int update_eob = -1;
Jingning Han41c7f442017-09-05 14:54:00 -0700353 FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700354 uint8_t levels_buf[TX_PAD_2D];
355 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -0800356 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800357 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Angie Chiang80b82262017-02-24 11:39:47 -0800358
Jingning Han7eab9ff2017-07-06 10:12:54 -0700359 (void)blk_row;
360 (void)blk_col;
Jingning Han94cea4a2017-09-30 14:13:23 -0700361 aom_write_bin(w, eob == 0,
362 ec_ctx->txb_skip_cdf[txs_ctx][txb_ctx->txb_skip_ctx], 2);
Angie Chiang5f0cb5e2017-12-11 16:07:50 -0800363#if CONFIG_TXK_SEL
Angie Chianga3f7d2e2017-12-07 19:51:14 -0800364 if (plane == 0 && eob == 0) {
365 assert(tx_type == DCT_DCT);
366 }
Angie Chiang5f0cb5e2017-12-11 16:07:50 -0800367#endif
Angie Chiang80b82262017-02-24 11:39:47 -0800368 if (eob == 0) return;
Linfeng Zhangce065ca2017-10-17 16:49:30 -0700369
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700370 av1_txb_init_levels(tcoeff, width, height, levels);
Linfeng Zhangce065ca2017-10-17 16:49:30 -0700371
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700372#if CONFIG_TXK_SEL
Debargha Mukherjee3ebb0d02017-12-14 05:05:18 -0800373 av1_write_tx_type(cm, xd, blk_row, blk_col, plane, tx_size, w);
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700374#endif
Angie Chiang80b82262017-02-24 11:39:47 -0800375
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800376 int eob_extra, dummy;
377 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
378 const int max_eob_pt = get_eob_pos_token(seg_eob, &dummy);
Dake Hea47cd6c2017-10-13 18:09:58 -0700379
Dake Hea47cd6c2017-10-13 18:09:58 -0700380 for (int i = 1; i < max_eob_pt; i++) {
Jingning Han35deaa72017-10-26 15:36:30 -0700381 int eob_pos_ctx = av1_get_eob_pos_ctx(tx_type, i);
Dake Hea47cd6c2017-10-13 18:09:58 -0700382
383 aom_write_bin(w, eob_pt == i,
384 ec_ctx->eob_flag_cdf[txs_ctx][plane_type][eob_pos_ctx], 2);
385 // aom_write_symbol(w, eob_pt == i,
386 // ec_ctx->eob_flag_cdf[AOMMIN(txs_ctx,3)][plane_type][eob_pos_ctx], 2);
387 if (eob_pt == i) {
388 break;
389 }
390 }
391
392 if (k_eob_offset_bits[eob_pt] > 0) {
Angie Chiang7ab884e2017-10-18 15:57:12 -0700393 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
394 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
395 aom_write_bin(w, bit, ec_ctx->eob_extra_cdf[txs_ctx][plane_type][eob_pt],
396 2);
397 for (int i = 1; i < k_eob_offset_bits[eob_pt]; i++) {
398 eob_shift = k_eob_offset_bits[eob_pt] - 1 - i;
399 bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700400 aom_write_bit(w, bit);
Dake Hea47cd6c2017-10-13 18:09:58 -0700401 }
402 }
Dake He03a32922017-10-31 08:06:45 -0700403
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800404 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_type, coeff_contexts);
405
406 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800407 const int pos = scan[c];
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800408 const int coeff_ctx = coeff_contexts[pos];
409 const tran_low_t v = tcoeff[pos];
Dake He03a32922017-10-31 08:06:45 -0700410
Ola Hugosson13892102017-11-06 08:01:44 +0100411#if CONFIG_LV_MAP_MULTI
Dake He3fe369c2017-11-16 17:56:44 -0800412#if USE_BASE_EOB_ALPHABET
413 if (c == eob - 1) {
414 aom_write_symbol(
415 w, AOMMIN(abs(v), 3) - 1,
416 ec_ctx->coeff_base_eob_cdf[txs_ctx][plane_type]
417 [coeff_ctx - SIG_COEF_CONTEXTS +
418 SIG_COEF_CONTEXTS_EOB],
419 3);
420 } else {
421 aom_write_symbol(w, AOMMIN(abs(v), 3),
422 ec_ctx->coeff_base_cdf[txs_ctx][plane_type][coeff_ctx],
423 4);
424 }
425#else
Thomas Davies736ddef2017-11-09 09:46:08 +0000426 aom_write_symbol(w, AOMMIN(abs(v), 3),
427 ec_ctx->coeff_base_cdf[txs_ctx][plane_type][coeff_ctx], 4);
Dake He3fe369c2017-11-16 17:56:44 -0800428#endif
Ola Hugosson13892102017-11-06 08:01:44 +0100429#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800430 const int is_nz = (v != 0);
Dake He03a32922017-10-31 08:06:45 -0700431
432 if (c < eob - 1) {
433 aom_write_bin(w, is_nz,
434 ec_ctx->nz_map_cdf[txs_ctx][plane_type][coeff_ctx], 2);
435 }
436 if (is_nz) {
437 const int level = abs(v);
438 int k;
439 for (k = 0; k < NUM_BASE_LEVELS; ++k) {
440 int is_k = (level > (k + 1));
441 int ctx = coeff_ctx;
442 aom_write_bin(w, is_k,
443 ec_ctx->coeff_base_cdf[txs_ctx][plane_type][k][ctx], 2);
444 if (is_k == 0) break;
445 }
446 }
Ola Hugosson13892102017-11-06 08:01:44 +0100447#endif
Dake He03a32922017-10-31 08:06:45 -0700448 }
449 update_eob = eob - 1;
Angie Chiang80b82262017-02-24 11:39:47 -0800450
Dake He43edb762017-10-26 10:29:46 -0700451 // Loop to code all signs in the transform block,
452 // starting with the sign of DC (if applicable)
453 for (c = 0; c < eob; ++c) {
Linfeng Zhang1015a342017-10-24 16:20:41 -0700454 const tran_low_t v = tcoeff[scan[c]];
455 const tran_low_t level = abs(v);
456 const int sign = (v < 0) ? 1 : 0;
Dake He43edb762017-10-26 10:29:46 -0700457 if (level == 0) continue;
458
459 if (c == 0) {
460#if LV_MAP_PROB
461 aom_write_bin(w, sign,
462 ec_ctx->dc_sign_cdf[plane_type][txb_ctx->dc_sign_ctx], 2);
463#else
464 aom_write(w, sign, ec_ctx->dc_sign[plane_type][txb_ctx->dc_sign_ctx]);
465#endif
466 } else {
467 aom_write_bit(w, sign);
468 }
469 }
470
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800471 if (update_eob >= 0) {
Dake He7d01ab52017-11-24 17:53:28 -0800472#if !CONFIG_LV_MAP_MULTI
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800473 av1_get_br_level_counts(levels, width, height, level_counts);
Dake He7d01ab52017-11-24 17:53:28 -0800474#endif
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800475 for (c = update_eob; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800476 const int pos = scan[c];
477 const tran_low_t level = abs(tcoeff[pos]);
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800478 int idx;
479 int ctx;
Angie Chiang80b82262017-02-24 11:39:47 -0800480
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800481 if (level <= NUM_BASE_LEVELS) continue;
Angie Chiang80b82262017-02-24 11:39:47 -0800482
Dake He7d01ab52017-11-24 17:53:28 -0800483// level is above 1.
484#if !CONFIG_LV_MAP_MULTI
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800485 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -0800486#endif
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800487 const int base_range = level - 1 - NUM_BASE_LEVELS;
Ola Hugossone72a2092017-11-12 09:11:53 +0100488#if CONFIG_LV_MAP_MULTI
Dake He7d01ab52017-11-24 17:53:28 -0800489#if USE_CAUSAL_BR_CTX
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800490 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos], tx_type);
Dake He7d01ab52017-11-24 17:53:28 -0800491
492#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800493 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -0800494#endif
Ola Hugossone72a2092017-11-12 09:11:53 +0100495 for (idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800496 const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
Dake Hee2d8f182017-12-14 13:28:00 -0800497 aom_write_symbol(w, k,
498#if 0
Dake He7d01ab52017-11-24 17:53:28 -0800499 ec_ctx->coeff_br_cdf[AOMMIN(txs_ctx, TX_16X16)][plane_type][ctx],
Dake Hee2d8f182017-12-14 13:28:00 -0800500#else
501 ec_ctx->coeff_br_cdf[AOMMIN(txs_ctx, TX_32X32)]
502 [plane_type][ctx],
503#endif
504 BR_CDF_SIZE);
Ola Hugossone72a2092017-11-12 09:11:53 +0100505 if (k < BR_CDF_SIZE - 1) break;
506 }
507 if (base_range < COEFF_BASE_RANGE) continue;
508#else
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800509 int br_set_idx = 0;
510 int br_base = 0;
511 int br_offset = 0;
Jingning Han87b01b52017-08-31 12:07:20 -0700512
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800513 if (base_range >= COEFF_BASE_RANGE)
514 br_set_idx = BASE_RANGE_SETS;
515 else
516 br_set_idx = coeff_to_br_index[base_range];
Jingning Han87b01b52017-08-31 12:07:20 -0700517
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800518 for (idx = 0; idx < BASE_RANGE_SETS; ++idx) {
519 aom_write_bin(w, idx == br_set_idx,
520 ec_ctx->coeff_br_cdf[txs_ctx][plane_type][idx][ctx], 2);
521 if (idx == br_set_idx) {
522 br_base = br_index_to_coeff[br_set_idx];
523 br_offset = base_range - br_base;
524 int extra_bits = (1 << br_extra_bits[idx]) - 1;
525 for (int tok = 0; tok < extra_bits; ++tok) {
526 if (tok == br_offset) {
527 aom_write_bin(w, 1,
528 ec_ctx->coeff_lps_cdf[txs_ctx][plane_type][ctx], 2);
529 break;
530 }
531 aom_write_bin(w, 0, ec_ctx->coeff_lps_cdf[txs_ctx][plane_type][ctx],
Jingning Han94cea4a2017-09-30 14:13:23 -0700532 2);
Jingning Han87b01b52017-08-31 12:07:20 -0700533 }
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800534 // aom_write_literal(w, br_offset, br_extra_bits[idx]);
535 break;
Jingning Han87b01b52017-08-31 12:07:20 -0700536 }
Jingning Han87b01b52017-08-31 12:07:20 -0700537 }
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800538
539 if (br_set_idx < BASE_RANGE_SETS) continue;
Ola Hugossone72a2092017-11-12 09:11:53 +0100540#endif
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800541 // use 0-th order Golomb code to handle the residual level.
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800542 write_golomb(w,
543 abs(tcoeff[pos]) - COEFF_BASE_RANGE - 1 - NUM_BASE_LEVELS);
Jingning Han87b01b52017-08-31 12:07:20 -0700544 }
Angie Chiang80b82262017-02-24 11:39:47 -0800545 }
546}
Angie Chiang47c72182017-02-27 14:30:38 -0800547
Angie Chiang140b3332017-12-12 17:29:25 -0800548typedef struct encode_txb_args {
549 const AV1_COMMON *cm;
550 MACROBLOCK *x;
551 aom_writer *w;
552} ENCODE_TXB_ARGS;
553
554static void av1_write_coeffs_txb_wrap(int plane, int block, int blk_row,
555 int blk_col, BLOCK_SIZE plane_bsize,
556 TX_SIZE tx_size, void *arg) {
557 (void)plane_bsize;
558 ENCODE_TXB_ARGS *enc_args = (ENCODE_TXB_ARGS *)arg;
559 const AV1_COMMON *cm = enc_args->cm;
560 MACROBLOCK *x = enc_args->x;
Angie Chiangc8af6112017-03-16 16:11:22 -0700561 MACROBLOCKD *xd = &x->e_mbd;
Angie Chiang140b3332017-12-12 17:29:25 -0800562 aom_writer *w = enc_args->w;
563 tran_low_t *tcoeff = BLOCK_OFFSET(x->mbmi_ext->tcoeff[plane], block);
564 uint16_t eob = x->mbmi_ext->eobs[plane][block];
565 TXB_CTX txb_ctx = { x->mbmi_ext->txb_skip_ctx[plane][block],
566 x->mbmi_ext->dc_sign_ctx[plane][block] };
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500567 av1_write_coeffs_txb(cm, xd, w, blk_row, blk_col, plane, tx_size, tcoeff, eob,
568 &txb_ctx);
Angie Chiang140b3332017-12-12 17:29:25 -0800569}
570
571void av1_write_coeffs_mb(const AV1_COMMON *const cm, MACROBLOCK *x,
572 aom_writer *w, int plane, BLOCK_SIZE bsize) {
573 ENCODE_TXB_ARGS enc_args = { cm, x, w };
574 MACROBLOCKD *xd = &x->e_mbd;
575 av1_foreach_transformed_block_in_plane(xd, bsize, plane,
576 av1_write_coeffs_txb_wrap, &enc_args);
Angie Chiangc8af6112017-03-16 16:11:22 -0700577}
578
Angie Chiang488f9212017-05-30 12:46:26 -0700579static INLINE int get_br_cost(tran_low_t abs_qc, int ctx,
Angie Chiang26d3e452017-09-29 17:40:02 -0700580 const int *coeff_lps) {
Angie Chiang488f9212017-05-30 12:46:26 -0700581 const tran_low_t min_level = 1 + NUM_BASE_LEVELS;
582 const tran_low_t max_level = 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE;
Jingning Handfd72322017-08-09 14:04:12 -0700583 (void)ctx;
Angie Chiang488f9212017-05-30 12:46:26 -0700584 if (abs_qc >= min_level) {
Angie Chiang488f9212017-05-30 12:46:26 -0700585 if (abs_qc >= max_level)
Jingning Han772dee32017-09-15 08:53:18 -0700586 return coeff_lps[COEFF_BASE_RANGE]; // COEFF_BASE_RANGE * cost0;
Angie Chiang488f9212017-05-30 12:46:26 -0700587 else
Jingning Han772dee32017-09-15 08:53:18 -0700588 return coeff_lps[(abs_qc - min_level)]; // * cost0 + cost1;
Angie Chiang488f9212017-05-30 12:46:26 -0700589 } else {
590 return 0;
591 }
592}
593
594static INLINE int get_base_cost(tran_low_t abs_qc, int ctx,
Jingning Handfd72322017-08-09 14:04:12 -0700595 const int coeff_base[2], int base_idx) {
Angie Chiang488f9212017-05-30 12:46:26 -0700596 const int level = base_idx + 1;
Jingning Handfd72322017-08-09 14:04:12 -0700597 (void)ctx;
Angie Chiang488f9212017-05-30 12:46:26 -0700598 if (abs_qc < level)
599 return 0;
600 else
Jingning Handfd72322017-08-09 14:04:12 -0700601 return coeff_base[abs_qc == level];
Angie Chiang488f9212017-05-30 12:46:26 -0700602}
603
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800604// Note: don't call this function when eob is 0.
605int av1_cost_coeffs_txb(const AV1_COMMON *const cm, const MACROBLOCK *x,
606 const int plane, const int blk_row, const int blk_col,
607 const int block, const TX_SIZE tx_size,
608 const TXB_CTX *const txb_ctx) {
609 const MACROBLOCKD *const xd = &x->e_mbd;
610 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Angie Chiang47c72182017-02-27 14:30:38 -0800611 const PLANE_TYPE plane_type = get_plane_type(plane);
Jingning Han19b5c8f2017-07-06 15:10:12 -0700612 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500613 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800614 const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Angie Chiang47c72182017-02-27 14:30:38 -0800615 const struct macroblock_plane *p = &x->plane[plane];
616 const int eob = p->eobs[block];
617 const tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
618 int c, cost;
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800619 const int txb_skip_ctx = txb_ctx->txb_skip_ctx;
Angie Chianga9ba58e2017-12-01 19:22:43 -0800620 const int bwl = get_txb_bwl(tx_size);
621 const int width = get_txb_wide(tx_size);
622 const int height = get_txb_high(tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -0700623 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800624 const int16_t *const scan = scan_order->scan;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700625 uint8_t levels_buf[TX_PAD_2D];
626 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -0800627 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800628 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800629 const LV_MAP_COEFF_COST *const coeff_costs =
630 &x->coeff_costs[txs_ctx][plane_type];
Angie Chiang47c72182017-02-27 14:30:38 -0800631
Jingning Handfd72322017-08-09 14:04:12 -0700632 cost = coeff_costs->txb_skip_cost[txb_skip_ctx][0];
Angie Chiang47c72182017-02-27 14:30:38 -0800633
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700634 av1_txb_init_levels(qcoeff, width, height, levels);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700635
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700636#if CONFIG_TXK_SEL
Yue Chenb23d00a2017-07-28 17:01:21 -0700637 cost += av1_tx_type_cost(cm, x, xd, mbmi->sb_type, plane, tx_size, tx_type);
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700638#endif
Angie Chiang05917872017-04-15 12:28:56 -0700639
Urvang Joshi80893152017-10-27 11:51:14 -0700640 const int seg_eob = av1_get_max_eob(tx_size);
Jingning Han35deaa72017-10-26 15:36:30 -0700641 int eob_cost = get_eob_cost(eob, seg_eob, coeff_costs, tx_type);
Dake He7d01ab52017-11-24 17:53:28 -0800642#if !CONFIG_LV_MAP_MULTI
Linfeng Zhang97fc4742017-11-07 12:57:25 -0800643 av1_get_br_level_counts(levels, width, height, level_counts);
Dake He7d01ab52017-11-24 17:53:28 -0800644#endif
Dake Hea47cd6c2017-10-13 18:09:58 -0700645 cost += eob_cost;
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800646
647 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_type, coeff_contexts);
648
Dake Hea47cd6c2017-10-13 18:09:58 -0700649 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800650 const int pos = scan[c];
651 const tran_low_t v = qcoeff[pos];
652 const int is_nz = (v != 0);
653 const int level = abs(v);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800654 const int coeff_ctx = coeff_contexts[pos];
Ola Hugosson13892102017-11-06 08:01:44 +0100655#if CONFIG_LV_MAP_MULTI
Dake He3fe369c2017-11-16 17:56:44 -0800656#if USE_BASE_EOB_ALPHABET
657 if (c == eob - 1) {
658 cost += coeff_costs
659 ->base_eob_cost[coeff_ctx - SIG_COEF_CONTEXTS +
660 SIG_COEF_CONTEXTS_EOB][AOMMIN(level, 3) - 1];
661 } else {
662 cost += coeff_costs->base_cost[coeff_ctx][AOMMIN(level, 3)];
663 }
664#else
Ola Hugosson13892102017-11-06 08:01:44 +0100665 cost += coeff_costs->base_cost[coeff_ctx][AOMMIN(level, 3)];
Dake He3fe369c2017-11-16 17:56:44 -0800666#endif
Linfeng Zhang1757fb62017-12-11 10:47:59 -0800667#else // CONFIG_LV_MAP_MULTI
Dake Hea47cd6c2017-10-13 18:09:58 -0700668 if (c < eob - 1) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700669 cost += coeff_costs->nz_map_cost[coeff_ctx][is_nz];
670 }
Ola Hugosson13892102017-11-06 08:01:44 +0100671#endif // CONFIG_LV_MAP_MULTI
Dake Hea47cd6c2017-10-13 18:09:58 -0700672
673 if (is_nz) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700674 int sign = (v < 0) ? 1 : 0;
675
676 // sign bit cost
677 if (c == 0) {
678 int dc_sign_ctx = txb_ctx->dc_sign_ctx;
679 cost += coeff_costs->dc_sign_cost[dc_sign_ctx][sign];
680 } else {
681 cost += av1_cost_bit(128, sign);
682 }
Ola Hugosson13892102017-11-06 08:01:44 +0100683#if !CONFIG_LV_MAP_MULTI
Dake He03a32922017-10-31 08:06:45 -0700684 int k;
685 for (k = 0; k < NUM_BASE_LEVELS; ++k) {
686 int is_k = (level > (k + 1));
687 int ctx = coeff_ctx;
688 // get_base_ctx_from_b(c, k, b0, b1, b2);
689 cost += coeff_costs->base_cost[k][ctx][is_k];
690 if (is_k == 0) break;
691 }
Ola Hugosson13892102017-11-06 08:01:44 +0100692#endif // CONFIG_LV_MAP_MULTI
Dake Hea47cd6c2017-10-13 18:09:58 -0700693 if (level > NUM_BASE_LEVELS) {
694 int ctx;
Dake He7d01ab52017-11-24 17:53:28 -0800695#if CONFIG_LV_MAP_MULTI && USE_CAUSAL_BR_CTX
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800696 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos], tx_type);
Dake He7d01ab52017-11-24 17:53:28 -0800697#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800698 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -0800699#endif
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800700 const int base_range = level - 1 - NUM_BASE_LEVELS;
Dake Hea47cd6c2017-10-13 18:09:58 -0700701 if (base_range < COEFF_BASE_RANGE) {
702 cost += coeff_costs->lps_cost[ctx][base_range];
703 } else {
704 cost += coeff_costs->lps_cost[ctx][COEFF_BASE_RANGE];
705 }
706
Dake Hea47cd6c2017-10-13 18:09:58 -0700707 if (level >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
708 // residual cost
709 int r = level - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
710 int ri = r;
711 int length = 0;
712
713 while (ri) {
714 ri >>= 1;
715 ++length;
716 }
717
718 for (ri = 0; ri < length - 1; ++ri) cost += av1_cost_bit(128, 0);
719
720 for (ri = length - 1; ri >= 0; --ri)
721 cost += av1_cost_bit(128, (r >> ri) & 0x01);
722 }
723 }
724 }
725 }
Angie Chiang47c72182017-02-27 14:30:38 -0800726 return cost;
727}
Angie Chiang0397eda2017-03-15 16:57:14 -0700728
Angie Chiang2affb3b2017-05-30 15:23:51 -0700729static INLINE int has_base(tran_low_t qc, int base_idx) {
730 const int level = base_idx + 1;
731 return abs(qc) >= level;
732}
733
Angie Chiang2affb3b2017-05-30 15:23:51 -0700734static INLINE int has_br(tran_low_t qc) {
735 return abs(qc) >= 1 + NUM_BASE_LEVELS;
736}
737
Angie Chiang488f9212017-05-30 12:46:26 -0700738static INLINE int get_sign_bit_cost(tran_low_t qc, int coeff_idx,
Jingning Handfd72322017-08-09 14:04:12 -0700739 const int (*dc_sign_cost)[2],
Angie Chiang488f9212017-05-30 12:46:26 -0700740 int dc_sign_ctx) {
741 const int sign = (qc < 0) ? 1 : 0;
742 // sign bit cost
743 if (coeff_idx == 0) {
Jingning Handfd72322017-08-09 14:04:12 -0700744 return dc_sign_cost[dc_sign_ctx][sign];
Angie Chiang488f9212017-05-30 12:46:26 -0700745 } else {
746 return av1_cost_bit(128, sign);
747 }
748}
749static INLINE int get_golomb_cost(int abs_qc) {
750 if (abs_qc >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
751 // residual cost
752 int r = abs_qc - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
753 int ri = r;
754 int length = 0;
755
756 while (ri) {
757 ri >>= 1;
758 ++length;
759 }
760
761 return av1_cost_literal(2 * length - 1);
762 } else {
763 return 0;
764 }
765}
766
Angie Chiang2affb3b2017-05-30 15:23:51 -0700767void gen_txb_cache(TxbCache *txb_cache, TxbInfo *txb_info) {
Angie Chiang481c01f2017-08-15 16:24:30 -0700768 // gen_nz_count_arr
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800769 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang481c01f2017-08-15 16:24:30 -0700770 const int bwl = txb_info->bwl;
771 const int height = txb_info->height;
Linfeng Zhang72e0b3f2017-10-18 13:32:12 -0700772 const tran_low_t *const qcoeff = txb_info->qcoeff;
Linfeng Zhangb6957c22017-10-25 13:17:28 -0700773 const uint8_t *const levels = txb_info->levels;
Angie Chiangdef11252017-08-18 14:37:32 -0700774 const BASE_CTX_TABLE *base_ctx_table =
775 txb_info->coeff_ctx_table->base_ctx_table;
Angie Chiang481c01f2017-08-15 16:24:30 -0700776 for (int c = 0; c < txb_info->eob; ++c) {
777 const int coeff_idx = scan[c]; // raster order
778 const int row = coeff_idx >> bwl;
779 const int col = coeff_idx - (row << bwl);
Jingning Han3422ac12017-10-25 20:37:53 -0700780
Linfeng Zhangf91f3ca2017-12-05 11:22:41 -0800781 txb_cache->nz_count_arr[coeff_idx] =
Linfeng Zhangd5647372017-12-05 17:06:07 -0800782 get_nz_count(levels + get_padded_idx(coeff_idx, bwl), bwl,
Linfeng Zhangf91f3ca2017-12-05 11:22:41 -0800783 tx_type_to_class[txb_info->tx_type]);
Dake Hea47cd6c2017-10-13 18:09:58 -0700784
Yaowu Xu102ef812017-12-12 11:31:03 -0800785 txb_cache->nz_ctx_arr[coeff_idx] =
786 get_nz_map_ctx_from_stats(0, coeff_idx, bwl, txb_info->tx_size,
787 tx_type_to_class[txb_info->tx_type]);
Angie Chiang481c01f2017-08-15 16:24:30 -0700788
789 // gen_base_count_mag_arr
790 if (!has_base(qcoeff[coeff_idx], 0)) continue;
791 int *base_mag = txb_cache->base_mag_arr[coeff_idx];
Angie Chiang9cde59f2017-08-16 15:24:55 -0700792 int count[NUM_BASE_LEVELS];
793 get_base_count_mag(base_mag, count, qcoeff, bwl, height, row, col);
Angie Chiang481c01f2017-08-15 16:24:30 -0700794
795 for (int i = 0; i < NUM_BASE_LEVELS; ++i) {
Angie Chiang9cde59f2017-08-16 15:24:55 -0700796 if (!has_base(qcoeff[coeff_idx], i)) break;
797 txb_cache->base_count_arr[i][coeff_idx] = count[i];
Angie Chiang481c01f2017-08-15 16:24:30 -0700798 const int level = i + 1;
Angie Chiang9cde59f2017-08-16 15:24:55 -0700799 txb_cache->base_ctx_arr[i][coeff_idx] =
Angie Chiangdef11252017-08-18 14:37:32 -0700800 base_ctx_table[row != 0][col != 0][base_mag[0] > level][count[i]];
Angie Chiang481c01f2017-08-15 16:24:30 -0700801 }
802
803 // gen_br_count_mag_arr
804 if (!has_br(qcoeff[coeff_idx])) continue;
805 int *br_count = txb_cache->br_count_arr + coeff_idx;
806 int *br_mag = txb_cache->br_mag_arr[coeff_idx];
Angie Chiangea8183b2017-08-17 14:36:35 -0700807 *br_count = get_br_count_mag(br_mag, qcoeff, bwl, height, row, col,
808 NUM_BASE_LEVELS);
Angie Chiang481c01f2017-08-15 16:24:30 -0700809 txb_cache->br_ctx_arr[coeff_idx] =
810 get_br_ctx_from_count_mag(row, col, *br_count, br_mag[0]);
811 }
Angie Chiang2affb3b2017-05-30 15:23:51 -0700812}
813
Jingning Handfd72322017-08-09 14:04:12 -0700814static INLINE const int *get_level_prob(int level, int coeff_idx,
815 const TxbCache *txb_cache,
816 const LV_MAP_COEFF_COST *txb_costs) {
Ola Hugosson13892102017-11-06 08:01:44 +0100817#if CONFIG_LV_MAP_MULTI
818 if (level < 1 + NUM_BASE_LEVELS) {
819 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
820 return &txb_costs->base_cost[ctx][level];
821#else
Angie Chiang7afbba42017-05-30 15:59:15 -0700822 if (level == 0) {
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700823 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700824 return txb_costs->nz_map_cost[ctx];
Angie Chiang7afbba42017-05-30 15:59:15 -0700825 } else if (level >= 1 && level < 1 + NUM_BASE_LEVELS) {
826 const int idx = level - 1;
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700827 const int ctx = txb_cache->base_ctx_arr[idx][coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700828 return txb_costs->base_cost[idx][ctx];
Ola Hugosson13892102017-11-06 08:01:44 +0100829#endif
Angie Chiang7afbba42017-05-30 15:59:15 -0700830 } else if (level >= 1 + NUM_BASE_LEVELS &&
831 level < 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700832 const int ctx = txb_cache->br_ctx_arr[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700833 return txb_costs->lps_cost[ctx];
Angie Chiang7afbba42017-05-30 15:59:15 -0700834 } else if (level >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Ola Hugosson13892102017-11-06 08:01:44 +0100835 // printf("get_level_prob does not support golomb\n");
Angie Chiang7afbba42017-05-30 15:59:15 -0700836 assert(0);
837 return 0;
838 } else {
839 assert(0);
840 return 0;
841 }
842}
843
Angie Chiangd19969e2017-05-30 18:02:33 -0700844static INLINE void update_mag_arr(int *mag_arr, int abs_qc) {
845 if (mag_arr[0] == abs_qc) {
846 mag_arr[1] -= 1;
847 assert(mag_arr[1] >= 0);
848 }
849}
850
Angie Chianga530ef42017-05-30 16:32:36 -0700851static INLINE int get_mag_from_mag_arr(const int *mag_arr) {
852 int mag;
853 if (mag_arr[1] > 0) {
854 mag = mag_arr[0];
855 } else if (mag_arr[0] > 0) {
856 mag = mag_arr[0] - 1;
857 } else {
858 // no neighbor
859 assert(mag_arr[0] == 0 && mag_arr[1] == 0);
860 mag = 0;
861 }
862 return mag;
863}
864
865static int neighbor_level_down_update(int *new_count, int *new_mag, int count,
866 const int *mag, int coeff_idx,
867 tran_low_t abs_nb_coeff, int nb_coeff_idx,
868 int level, const TxbInfo *txb_info) {
869 *new_count = count;
870 *new_mag = get_mag_from_mag_arr(mag);
871
872 int update = 0;
873 // check if br_count changes
874 if (abs_nb_coeff == level) {
875 update = 1;
876 *new_count -= 1;
877 assert(*new_count >= 0);
878 }
879 const int row = coeff_idx >> txb_info->bwl;
880 const int col = coeff_idx - (row << txb_info->bwl);
881 const int nb_row = nb_coeff_idx >> txb_info->bwl;
882 const int nb_col = nb_coeff_idx - (nb_row << txb_info->bwl);
883
884 // check if mag changes
885 if (nb_row >= row && nb_col >= col) {
886 if (abs_nb_coeff == mag[0]) {
887 assert(mag[1] > 0);
888 if (mag[1] == 1) {
889 // the nb is the only qc with max mag
890 *new_mag -= 1;
891 assert(*new_mag >= 0);
892 update = 1;
893 }
894 }
895 }
896 return update;
897}
898
899static int try_neighbor_level_down_br(int coeff_idx, int nb_coeff_idx,
900 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700901 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -0700902 const TxbInfo *txb_info) {
903 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
904 const tran_low_t abs_qc = abs(qc);
905 const int level = NUM_BASE_LEVELS + 1;
906 if (abs_qc < level) return 0;
907
908 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
909 const tran_low_t abs_nb_coeff = abs(nb_coeff);
910 const int count = txb_cache->br_count_arr[coeff_idx];
911 const int *mag = txb_cache->br_mag_arr[coeff_idx];
912 int new_count;
913 int new_mag;
914 const int update =
915 neighbor_level_down_update(&new_count, &new_mag, count, mag, coeff_idx,
916 abs_nb_coeff, nb_coeff_idx, level, txb_info);
917 if (update) {
918 const int row = coeff_idx >> txb_info->bwl;
919 const int col = coeff_idx - (row << txb_info->bwl);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700920 const int ctx = txb_cache->br_ctx_arr[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700921 const int org_cost = get_br_cost(abs_qc, ctx, txb_costs->lps_cost[ctx]);
Angie Chianga530ef42017-05-30 16:32:36 -0700922
923 const int new_ctx = get_br_ctx_from_count_mag(row, col, new_count, new_mag);
Jingning Handfd72322017-08-09 14:04:12 -0700924 const int new_cost =
925 get_br_cost(abs_qc, new_ctx, txb_costs->lps_cost[new_ctx]);
Angie Chianga530ef42017-05-30 16:32:36 -0700926 const int cost_diff = -org_cost + new_cost;
927 return cost_diff;
928 } else {
929 return 0;
930 }
931}
932
933static int try_neighbor_level_down_base(int coeff_idx, int nb_coeff_idx,
934 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700935 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -0700936 const TxbInfo *txb_info) {
Ola Hugosson13892102017-11-06 08:01:44 +0100937#if CONFIG_LV_MAP_MULTI
938 // TODO(olah): not implemented yet
939 (void)coeff_idx;
940 (void)nb_coeff_idx;
941 (void)txb_cache;
942 (void)txb_costs;
943 (void)txb_info;
944 return 0;
945#else
Angie Chianga530ef42017-05-30 16:32:36 -0700946 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
947 const tran_low_t abs_qc = abs(qc);
Angie Chiangdef11252017-08-18 14:37:32 -0700948 const BASE_CTX_TABLE *base_ctx_table =
949 txb_info->coeff_ctx_table->base_ctx_table;
Angie Chianga530ef42017-05-30 16:32:36 -0700950
951 int cost_diff = 0;
952 for (int base_idx = 0; base_idx < NUM_BASE_LEVELS; ++base_idx) {
953 const int level = base_idx + 1;
954 if (abs_qc < level) continue;
955
956 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
957 const tran_low_t abs_nb_coeff = abs(nb_coeff);
958
959 const int count = txb_cache->base_count_arr[base_idx][coeff_idx];
960 const int *mag = txb_cache->base_mag_arr[coeff_idx];
961 int new_count;
962 int new_mag;
963 const int update =
964 neighbor_level_down_update(&new_count, &new_mag, count, mag, coeff_idx,
965 abs_nb_coeff, nb_coeff_idx, level, txb_info);
966 if (update) {
967 const int row = coeff_idx >> txb_info->bwl;
968 const int col = coeff_idx - (row << txb_info->bwl);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700969 const int ctx = txb_cache->base_ctx_arr[base_idx][coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700970 const int org_cost = get_base_cost(
971 abs_qc, ctx, txb_costs->base_cost[base_idx][ctx], base_idx);
Angie Chianga530ef42017-05-30 16:32:36 -0700972
973 const int new_ctx =
Angie Chiangdef11252017-08-18 14:37:32 -0700974 base_ctx_table[row != 0][col != 0][new_mag > level][new_count];
Jingning Handfd72322017-08-09 14:04:12 -0700975 const int new_cost = get_base_cost(
976 abs_qc, new_ctx, txb_costs->base_cost[base_idx][new_ctx], base_idx);
Angie Chianga530ef42017-05-30 16:32:36 -0700977 cost_diff += -org_cost + new_cost;
978 }
979 }
980 return cost_diff;
Ola Hugosson13892102017-11-06 08:01:44 +0100981#endif
Angie Chianga530ef42017-05-30 16:32:36 -0700982}
983
984static int try_neighbor_level_down_nz(int coeff_idx, int nb_coeff_idx,
985 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700986 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -0700987 TxbInfo *txb_info) {
988 // assume eob doesn't change
989 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
990 const tran_low_t abs_qc = abs(qc);
991 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
992 const tran_low_t abs_nb_coeff = abs(nb_coeff);
993 if (abs_nb_coeff != 1) return 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800994 const int16_t *const iscan = txb_info->scan_order->iscan;
Angie Chianga530ef42017-05-30 16:32:36 -0700995 const int scan_idx = iscan[coeff_idx];
996 if (scan_idx == txb_info->seg_eob) return 0;
997 const int nb_scan_idx = iscan[nb_coeff_idx];
998 if (nb_scan_idx < scan_idx) {
999 const int count = txb_cache->nz_count_arr[coeff_idx];
Linfeng Zhang8ac45572017-11-29 11:39:51 -08001000 (void)count;
Angie Chianga530ef42017-05-30 16:32:36 -07001001 assert(count > 0);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001002 update_qcoeff(nb_coeff_idx, get_lower_coeff(nb_coeff), txb_info);
Linfeng Zhang8ac45572017-11-29 11:39:51 -08001003 const int new_ctx = get_nz_map_ctx_from_stats(
Yaowu Xu102ef812017-12-12 11:31:03 -08001004 0, coeff_idx, txb_info->bwl, txb_info->tx_size,
1005 tx_type_to_class[txb_info->tx_type]);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001006 update_qcoeff(nb_coeff_idx, nb_coeff, txb_info);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001007 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
Ola Hugosson13892102017-11-06 08:01:44 +01001008#if CONFIG_LV_MAP_MULTI
1009 const int org_cost = txb_costs->base_cost[ctx][AOMMIN(abs_qc, 3)];
1010 const int new_cost = txb_costs->base_cost[new_ctx][AOMMIN(abs_qc, 3)];
1011#else
Angie Chianga530ef42017-05-30 16:32:36 -07001012 const int is_nz = abs_qc > 0;
Jingning Handfd72322017-08-09 14:04:12 -07001013 const int org_cost = txb_costs->nz_map_cost[ctx][is_nz];
1014 const int new_cost = txb_costs->nz_map_cost[new_ctx][is_nz];
Ola Hugosson13892102017-11-06 08:01:44 +01001015#endif
Angie Chianga530ef42017-05-30 16:32:36 -07001016 const int cost_diff = new_cost - org_cost;
1017 return cost_diff;
1018 } else {
1019 return 0;
1020 }
1021}
1022
1023static int try_self_level_down(tran_low_t *low_coeff, int coeff_idx,
1024 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001025 const LV_MAP_COEFF_COST *txb_costs,
1026 TxbInfo *txb_info) {
Angie Chiang7afbba42017-05-30 15:59:15 -07001027 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1028 if (qc == 0) {
1029 *low_coeff = 0;
1030 return 0;
1031 }
1032 const tran_low_t abs_qc = abs(qc);
1033 *low_coeff = get_lower_coeff(qc);
1034 int cost_diff;
1035 if (*low_coeff == 0) {
1036 const int scan_idx = txb_info->scan_order->iscan[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -07001037 const int *level_cost =
1038 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1039 const int *low_level_cost =
1040 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
Jingning Han3422ac12017-10-25 20:37:53 -07001041
Dake Hea47cd6c2017-10-13 18:09:58 -07001042 if (scan_idx < txb_info->eob - 1) {
Angie Chiang7afbba42017-05-30 15:59:15 -07001043 // When level-0, we code the binary of abs_qc > level
1044 // but when level-k k > 0 we code the binary of abs_qc == level
1045 // That's why wee need this special treatment for level-0 map
1046 // TODO(angiebird): make leve-0 consistent to other levels
Jingning Handfd72322017-08-09 14:04:12 -07001047 cost_diff = -level_cost[1] + low_level_cost[0] - low_level_cost[1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001048 } else {
Jingning Handfd72322017-08-09 14:04:12 -07001049 cost_diff = -level_cost[1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001050 }
1051
Angie Chiang7afbba42017-05-30 15:59:15 -07001052 const int sign_cost = get_sign_bit_cost(
Jingning Handfd72322017-08-09 14:04:12 -07001053 qc, coeff_idx, txb_costs->dc_sign_cost, txb_info->txb_ctx->dc_sign_ctx);
Angie Chiang7afbba42017-05-30 15:59:15 -07001054 cost_diff -= sign_cost;
Jingning Han772dee32017-09-15 08:53:18 -07001055 } else if (abs_qc <= NUM_BASE_LEVELS) {
1056 const int *level_cost =
1057 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1058 const int *low_level_cost =
1059 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1060 cost_diff = -level_cost[1] + low_level_cost[1] - low_level_cost[0];
1061 } else if (abs_qc == NUM_BASE_LEVELS + 1) {
1062 const int *level_cost =
1063 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1064 const int *low_level_cost =
1065 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1066 cost_diff = -level_cost[0] + low_level_cost[1] - low_level_cost[0];
Angie Chiang7afbba42017-05-30 15:59:15 -07001067 } else if (abs_qc < 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Jingning Handfd72322017-08-09 14:04:12 -07001068 const int *level_cost =
1069 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1070 const int *low_level_cost =
1071 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1072
Jingning Han772dee32017-09-15 08:53:18 -07001073 cost_diff = -level_cost[abs_qc - 1 - NUM_BASE_LEVELS] +
1074 low_level_cost[abs(*low_coeff) - 1 - NUM_BASE_LEVELS];
Angie Chiang7afbba42017-05-30 15:59:15 -07001075 } else if (abs_qc == 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Jingning Handfd72322017-08-09 14:04:12 -07001076 const int *low_level_cost =
1077 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
Jingning Han772dee32017-09-15 08:53:18 -07001078 cost_diff = -get_golomb_cost(abs_qc) - low_level_cost[COEFF_BASE_RANGE] +
1079 low_level_cost[COEFF_BASE_RANGE - 1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001080 } else {
1081 assert(abs_qc > 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE);
1082 const tran_low_t abs_low_coeff = abs(*low_coeff);
1083 cost_diff = -get_golomb_cost(abs_qc) + get_golomb_cost(abs_low_coeff);
1084 }
1085 return cost_diff;
1086}
1087
Angie Chianga530ef42017-05-30 16:32:36 -07001088#define COST_MAP_SIZE 5
1089#define COST_MAP_OFFSET 2
1090
1091static INLINE int check_nz_neighbor(tran_low_t qc) { return abs(qc) == 1; }
1092
1093static INLINE int check_base_neighbor(tran_low_t qc) {
1094 return abs(qc) <= 1 + NUM_BASE_LEVELS;
1095}
1096
1097static INLINE int check_br_neighbor(tran_low_t qc) {
1098 return abs(qc) > BR_MAG_OFFSET;
1099}
1100
Angie Chiang87278292017-10-18 09:59:47 -07001101#define FAST_OPTIMIZE_TXB 1
Angie Chiange80957f2017-09-05 10:48:00 -07001102
1103#if FAST_OPTIMIZE_TXB
1104#define ALNB_REF_OFFSET_NUM 2
Linfeng Zhang4afda452017-10-24 10:34:04 -07001105static const int alnb_ref_offset[ALNB_REF_OFFSET_NUM][2] = {
Angie Chiange80957f2017-09-05 10:48:00 -07001106 { -1, 0 }, { 0, -1 },
1107};
1108#define NB_REF_OFFSET_NUM 4
Linfeng Zhang4afda452017-10-24 10:34:04 -07001109static const int nb_ref_offset[NB_REF_OFFSET_NUM][2] = {
Angie Chiange80957f2017-09-05 10:48:00 -07001110 { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 },
1111};
1112#endif // FAST_OPTIMIZE_TXB
1113
Angie Chianga530ef42017-05-30 16:32:36 -07001114// TODO(angiebird): add static to this function once it's called
1115int try_level_down(int coeff_idx, const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001116 const LV_MAP_COEFF_COST *txb_costs, TxbInfo *txb_info,
Angie Chiang25645b72017-09-24 14:28:49 -07001117 int (*cost_map)[COST_MAP_SIZE], int fast_mode) {
1118#if !FAST_OPTIMIZE_TXB
1119 (void)fast_mode;
1120#endif
Angie Chianga530ef42017-05-30 16:32:36 -07001121 if (cost_map) {
1122 for (int i = 0; i < COST_MAP_SIZE; ++i) av1_zero(cost_map[i]);
1123 }
1124
1125 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1126 tran_low_t low_coeff;
1127 if (qc == 0) return 0;
1128 int accu_cost_diff = 0;
1129
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001130 const int16_t *const iscan = txb_info->scan_order->iscan;
Angie Chianga530ef42017-05-30 16:32:36 -07001131 const int eob = txb_info->eob;
1132 const int scan_idx = iscan[coeff_idx];
1133 if (scan_idx < eob) {
1134 const int cost_diff = try_self_level_down(&low_coeff, coeff_idx, txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001135 txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001136 if (cost_map)
1137 cost_map[0 + COST_MAP_OFFSET][0 + COST_MAP_OFFSET] = cost_diff;
1138 accu_cost_diff += cost_diff;
1139 }
1140
1141 const int row = coeff_idx >> txb_info->bwl;
1142 const int col = coeff_idx - (row << txb_info->bwl);
1143 if (check_nz_neighbor(qc)) {
Angie Chiange80957f2017-09-05 10:48:00 -07001144#if FAST_OPTIMIZE_TXB
Linfeng Zhang4afda452017-10-24 10:34:04 -07001145 const int(*ref_offset)[2];
Angie Chiang25645b72017-09-24 14:28:49 -07001146 int ref_num;
1147 if (fast_mode) {
1148 ref_offset = alnb_ref_offset;
1149 ref_num = ALNB_REF_OFFSET_NUM;
1150 } else {
1151 ref_offset = sig_ref_offset;
1152 ref_num = SIG_REF_OFFSET_NUM;
1153 }
Angie Chiange80957f2017-09-05 10:48:00 -07001154#else
Linfeng Zhang4afda452017-10-24 10:34:04 -07001155 const int(*ref_offset)[2] = sig_ref_offset;
Angie Chiange80957f2017-09-05 10:48:00 -07001156 const int ref_num = SIG_REF_OFFSET_NUM;
1157#endif
1158 for (int i = 0; i < ref_num; ++i) {
1159 const int nb_row = row - ref_offset[i][0];
1160 const int nb_col = col - ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001161 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han4cbb3632017-06-13 12:50:33 -07001162
Angie Chiang0c89dca2017-08-17 16:36:18 -07001163 if (nb_row < 0 || nb_col < 0 || nb_row >= txb_info->height ||
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001164 nb_col >= txb_info->width)
Jingning Han3455e762017-06-13 21:15:44 -07001165 continue;
1166
Angie Chianga530ef42017-05-30 16:32:36 -07001167 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001168 if (nb_scan_idx < eob) {
Angie Chianga530ef42017-05-30 16:32:36 -07001169 const int cost_diff = try_neighbor_level_down_nz(
Jingning Handfd72322017-08-09 14:04:12 -07001170 nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001171 if (cost_map)
1172 cost_map[nb_row - row + COST_MAP_OFFSET]
1173 [nb_col - col + COST_MAP_OFFSET] += cost_diff;
1174 accu_cost_diff += cost_diff;
1175 }
1176 }
1177 }
1178
1179 if (check_base_neighbor(qc)) {
Angie Chiange80957f2017-09-05 10:48:00 -07001180#if FAST_OPTIMIZE_TXB
Linfeng Zhang4afda452017-10-24 10:34:04 -07001181 const int(*ref_offset)[2];
Angie Chiang25645b72017-09-24 14:28:49 -07001182 int ref_num;
1183 if (fast_mode) {
1184 ref_offset = nb_ref_offset;
1185 ref_num = NB_REF_OFFSET_NUM;
1186 } else {
1187 ref_offset = base_ref_offset;
1188 ref_num = BASE_CONTEXT_POSITION_NUM;
1189 }
Angie Chiange80957f2017-09-05 10:48:00 -07001190#else
Linfeng Zhangce065ca2017-10-17 16:49:30 -07001191 const int(*ref_offset)[2] = base_ref_offset;
Angie Chiang25645b72017-09-24 14:28:49 -07001192 int ref_num = BASE_CONTEXT_POSITION_NUM;
Angie Chiange80957f2017-09-05 10:48:00 -07001193#endif
1194 for (int i = 0; i < ref_num; ++i) {
1195 const int nb_row = row - ref_offset[i][0];
1196 const int nb_col = col - ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001197 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001198
Angie Chiang0c89dca2017-08-17 16:36:18 -07001199 if (nb_row < 0 || nb_col < 0 || nb_row >= txb_info->height ||
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001200 nb_col >= txb_info->width)
Jingning Han3455e762017-06-13 21:15:44 -07001201 continue;
1202
Angie Chianga530ef42017-05-30 16:32:36 -07001203 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001204 if (nb_scan_idx < eob) {
Angie Chianga530ef42017-05-30 16:32:36 -07001205 const int cost_diff = try_neighbor_level_down_base(
Jingning Handfd72322017-08-09 14:04:12 -07001206 nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001207 if (cost_map)
1208 cost_map[nb_row - row + COST_MAP_OFFSET]
1209 [nb_col - col + COST_MAP_OFFSET] += cost_diff;
1210 accu_cost_diff += cost_diff;
1211 }
1212 }
1213 }
1214
1215 if (check_br_neighbor(qc)) {
Angie Chiange80957f2017-09-05 10:48:00 -07001216#if FAST_OPTIMIZE_TXB
Linfeng Zhang4afda452017-10-24 10:34:04 -07001217 const int(*ref_offset)[2];
Angie Chiang25645b72017-09-24 14:28:49 -07001218 int ref_num;
1219 if (fast_mode) {
1220 ref_offset = nb_ref_offset;
1221 ref_num = NB_REF_OFFSET_NUM;
1222 } else {
1223 ref_offset = br_ref_offset;
1224 ref_num = BR_CONTEXT_POSITION_NUM;
1225 }
Angie Chiange80957f2017-09-05 10:48:00 -07001226#else
Linfeng Zhangce065ca2017-10-17 16:49:30 -07001227 const int(*ref_offset)[2] = br_ref_offset;
Angie Chiange80957f2017-09-05 10:48:00 -07001228 const int ref_num = BR_CONTEXT_POSITION_NUM;
1229#endif
1230 for (int i = 0; i < ref_num; ++i) {
1231 const int nb_row = row - ref_offset[i][0];
1232 const int nb_col = col - ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001233 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001234
Angie Chiang0c89dca2017-08-17 16:36:18 -07001235 if (nb_row < 0 || nb_col < 0 || nb_row >= txb_info->height ||
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001236 nb_col >= txb_info->width)
Jingning Han3455e762017-06-13 21:15:44 -07001237 continue;
1238
Angie Chianga530ef42017-05-30 16:32:36 -07001239 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001240 if (nb_scan_idx < eob) {
Angie Chianga530ef42017-05-30 16:32:36 -07001241 const int cost_diff = try_neighbor_level_down_br(
Jingning Handfd72322017-08-09 14:04:12 -07001242 nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chianga530ef42017-05-30 16:32:36 -07001243 if (cost_map)
1244 cost_map[nb_row - row + COST_MAP_OFFSET]
1245 [nb_col - col + COST_MAP_OFFSET] += cost_diff;
1246 accu_cost_diff += cost_diff;
1247 }
1248 }
1249 }
1250
1251 return accu_cost_diff;
1252}
1253
Angie Chiangc77799b2017-05-30 17:08:17 -07001254static int get_low_coeff_cost(int coeff_idx, const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001255 const LV_MAP_COEFF_COST *txb_costs,
Angie Chiangc77799b2017-05-30 17:08:17 -07001256 const TxbInfo *txb_info) {
1257 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1258 const int abs_qc = abs(qc);
1259 assert(abs_qc <= 1);
1260 int cost = 0;
Jingning Han3422ac12017-10-25 20:37:53 -07001261
Ola Hugosson13892102017-11-06 08:01:44 +01001262#if CONFIG_LV_MAP_MULTI
1263 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
1264 cost += txb_costs->base_cost[ctx][AOMMIN(abs_qc, 3)];
1265 if (qc != 0) {
1266 cost += get_sign_bit_cost(qc, coeff_idx, txb_costs->dc_sign_cost,
1267 txb_info->txb_ctx->dc_sign_ctx);
1268 }
1269#else
1270 const int scan_idx = txb_info->scan_order->iscan[coeff_idx];
Dake Hea47cd6c2017-10-13 18:09:58 -07001271 if (scan_idx < txb_info->eob - 1) {
Jingning Handfd72322017-08-09 14:04:12 -07001272 const int *level_cost = get_level_prob(0, coeff_idx, txb_cache, txb_costs);
1273 cost += level_cost[qc != 0];
Angie Chiangc77799b2017-05-30 17:08:17 -07001274 }
1275
1276 if (qc != 0) {
1277 const int base_idx = 0;
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001278 const int ctx = txb_cache->base_ctx_arr[base_idx][coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -07001279 cost += get_base_cost(abs_qc, ctx, txb_costs->base_cost[base_idx][ctx],
1280 base_idx);
Jingning Handfd72322017-08-09 14:04:12 -07001281 cost += get_sign_bit_cost(qc, coeff_idx, txb_costs->dc_sign_cost,
Angie Chiangc77799b2017-05-30 17:08:17 -07001282 txb_info->txb_ctx->dc_sign_ctx);
1283 }
Ola Hugosson13892102017-11-06 08:01:44 +01001284#endif
Angie Chiangc77799b2017-05-30 17:08:17 -07001285 return cost;
1286}
1287
1288static INLINE void set_eob(TxbInfo *txb_info, int eob) {
1289 txb_info->eob = eob;
Urvang Joshi80893152017-10-27 11:51:14 -07001290 txb_info->seg_eob = av1_get_max_eob(txb_info->tx_size);
Angie Chiangc77799b2017-05-30 17:08:17 -07001291}
1292
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001293static INLINE int get_eob_ctx(const int coeff_idx, // raster order
1294 const TX_SIZE txs_ctx) {
1295 if (txs_ctx == TX_4X4) return av1_coeff_band_4x4[coeff_idx];
1296 if (txs_ctx == TX_8X8) return av1_coeff_band_8x8[coeff_idx];
1297 if (txs_ctx == TX_16X16) return av1_coeff_band_16x16[coeff_idx];
1298 if (txs_ctx == TX_32X32) return av1_coeff_band_32x32[coeff_idx];
1299
1300#if CONFIG_TX64X64
1301 // Since TX64X64 use 32x32 coeff buffer, so it share the same coeff_band with
1302 // TX32X32
1303 if (txs_ctx == TX_64X64) return av1_coeff_band_32x32[coeff_idx];
1304#endif // CONFIG_TX64X64
1305
1306 assert(0 && "Invalid value of txs_ctx");
1307 return 0;
1308}
1309
Angie Chiangc77799b2017-05-30 17:08:17 -07001310// TODO(angiebird): add static to this function once it's called
1311int try_change_eob(int *new_eob, int coeff_idx, const TxbCache *txb_cache,
Angie Chiang25645b72017-09-24 14:28:49 -07001312 const LV_MAP_COEFF_COST *txb_costs, TxbInfo *txb_info,
1313 int fast_mode) {
Angie Chiangc77799b2017-05-30 17:08:17 -07001314 assert(txb_info->eob > 0);
1315 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1316 const int abs_qc = abs(qc);
1317 if (abs_qc != 1) {
1318 *new_eob = -1;
1319 return 0;
1320 }
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001321 const int16_t *const iscan = txb_info->scan_order->iscan;
1322 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiangc77799b2017-05-30 17:08:17 -07001323 const int scan_idx = iscan[coeff_idx];
1324 *new_eob = 0;
1325 int cost_diff = 0;
Jingning Handfd72322017-08-09 14:04:12 -07001326 cost_diff -= get_low_coeff_cost(coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chiangc77799b2017-05-30 17:08:17 -07001327 for (int si = scan_idx - 1; si >= 0; --si) {
1328 const int ci = scan[si];
1329 if (txb_info->qcoeff[ci] != 0) {
1330 *new_eob = si + 1;
1331 break;
1332 } else {
Jingning Handfd72322017-08-09 14:04:12 -07001333 cost_diff -= get_low_coeff_cost(ci, txb_cache, txb_costs, txb_info);
Angie Chiangc77799b2017-05-30 17:08:17 -07001334 }
1335 }
1336
1337 const int org_eob = txb_info->eob;
1338 set_eob(txb_info, *new_eob);
Angie Chiang25645b72017-09-24 14:28:49 -07001339 cost_diff += try_level_down(coeff_idx, txb_cache, txb_costs, txb_info, NULL,
1340 fast_mode);
Angie Chiangc77799b2017-05-30 17:08:17 -07001341 set_eob(txb_info, org_eob);
1342
1343 if (*new_eob > 0) {
1344 // Note that get_eob_ctx does NOT actually account for qcoeff, so we don't
1345 // need to lower down the qcoeff here
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001346 const int eob_ctx = get_eob_ctx(scan[*new_eob - 1], txb_info->txs_ctx);
Jingning Handfd72322017-08-09 14:04:12 -07001347 cost_diff -= txb_costs->eob_cost[eob_ctx][0];
1348 cost_diff += txb_costs->eob_cost[eob_ctx][1];
Angie Chiangc77799b2017-05-30 17:08:17 -07001349 } else {
1350 const int txb_skip_ctx = txb_info->txb_ctx->txb_skip_ctx;
Jingning Handfd72322017-08-09 14:04:12 -07001351 cost_diff -= txb_costs->txb_skip_cost[txb_skip_ctx][0];
1352 cost_diff += txb_costs->txb_skip_cost[txb_skip_ctx][1];
Angie Chiangc77799b2017-05-30 17:08:17 -07001353 }
1354 return cost_diff;
1355}
Angie Chiang47e07072017-05-30 17:27:01 -07001356
Angie Chiangd19969e2017-05-30 18:02:33 -07001357// TODO(angiebird): add static to this function it's called
Linfeng Zhang1015a342017-10-24 16:20:41 -07001358void update_level_down(const int coeff_idx, TxbCache *const txb_cache,
1359 TxbInfo *const txb_info) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001360 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1361 const int abs_qc = abs(qc);
1362 if (qc == 0) return;
1363 const tran_low_t low_coeff = get_lower_coeff(qc);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001364 update_coeff(coeff_idx, low_coeff, txb_info);
Angie Chiangd19969e2017-05-30 18:02:33 -07001365
1366 const int row = coeff_idx >> txb_info->bwl;
1367 const int col = coeff_idx - (row << txb_info->bwl);
1368 const int eob = txb_info->eob;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001369 const int16_t *const iscan = txb_info->scan_order->iscan;
Angie Chiangd19969e2017-05-30 18:02:33 -07001370 for (int i = 0; i < SIG_REF_OFFSET_NUM; ++i) {
1371 const int nb_row = row - sig_ref_offset[i][0];
1372 const int nb_col = col - sig_ref_offset[i][1];
Jingning Han3455e762017-06-13 21:15:44 -07001373
1374 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001375 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001376 continue;
1377
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001378 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiangd19969e2017-05-30 18:02:33 -07001379 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001380 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001381 const int scan_idx = iscan[coeff_idx];
1382 if (scan_idx < nb_scan_idx) {
1383 const int level = 1;
1384 if (abs_qc == level) {
1385 txb_cache->nz_count_arr[nb_coeff_idx] -= 1;
1386 assert(txb_cache->nz_count_arr[nb_coeff_idx] >= 0);
1387 }
Yaowu Xu102ef812017-12-12 11:31:03 -08001388 txb_cache->nz_ctx_arr[nb_coeff_idx] = get_nz_map_ctx_from_stats(
1389 0, nb_coeff_idx, txb_info->bwl, txb_info->tx_size,
1390 tx_type_to_class[txb_info->tx_type]);
Angie Chiangd19969e2017-05-30 18:02:33 -07001391 }
1392 }
1393 }
1394
Angie Chiangdef11252017-08-18 14:37:32 -07001395 const BASE_CTX_TABLE *base_ctx_table =
1396 txb_info->coeff_ctx_table->base_ctx_table;
Angie Chiangd19969e2017-05-30 18:02:33 -07001397 for (int i = 0; i < BASE_CONTEXT_POSITION_NUM; ++i) {
1398 const int nb_row = row - base_ref_offset[i][0];
1399 const int nb_col = col - base_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001400 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001401
1402 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001403 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001404 continue;
1405
Angie Chiangd19969e2017-05-30 18:02:33 -07001406 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
1407 if (!has_base(nb_coeff, 0)) continue;
1408 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001409 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001410 if (row >= nb_row && col >= nb_col)
1411 update_mag_arr(txb_cache->base_mag_arr[nb_coeff_idx], abs_qc);
1412 const int mag =
1413 get_mag_from_mag_arr(txb_cache->base_mag_arr[nb_coeff_idx]);
1414 for (int base_idx = 0; base_idx < NUM_BASE_LEVELS; ++base_idx) {
1415 if (!has_base(nb_coeff, base_idx)) continue;
1416 const int level = base_idx + 1;
1417 if (abs_qc == level) {
1418 txb_cache->base_count_arr[base_idx][nb_coeff_idx] -= 1;
1419 assert(txb_cache->base_count_arr[base_idx][nb_coeff_idx] >= 0);
1420 }
1421 const int count = txb_cache->base_count_arr[base_idx][nb_coeff_idx];
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001422 txb_cache->base_ctx_arr[base_idx][nb_coeff_idx] =
Angie Chiangdef11252017-08-18 14:37:32 -07001423 base_ctx_table[nb_row != 0][nb_col != 0][mag > level][count];
Angie Chiangd19969e2017-05-30 18:02:33 -07001424 }
1425 }
1426 }
1427
1428 for (int i = 0; i < BR_CONTEXT_POSITION_NUM; ++i) {
1429 const int nb_row = row - br_ref_offset[i][0];
1430 const int nb_col = col - br_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001431 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001432
1433 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001434 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001435 continue;
1436
Angie Chiangd19969e2017-05-30 18:02:33 -07001437 const int nb_scan_idx = iscan[nb_coeff_idx];
1438 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
1439 if (!has_br(nb_coeff)) continue;
Jingning Han3455e762017-06-13 21:15:44 -07001440 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001441 const int level = 1 + NUM_BASE_LEVELS;
1442 if (abs_qc == level) {
1443 txb_cache->br_count_arr[nb_coeff_idx] -= 1;
1444 assert(txb_cache->br_count_arr[nb_coeff_idx] >= 0);
1445 }
1446 if (row >= nb_row && col >= nb_col)
1447 update_mag_arr(txb_cache->br_mag_arr[nb_coeff_idx], abs_qc);
1448 const int count = txb_cache->br_count_arr[nb_coeff_idx];
1449 const int mag = get_mag_from_mag_arr(txb_cache->br_mag_arr[nb_coeff_idx]);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001450 txb_cache->br_ctx_arr[nb_coeff_idx] =
Angie Chiangd19969e2017-05-30 18:02:33 -07001451 get_br_ctx_from_count_mag(nb_row, nb_col, count, mag);
Angie Chiangd19969e2017-05-30 18:02:33 -07001452 }
1453 }
1454}
1455
Linfeng Zhang1015a342017-10-24 16:20:41 -07001456static int get_coeff_cost(const tran_low_t qc, const int scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +01001457#if CONFIG_LV_MAP_MULTI
1458 const int is_eob,
1459#endif
Linfeng Zhang1015a342017-10-24 16:20:41 -07001460 const TxbInfo *const txb_info,
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001461 const LV_MAP_COEFF_COST *const txb_costs,
1462 const int coeff_ctx) {
Angie Chiang488f9212017-05-30 12:46:26 -07001463 const TXB_CTX *txb_ctx = txb_info->txb_ctx;
1464 const int is_nz = (qc != 0);
1465 const tran_low_t abs_qc = abs(qc);
1466 int cost = 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001467 const int16_t *const scan = txb_info->scan_order->scan;
1468 const int pos = scan[scan_idx];
Dake He03a32922017-10-31 08:06:45 -07001469
Ola Hugosson13892102017-11-06 08:01:44 +01001470#if CONFIG_LV_MAP_MULTI
Dake He3fe369c2017-11-16 17:56:44 -08001471#if USE_BASE_EOB_ALPHABET
1472 if (is_eob) {
1473 cost +=
1474 txb_costs->base_eob_cost[coeff_ctx - SIG_COEF_CONTEXTS +
1475 SIG_COEF_CONTEXTS_EOB][AOMMIN(abs_qc, 3) - 1];
1476 } else {
1477 cost += txb_costs->base_cost[coeff_ctx][AOMMIN(abs_qc, 3)];
1478 }
1479
1480#else
Ola Hugosson13892102017-11-06 08:01:44 +01001481 cost += txb_costs->base_cost[coeff_ctx][AOMMIN(abs_qc, 3)];
Dake He3fe369c2017-11-16 17:56:44 -08001482#endif
Ola Hugosson13892102017-11-06 08:01:44 +01001483#else
Dake Hea47cd6c2017-10-13 18:09:58 -07001484 if (scan_idx < txb_info->eob - 1) {
Jingning Handfd72322017-08-09 14:04:12 -07001485 cost += txb_costs->nz_map_cost[coeff_ctx][is_nz];
Angie Chiang488f9212017-05-30 12:46:26 -07001486 }
Ola Hugosson13892102017-11-06 08:01:44 +01001487#endif
Angie Chiang488f9212017-05-30 12:46:26 -07001488 if (is_nz) {
Jingning Handfd72322017-08-09 14:04:12 -07001489 cost += get_sign_bit_cost(qc, scan_idx, txb_costs->dc_sign_cost,
Angie Chiang488f9212017-05-30 12:46:26 -07001490 txb_ctx->dc_sign_ctx);
1491
Ola Hugosson13892102017-11-06 08:01:44 +01001492#if !CONFIG_LV_MAP_MULTI
Dake He03a32922017-10-31 08:06:45 -07001493 int k;
1494 for (k = 0; k < NUM_BASE_LEVELS; ++k) {
1495 int ctx = coeff_ctx;
1496 int is_k = (abs_qc > (k + 1));
1497
1498 cost += txb_costs->base_cost[k][ctx][is_k];
1499 if (is_k == 0) break;
1500 }
Ola Hugosson13892102017-11-06 08:01:44 +01001501#endif
Angie Chiang488f9212017-05-30 12:46:26 -07001502 if (abs_qc > NUM_BASE_LEVELS) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001503 const int row = pos >> txb_info->bwl;
1504 const int col = pos - (row << txb_info->bwl);
Dake He7d01ab52017-11-24 17:53:28 -08001505
1506#if CONFIG_LV_MAP_MULTI && USE_CAUSAL_BR_CTX
1507 (void)col;
1508 const int count = 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001509 const int ctx = get_br_ctx(txb_info->levels, pos, txb_info->bwl, count,
1510 txb_info->tx_type);
Dake He7d01ab52017-11-24 17:53:28 -08001511#else
Linfeng Zhang97fc4742017-11-07 12:57:25 -08001512 const int count = get_level_count(
1513 txb_info->levels, (1 << txb_info->bwl) + TX_PAD_HOR, row, col,
1514 NUM_BASE_LEVELS, br_ref_offset, BR_CONTEXT_POSITION_NUM);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001515 const int ctx = get_br_ctx(txb_info->levels, pos, txb_info->bwl, count);
Dake He7d01ab52017-11-24 17:53:28 -08001516#endif
Jingning Handfd72322017-08-09 14:04:12 -07001517 cost += get_br_cost(abs_qc, ctx, txb_costs->lps_cost[ctx]);
Angie Chiang488f9212017-05-30 12:46:26 -07001518 cost += get_golomb_cost(abs_qc);
1519 }
Angie Chiang488f9212017-05-30 12:46:26 -07001520 }
1521 return cost;
1522}
1523
Angie Chiang47e07072017-05-30 17:27:01 -07001524#if TEST_OPTIMIZE_TXB
Angie Chiang5e012fe2017-05-30 18:47:39 -07001525#define ALL_REF_OFFSET_NUM 17
Linfeng Zhang4afda452017-10-24 10:34:04 -07001526static const int all_ref_offset[ALL_REF_OFFSET_NUM][2] = {
Angie Chiang5e012fe2017-05-30 18:47:39 -07001527 { 0, 0 }, { -2, -1 }, { -2, 0 }, { -2, 1 }, { -1, -2 }, { -1, -1 },
1528 { -1, 0 }, { -1, 1 }, { 0, -2 }, { 0, -1 }, { 1, -2 }, { 1, -1 },
1529 { 1, 0 }, { 2, 0 }, { 0, 1 }, { 0, 2 }, { 1, 1 },
1530};
1531
Angie Chiang0b2795c2017-09-29 16:00:08 -07001532static int try_level_down_ref(int coeff_idx, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang5e012fe2017-05-30 18:47:39 -07001533 TxbInfo *txb_info,
1534 int (*cost_map)[COST_MAP_SIZE]) {
1535 if (cost_map) {
1536 for (int i = 0; i < COST_MAP_SIZE; ++i) av1_zero(cost_map[i]);
1537 }
1538 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1539 if (qc == 0) return 0;
1540 int row = coeff_idx >> txb_info->bwl;
1541 int col = coeff_idx - (row << txb_info->bwl);
1542 int org_cost = 0;
1543 for (int i = 0; i < ALL_REF_OFFSET_NUM; ++i) {
1544 int nb_row = row - all_ref_offset[i][0];
1545 int nb_col = col - all_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001546 int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001547 int nb_scan_idx = txb_info->scan_order->iscan[nb_coeff_idx];
1548 if (nb_scan_idx < txb_info->eob && nb_row >= 0 && nb_col >= 0 &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001549 nb_row < txb_info->height && nb_col < txb_info->width) {
Linfeng Zhang960e7002017-12-11 13:46:40 -08001550 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001551 const int coeff_ctx =
1552 get_nz_map_ctx(txb_info->levels, nb_coeff_idx, txb_info->bwl,
1553#if CONFIG_LV_MAP_MULTI
1554 txb_info->height, nb_scan_idx, is_eob,
1555#endif
1556 txb_info->tx_size, txb_info->tx_type);
Linfeng Zhang960e7002017-12-11 13:46:40 -08001557 const int cost = get_coeff_cost(nb_coeff, nb_scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +01001558#if CONFIG_LV_MAP_MULTI
Linfeng Zhang960e7002017-12-11 13:46:40 -08001559 is_eob,
Ola Hugosson13892102017-11-06 08:01:44 +01001560#endif
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001561 txb_info, txb_costs, coeff_ctx);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001562 if (cost_map)
1563 cost_map[nb_row - row + COST_MAP_OFFSET]
1564 [nb_col - col + COST_MAP_OFFSET] -= cost;
1565 org_cost += cost;
1566 }
1567 }
Linfeng Zhang1015a342017-10-24 16:20:41 -07001568 update_qcoeff(coeff_idx, get_lower_coeff(qc), txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001569 int new_cost = 0;
1570 for (int i = 0; i < ALL_REF_OFFSET_NUM; ++i) {
1571 int nb_row = row - all_ref_offset[i][0];
1572 int nb_col = col - all_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001573 int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001574 int nb_scan_idx = txb_info->scan_order->iscan[nb_coeff_idx];
1575 if (nb_scan_idx < txb_info->eob && nb_row >= 0 && nb_col >= 0 &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001576 nb_row < txb_info->height && nb_col < txb_info->width) {
Linfeng Zhang960e7002017-12-11 13:46:40 -08001577 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001578 const int coeff_ctx =
1579 get_nz_map_ctx(txb_info->levels, nb_coeff_idx, txb_info->bwl,
1580#if CONFIG_LV_MAP_MULTI
1581 txb_info->height, nb_scan_idx, is_eob,
1582#endif
1583 txb_info->tx_size, txb_info->tx_type);
Linfeng Zhang960e7002017-12-11 13:46:40 -08001584 const int cost = get_coeff_cost(nb_coeff, nb_scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +01001585#if CONFIG_LV_MAP_MULTI
Linfeng Zhang960e7002017-12-11 13:46:40 -08001586 is_eob,
Ola Hugosson13892102017-11-06 08:01:44 +01001587#endif
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001588 txb_info, txb_costs, coeff_ctx);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001589 if (cost_map)
1590 cost_map[nb_row - row + COST_MAP_OFFSET]
1591 [nb_col - col + COST_MAP_OFFSET] += cost;
1592 new_cost += cost;
1593 }
1594 }
Linfeng Zhang1015a342017-10-24 16:20:41 -07001595 update_qcoeff(coeff_idx, qc, txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001596 return new_cost - org_cost;
1597}
1598
1599static void test_level_down(int coeff_idx, const TxbCache *txb_cache,
Angie Chiang0b2795c2017-09-29 16:00:08 -07001600 const LV_MAP_COEFF_COST *txb_costs,
1601 TxbInfo *txb_info) {
Angie Chiang47e07072017-05-30 17:27:01 -07001602 int cost_map[COST_MAP_SIZE][COST_MAP_SIZE];
1603 int ref_cost_map[COST_MAP_SIZE][COST_MAP_SIZE];
1604 const int cost_diff =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001605 try_level_down(coeff_idx, txb_cache, txb_costs, txb_info, cost_map, 0);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001606 const int cost_diff_ref =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001607 try_level_down_ref(coeff_idx, txb_costs, txb_info, ref_cost_map);
Angie Chiang47e07072017-05-30 17:27:01 -07001608 if (cost_diff != cost_diff_ref) {
1609 printf("qc %d cost_diff %d cost_diff_ref %d\n", txb_info->qcoeff[coeff_idx],
1610 cost_diff, cost_diff_ref);
1611 for (int r = 0; r < COST_MAP_SIZE; ++r) {
1612 for (int c = 0; c < COST_MAP_SIZE; ++c) {
1613 printf("%d:%d ", cost_map[r][c], ref_cost_map[r][c]);
1614 }
1615 printf("\n");
1616 }
1617 }
1618}
1619#endif
1620
Angie Chiang488f9212017-05-30 12:46:26 -07001621// TODO(angiebird): make this static once it's called
Jingning Handfd72322017-08-09 14:04:12 -07001622int get_txb_cost(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs) {
Angie Chiang488f9212017-05-30 12:46:26 -07001623 int cost = 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001624 const int txb_skip_ctx = txb_info->txb_ctx->txb_skip_ctx;
1625 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang488f9212017-05-30 12:46:26 -07001626 if (txb_info->eob == 0) {
Jingning Handfd72322017-08-09 14:04:12 -07001627 cost = txb_costs->txb_skip_cost[txb_skip_ctx][1];
Angie Chiang488f9212017-05-30 12:46:26 -07001628 return cost;
1629 }
Jingning Handfd72322017-08-09 14:04:12 -07001630 cost = txb_costs->txb_skip_cost[txb_skip_ctx][0];
Angie Chiang488f9212017-05-30 12:46:26 -07001631 for (int c = 0; c < txb_info->eob; ++c) {
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001632 const int pos = scan[c];
1633 const tran_low_t qc = txb_info->qcoeff[pos];
1634 const int coeff_ctx =
1635 get_nz_map_ctx(txb_info->levels, pos, txb_info->bwl,
1636#if CONFIG_LV_MAP_MULTI
1637 txb_info->height, c, c == txb_info->eob - 1,
1638#endif
1639 txb_info->tx_size, txb_info->tx_type);
Linfeng Zhang960e7002017-12-11 13:46:40 -08001640 const int coeff_cost = get_coeff_cost(qc, c,
Ola Hugosson13892102017-11-06 08:01:44 +01001641#if CONFIG_LV_MAP_MULTI
Linfeng Zhang960e7002017-12-11 13:46:40 -08001642 c == txb_info->eob - 1,
Ola Hugosson13892102017-11-06 08:01:44 +01001643#endif
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001644 txb_info, txb_costs, coeff_ctx);
Angie Chiang488f9212017-05-30 12:46:26 -07001645 cost += coeff_cost;
1646 }
1647 return cost;
1648}
1649
Angie Chiang5e012fe2017-05-30 18:47:39 -07001650#if TEST_OPTIMIZE_TXB
Angie Chiang0b2795c2017-09-29 16:00:08 -07001651void test_try_change_eob(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang5e012fe2017-05-30 18:47:39 -07001652 TxbCache *txb_cache) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001653 const int eob = txb_info->eob;
1654 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001655 if (eob > 0) {
1656 int last_si = eob - 1;
1657 int last_ci = scan[last_si];
1658 int last_coeff = txb_info->qcoeff[last_ci];
1659 if (abs(last_coeff) == 1) {
1660 int new_eob;
1661 int cost_diff =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001662 try_change_eob(&new_eob, last_ci, txb_cache, txb_costs, txb_info, 0);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001663 int org_eob = txb_info->eob;
Angie Chiang0b2795c2017-09-29 16:00:08 -07001664 int cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001665
Linfeng Zhang1015a342017-10-24 16:20:41 -07001666 update_qcoeff(last_ci, get_lower_coeff(last_coeff), txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001667 set_eob(txb_info, new_eob);
Angie Chiang0b2795c2017-09-29 16:00:08 -07001668 int new_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001669 set_eob(txb_info, org_eob);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001670 update_qcoeff(last_ci, last_coeff, txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001671
1672 int ref_cost_diff = -cost + new_cost;
1673 if (cost_diff != ref_cost_diff)
1674 printf("org_eob %d new_eob %d cost_diff %d ref_cost_diff %d\n", org_eob,
1675 new_eob, cost_diff, ref_cost_diff);
1676 }
1677 }
1678}
1679#endif
1680
Angie Chiang47e07072017-05-30 17:27:01 -07001681void try_level_down_facade(LevelDownStats *stats, int scan_idx,
Jingning Handfd72322017-08-09 14:04:12 -07001682 const TxbCache *txb_cache,
1683 const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang25645b72017-09-24 14:28:49 -07001684 TxbInfo *txb_info, int fast_mode) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001685 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang47e07072017-05-30 17:27:01 -07001686 const int coeff_idx = scan[scan_idx];
1687 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1688 stats->new_eob = -1;
1689 stats->update = 0;
1690 if (qc == 0) {
1691 return;
1692 }
1693
1694 const tran_low_t tqc = txb_info->tcoeff[coeff_idx];
1695 const int dqv = txb_info->dequant[coeff_idx != 0];
1696
1697 const tran_low_t dqc = qcoeff_to_dqcoeff(qc, dqv, txb_info->shift);
Jingning Han641c1e52017-10-13 09:42:49 -07001698
1699 if (scan_idx != txb_info->eob - 1)
1700 if (abs(dqc) < abs(tqc)) return;
1701
Angie Chiang47e07072017-05-30 17:27:01 -07001702 const int64_t dqc_dist = get_coeff_dist(tqc, dqc, txb_info->shift);
1703
1704 stats->low_qc = get_lower_coeff(qc);
1705 stats->low_dqc = qcoeff_to_dqcoeff(stats->low_qc, dqv, txb_info->shift);
1706 const int64_t low_dqc_dist =
1707 get_coeff_dist(tqc, stats->low_dqc, txb_info->shift);
1708
1709 stats->dist_diff = -dqc_dist + low_dqc_dist;
1710 stats->cost_diff = 0;
1711 stats->new_eob = txb_info->eob;
1712 if (scan_idx == txb_info->eob - 1 && abs(qc) == 1) {
1713 stats->cost_diff = try_change_eob(&stats->new_eob, coeff_idx, txb_cache,
Angie Chiang25645b72017-09-24 14:28:49 -07001714 txb_costs, txb_info, fast_mode);
Angie Chiang47e07072017-05-30 17:27:01 -07001715 } else {
Angie Chiang25645b72017-09-24 14:28:49 -07001716 stats->cost_diff = try_level_down(coeff_idx, txb_cache, txb_costs, txb_info,
1717 NULL, fast_mode);
Angie Chiang47e07072017-05-30 17:27:01 -07001718#if TEST_OPTIMIZE_TXB
Angie Chiang0b2795c2017-09-29 16:00:08 -07001719 test_level_down(coeff_idx, txb_cache, txb_costs, txb_info);
Angie Chiang47e07072017-05-30 17:27:01 -07001720#endif
1721 }
Urvang Joshi70006e42017-06-14 16:08:55 -07001722 stats->rd_diff = RDCOST(txb_info->rdmult, stats->cost_diff, stats->dist_diff);
Angie Chiang47e07072017-05-30 17:27:01 -07001723 if (stats->rd_diff < 0) stats->update = 1;
1724 return;
1725}
Angie Chiang07c57f32017-05-30 18:18:33 -07001726
Jingning Han3422ac12017-10-25 20:37:53 -07001727#if 1
Dake Hea47cd6c2017-10-13 18:09:58 -07001728static int optimize_txb(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
1729 TxbCache *txb_cache, int dry_run, int fast_mode) {
1730 (void)fast_mode;
1731 (void)txb_cache;
1732 int update = 0;
Dake He59881772017-11-24 07:00:02 -08001733 // return update; // TODO(DKHE): training only.
Dake Hea47cd6c2017-10-13 18:09:58 -07001734 if (txb_info->eob == 0) return update;
Urvang Joshi80893152017-10-27 11:51:14 -07001735 const int max_eob = av1_get_max_eob(txb_info->tx_size);
Dake Hea47cd6c2017-10-13 18:09:58 -07001736
1737#if TEST_OPTIMIZE_TXB
1738 int64_t sse;
1739 int64_t org_dist =
1740 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1741 (1 << (2 * txb_info->shift));
1742 int org_cost = get_txb_cost(txb_info, txb_probs);
1743#endif
1744
1745 tran_low_t *org_qcoeff = txb_info->qcoeff;
1746 tran_low_t *org_dqcoeff = txb_info->dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001747 uint8_t *const org_levels = txb_info->levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001748
1749 tran_low_t tmp_qcoeff[MAX_TX_SQUARE];
1750 tran_low_t tmp_dqcoeff[MAX_TX_SQUARE];
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001751 uint8_t tmp_levels_buf[TX_PAD_2D];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001752 uint8_t *const tmp_levels = set_levels(tmp_levels_buf, txb_info->width);
Dake Hea47cd6c2017-10-13 18:09:58 -07001753 const int org_eob = txb_info->eob;
1754 if (dry_run) {
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001755 const int stride = txb_info->width + TX_PAD_HOR;
1756 const int levels_size =
1757
1758 (stride * (txb_info->height + TX_PAD_VER) + TX_PAD_END);
Dake Hea47cd6c2017-10-13 18:09:58 -07001759 memcpy(tmp_qcoeff, org_qcoeff, sizeof(org_qcoeff[0]) * max_eob);
1760 memcpy(tmp_dqcoeff, org_dqcoeff, sizeof(org_dqcoeff[0]) * max_eob);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001761 memcpy(tmp_levels, org_levels - TX_PAD_TOP * stride,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001762 sizeof(org_levels[0]) * levels_size);
Dake Hea47cd6c2017-10-13 18:09:58 -07001763 txb_info->qcoeff = tmp_qcoeff;
1764 txb_info->dqcoeff = tmp_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001765 txb_info->levels = tmp_levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001766 }
1767
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001768 const int16_t *const scan = txb_info->scan_order->scan;
Dake Hea47cd6c2017-10-13 18:09:58 -07001769
1770 // forward optimize the nz_map`
1771 const int init_eob = txb_info->eob;
1772 const int seg_eob = txb_info->seg_eob;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001773 const int eob_cost =
1774 get_eob_cost(init_eob, seg_eob, txb_costs, txb_info->tx_type);
Dake Hea47cd6c2017-10-13 18:09:58 -07001775
1776 // backward optimize the level-k map
1777 int64_t accu_rate = eob_cost;
1778 int64_t accu_dist = 0;
1779 int64_t prev_eob_rd_cost = INT64_MAX;
1780 int64_t cur_eob_rd_cost = 0;
Jingning Han8be58fa2017-12-18 09:46:13 -08001781 int8_t has_nz_tail = 0;
Dake Hea47cd6c2017-10-13 18:09:58 -07001782
1783 for (int si = init_eob - 1; si >= 0; --si) {
1784 const int coeff_idx = scan[si];
1785 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1786
1787 LevelDownStats stats;
Linfeng Zhang960e7002017-12-11 13:46:40 -08001788 get_dist_cost_stats(&stats, si,
Ola Hugosson13892102017-11-06 08:01:44 +01001789#if CONFIG_LV_MAP_MULTI
Linfeng Zhang960e7002017-12-11 13:46:40 -08001790 si == init_eob - 1,
Ola Hugosson13892102017-11-06 08:01:44 +01001791#endif
Linfeng Zhang960e7002017-12-11 13:46:40 -08001792 txb_costs, txb_info);
Dake Hea47cd6c2017-10-13 18:09:58 -07001793
1794 if (qc == 0) {
1795 accu_rate += stats.rate;
1796 } else {
Jingning Han8be58fa2017-12-18 09:46:13 -08001797 if (has_nz_tail < 2) {
1798 // check if it is better to make this the last significant coefficient
1799 int cur_eob_rate =
1800 get_eob_cost(si + 1, seg_eob, txb_costs, txb_info->tx_type);
1801 cur_eob_rd_cost = RDCOST(txb_info->rdmult, cur_eob_rate, 0);
1802 prev_eob_rd_cost =
1803 RDCOST(txb_info->rdmult, accu_rate + stats.nz_rate, accu_dist);
1804 if (cur_eob_rd_cost <= prev_eob_rd_cost) {
1805 update = 1;
1806 for (int j = si + 1; j < txb_info->eob; j++) {
1807 const int coeff_pos_j = scan[j];
1808 update_coeff(coeff_pos_j, 0, txb_info);
1809 }
1810 txb_info->eob = si + 1;
Dake Hea47cd6c2017-10-13 18:09:58 -07001811
Jingning Han8be58fa2017-12-18 09:46:13 -08001812 // rerun cost calculation due to change of eob
1813 accu_rate = cur_eob_rate;
1814 accu_dist = 0;
1815 get_dist_cost_stats(&stats, si,
Ola Hugosson13892102017-11-06 08:01:44 +01001816#if CONFIG_LV_MAP_MULTI
Jingning Han8be58fa2017-12-18 09:46:13 -08001817 1,
Ola Hugosson13892102017-11-06 08:01:44 +01001818#endif
Jingning Han8be58fa2017-12-18 09:46:13 -08001819 txb_costs, txb_info);
1820 accu_rate += stats.rate;
1821 accu_dist += stats.dist;
1822 continue;
1823 }
Dake Hea47cd6c2017-10-13 18:09:58 -07001824 }
1825
1826 int bUpdCoeff = 0;
1827 if (stats.rd_low < stats.rd) {
Jingning Hana7a6f4e2017-12-13 14:44:08 -08001828 if (si < txb_info->eob - 1) {
Dake Hea47cd6c2017-10-13 18:09:58 -07001829 bUpdCoeff = 1;
1830 update = 1;
1831 }
Jingning Han8be58fa2017-12-18 09:46:13 -08001832 } else {
1833 ++has_nz_tail;
Dake Hea47cd6c2017-10-13 18:09:58 -07001834 }
1835
1836 if (bUpdCoeff) {
1837 update_coeff(coeff_idx, stats.low_qc, txb_info);
1838 accu_rate += stats.rate_low;
1839 accu_dist += stats.dist_low;
1840 } else {
1841 accu_rate += stats.rate;
1842 accu_dist += stats.dist;
1843 }
1844 }
1845 } // for (si)
Jingning Hana7a6f4e2017-12-13 14:44:08 -08001846
Dake Hea47cd6c2017-10-13 18:09:58 -07001847 int non_zero_blk_rate =
1848 txb_costs->txb_skip_cost[txb_info->txb_ctx->txb_skip_ctx][0];
1849 prev_eob_rd_cost =
1850 RDCOST(txb_info->rdmult, accu_rate + non_zero_blk_rate, accu_dist);
1851
1852 int zero_blk_rate =
1853 txb_costs->txb_skip_cost[txb_info->txb_ctx->txb_skip_ctx][1];
1854 int64_t zero_blk_rd_cost = RDCOST(txb_info->rdmult, zero_blk_rate, 0);
1855 if (zero_blk_rd_cost <= prev_eob_rd_cost) {
1856 update = 1;
1857 for (int j = 0; j < txb_info->eob; j++) {
1858 const int coeff_pos_j = scan[j];
1859 update_coeff(coeff_pos_j, 0, txb_info);
1860 }
1861 txb_info->eob = 0;
1862 }
1863
1864#if TEST_OPTIMIZE_TXB
1865 int cost_diff = 0;
1866 int64_t dist_diff = 0;
1867 int64_t rd_diff = 0;
1868 int64_t new_dist =
1869 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1870 (1 << (2 * txb_info->shift));
1871 int new_cost = get_txb_cost(txb_info, txb_probs);
1872 int64_t ref_dist_diff = new_dist - org_dist;
1873 int ref_cost_diff = new_cost - org_cost;
1874 if (cost_diff != ref_cost_diff || dist_diff != ref_dist_diff)
1875 printf(
1876 "overall rd_diff %ld\ncost_diff %d ref_cost_diff%d\ndist_diff %ld "
1877 "ref_dist_diff %ld\neob %d new_eob %d\n\n",
1878 rd_diff, cost_diff, ref_cost_diff, dist_diff, ref_dist_diff, org_eob,
1879 txb_info->eob);
1880#endif
1881 if (dry_run) {
1882 txb_info->qcoeff = org_qcoeff;
1883 txb_info->dqcoeff = org_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001884 txb_info->levels = org_levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001885 set_eob(txb_info, org_eob);
1886 }
1887 return update;
1888}
1889
1890#else
Jingning Handfd72322017-08-09 14:04:12 -07001891static int optimize_txb(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang25645b72017-09-24 14:28:49 -07001892 TxbCache *txb_cache, int dry_run, int fast_mode) {
Angie Chiang07c57f32017-05-30 18:18:33 -07001893 int update = 0;
1894 if (txb_info->eob == 0) return update;
1895 int cost_diff = 0;
1896 int64_t dist_diff = 0;
1897 int64_t rd_diff = 0;
Urvang Joshi80893152017-10-27 11:51:14 -07001898 const int max_eob = av1_get_max_eob(txb_info->tx_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07001899
1900#if TEST_OPTIMIZE_TXB
1901 int64_t sse;
1902 int64_t org_dist =
1903 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1904 (1 << (2 * txb_info->shift));
Angie Chiang0b2795c2017-09-29 16:00:08 -07001905 int org_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang07c57f32017-05-30 18:18:33 -07001906#endif
1907
1908 tran_low_t *org_qcoeff = txb_info->qcoeff;
1909 tran_low_t *org_dqcoeff = txb_info->dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001910 uint8_t *const org_levels = txb_info->levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07001911
1912 tran_low_t tmp_qcoeff[MAX_TX_SQUARE];
1913 tran_low_t tmp_dqcoeff[MAX_TX_SQUARE];
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001914 uint8_t tmp_levels_buf[TX_PAD_2D];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001915 uint8_t *const tmp_levels = set_levels(tmp_levels_buf, txb_info->width);
Angie Chiang07c57f32017-05-30 18:18:33 -07001916 const int org_eob = txb_info->eob;
1917 if (dry_run) {
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001918 const int stride = txb_info->width + TX_PAD_HOR;
1919 const int levels_size =
1920
1921 (stride * (txb_info->height + TX_PAD_VER) + TX_PAD_END);
Angie Chiang07c57f32017-05-30 18:18:33 -07001922 memcpy(tmp_qcoeff, org_qcoeff, sizeof(org_qcoeff[0]) * max_eob);
1923 memcpy(tmp_dqcoeff, org_dqcoeff, sizeof(org_dqcoeff[0]) * max_eob);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001924 memcpy(tmp_levels, org_levels - TX_PAD_TOP * stride,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001925 sizeof(org_levels[0]) * levels_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07001926 txb_info->qcoeff = tmp_qcoeff;
1927 txb_info->dqcoeff = tmp_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001928 txb_info->levels = tmp_levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07001929 }
1930
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001931 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang07c57f32017-05-30 18:18:33 -07001932
1933 // forward optimize the nz_map
1934 const int cur_eob = txb_info->eob;
1935 for (int si = 0; si < cur_eob; ++si) {
1936 const int coeff_idx = scan[si];
1937 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1938 if (abs(qc) == 1) {
1939 LevelDownStats stats;
Angie Chiang25645b72017-09-24 14:28:49 -07001940 try_level_down_facade(&stats, si, txb_cache, txb_costs, txb_info,
1941 fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07001942 if (stats.update) {
1943 update = 1;
1944 cost_diff += stats.cost_diff;
1945 dist_diff += stats.dist_diff;
1946 rd_diff += stats.rd_diff;
1947 update_level_down(coeff_idx, txb_cache, txb_info);
1948 set_eob(txb_info, stats.new_eob);
1949 }
1950 }
1951 }
1952
1953 // backward optimize the level-k map
Angie Chiang530b3042017-08-17 15:08:58 -07001954 int eob_fix = 0;
Angie Chiang07c57f32017-05-30 18:18:33 -07001955 for (int si = txb_info->eob - 1; si >= 0; --si) {
Angie Chiang530b3042017-08-17 15:08:58 -07001956 const int coeff_idx = scan[si];
1957 if (eob_fix == 1 && txb_info->qcoeff[coeff_idx] == 1) {
1958 // when eob is fixed, there is not need to optimize again when
1959 // abs(qc) == 1
1960 continue;
1961 }
Angie Chiang07c57f32017-05-30 18:18:33 -07001962 LevelDownStats stats;
Angie Chiang25645b72017-09-24 14:28:49 -07001963 try_level_down_facade(&stats, si, txb_cache, txb_costs, txb_info,
1964 fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07001965 if (stats.update) {
1966#if TEST_OPTIMIZE_TXB
1967// printf("si %d low_qc %d cost_diff %d dist_diff %ld rd_diff %ld eob %d new_eob
1968// %d\n", si, stats.low_qc, stats.cost_diff, stats.dist_diff, stats.rd_diff,
1969// txb_info->eob, stats.new_eob);
1970#endif
1971 update = 1;
1972 cost_diff += stats.cost_diff;
1973 dist_diff += stats.dist_diff;
1974 rd_diff += stats.rd_diff;
1975 update_level_down(coeff_idx, txb_cache, txb_info);
1976 set_eob(txb_info, stats.new_eob);
1977 }
Angie Chiang530b3042017-08-17 15:08:58 -07001978 if (eob_fix == 0 && txb_info->qcoeff[coeff_idx] != 0) eob_fix = 1;
Angie Chiang07c57f32017-05-30 18:18:33 -07001979 if (si > txb_info->eob) si = txb_info->eob;
1980 }
1981#if TEST_OPTIMIZE_TXB
1982 int64_t new_dist =
1983 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1984 (1 << (2 * txb_info->shift));
Angie Chiang0b2795c2017-09-29 16:00:08 -07001985 int new_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang07c57f32017-05-30 18:18:33 -07001986 int64_t ref_dist_diff = new_dist - org_dist;
1987 int ref_cost_diff = new_cost - org_cost;
1988 if (cost_diff != ref_cost_diff || dist_diff != ref_dist_diff)
1989 printf(
1990 "overall rd_diff %ld\ncost_diff %d ref_cost_diff%d\ndist_diff %ld "
1991 "ref_dist_diff %ld\neob %d new_eob %d\n\n",
1992 rd_diff, cost_diff, ref_cost_diff, dist_diff, ref_dist_diff, org_eob,
1993 txb_info->eob);
1994#endif
1995 if (dry_run) {
1996 txb_info->qcoeff = org_qcoeff;
1997 txb_info->dqcoeff = org_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001998 txb_info->levels = org_levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07001999 set_eob(txb_info, org_eob);
2000 }
2001 return update;
2002}
Dake Hea47cd6c2017-10-13 18:09:58 -07002003#endif
Angie Chiang07c57f32017-05-30 18:18:33 -07002004
2005// These numbers are empirically obtained.
2006static const int plane_rd_mult[REF_TYPES][PLANE_TYPES] = {
Angie Chiang07c57f32017-05-30 18:18:33 -07002007 { 17, 13 }, { 16, 10 },
Angie Chiang07c57f32017-05-30 18:18:33 -07002008};
2009
Jingning Han7eab9ff2017-07-06 10:12:54 -07002010int av1_optimize_txb(const AV1_COMMON *cm, MACROBLOCK *x, int plane,
2011 int blk_row, int blk_col, int block, TX_SIZE tx_size,
Angie Chiang25645b72017-09-24 14:28:49 -07002012 TXB_CTX *txb_ctx, int fast_mode) {
Angie Chiang07c57f32017-05-30 18:18:33 -07002013 MACROBLOCKD *const xd = &x->e_mbd;
2014 const PLANE_TYPE plane_type = get_plane_type(plane);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -08002015 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Jingning Han19b5c8f2017-07-06 15:10:12 -07002016 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002017 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07002018 const MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
2019 const struct macroblock_plane *p = &x->plane[plane];
2020 struct macroblockd_plane *pd = &xd->plane[plane];
2021 const int eob = p->eobs[block];
2022 tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2023 tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
2024 const tran_low_t *tcoeff = BLOCK_OFFSET(p->coeff, block);
Monty Montgomery125c0fc2017-10-26 00:44:35 -04002025 const int16_t *dequant = p->dequant_QTX;
Urvang Joshi80893152017-10-27 11:51:14 -07002026 const int seg_eob = av1_get_max_eob(tx_size);
Angie Chianga9ba58e2017-12-01 19:22:43 -08002027 const int bwl = get_txb_bwl(tx_size);
2028 const int width = get_txb_wide(tx_size);
2029 const int height = get_txb_high(tx_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07002030 const int is_inter = is_inter_block(mbmi);
Angie Chiangbd99b382017-06-20 15:11:16 -07002031 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Jingning Handfd72322017-08-09 14:04:12 -07002032 const LV_MAP_COEFF_COST txb_costs = x->coeff_costs[txs_ctx][plane_type];
Angie Chiang07c57f32017-05-30 18:18:33 -07002033
Montybca9e9e2017-12-14 06:23:29 -06002034#if CONFIG_DAALA_TX
2035 const int shift = 0;
2036#else
Angie Chiang07c57f32017-05-30 18:18:33 -07002037 const int shift = av1_get_tx_scale(tx_size);
Montybca9e9e2017-12-14 06:23:29 -06002038#endif
Angie Chiang07c57f32017-05-30 18:18:33 -07002039 const int64_t rdmult =
Jingning Hanb433f4c2017-11-17 15:43:59 -08002040 ((x->rdmult * plane_rd_mult[is_inter][plane_type] << (2 * (xd->bd - 8))) +
2041 2) >>
2042 2;
Linfeng Zhang679d81e2017-10-31 15:27:42 -07002043 uint8_t levels_buf[TX_PAD_2D];
2044 uint8_t *const levels = set_levels(levels_buf, width);
Angie Chiang07c57f32017-05-30 18:18:33 -07002045
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002046 assert(width == (1 << bwl));
Linfeng Zhang1015a342017-10-24 16:20:41 -07002047 TxbInfo txb_info = {
2048 qcoeff, levels, dqcoeff, tcoeff, dequant, shift,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002049 tx_size, txs_ctx, tx_type, bwl, width, height,
Linfeng Zhang1015a342017-10-24 16:20:41 -07002050 eob, seg_eob, scan_order, txb_ctx, rdmult, &cm->coeff_ctx_table
2051 };
2052
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002053 av1_txb_init_levels(qcoeff, width, height, levels);
Urvang Joshi70006e42017-06-14 16:08:55 -07002054
Angie Chiang93af45f2017-10-23 18:19:59 -07002055 const int update = optimize_txb(&txb_info, &txb_costs, NULL, 0, fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07002056
Jingning Hand7e99112017-12-13 09:47:45 -08002057 if (update) {
2058 p->eobs[block] = txb_info.eob;
2059 p->txb_entropy_ctx[block] =
2060 av1_get_txb_entropy_context(qcoeff, scan_order, txb_info.eob);
2061 }
Angie Chiang07c57f32017-05-30 18:18:33 -07002062 return txb_info.eob;
2063}
Jingning Hand7e99112017-12-13 09:47:45 -08002064
Angie Chiang74e23072017-03-24 14:54:23 -07002065int av1_get_txb_entropy_context(const tran_low_t *qcoeff,
2066 const SCAN_ORDER *scan_order, int eob) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002067 const int16_t *const scan = scan_order->scan;
Angie Chiang74e23072017-03-24 14:54:23 -07002068 int cul_level = 0;
2069 int c;
Jingning Han339cf932017-09-18 10:17:02 -07002070
2071 if (eob == 0) return 0;
Angie Chiang74e23072017-03-24 14:54:23 -07002072 for (c = 0; c < eob; ++c) {
2073 cul_level += abs(qcoeff[scan[c]]);
2074 }
2075
2076 cul_level = AOMMIN(COEFF_CONTEXT_MASK, cul_level);
2077 set_dc_sign(&cul_level, qcoeff[0]);
2078
2079 return cul_level;
2080}
2081
Jingning Han4fe5f672017-05-19 15:46:07 -07002082void av1_update_txb_context_b(int plane, int block, int blk_row, int blk_col,
2083 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
2084 void *arg) {
Jingning Han6171ae72017-05-18 20:15:06 -07002085 struct tokenize_b_args *const args = arg;
Angie Chiang36d616b2017-03-22 13:58:36 -07002086 const AV1_COMP *cpi = args->cpi;
2087 const AV1_COMMON *cm = &cpi->common;
Angie Chiang0397eda2017-03-15 16:57:14 -07002088 ThreadData *const td = args->td;
2089 MACROBLOCK *const x = &td->mb;
2090 MACROBLOCKD *const xd = &x->e_mbd;
Angie Chiang36d616b2017-03-22 13:58:36 -07002091 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiang0397eda2017-03-15 16:57:14 -07002092 struct macroblock_plane *p = &x->plane[plane];
2093 struct macroblockd_plane *pd = &xd->plane[plane];
Angie Chiang36d616b2017-03-22 13:58:36 -07002094 const uint16_t eob = p->eobs[block];
2095 const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2096 const PLANE_TYPE plane_type = pd->plane_type;
Jingning Han19b5c8f2017-07-06 15:10:12 -07002097 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002098 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07002099 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Angie Chiang0397eda2017-03-15 16:57:14 -07002100 (void)plane_bsize;
Angie Chiang36d616b2017-03-22 13:58:36 -07002101
Angie Chiang74e23072017-03-24 14:54:23 -07002102 int cul_level = av1_get_txb_entropy_context(qcoeff, scan_order, eob);
Angie Chiang36d616b2017-03-22 13:58:36 -07002103 av1_set_contexts(xd, pd, plane, tx_size, cul_level, blk_col, blk_row);
Angie Chiang0397eda2017-03-15 16:57:14 -07002104}
2105
Jingning Han4fe5f672017-05-19 15:46:07 -07002106void av1_update_and_record_txb_context(int plane, int block, int blk_row,
2107 int blk_col, BLOCK_SIZE plane_bsize,
2108 TX_SIZE tx_size, void *arg) {
Jingning Han6171ae72017-05-18 20:15:06 -07002109 struct tokenize_b_args *const args = arg;
Angie Chiang0397eda2017-03-15 16:57:14 -07002110 const AV1_COMP *cpi = args->cpi;
2111 const AV1_COMMON *cm = &cpi->common;
2112 ThreadData *const td = args->td;
2113 MACROBLOCK *const x = &td->mb;
2114 MACROBLOCKD *const xd = &x->e_mbd;
2115 struct macroblock_plane *p = &x->plane[plane];
2116 struct macroblockd_plane *pd = &xd->plane[plane];
2117 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Linfeng Zhang848f7bc2017-10-31 15:26:07 -07002118 int eob = p->eobs[block], update_eob = -1;
Angie Chiang0397eda2017-03-15 16:57:14 -07002119 const PLANE_TYPE plane_type = pd->plane_type;
2120 const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2121 tran_low_t *tcoeff = BLOCK_OFFSET(x->mbmi_ext->tcoeff[plane], block);
2122 const int segment_id = mbmi->segment_id;
Jingning Han19b5c8f2017-07-06 15:10:12 -07002123 const TX_TYPE tx_type =
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002124 av1_get_tx_type(plane_type, xd, blk_row, blk_col, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07002125 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002126 const int16_t *const scan = scan_order->scan;
hui suc0cf71d2017-07-20 16:38:50 -07002127 const int seg_eob = av1_get_tx_eob(&cpi->common.seg, segment_id, tx_size);
Linfeng Zhang1015a342017-10-24 16:20:41 -07002128 int c;
Angie Chiang85901562017-03-17 12:03:27 -07002129 TXB_CTX txb_ctx;
2130 get_txb_ctx(plane_bsize, tx_size, plane, pd->above_context + blk_col,
2131 pd->left_context + blk_row, &txb_ctx);
Angie Chianga9ba58e2017-12-01 19:22:43 -08002132 const int bwl = get_txb_bwl(tx_size);
2133 const int width = get_txb_wide(tx_size);
2134 const int height = get_txb_high(tx_size);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07002135 uint8_t levels_buf[TX_PAD_2D];
2136 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -08002137 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Yunqing Wang0e141b52017-11-02 15:08:58 -07002138 const uint8_t allow_update_cdf = args->allow_update_cdf;
Angie Chiang0397eda2017-03-15 16:57:14 -07002139
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -08002140 TX_SIZE txsize_ctx = get_txsize_entropy_ctx(tx_size);
Jingning Han8f661602017-08-19 08:16:50 -07002141 FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
Linfeng Zhangd67c13f2017-12-11 11:49:12 -08002142 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Jingning Han48be0e12017-06-13 12:12:01 -07002143
Angie Chiang0397eda2017-03-15 16:57:14 -07002144 memcpy(tcoeff, qcoeff, sizeof(*tcoeff) * seg_eob);
2145
Jingning Han48be0e12017-06-13 12:12:01 -07002146 ++td->counts->txb_skip[txsize_ctx][txb_ctx.txb_skip_ctx][eob == 0];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002147 if (allow_update_cdf)
2148 update_bin(ec_ctx->txb_skip_cdf[txsize_ctx][txb_ctx.txb_skip_ctx], eob == 0,
2149 2);
Angie Chiang85901562017-03-17 12:03:27 -07002150 x->mbmi_ext->txb_skip_ctx[plane][block] = txb_ctx.txb_skip_ctx;
Angie Chiang0397eda2017-03-15 16:57:14 -07002151
2152 x->mbmi_ext->eobs[plane][block] = eob;
2153
2154 if (eob == 0) {
2155 av1_set_contexts(xd, pd, plane, tx_size, 0, blk_col, blk_row);
2156 return;
2157 }
2158
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002159 av1_txb_init_levels(tcoeff, width, height, levels);
Linfeng Zhangce065ca2017-10-17 16:49:30 -07002160
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002161#if CONFIG_TXK_SEL
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002162 av1_update_tx_type_count(cm, xd, blk_row, blk_col, plane, mbmi->sb_type,
Debargha Mukherjee3ebb0d02017-12-14 05:05:18 -08002163 tx_size, td->counts, allow_update_cdf);
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002164#endif
Angie Chiang0397eda2017-03-15 16:57:14 -07002165
Dake Hea47cd6c2017-10-13 18:09:58 -07002166 unsigned int(*nz_map_count)[SIG_COEF_CONTEXTS][2] =
2167 &(td->counts->nz_map[txsize_ctx][plane_type]);
Jingning Han35deaa72017-10-26 15:36:30 -07002168 av1_update_eob_context(eob, seg_eob, tx_size, tx_type, plane_type, ec_ctx,
Yunqing Wang0e141b52017-11-02 15:08:58 -07002169 td->counts, allow_update_cdf);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -08002170
2171 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_type, coeff_contexts);
2172
Dake He03a32922017-10-31 08:06:45 -07002173 update_eob = eob - 1;
Dake Hea47cd6c2017-10-13 18:09:58 -07002174 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002175 const int pos = scan[c];
Linfeng Zhangd67c13f2017-12-11 11:49:12 -08002176 const int coeff_ctx = coeff_contexts[pos];
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002177 const tran_low_t v = qcoeff[pos];
2178 const int is_nz = (v != 0);
Dake He03a32922017-10-31 08:06:45 -07002179
Ola Hugosson13892102017-11-06 08:01:44 +01002180#if CONFIG_LV_MAP_MULTI
2181 (void)is_nz;
2182 (void)nz_map_count;
Dake He3fe369c2017-11-16 17:56:44 -08002183#if USE_BASE_EOB_ALPHABET
2184 if (c == eob - 1) {
2185 update_cdf(ec_ctx->coeff_base_eob_cdf[txsize_ctx][plane_type]
2186 [coeff_ctx - SIG_COEF_CONTEXTS +
2187 SIG_COEF_CONTEXTS_EOB],
2188 AOMMIN(abs(v), 3) - 1, 3);
2189 } else {
2190 update_cdf(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][coeff_ctx],
2191 AOMMIN(abs(v), 3), 4);
2192 }
Dake He59881772017-11-24 07:00:02 -08002193 {
2194 if (c < eob - 1) {
2195 ++(*nz_map_count)[coeff_ctx][is_nz];
2196 }
2197 if (is_nz) {
2198 for (int k = 0; k < NUM_BASE_LEVELS; ++k) {
2199 int is_k = (abs(v) > (k + 1));
2200 ++td->counts->coeff_base[txsize_ctx][plane_type][k][coeff_ctx][is_k];
2201 if (is_k == 0) break;
2202 }
2203 }
2204 }
2205
Dake He3fe369c2017-11-16 17:56:44 -08002206#else
Ola Hugosson13892102017-11-06 08:01:44 +01002207 update_cdf(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][coeff_ctx],
2208 AOMMIN(abs(v), 3), 4);
Dake He3fe369c2017-11-16 17:56:44 -08002209#endif
Linfeng Zhang1757fb62017-12-11 10:47:59 -08002210#else
Dake He03a32922017-10-31 08:06:45 -07002211 if (c < eob - 1) {
2212 ++(*nz_map_count)[coeff_ctx][is_nz];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002213 if (allow_update_cdf)
2214 update_cdf(ec_ctx->nz_map_cdf[txsize_ctx][plane_type][coeff_ctx], is_nz,
2215 2);
Dake He03a32922017-10-31 08:06:45 -07002216 }
2217
2218 if (is_nz) {
2219 int k;
2220 for (k = 0; k < NUM_BASE_LEVELS; ++k) {
2221 int ctx = coeff_ctx;
2222 int is_k = (abs(v) > (k + 1));
2223
2224 ++td->counts->coeff_base[txsize_ctx][plane_type][k][ctx][is_k];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002225 if (allow_update_cdf)
2226 update_bin(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][k][ctx],
2227 is_k, 2);
Dake He03a32922017-10-31 08:06:45 -07002228 if (is_k == 0) break;
2229 }
2230 }
Dake He03a32922017-10-31 08:06:45 -07002231#endif
Dake Hea47cd6c2017-10-13 18:09:58 -07002232 }
Dake Hea47cd6c2017-10-13 18:09:58 -07002233
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002234 // Update the context needed to code the DC sign (if applicable)
2235 const int sign = (tcoeff[0] < 0) ? 1 : 0;
2236 if (tcoeff[0] != 0) {
Dake He43edb762017-10-26 10:29:46 -07002237 int dc_sign_ctx = txb_ctx.dc_sign_ctx;
2238
2239 ++td->counts->dc_sign[plane_type][dc_sign_ctx][sign];
2240#if LV_MAP_PROB
Yunqing Wang0e141b52017-11-02 15:08:58 -07002241 if (allow_update_cdf)
2242 update_bin(ec_ctx->dc_sign_cdf[plane_type][dc_sign_ctx], sign, 2);
Dake He43edb762017-10-26 10:29:46 -07002243#endif
2244 x->mbmi_ext->dc_sign_ctx[plane][block] = dc_sign_ctx;
2245 }
2246
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002247 if (update_eob >= 0) {
Dake He7d01ab52017-11-24 17:53:28 -08002248#if !CONFIG_LV_MAP_MULTI
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002249 av1_get_br_level_counts(levels, width, height, level_counts);
Dake He7d01ab52017-11-24 17:53:28 -08002250#endif
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002251 for (c = update_eob; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002252 const int pos = scan[c];
2253 const tran_low_t level = abs(tcoeff[pos]);
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002254 int idx;
2255 int ctx;
Angie Chiang0397eda2017-03-15 16:57:14 -07002256
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002257 if (level <= NUM_BASE_LEVELS) continue;
Angie Chiang0397eda2017-03-15 16:57:14 -07002258
Dake He7d01ab52017-11-24 17:53:28 -08002259// level is above 1.
2260#if !CONFIG_LV_MAP_MULTI
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002261 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -08002262#endif
Jingning Han87b01b52017-08-31 12:07:20 -07002263
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002264 const int base_range = level - 1 - NUM_BASE_LEVELS;
Ola Hugossone72a2092017-11-12 09:11:53 +01002265#if CONFIG_LV_MAP_MULTI
Dake He7d01ab52017-11-24 17:53:28 -08002266#if USE_CAUSAL_BR_CTX
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002267 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos], tx_type);
Dake He7d01ab52017-11-24 17:53:28 -08002268#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002269 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos]);
Dake He7d01ab52017-11-24 17:53:28 -08002270#endif
Ola Hugossone72a2092017-11-12 09:11:53 +01002271 for (idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002272 const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
Dake He7d01ab52017-11-24 17:53:28 -08002273 update_cdf(
Dake Hee2d8f182017-12-14 13:28:00 -08002274#if 0
Dake He7d01ab52017-11-24 17:53:28 -08002275 ec_ctx->coeff_br_cdf[AOMMIN(txsize_ctx, TX_16X16)][plane_type][ctx],
Dake Hee2d8f182017-12-14 13:28:00 -08002276#else
2277 ec_ctx->coeff_br_cdf[AOMMIN(txsize_ctx, TX_32X32)][plane_type][ctx],
2278#endif
Dake He7d01ab52017-11-24 17:53:28 -08002279 k, BR_CDF_SIZE);
2280 for (int lps = 0; lps < BR_CDF_SIZE - 1; lps++) {
Dake Hee2d8f182017-12-14 13:28:00 -08002281#if 0
Dake He7d01ab52017-11-24 17:53:28 -08002282 ++td->counts->coeff_lps[AOMMIN(txsize_ctx, TX_16X16)][plane_type][lps]
2283 [ctx][lps == k];
Dake Hee2d8f182017-12-14 13:28:00 -08002284#else
2285 ++td->counts->coeff_lps[AOMMIN(txsize_ctx, TX_32X32)][plane_type][lps]
2286 [ctx][lps == k];
2287#endif
Dake He59881772017-11-24 07:00:02 -08002288 if (lps == k) break;
2289 }
Dake Hee2d8f182017-12-14 13:28:00 -08002290 ++td->counts->coeff_lps_multi[AOMMIN(txsize_ctx, TX_32X32)][plane_type]
2291 [ctx][k];
Dake He59881772017-11-24 07:00:02 -08002292
Ola Hugossone72a2092017-11-12 09:11:53 +01002293 if (k < BR_CDF_SIZE - 1) break;
2294 }
2295#else
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002296 const int br_set_idx = base_range < COEFF_BASE_RANGE
2297 ? coeff_to_br_index[base_range]
2298 : BASE_RANGE_SETS;
Jingning Han87b01b52017-08-31 12:07:20 -07002299
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002300 for (idx = 0; idx < BASE_RANGE_SETS; ++idx) {
2301 if (idx == br_set_idx) {
2302 int br_base = br_index_to_coeff[br_set_idx];
2303 int br_offset = base_range - br_base;
2304 ++td->counts->coeff_br[txsize_ctx][plane_type][idx][ctx][1];
Yunqing Wang0e141b52017-11-02 15:08:58 -07002305 if (allow_update_cdf)
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002306 update_bin(ec_ctx->coeff_br_cdf[txsize_ctx][plane_type][idx][ctx],
2307 1, 2);
2308 int extra_bits = (1 << br_extra_bits[idx]) - 1;
2309 for (int tok = 0; tok < extra_bits; ++tok) {
2310 if (br_offset == tok) {
2311 ++td->counts->coeff_lps[txsize_ctx][plane_type][ctx][1];
2312 if (allow_update_cdf)
2313 update_bin(ec_ctx->coeff_lps_cdf[txsize_ctx][plane_type][ctx],
2314 1, 2);
2315 break;
2316 }
2317 ++td->counts->coeff_lps[txsize_ctx][plane_type][ctx][0];
2318 if (allow_update_cdf)
2319 update_bin(ec_ctx->coeff_lps_cdf[txsize_ctx][plane_type][ctx], 0,
2320 2);
2321 }
2322 break;
Jingning Han87b01b52017-08-31 12:07:20 -07002323 }
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002324 ++td->counts->coeff_br[txsize_ctx][plane_type][idx][ctx][0];
2325 if (allow_update_cdf)
2326 update_bin(ec_ctx->coeff_br_cdf[txsize_ctx][plane_type][idx][ctx], 0,
2327 2);
Jingning Han87b01b52017-08-31 12:07:20 -07002328 }
Ola Hugossone72a2092017-11-12 09:11:53 +01002329#endif
Linfeng Zhang97fc4742017-11-07 12:57:25 -08002330 // use 0-th order Golomb code to handle the residual level.
Jingning Han87b01b52017-08-31 12:07:20 -07002331 }
Angie Chiang0397eda2017-03-15 16:57:14 -07002332 }
Angie Chiang36d616b2017-03-22 13:58:36 -07002333
Angie Chiang63d190a2017-10-23 15:43:05 -07002334 int cul_level = av1_get_txb_entropy_context(tcoeff, scan_order, eob);
Angie Chiang0397eda2017-03-15 16:57:14 -07002335 av1_set_contexts(xd, pd, plane, tx_size, cul_level, blk_col, blk_row);
2336}
2337
2338void av1_update_txb_context(const AV1_COMP *cpi, ThreadData *td,
2339 RUN_TYPE dry_run, BLOCK_SIZE bsize, int *rate,
Yunqing Wang0e141b52017-11-02 15:08:58 -07002340 int mi_row, int mi_col, uint8_t allow_update_cdf) {
Angie Chiang0397eda2017-03-15 16:57:14 -07002341 MACROBLOCK *const x = &td->mb;
2342 MACROBLOCKD *const xd = &x->e_mbd;
2343 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yunqing Wang0e141b52017-11-02 15:08:58 -07002344 struct tokenize_b_args arg = { cpi, td, NULL, 0, allow_update_cdf };
Angie Chiang0397eda2017-03-15 16:57:14 -07002345 (void)rate;
2346 (void)mi_row;
2347 (void)mi_col;
2348 if (mbmi->skip) {
Timothy B. Terriberrya2d5cde2017-05-10 18:33:50 -07002349 av1_reset_skip_context(xd, mi_row, mi_col, bsize);
Angie Chiang0397eda2017-03-15 16:57:14 -07002350 return;
2351 }
2352
2353 if (!dry_run) {
Jingning Han94652b82017-04-04 09:45:02 -07002354 av1_foreach_transformed_block(xd, bsize, mi_row, mi_col,
Jingning Han4fe5f672017-05-19 15:46:07 -07002355 av1_update_and_record_txb_context, &arg);
Angie Chiangc8af6112017-03-16 16:11:22 -07002356 } else if (dry_run == DRY_RUN_NORMAL) {
Jingning Han4fe5f672017-05-19 15:46:07 -07002357 av1_foreach_transformed_block(xd, bsize, mi_row, mi_col,
2358 av1_update_txb_context_b, &arg);
Angie Chiangc8af6112017-03-16 16:11:22 -07002359 } else {
2360 printf("DRY_RUN_COSTCOEFFS is not supported yet\n");
2361 assert(0);
Angie Chiang0397eda2017-03-15 16:57:14 -07002362 }
2363}
Angie Chiang800df032017-03-22 11:14:12 -07002364
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002365#if CONFIG_TXK_SEL
Angie Chiang808d8592017-04-06 18:36:55 -07002366int64_t av1_search_txk_type(const AV1_COMP *cpi, MACROBLOCK *x, int plane,
2367 int block, int blk_row, int blk_col,
2368 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
Angie Chiang65a39bb2017-04-11 16:50:04 -07002369 const ENTROPY_CONTEXT *a, const ENTROPY_CONTEXT *l,
2370 int use_fast_coef_costing, RD_STATS *rd_stats) {
Angie Chiang808d8592017-04-06 18:36:55 -07002371 const AV1_COMMON *cm = &cpi->common;
2372 MACROBLOCKD *xd = &x->e_mbd;
2373 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
2374 TX_TYPE txk_start = DCT_DCT;
2375 TX_TYPE txk_end = TX_TYPES - 1;
2376 TX_TYPE best_tx_type = txk_start;
2377 int64_t best_rd = INT64_MAX;
Angie Chiang4e16ea62017-12-15 17:58:44 -08002378 uint8_t best_txb_ctx = 0;
2379 uint16_t best_eob = 0;
Jingning Hane3b81bc2017-06-23 11:43:52 -07002380 RD_STATS best_rd_stats;
Angie Chiang808d8592017-04-06 18:36:55 -07002381 TX_TYPE tx_type;
Jingning Hane3b81bc2017-06-23 11:43:52 -07002382
2383 av1_invalid_rd_stats(&best_rd_stats);
2384
Angie Chiang808d8592017-04-06 18:36:55 -07002385 for (tx_type = txk_start; tx_type <= txk_end; ++tx_type) {
Angie Chiangbce07f12017-12-01 16:34:31 -08002386 if (plane == 0)
2387 mbmi->txk_type[(blk_row << MAX_MIB_SIZE_LOG2) + blk_col] = tx_type;
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002388 TX_TYPE ref_tx_type =
2389 av1_get_tx_type(get_plane_type(plane), xd, blk_row, blk_col, tx_size);
Angie Chiang00491e02017-04-11 17:55:10 -07002390 if (tx_type != ref_tx_type) {
hui su45b64752017-07-12 16:54:35 -07002391 // use av1_get_tx_type() to check if the tx_type is valid for the current
2392 // mode if it's not, we skip it here.
Angie Chiang00491e02017-04-11 17:55:10 -07002393 continue;
2394 }
Jingning Hane57d6322017-07-03 18:50:25 -07002395
Hui Suddbcde22017-09-18 17:22:02 -07002396 const int is_inter = is_inter_block(mbmi);
Angie Chiang53bf1e92017-11-29 16:53:07 -08002397 const TxSetType tx_set_type = get_ext_tx_set_type(
2398 tx_size, mbmi->sb_type, is_inter, cm->reduced_tx_set_used);
Hui Suddbcde22017-09-18 17:22:02 -07002399 if (!av1_ext_tx_used[tx_set_type][tx_type]) continue;
Jingning Hane57d6322017-07-03 18:50:25 -07002400
Angie Chiang808d8592017-04-06 18:36:55 -07002401 RD_STATS this_rd_stats;
2402 av1_invalid_rd_stats(&this_rd_stats);
Angie Chiangdaccae32017-12-04 09:34:44 -08002403#if DISABLE_TRELLISQ_SEARCH
2404 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Sarah Parkere8d0d4c2017-12-06 15:11:37 -08002405 AV1_XFORM_QUANT_B);
Angie Chiangdaccae32017-12-04 09:34:44 -08002406#else
Angie Chiang808d8592017-04-06 18:36:55 -07002407 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Sarah Parkere8d0d4c2017-12-06 15:11:37 -08002408 AV1_XFORM_QUANT_FP);
Jingning Han7eab9ff2017-07-06 10:12:54 -07002409 av1_optimize_b(cm, x, plane, blk_row, blk_col, block, plane_bsize, tx_size,
Angie Chiang25645b72017-09-24 14:28:49 -07002410 a, l, 1);
Angie Chiangdaccae32017-12-04 09:34:44 -08002411#endif
Angie Chiang808d8592017-04-06 18:36:55 -07002412 av1_dist_block(cpi, x, plane, plane_bsize, block, blk_row, blk_col, tx_size,
Angie Chiang2ed03a32017-04-16 18:00:06 -07002413 &this_rd_stats.dist, &this_rd_stats.sse,
2414 OUTPUT_HAS_PREDICTED_PIXELS);
Angie Chiangbd99b382017-06-20 15:11:16 -07002415 const SCAN_ORDER *scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Jingning Han7eab9ff2017-07-06 10:12:54 -07002416 this_rd_stats.rate =
2417 av1_cost_coeffs(cpi, x, plane, blk_row, blk_col, block, tx_size,
2418 scan_order, a, l, use_fast_coef_costing);
Urvang Joshi70006e42017-06-14 16:08:55 -07002419 int rd = RDCOST(x->rdmult, this_rd_stats.rate, this_rd_stats.dist);
Jingning Han19b5c8f2017-07-06 15:10:12 -07002420
Angie Chiang808d8592017-04-06 18:36:55 -07002421 if (rd < best_rd) {
2422 best_rd = rd;
Jingning Hane3b81bc2017-06-23 11:43:52 -07002423 best_rd_stats = this_rd_stats;
Angie Chiang808d8592017-04-06 18:36:55 -07002424 best_tx_type = tx_type;
Angie Chiang4e16ea62017-12-15 17:58:44 -08002425 best_txb_ctx = x->plane[plane].txb_entropy_ctx[block];
2426 best_eob = x->plane[plane].eobs[block];
Angie Chiang808d8592017-04-06 18:36:55 -07002427 }
2428 }
Jingning Hane3b81bc2017-06-23 11:43:52 -07002429
2430 av1_merge_rd_stats(rd_stats, &best_rd_stats);
2431
Angie Chianga3f7d2e2017-12-07 19:51:14 -08002432 if (best_eob == 0) best_tx_type = DCT_DCT;
Jingning Han19b5c8f2017-07-06 15:10:12 -07002433
Angie Chiangbce07f12017-12-01 16:34:31 -08002434 if (plane == 0)
2435 mbmi->txk_type[(blk_row << MAX_MIB_SIZE_LOG2) + blk_col] = best_tx_type;
Angie Chiang4e16ea62017-12-15 17:58:44 -08002436 x->plane[plane].txb_entropy_ctx[block] = best_txb_ctx;
Jingning Han47558172017-07-05 16:33:19 -07002437
Angie Chiang2ed03a32017-04-16 18:00:06 -07002438 if (!is_inter_block(mbmi)) {
Angie Chiangdaccae32017-12-04 09:34:44 -08002439// intra mode needs decoded result such that the next transform block
2440// can use it for prediction.
2441#if DISABLE_TRELLISQ_SEARCH
2442 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Sarah Parkere8d0d4c2017-12-06 15:11:37 -08002443 AV1_XFORM_QUANT_B);
Angie Chiangdaccae32017-12-04 09:34:44 -08002444#else
Jingning Han47558172017-07-05 16:33:19 -07002445 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
Sarah Parkere8d0d4c2017-12-06 15:11:37 -08002446 AV1_XFORM_QUANT_FP);
Jingning Han7eab9ff2017-07-06 10:12:54 -07002447 av1_optimize_b(cm, x, plane, blk_row, blk_col, block, plane_bsize, tx_size,
Angie Chiang25645b72017-09-24 14:28:49 -07002448 a, l, 1);
Angie Chiangdaccae32017-12-04 09:34:44 -08002449#endif
Jingning Han47558172017-07-05 16:33:19 -07002450
Angie Chiang2ed03a32017-04-16 18:00:06 -07002451 av1_inverse_transform_block_facade(xd, plane, block, blk_row, blk_col,
Frederic Barbier33b39f02017-11-21 11:11:24 +01002452 x->plane[plane].eobs[block],
2453 cm->reduced_tx_set_used);
Angie Chiang2ed03a32017-04-16 18:00:06 -07002454 }
Angie Chiang808d8592017-04-06 18:36:55 -07002455 return best_rd;
2456}
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002457#endif // CONFIG_TXK_SEL