blob: 569b3d2ce24fed50de5e5245fe199e99bc9a6a0c [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
Angie Chiang41220ab2018-02-14 17:48:23 -080012#include "av1/encoder/encodetxb.h"
13
Linfeng Zhangae7b2f32017-11-08 15:46:57 -080014#include "aom_ports/mem.h"
Angie Chiang0397eda2017-03-15 16:57:14 -070015#include "av1/common/blockd.h"
Angie Chiange50f3ec2017-04-10 15:50:33 -070016#include "av1/common/idct.h"
Angie Chiang0397eda2017-03-15 16:57:14 -070017#include "av1/common/pred_common.h"
Angie Chiang41220ab2018-02-14 17:48:23 -080018#include "av1/common/scan.h"
Angie Chiang1628fcc2017-04-13 16:30:30 -070019#include "av1/encoder/bitstream.h"
Angie Chiang47c72182017-02-27 14:30:38 -080020#include "av1/encoder/cost.h"
Angie Chiang41220ab2018-02-14 17:48:23 -080021#include "av1/encoder/encodeframe.h"
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -080022#include "av1/encoder/hash.h"
Angie Chiang808d8592017-04-06 18:36:55 -070023#include "av1/encoder/rdopt.h"
Angie Chiang0397eda2017-03-15 16:57:14 -070024#include "av1/encoder/tokenize.h"
Angie Chiang80b82262017-02-24 11:39:47 -080025
Angie Chiang47e07072017-05-30 17:27:01 -070026#define TEST_OPTIMIZE_TXB 0
27
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -080028static int hbt_needs_init = 1;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -080029static CRC_CALCULATOR crc_calculator;
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -080030static const int HBT_EOB = 16; // also the length in opt_qcoeff
31static const int HBT_TABLE_SIZE = 65536; // 16 bit: holds 65536 'arrays'
32static const int HBT_ARRAY_LENGTH = 256; // 8 bit: 256 entries
33// If removed in hbt_create_hashes or increased beyond int8_t, widen deltas type
34static const int HBT_KICKOUT = 3;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -080035
36typedef struct OptTxbQcoeff {
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -080037 // Use larger type if larger/no kickout value is used in hbt_create_hashes
38 int8_t deltas[16];
39 uint32_t hbt_qc_hash;
40 uint32_t hbt_ctx_hash;
41 int init;
42 int rate_cost;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -080043} OptTxbQcoeff;
44
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -080045OptTxbQcoeff *hbt_hash_table;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -080046
Dake Hea47cd6c2017-10-13 18:09:58 -070047typedef struct LevelDownStats {
48 int update;
49 tran_low_t low_qc;
50 tran_low_t low_dqc;
Dake Hea47cd6c2017-10-13 18:09:58 -070051 int64_t dist0;
52 int rate;
53 int rate_low;
54 int64_t dist;
55 int64_t dist_low;
56 int64_t rd;
57 int64_t rd_low;
Dake He4d447692017-12-15 09:10:06 -080058 int64_t nz_rd;
Dake Hea47cd6c2017-10-13 18:09:58 -070059 int64_t rd_diff;
60 int cost_diff;
61 int64_t dist_diff;
62 int new_eob;
63} LevelDownStats;
64
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070065void av1_alloc_txb_buf(AV1_COMP *cpi) {
Angie Chiangc484abe2017-03-20 15:43:11 -070066#if 0
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070067 AV1_COMMON *cm = &cpi->common;
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +000068 const int num_planes = av1_num_planes(cm);
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070069 int mi_block_size = 1 << MI_SIZE_LOG2;
70 // TODO(angiebird): Make sure cm->subsampling_x/y is set correctly, and then
71 // use precise buffer size according to cm->subsampling_x/y
72 int pixel_stride = mi_block_size * cm->mi_cols;
73 int pixel_height = mi_block_size * cm->mi_rows;
74 int i;
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +000075 for (i = 0; i < num_planes; ++i) {
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070076 CHECK_MEM_ERROR(
77 cm, cpi->tcoeff_buf[i],
78 aom_malloc(sizeof(*cpi->tcoeff_buf[i]) * pixel_stride * pixel_height));
79 }
Angie Chiangc484abe2017-03-20 15:43:11 -070080#else
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070081 AV1_COMMON *cm = &cpi->common;
Imdad Sardharwalla4ec84ab2018-02-06 12:20:18 +000082 int size = ((cm->mi_rows >> cm->seq_params.mib_size_log2) + 1) *
83 ((cm->mi_cols >> cm->seq_params.mib_size_log2) + 1);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070084
Angie Chiang9367e3e2017-10-02 16:28:11 -070085 av1_free_txb_buf(cpi);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -070086 // TODO(jingning): This should be further reduced.
87 CHECK_MEM_ERROR(cm, cpi->coeff_buffer_base,
88 aom_malloc(sizeof(*cpi->coeff_buffer_base) * size));
Angie Chiangc484abe2017-03-20 15:43:11 -070089#endif
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070090}
91
92void av1_free_txb_buf(AV1_COMP *cpi) {
Angie Chiangc484abe2017-03-20 15:43:11 -070093#if 0
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070094 int i;
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +000095 const AV1_COMMON *const cm = &cpi->common;
96 const int num_planes = av1_num_planes(cm);
97 for (i = 0; i < num_planes; ++i) {
Angie Chiangf0fbf9d2017-03-15 15:01:22 -070098 aom_free(cpi->tcoeff_buf[i]);
99 }
Angie Chiangc484abe2017-03-20 15:43:11 -0700100#else
Jingning Hanf5a4d3b2017-08-27 23:01:19 -0700101 aom_free(cpi->coeff_buffer_base);
Angie Chiangc484abe2017-03-20 15:43:11 -0700102#endif
Angie Chiangf0fbf9d2017-03-15 15:01:22 -0700103}
104
Jingning Hanf5a4d3b2017-08-27 23:01:19 -0700105void av1_set_coeff_buffer(const AV1_COMP *const cpi, MACROBLOCK *const x,
106 int mi_row, int mi_col) {
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +0000107 const AV1_COMMON *const cm = &cpi->common;
108 const int num_planes = av1_num_planes(cm);
Imdad Sardharwalla4ec84ab2018-02-06 12:20:18 +0000109 int mib_size_log2 = cm->seq_params.mib_size_log2;
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +0000110 int stride = (cm->mi_cols >> mib_size_log2) + 1;
Dominic Symes917d6c02017-10-11 18:00:52 +0200111 int offset = (mi_row >> mib_size_log2) * stride + (mi_col >> mib_size_log2);
Jingning Hanf5a4d3b2017-08-27 23:01:19 -0700112 CB_COEFF_BUFFER *coeff_buf = &cpi->coeff_buffer_base[offset];
113 const int txb_offset = x->cb_offset / (TX_SIZE_W_MIN * TX_SIZE_H_MIN);
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +0000114 for (int plane = 0; plane < num_planes; ++plane) {
Jingning Hanf5a4d3b2017-08-27 23:01:19 -0700115 x->mbmi_ext->tcoeff[plane] = coeff_buf->tcoeff[plane] + x->cb_offset;
116 x->mbmi_ext->eobs[plane] = coeff_buf->eobs[plane] + txb_offset;
117 x->mbmi_ext->txb_skip_ctx[plane] =
118 coeff_buf->txb_skip_ctx[plane] + txb_offset;
119 x->mbmi_ext->dc_sign_ctx[plane] =
120 coeff_buf->dc_sign_ctx[plane] + txb_offset;
121 }
122}
123
Angie Chiang80b82262017-02-24 11:39:47 -0800124static void write_golomb(aom_writer *w, int level) {
125 int x = level + 1;
126 int i = x;
127 int length = 0;
128
129 while (i) {
130 i >>= 1;
131 ++length;
132 }
133 assert(length > 0);
134
135 for (i = 0; i < length - 1; ++i) aom_write_bit(w, 0);
136
137 for (i = length - 1; i >= 0; --i) aom_write_bit(w, (x >> i) & 0x01);
138}
139
Dake Hea47cd6c2017-10-13 18:09:58 -0700140static INLINE tran_low_t get_lower_coeff(tran_low_t qc) {
141 if (qc == 0) {
142 return 0;
143 }
144 return qc > 0 ? qc - 1 : qc + 1;
145}
146
Angie Chiangb3167a62018-01-30 19:37:57 -0800147static INLINE tran_low_t qcoeff_to_dqcoeff(tran_low_t qc, int coeff_idx,
Sarah Parker3d752092017-12-20 15:37:55 -0800148#if CONFIG_NEW_QUANT
Sarah Parker98c8dd72018-01-12 15:42:24 -0800149#if CONFIG_AOM_QM
Angie Chiangb3167a62018-01-30 19:37:57 -0800150 int dq_idx,
Sarah Parker98c8dd72018-01-12 15:42:24 -0800151#else
Sarah Parker3d752092017-12-20 15:37:55 -0800152 const tran_low_t *nq_dq,
Sarah Parker98c8dd72018-01-12 15:42:24 -0800153#endif // CONFIG_AOM_QM
Sarah Parker3d752092017-12-20 15:37:55 -0800154#endif // CONFIG_NEW_QUANT
Angie Chiangb3167a62018-01-30 19:37:57 -0800155 int dqv, int shift,
156 const qm_val_t *iqmatrix) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700157 int sgn = qc < 0 ? -1 : 1;
Sarah Parker3d752092017-12-20 15:37:55 -0800158#if CONFIG_NEW_QUANT
Sarah Parker98c8dd72018-01-12 15:42:24 -0800159#if CONFIG_AOM_QM
Angie Chiangb3167a62018-01-30 19:37:57 -0800160 int is_ac_coeff = coeff_idx != 0;
Sarah Parker98c8dd72018-01-12 15:42:24 -0800161 int dqcoeff = av1_dequant_coeff_nuq(abs(qc), dqv, dq_idx, is_ac_coeff, shift);
162#else
Angie Chiangb3167a62018-01-30 19:37:57 -0800163 (void)coeff_idx;
Sarah Parker8a086e02018-01-10 14:56:42 -0800164 int dqcoeff = av1_dequant_coeff_nuq(abs(qc), dqv, nq_dq, shift);
Sarah Parker98c8dd72018-01-12 15:42:24 -0800165#endif // CONFIG_AOM_QM
Sarah Parker8a086e02018-01-10 14:56:42 -0800166 return sgn * dqcoeff;
Sarah Parker3d752092017-12-20 15:37:55 -0800167#endif // CONFIG_NEW_QUANT
Angie Chiangb3167a62018-01-30 19:37:57 -0800168 if (iqmatrix != NULL)
169 dqv =
170 ((iqmatrix[coeff_idx] * dqv) + (1 << (AOM_QM_BITS - 1))) >> AOM_QM_BITS;
Dake Hea47cd6c2017-10-13 18:09:58 -0700171 return sgn * ((abs(qc) * dqv) >> shift);
172}
173
174static INLINE int64_t get_coeff_dist(tran_low_t tcoeff, tran_low_t dqcoeff,
175 int shift) {
176 const int64_t diff = (tcoeff - dqcoeff) * (1 << shift);
177 const int64_t error = diff * diff;
178 return error;
179}
180
Jingning Han35deaa72017-10-26 15:36:30 -0700181void av1_update_eob_context(int eob, int seg_eob, TX_SIZE tx_size,
182 TX_TYPE tx_type, PLANE_TYPE plane,
Yunqing Wang0e141b52017-11-02 15:08:58 -0700183 FRAME_CONTEXT *ec_ctx, FRAME_COUNTS *counts,
184 uint8_t allow_update_cdf) {
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800185 int eob_extra, dummy;
186 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
187 const int max_eob_pt = get_eob_pos_token(seg_eob, &dummy);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -0800188 TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Dake Hea47cd6c2017-10-13 18:09:58 -0700189
Dake He0db7d0e2017-12-21 15:23:20 -0800190 (void)max_eob_pt;
191 const int eob_multi_size = txsize_log2_minus4[tx_size];
192 const int eob_multi_ctx = (tx_type_to_class[tx_type] == TX_CLASS_2D) ? 0 : 1;
193
194 switch (eob_multi_size) {
195 case 0:
196 ++counts->eob_multi16[plane][eob_multi_ctx][eob_pt - 1];
197 if (allow_update_cdf)
198 update_cdf(ec_ctx->eob_flag_cdf16[plane][eob_multi_ctx], eob_pt - 1, 5);
199 break;
200 case 1:
201 ++counts->eob_multi32[plane][eob_multi_ctx][eob_pt - 1];
202 if (allow_update_cdf)
203 update_cdf(ec_ctx->eob_flag_cdf32[plane][eob_multi_ctx], eob_pt - 1, 6);
204 break;
205 case 2:
206 ++counts->eob_multi64[plane][eob_multi_ctx][eob_pt - 1];
207 if (allow_update_cdf)
208 update_cdf(ec_ctx->eob_flag_cdf64[plane][eob_multi_ctx], eob_pt - 1, 7);
209 break;
210 case 3:
211 ++counts->eob_multi128[plane][eob_multi_ctx][eob_pt - 1];
Hui Su1cb1c002018-02-05 18:21:20 -0800212 if (allow_update_cdf) {
Dake He0db7d0e2017-12-21 15:23:20 -0800213 update_cdf(ec_ctx->eob_flag_cdf128[plane][eob_multi_ctx], eob_pt - 1,
214 8);
Hui Su1cb1c002018-02-05 18:21:20 -0800215 }
Dake He0db7d0e2017-12-21 15:23:20 -0800216 break;
217 case 4:
218 ++counts->eob_multi256[plane][eob_multi_ctx][eob_pt - 1];
Hui Su1cb1c002018-02-05 18:21:20 -0800219 if (allow_update_cdf) {
Dake He0db7d0e2017-12-21 15:23:20 -0800220 update_cdf(ec_ctx->eob_flag_cdf256[plane][eob_multi_ctx], eob_pt - 1,
221 9);
Hui Su1cb1c002018-02-05 18:21:20 -0800222 }
Dake He0db7d0e2017-12-21 15:23:20 -0800223 break;
224 case 5:
225 ++counts->eob_multi512[plane][eob_multi_ctx][eob_pt - 1];
Hui Su1cb1c002018-02-05 18:21:20 -0800226 if (allow_update_cdf) {
Dake He0db7d0e2017-12-21 15:23:20 -0800227 update_cdf(ec_ctx->eob_flag_cdf512[plane][eob_multi_ctx], eob_pt - 1,
228 10);
Hui Su1cb1c002018-02-05 18:21:20 -0800229 }
Dake He0db7d0e2017-12-21 15:23:20 -0800230 break;
231 case 6:
232 default:
233 ++counts->eob_multi1024[plane][eob_multi_ctx][eob_pt - 1];
Hui Su1cb1c002018-02-05 18:21:20 -0800234 if (allow_update_cdf) {
Dake He0db7d0e2017-12-21 15:23:20 -0800235 update_cdf(ec_ctx->eob_flag_cdf1024[plane][eob_multi_ctx], eob_pt - 1,
236 11);
Hui Su1cb1c002018-02-05 18:21:20 -0800237 }
Dake He0db7d0e2017-12-21 15:23:20 -0800238 break;
239 }
Jingning Han00803a72017-10-25 16:04:34 -0700240
Angie Chiang7ab884e2017-10-18 15:57:12 -0700241 if (k_eob_offset_bits[eob_pt] > 0) {
242 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
243 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Hui Su1e959892018-01-22 12:14:43 -0800244#if CONFIG_ENTROPY_STATS
Jingning Han35deaa72017-10-26 15:36:30 -0700245 counts->eob_extra[txs_ctx][plane][eob_pt][bit]++;
Hui Su1e959892018-01-22 12:14:43 -0800246#endif // CONFIG_ENTROPY_STATS
Yunqing Wang0e141b52017-11-02 15:08:58 -0700247 if (allow_update_cdf)
248 update_cdf(ec_ctx->eob_extra_cdf[txs_ctx][plane][eob_pt], bit, 2);
Angie Chiang7ab884e2017-10-18 15:57:12 -0700249 }
Dake Hea47cd6c2017-10-13 18:09:58 -0700250}
251
252static int get_eob_cost(int eob, int seg_eob,
Dake He0db7d0e2017-12-21 15:23:20 -0800253 const LV_MAP_EOB_COST *txb_eob_costs,
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100254 const LV_MAP_COEFF_COST *txb_costs, TX_TYPE tx_type) {
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800255 int eob_extra, dummy;
256 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
257 const int max_eob_pt = get_eob_pos_token(seg_eob, &dummy);
Dake Hea47cd6c2017-10-13 18:09:58 -0700258 int eob_cost = 0;
Dake He0db7d0e2017-12-21 15:23:20 -0800259 (void)max_eob_pt;
260 const int eob_multi_ctx = (tx_type_to_class[tx_type] == TX_CLASS_2D) ? 0 : 1;
261 eob_cost = txb_eob_costs->eob_cost[eob_multi_ctx][eob_pt - 1];
Dake He0db7d0e2017-12-21 15:23:20 -0800262
Dake Hea47cd6c2017-10-13 18:09:58 -0700263 if (k_eob_offset_bits[eob_pt] > 0) {
Hui Su751a2332018-01-23 11:35:03 -0800264 const int eob_shift = k_eob_offset_bits[eob_pt] - 1;
265 const int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Angie Chiang7ab884e2017-10-18 15:57:12 -0700266 eob_cost += txb_costs->eob_extra_cost[eob_pt][bit];
Hui Su751a2332018-01-23 11:35:03 -0800267 const int offset_bits = k_eob_offset_bits[eob_pt];
268 if (offset_bits > 1) eob_cost += av1_cost_literal(offset_bits - 1);
Dake Hea47cd6c2017-10-13 18:09:58 -0700269 }
270 return eob_cost;
271}
272
Linfeng Zhang1015a342017-10-24 16:20:41 -0700273static int get_coeff_cost(const tran_low_t qc, const int scan_idx,
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100274 const int is_eob, const TxbInfo *const txb_info,
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -0800275 const LV_MAP_COEFF_COST *const txb_costs,
276 const int coeff_ctx);
Dake Hea47cd6c2017-10-13 18:09:58 -0700277
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800278static void get_dist_cost_stats(LevelDownStats *const stats, const int scan_idx,
Ola Hugosson13892102017-11-06 08:01:44 +0100279 const int is_eob,
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800280 const LV_MAP_COEFF_COST *const txb_costs,
Cheng Chen37d88732018-01-09 14:02:41 -0800281 const TxbInfo *const txb_info,
282 int has_nz_tail) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800283 const int16_t *const scan = txb_info->scan_order->scan;
Dake Hea47cd6c2017-10-13 18:09:58 -0700284 const int coeff_idx = scan[scan_idx];
285 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
Linfeng Zhang1015a342017-10-24 16:20:41 -0700286 const uint8_t *const levels = txb_info->levels;
Dake Hea47cd6c2017-10-13 18:09:58 -0700287 stats->new_eob = -1;
288 stats->update = 0;
Debargha Mukherjeee2f6b162018-01-04 17:23:05 -0800289 stats->rd_low = 0;
290 stats->rd = 0;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -0800291 stats->nz_rd = 0;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -0800292 stats->dist_low = 0;
293 stats->rate_low = 0;
294 stats->low_qc = 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700295
296 const tran_low_t tqc = txb_info->tcoeff[coeff_idx];
297 const int dqv = txb_info->dequant[coeff_idx != 0];
Sarah Parker3d752092017-12-20 15:37:55 -0800298#if CONFIG_NEW_QUANT
Sarah Parker98c8dd72018-01-12 15:42:24 -0800299#if CONFIG_AOM_QM
300 const int dq_idx = txb_info->dq_idx;
301#else
Sarah Parker3d752092017-12-20 15:37:55 -0800302 const tran_low_t *nq_dequant_val = txb_info->nq_dequant_vals[coeff_idx != 0];
Sarah Parker98c8dd72018-01-12 15:42:24 -0800303#endif // CONFIG_AOM_QM
Sarah Parker3d752092017-12-20 15:37:55 -0800304#endif // CONFIG_NEW_QUANT
Dake Hea47cd6c2017-10-13 18:09:58 -0700305
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100306 const int coeff_ctx =
307 get_nz_map_ctx(levels, coeff_idx, txb_info->bwl, txb_info->height,
308 scan_idx, is_eob, txb_info->tx_size, txb_info->tx_type);
309 const int qc_cost =
310 get_coeff_cost(qc, scan_idx, is_eob, txb_info, txb_costs, coeff_ctx);
Dake Hea47cd6c2017-10-13 18:09:58 -0700311 if (qc == 0) {
Cheng Chen79641202018-01-04 18:52:52 -0800312 stats->dist = 0;
313 stats->rate = qc_cost;
Dake Hea47cd6c2017-10-13 18:09:58 -0700314 return;
Cheng Chen79641202018-01-04 18:52:52 -0800315 } else {
Angie Chiangb3167a62018-01-30 19:37:57 -0800316 const tran_low_t dqc =
317 qcoeff_to_dqcoeff(qc, coeff_idx,
Cheng Chen79641202018-01-04 18:52:52 -0800318#if CONFIG_NEW_QUANT
Sarah Parker98c8dd72018-01-12 15:42:24 -0800319#if CONFIG_AOM_QM
Angie Chiangb3167a62018-01-30 19:37:57 -0800320 dq_idx,
Sarah Parker98c8dd72018-01-12 15:42:24 -0800321#else
Angie Chiangb3167a62018-01-30 19:37:57 -0800322 nq_dequant_val,
Sarah Parker98c8dd72018-01-12 15:42:24 -0800323#endif // CONFIG_AOM_QM
Cheng Chen79641202018-01-04 18:52:52 -0800324#endif // CONFIG_NEW_QUANT
Angie Chiangb3167a62018-01-30 19:37:57 -0800325 dqv, txb_info->shift, txb_info->iqmatrix);
Cheng Chen79641202018-01-04 18:52:52 -0800326 const int64_t dqc_dist = get_coeff_dist(tqc, dqc, txb_info->shift);
327
328 // distortion difference when coefficient is quantized to 0
Angie Chiangb3167a62018-01-30 19:37:57 -0800329 const tran_low_t dqc0 =
330 qcoeff_to_dqcoeff(0, coeff_idx,
Cheng Chen79641202018-01-04 18:52:52 -0800331#if CONFIG_NEW_QUANT
Sarah Parker98c8dd72018-01-12 15:42:24 -0800332#if CONFIG_AOM_QM
Angie Chiangb3167a62018-01-30 19:37:57 -0800333 dq_idx,
Sarah Parker98c8dd72018-01-12 15:42:24 -0800334#else
Angie Chiangb3167a62018-01-30 19:37:57 -0800335 nq_dequant_val,
Sarah Parker98c8dd72018-01-12 15:42:24 -0800336#endif // CONFIG_AOM_QM
Cheng Chen79641202018-01-04 18:52:52 -0800337#endif // CONFIG_NEW_QUANT
Angie Chiangb3167a62018-01-30 19:37:57 -0800338 dqv, txb_info->shift, txb_info->iqmatrix);
Cheng Chen79641202018-01-04 18:52:52 -0800339
340 stats->dist0 = get_coeff_dist(tqc, dqc0, txb_info->shift);
341 stats->dist = dqc_dist - stats->dist0;
342 stats->rate = qc_cost;
Dake Hea47cd6c2017-10-13 18:09:58 -0700343 }
Cheng Chen79641202018-01-04 18:52:52 -0800344
Dake Hea47cd6c2017-10-13 18:09:58 -0700345 stats->rd = RDCOST(txb_info->rdmult, stats->rate, stats->dist);
346
347 stats->low_qc = get_lower_coeff(qc);
Dake Hea47cd6c2017-10-13 18:09:58 -0700348
Dake He4d447692017-12-15 09:10:06 -0800349 if (is_eob && stats->low_qc == 0) {
Dake He4d447692017-12-15 09:10:06 -0800350 stats->rd_low = stats->rd; // disable selection of low_qc in this case.
Ola Hugosson13892102017-11-06 08:01:44 +0100351 } else {
Cheng Chen37d88732018-01-09 14:02:41 -0800352 if (stats->low_qc == 0) {
353 stats->dist_low = 0;
354 } else {
Angie Chiangb3167a62018-01-30 19:37:57 -0800355 stats->low_dqc =
356 qcoeff_to_dqcoeff(stats->low_qc, coeff_idx,
Dake He4d447692017-12-15 09:10:06 -0800357#if CONFIG_NEW_QUANT
Sarah Parker98c8dd72018-01-12 15:42:24 -0800358#if CONFIG_AOM_QM
Angie Chiangb3167a62018-01-30 19:37:57 -0800359 dq_idx,
Sarah Parker98c8dd72018-01-12 15:42:24 -0800360#else
Angie Chiangb3167a62018-01-30 19:37:57 -0800361 nq_dequant_val,
Sarah Parker98c8dd72018-01-12 15:42:24 -0800362#endif // CONFIG_AOM_QM
Dake He4d447692017-12-15 09:10:06 -0800363#endif // CONFIG_NEW_QUANT
Angie Chiangb3167a62018-01-30 19:37:57 -0800364 dqv, txb_info->shift, txb_info->iqmatrix);
Cheng Chen37d88732018-01-09 14:02:41 -0800365 const int64_t low_dqc_dist =
366 get_coeff_dist(tqc, stats->low_dqc, txb_info->shift);
367 stats->dist_low = low_dqc_dist - stats->dist0;
368 }
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100369 const int low_qc_cost = get_coeff_cost(stats->low_qc, scan_idx, is_eob,
Yaowu Xu0154f2b2018-01-04 09:01:17 -0800370 txb_info, txb_costs, coeff_ctx);
Dake He4d447692017-12-15 09:10:06 -0800371 stats->rate_low = low_qc_cost;
372 stats->rd_low = RDCOST(txb_info->rdmult, stats->rate_low, stats->dist_low);
Ola Hugosson13892102017-11-06 08:01:44 +0100373 }
Cheng Chenec32a742018-01-12 19:09:39 -0800374 if ((has_nz_tail < 2) && !is_eob) {
Cheng Chen37d88732018-01-09 14:02:41 -0800375 (void)levels;
376 const int coeff_ctx_temp =
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100377 get_nz_map_ctx(levels, coeff_idx, txb_info->bwl, txb_info->height,
378 scan_idx, 1, txb_info->tx_size, txb_info->tx_type);
Cheng Chen37d88732018-01-09 14:02:41 -0800379 const int qc_eob_cost =
380 get_coeff_cost(qc, scan_idx, 1, txb_info, txb_costs, coeff_ctx_temp);
381 int64_t rd_eob = RDCOST(txb_info->rdmult, qc_eob_cost, stats->dist);
382 if (stats->low_qc != 0) {
383 const int low_qc_eob_cost = get_coeff_cost(
384 stats->low_qc, scan_idx, 1, txb_info, txb_costs, coeff_ctx_temp);
385 int64_t rd_eob_low =
386 RDCOST(txb_info->rdmult, low_qc_eob_cost, stats->dist_low);
387 rd_eob = (rd_eob > rd_eob_low) ? rd_eob_low : rd_eob;
388 }
389
390 stats->nz_rd = AOMMIN(stats->rd_low, stats->rd) - rd_eob;
Cheng Chen37d88732018-01-09 14:02:41 -0800391 }
Dake Hea47cd6c2017-10-13 18:09:58 -0700392}
393
Linfeng Zhang1015a342017-10-24 16:20:41 -0700394static INLINE void update_qcoeff(const int coeff_idx, const tran_low_t qc,
395 const TxbInfo *const txb_info) {
Dake Hea47cd6c2017-10-13 18:09:58 -0700396 txb_info->qcoeff[coeff_idx] = qc;
Linfeng Zhangd5647372017-12-05 17:06:07 -0800397 txb_info->levels[get_padded_idx(coeff_idx, txb_info->bwl)] =
Jingning Han5cb408e2017-11-17 14:43:39 -0800398 (uint8_t)clamp(abs(qc), 0, INT8_MAX);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700399}
400
401static INLINE void update_coeff(const int coeff_idx, const tran_low_t qc,
402 const TxbInfo *const txb_info) {
403 update_qcoeff(coeff_idx, qc, txb_info);
Dake Hea47cd6c2017-10-13 18:09:58 -0700404 const int dqv = txb_info->dequant[coeff_idx != 0];
Sarah Parker3d752092017-12-20 15:37:55 -0800405#if CONFIG_NEW_QUANT
Sarah Parker98c8dd72018-01-12 15:42:24 -0800406#if CONFIG_AOM_QM
407 const int dq_idx = txb_info->dq_idx;
408#else
Sarah Parker3d752092017-12-20 15:37:55 -0800409 const tran_low_t *nq_dequant_val = txb_info->nq_dequant_vals[coeff_idx != 0];
Sarah Parker98c8dd72018-01-12 15:42:24 -0800410#endif // CONFIG_AOM_QM
Sarah Parker3d752092017-12-20 15:37:55 -0800411#endif // CONFIG_NEW_QUANT
Angie Chiangb3167a62018-01-30 19:37:57 -0800412 txb_info->dqcoeff[coeff_idx] =
413 qcoeff_to_dqcoeff(qc, coeff_idx,
Sarah Parker3d752092017-12-20 15:37:55 -0800414#if CONFIG_NEW_QUANT
Sarah Parker98c8dd72018-01-12 15:42:24 -0800415#if CONFIG_AOM_QM
Angie Chiangb3167a62018-01-30 19:37:57 -0800416 dq_idx,
Sarah Parker98c8dd72018-01-12 15:42:24 -0800417#else
Angie Chiangb3167a62018-01-30 19:37:57 -0800418 nq_dequant_val,
Sarah Parker98c8dd72018-01-12 15:42:24 -0800419#endif // CONFIG_AOM_QM
Sarah Parker3d752092017-12-20 15:37:55 -0800420#endif // CONFIG_NEW_QUANT
Angie Chiangb3167a62018-01-30 19:37:57 -0800421 dqv, txb_info->shift, txb_info->iqmatrix);
Dake Hea47cd6c2017-10-13 18:09:58 -0700422}
423
Linfeng Zhang1015a342017-10-24 16:20:41 -0700424static INLINE void av1_txb_init_levels(const tran_low_t *const coeff,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700425 const int width, const int height,
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700426 uint8_t *const levels) {
427 const int stride = width + TX_PAD_HOR;
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700428 uint8_t *ls = levels;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700429
430 memset(levels - TX_PAD_TOP * stride, 0,
431 sizeof(*levels) * TX_PAD_TOP * stride);
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700432 memset(levels + stride * height, 0,
433 sizeof(*levels) * (TX_PAD_BOTTOM * stride + TX_PAD_END));
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700434
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700435 for (int i = 0; i < height; i++) {
436 for (int j = 0; j < width; j++) {
Jingning Han5cb408e2017-11-17 14:43:39 -0800437 *ls++ = (uint8_t)clamp(abs(coeff[i * width + j]), 0, INT8_MAX);
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700438 }
439 for (int j = 0; j < TX_PAD_HOR; j++) {
440 *ls++ = 0;
441 }
Linfeng Zhang1015a342017-10-24 16:20:41 -0700442 }
443}
444
Linfeng Zhang0ba23e82017-12-20 16:27:28 -0800445void av1_get_nz_map_contexts_c(const uint8_t *const levels,
446 const int16_t *const scan, const uint16_t eob,
447 const TX_SIZE tx_size, const TX_TYPE tx_type,
448 int8_t *const coeff_contexts) {
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800449 const int bwl = get_txb_bwl(tx_size);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800450 const int height = get_txb_high(tx_size);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800451 for (int i = 0; i < eob; ++i) {
452 const int pos = scan[i];
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100453 coeff_contexts[pos] = get_nz_map_ctx(levels, pos, bwl, height, i,
454 i == eob - 1, tx_size, tx_type);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800455 }
456}
457
Angie Chiang80b82262017-02-24 11:39:47 -0800458void av1_write_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCKD *xd,
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500459 aom_writer *w, int blk_row, int blk_col, int plane,
460 TX_SIZE tx_size, const tran_low_t *tcoeff,
Jingning Han7eab9ff2017-07-06 10:12:54 -0700461 uint16_t eob, TXB_CTX *txb_ctx) {
Angie Chiang80b82262017-02-24 11:39:47 -0800462 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiangcea11f22017-02-24 12:30:40 -0800463 const PLANE_TYPE plane_type = get_plane_type(plane);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -0800464 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Sarah Parker7c71cc02018-01-29 12:27:58 -0800465 const TX_TYPE tx_type = av1_get_tx_type(plane_type, xd, blk_row, blk_col,
466 tx_size, cm->reduced_tx_set_used);
Angie Chiangbd99b382017-06-20 15:11:16 -0700467 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800468 const int16_t *const scan = scan_order->scan;
Urvang Joshi80893152017-10-27 11:51:14 -0700469 const int seg_eob = av1_get_max_eob(tx_size);
Angie Chiang80b82262017-02-24 11:39:47 -0800470 int c;
Angie Chianga9ba58e2017-12-01 19:22:43 -0800471 const int bwl = get_txb_bwl(tx_size);
472 const int width = get_txb_wide(tx_size);
473 const int height = get_txb_high(tx_size);
Jingning Han41c7f442017-09-05 14:54:00 -0700474 FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700475 uint8_t levels_buf[TX_PAD_2D];
476 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -0800477 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800478 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Angie Chiang41220ab2018-02-14 17:48:23 -0800479 uint16_t update_pos[MAX_TX_SQUARE];
480 int num_updates = 0;
Angie Chiang80b82262017-02-24 11:39:47 -0800481
Hui Su41d61522018-01-23 10:47:55 -0800482 aom_write_symbol(w, eob == 0,
483 ec_ctx->txb_skip_cdf[txs_ctx][txb_ctx->txb_skip_ctx], 2);
Angie Chiang5f0cb5e2017-12-11 16:07:50 -0800484#if CONFIG_TXK_SEL
Angie Chianga3f7d2e2017-12-07 19:51:14 -0800485 if (plane == 0 && eob == 0) {
486 assert(tx_type == DCT_DCT);
487 }
Angie Chiang5f0cb5e2017-12-11 16:07:50 -0800488#endif
Angie Chiang80b82262017-02-24 11:39:47 -0800489 if (eob == 0) return;
Linfeng Zhangce065ca2017-10-17 16:49:30 -0700490
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700491 av1_txb_init_levels(tcoeff, width, height, levels);
Linfeng Zhangce065ca2017-10-17 16:49:30 -0700492
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700493#if CONFIG_TXK_SEL
Debargha Mukherjee3ebb0d02017-12-14 05:05:18 -0800494 av1_write_tx_type(cm, xd, blk_row, blk_col, plane, tx_size, w);
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700495#endif
Angie Chiang80b82262017-02-24 11:39:47 -0800496
Linfeng Zhang0c72b2f2017-12-04 10:59:28 -0800497 int eob_extra, dummy;
498 const int eob_pt = get_eob_pos_token(eob, &eob_extra);
499 const int max_eob_pt = get_eob_pos_token(seg_eob, &dummy);
Dake Hea47cd6c2017-10-13 18:09:58 -0700500
Dake He0db7d0e2017-12-21 15:23:20 -0800501 (void)max_eob_pt;
502 const int eob_multi_size = txsize_log2_minus4[tx_size];
503 const int eob_multi_ctx = (tx_type_to_class[tx_type] == TX_CLASS_2D) ? 0 : 1;
504 switch (eob_multi_size) {
505 case 0:
506 aom_write_symbol(w, eob_pt - 1,
507 ec_ctx->eob_flag_cdf16[plane_type][eob_multi_ctx], 5);
508 break;
509 case 1:
510 aom_write_symbol(w, eob_pt - 1,
511 ec_ctx->eob_flag_cdf32[plane_type][eob_multi_ctx], 6);
512 break;
513 case 2:
514 aom_write_symbol(w, eob_pt - 1,
515 ec_ctx->eob_flag_cdf64[plane_type][eob_multi_ctx], 7);
516 break;
517 case 3:
518 aom_write_symbol(w, eob_pt - 1,
519 ec_ctx->eob_flag_cdf128[plane_type][eob_multi_ctx], 8);
520 break;
521 case 4:
522 aom_write_symbol(w, eob_pt - 1,
523 ec_ctx->eob_flag_cdf256[plane_type][eob_multi_ctx], 9);
524 break;
525 case 5:
526 aom_write_symbol(w, eob_pt - 1,
527 ec_ctx->eob_flag_cdf512[plane_type][eob_multi_ctx], 10);
528 break;
529 default:
530 aom_write_symbol(w, eob_pt - 1,
531 ec_ctx->eob_flag_cdf1024[plane_type][eob_multi_ctx], 11);
532 break;
533 }
534
Dake Hea47cd6c2017-10-13 18:09:58 -0700535 if (k_eob_offset_bits[eob_pt] > 0) {
Angie Chiang7ab884e2017-10-18 15:57:12 -0700536 int eob_shift = k_eob_offset_bits[eob_pt] - 1;
537 int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Hui Su41d61522018-01-23 10:47:55 -0800538 aom_write_symbol(w, bit, ec_ctx->eob_extra_cdf[txs_ctx][plane_type][eob_pt],
539 2);
Angie Chiang7ab884e2017-10-18 15:57:12 -0700540 for (int i = 1; i < k_eob_offset_bits[eob_pt]; i++) {
541 eob_shift = k_eob_offset_bits[eob_pt] - 1 - i;
542 bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700543 aom_write_bit(w, bit);
Dake Hea47cd6c2017-10-13 18:09:58 -0700544 }
545 }
Dake He03a32922017-10-31 08:06:45 -0700546
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800547 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_type, coeff_contexts);
548
549 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800550 const int pos = scan[c];
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800551 const int coeff_ctx = coeff_contexts[pos];
552 const tran_low_t v = tcoeff[pos];
Angie Chiang41220ab2018-02-14 17:48:23 -0800553 const tran_low_t level = abs(v);
Dake He03a32922017-10-31 08:06:45 -0700554
Dake He3fe369c2017-11-16 17:56:44 -0800555 if (c == eob - 1) {
556 aom_write_symbol(
Angie Chiang41220ab2018-02-14 17:48:23 -0800557 w, AOMMIN(level, 3) - 1,
Dake He4d447692017-12-15 09:10:06 -0800558 ec_ctx->coeff_base_eob_cdf[txs_ctx][plane_type][coeff_ctx], 3);
Dake He3fe369c2017-11-16 17:56:44 -0800559 } else {
Angie Chiang41220ab2018-02-14 17:48:23 -0800560 aom_write_symbol(w, AOMMIN(level, 3),
Dake He3fe369c2017-11-16 17:56:44 -0800561 ec_ctx->coeff_base_cdf[txs_ctx][plane_type][coeff_ctx],
562 4);
563 }
Angie Chiang41220ab2018-02-14 17:48:23 -0800564 if (level > NUM_BASE_LEVELS) {
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100565 // level is above 1.
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800566 const int base_range = level - 1 - NUM_BASE_LEVELS;
Angie Chiang41220ab2018-02-14 17:48:23 -0800567 const int br_ctx =
568 get_br_ctx(levels, pos, bwl, level_counts[pos], tx_type);
Angie Chiang41220ab2018-02-14 17:48:23 -0800569 for (int idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800570 const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
Dake Hee2d8f182017-12-14 13:28:00 -0800571 aom_write_symbol(w, k,
572#if 0
Dake He7d01ab52017-11-24 17:53:28 -0800573 ec_ctx->coeff_br_cdf[AOMMIN(txs_ctx, TX_16X16)][plane_type][ctx],
Dake Hee2d8f182017-12-14 13:28:00 -0800574#else
575 ec_ctx->coeff_br_cdf[AOMMIN(txs_ctx, TX_32X32)]
Angie Chiang41220ab2018-02-14 17:48:23 -0800576 [plane_type][br_ctx],
Dake Hee2d8f182017-12-14 13:28:00 -0800577#endif
578 BR_CDF_SIZE);
Ola Hugossone72a2092017-11-12 09:11:53 +0100579 if (k < BR_CDF_SIZE - 1) break;
580 }
Angie Chiang41220ab2018-02-14 17:48:23 -0800581 if (level > COEFF_BASE_RANGE + NUM_BASE_LEVELS) {
582 update_pos[num_updates] = pos;
583 ++num_updates;
584 }
585 }
586 }
587
588 for (int i = 0; i < num_updates; ++i) {
589 const int pos = update_pos[i];
590 write_golomb(w, abs(tcoeff[pos]) - COEFF_BASE_RANGE - 1 - NUM_BASE_LEVELS);
591 }
592
593 // Loop to code all signs in the transform block,
594 // starting with the sign of DC (if applicable)
595 for (c = 0; c < eob; ++c) {
596 const tran_low_t v = tcoeff[scan[c]];
597 const int sign = (v < 0) ? 1 : 0;
598 if (v != 0) {
599 if (c == 0) {
600 aom_write_symbol(
601 w, sign, ec_ctx->dc_sign_cdf[plane_type][txb_ctx->dc_sign_ctx], 2);
602 } else {
603 aom_write_bit(w, sign);
604 }
Jingning Han87b01b52017-08-31 12:07:20 -0700605 }
Angie Chiang80b82262017-02-24 11:39:47 -0800606 }
607}
Angie Chiang47c72182017-02-27 14:30:38 -0800608
Angie Chiang140b3332017-12-12 17:29:25 -0800609typedef struct encode_txb_args {
610 const AV1_COMMON *cm;
611 MACROBLOCK *x;
612 aom_writer *w;
613} ENCODE_TXB_ARGS;
614
Jingning Han3a32e102018-01-11 16:00:35 -0800615static void write_coeffs_txb_wrap(const AV1_COMMON *cm, MACROBLOCK *x,
616 aom_writer *w, int plane, int block,
617 int blk_row, int blk_col, TX_SIZE tx_size) {
Angie Chiangc8af6112017-03-16 16:11:22 -0700618 MACROBLOCKD *xd = &x->e_mbd;
Angie Chiang140b3332017-12-12 17:29:25 -0800619 tran_low_t *tcoeff = BLOCK_OFFSET(x->mbmi_ext->tcoeff[plane], block);
620 uint16_t eob = x->mbmi_ext->eobs[plane][block];
621 TXB_CTX txb_ctx = { x->mbmi_ext->txb_skip_ctx[plane][block],
622 x->mbmi_ext->dc_sign_ctx[plane][block] };
Luc Trudeau2eb9b842017-12-13 11:19:16 -0500623 av1_write_coeffs_txb(cm, xd, w, blk_row, blk_col, plane, tx_size, tcoeff, eob,
624 &txb_ctx);
Angie Chiang140b3332017-12-12 17:29:25 -0800625}
626
Jingning Han4b48cd12018-01-11 15:56:42 -0800627void av1_write_coeffs_mb(const AV1_COMMON *const cm, MACROBLOCK *x, int mi_row,
Jingning Hanad54a982018-01-12 14:40:29 -0800628 int mi_col, aom_writer *w, BLOCK_SIZE bsize) {
Angie Chiang140b3332017-12-12 17:29:25 -0800629 MACROBLOCKD *xd = &x->e_mbd;
Jingning Hanad54a982018-01-12 14:40:29 -0800630 const int num_planes = av1_num_planes(cm);
631 int block[MAX_MB_PLANE] = { 0 };
Jingning Han4b48cd12018-01-11 15:56:42 -0800632 int row, col;
Jingning Hanad54a982018-01-12 14:40:29 -0800633 const struct macroblockd_plane *const y_pd = &xd->plane[0];
634 const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, y_pd);
635 const int max_blocks_wide = max_block_wide(xd, plane_bsize, 0);
636 const int max_blocks_high = max_block_high(xd, plane_bsize, 0);
637 const BLOCK_SIZE max_unit_bsize = get_plane_block_size(BLOCK_64X64, y_pd);
Jingning Han4b48cd12018-01-11 15:56:42 -0800638 int mu_blocks_wide = block_size_wide[max_unit_bsize] >> tx_size_wide_log2[0];
639 int mu_blocks_high = block_size_high[max_unit_bsize] >> tx_size_high_log2[0];
640 mu_blocks_wide = AOMMIN(max_blocks_wide, mu_blocks_wide);
641 mu_blocks_high = AOMMIN(max_blocks_high, mu_blocks_high);
642
643 for (row = 0; row < max_blocks_high; row += mu_blocks_high) {
Jingning Han4b48cd12018-01-11 15:56:42 -0800644 for (col = 0; col < max_blocks_wide; col += mu_blocks_wide) {
Jingning Hanad54a982018-01-12 14:40:29 -0800645 for (int plane = 0; plane < num_planes; ++plane) {
646 const struct macroblockd_plane *const pd = &xd->plane[plane];
647 if (!is_chroma_reference(mi_row, mi_col, bsize, pd->subsampling_x,
648 pd->subsampling_y))
649 continue;
650 const TX_SIZE tx_size = av1_get_tx_size(plane, xd);
651 const int stepr = tx_size_high_unit[tx_size];
652 const int stepc = tx_size_wide_unit[tx_size];
653 const int step = stepr * stepc;
Jingning Han4b48cd12018-01-11 15:56:42 -0800654
Jingning Hanad54a982018-01-12 14:40:29 -0800655 const int unit_height = ROUND_POWER_OF_TWO(
656 AOMMIN(mu_blocks_high + row, max_blocks_high), pd->subsampling_y);
657 const int unit_width = ROUND_POWER_OF_TWO(
658 AOMMIN(mu_blocks_wide + col, max_blocks_wide), pd->subsampling_x);
659 for (int blk_row = row >> pd->subsampling_y; blk_row < unit_height;
660 blk_row += stepr) {
661 for (int blk_col = col >> pd->subsampling_x; blk_col < unit_width;
662 blk_col += stepc) {
663 write_coeffs_txb_wrap(cm, x, w, plane, block[plane], blk_row,
664 blk_col, tx_size);
665 block[plane] += step;
666 }
Jingning Han4b48cd12018-01-11 15:56:42 -0800667 }
668 }
669 }
670 }
Angie Chiangc8af6112017-03-16 16:11:22 -0700671}
672
Angie Chiang488f9212017-05-30 12:46:26 -0700673static INLINE int get_br_cost(tran_low_t abs_qc, int ctx,
Angie Chiang26d3e452017-09-29 17:40:02 -0700674 const int *coeff_lps) {
Angie Chiang488f9212017-05-30 12:46:26 -0700675 const tran_low_t min_level = 1 + NUM_BASE_LEVELS;
676 const tran_low_t max_level = 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE;
Jingning Handfd72322017-08-09 14:04:12 -0700677 (void)ctx;
Angie Chiang488f9212017-05-30 12:46:26 -0700678 if (abs_qc >= min_level) {
Angie Chiang488f9212017-05-30 12:46:26 -0700679 if (abs_qc >= max_level)
Jingning Han772dee32017-09-15 08:53:18 -0700680 return coeff_lps[COEFF_BASE_RANGE]; // COEFF_BASE_RANGE * cost0;
Angie Chiang488f9212017-05-30 12:46:26 -0700681 else
Jingning Han772dee32017-09-15 08:53:18 -0700682 return coeff_lps[(abs_qc - min_level)]; // * cost0 + cost1;
Angie Chiang488f9212017-05-30 12:46:26 -0700683 } else {
684 return 0;
685 }
686}
687
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800688// Note: don't call this function when eob is 0.
689int av1_cost_coeffs_txb(const AV1_COMMON *const cm, const MACROBLOCK *x,
690 const int plane, const int blk_row, const int blk_col,
691 const int block, const TX_SIZE tx_size,
692 const TXB_CTX *const txb_ctx) {
693 const MACROBLOCKD *const xd = &x->e_mbd;
694 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Angie Chiang47c72182017-02-27 14:30:38 -0800695 const PLANE_TYPE plane_type = get_plane_type(plane);
Sarah Parker7c71cc02018-01-29 12:27:58 -0800696 const TX_TYPE tx_type = av1_get_tx_type(plane_type, xd, blk_row, blk_col,
697 tx_size, cm->reduced_tx_set_used);
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800698 const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Angie Chiang47c72182017-02-27 14:30:38 -0800699 const struct macroblock_plane *p = &x->plane[plane];
700 const int eob = p->eobs[block];
701 const tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
702 int c, cost;
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800703 const int txb_skip_ctx = txb_ctx->txb_skip_ctx;
Angie Chianga9ba58e2017-12-01 19:22:43 -0800704 const int bwl = get_txb_bwl(tx_size);
705 const int width = get_txb_wide(tx_size);
706 const int height = get_txb_high(tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -0700707 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800708 const int16_t *const scan = scan_order->scan;
Linfeng Zhang679d81e2017-10-31 15:27:42 -0700709 uint8_t levels_buf[TX_PAD_2D];
710 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -0800711 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800712 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Linfeng Zhangc02b4112017-12-21 13:11:36 -0800713 const LV_MAP_COEFF_COST *const coeff_costs =
714 &x->coeff_costs[txs_ctx][plane_type];
Angie Chiang47c72182017-02-27 14:30:38 -0800715
Dake He0db7d0e2017-12-21 15:23:20 -0800716 const int eob_multi_size = txsize_log2_minus4[tx_size];
717 const LV_MAP_EOB_COST *const eob_costs =
718 &x->eob_costs[eob_multi_size][plane_type];
Dake He56416352017-12-26 15:43:34 -0800719 // eob must be greater than 0 here.
720 assert(eob > 0);
Jingning Handfd72322017-08-09 14:04:12 -0700721 cost = coeff_costs->txb_skip_cost[txb_skip_ctx][0];
Angie Chiang47c72182017-02-27 14:30:38 -0800722
Linfeng Zhang1122d7d2017-10-31 15:30:28 -0700723 av1_txb_init_levels(qcoeff, width, height, levels);
Linfeng Zhang1015a342017-10-24 16:20:41 -0700724
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700725#if CONFIG_TXK_SEL
Yue Chenb23d00a2017-07-28 17:01:21 -0700726 cost += av1_tx_type_cost(cm, x, xd, mbmi->sb_type, plane, tx_size, tx_type);
Angie Chiangcd9b03f2017-04-16 13:37:13 -0700727#endif
Angie Chiang05917872017-04-15 12:28:56 -0700728
Urvang Joshi80893152017-10-27 11:51:14 -0700729 const int seg_eob = av1_get_max_eob(tx_size);
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +0100730 int eob_cost = get_eob_cost(eob, seg_eob, eob_costs, coeff_costs, tx_type);
Dake Hea47cd6c2017-10-13 18:09:58 -0700731 cost += eob_cost;
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800732
733 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_type, coeff_contexts);
734
Dake Hea47cd6c2017-10-13 18:09:58 -0700735 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800736 const int pos = scan[c];
737 const tran_low_t v = qcoeff[pos];
738 const int is_nz = (v != 0);
739 const int level = abs(v);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -0800740 const int coeff_ctx = coeff_contexts[pos];
Dake He3fe369c2017-11-16 17:56:44 -0800741 if (c == eob - 1) {
Dake He4d447692017-12-15 09:10:06 -0800742 cost += coeff_costs->base_eob_cost[coeff_ctx][AOMMIN(level, 3) - 1];
Dake He3fe369c2017-11-16 17:56:44 -0800743 } else {
744 cost += coeff_costs->base_cost[coeff_ctx][AOMMIN(level, 3)];
745 }
Dake Hea47cd6c2017-10-13 18:09:58 -0700746
747 if (is_nz) {
Hui Su751a2332018-01-23 11:35:03 -0800748 const int sign = (v < 0) ? 1 : 0;
Dake Hea47cd6c2017-10-13 18:09:58 -0700749
750 // sign bit cost
751 if (c == 0) {
752 int dc_sign_ctx = txb_ctx->dc_sign_ctx;
753 cost += coeff_costs->dc_sign_cost[dc_sign_ctx][sign];
754 } else {
Hui Su751a2332018-01-23 11:35:03 -0800755 cost += av1_cost_literal(1);
Dake Hea47cd6c2017-10-13 18:09:58 -0700756 }
Dake Hea47cd6c2017-10-13 18:09:58 -0700757 if (level > NUM_BASE_LEVELS) {
758 int ctx;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800759 ctx = get_br_ctx(levels, pos, bwl, level_counts[pos], tx_type);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800760 const int base_range = level - 1 - NUM_BASE_LEVELS;
Dake Hea47cd6c2017-10-13 18:09:58 -0700761 if (base_range < COEFF_BASE_RANGE) {
762 cost += coeff_costs->lps_cost[ctx][base_range];
763 } else {
764 cost += coeff_costs->lps_cost[ctx][COEFF_BASE_RANGE];
765 }
766
Dake Hea47cd6c2017-10-13 18:09:58 -0700767 if (level >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
768 // residual cost
Hui Su751a2332018-01-23 11:35:03 -0800769 const int ri = level - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
770 const int length = get_msb(ri) + 1;
771 cost += av1_cost_literal(2 * length);
Dake Hea47cd6c2017-10-13 18:09:58 -0700772 }
773 }
774 }
775 }
Angie Chiang47c72182017-02-27 14:30:38 -0800776 return cost;
777}
Angie Chiang0397eda2017-03-15 16:57:14 -0700778
Angie Chiang2affb3b2017-05-30 15:23:51 -0700779static INLINE int has_base(tran_low_t qc, int base_idx) {
780 const int level = base_idx + 1;
781 return abs(qc) >= level;
782}
783
Angie Chiang2affb3b2017-05-30 15:23:51 -0700784static INLINE int has_br(tran_low_t qc) {
785 return abs(qc) >= 1 + NUM_BASE_LEVELS;
786}
787
Angie Chiang488f9212017-05-30 12:46:26 -0700788static INLINE int get_sign_bit_cost(tran_low_t qc, int coeff_idx,
Jingning Handfd72322017-08-09 14:04:12 -0700789 const int (*dc_sign_cost)[2],
Angie Chiang488f9212017-05-30 12:46:26 -0700790 int dc_sign_ctx) {
791 const int sign = (qc < 0) ? 1 : 0;
792 // sign bit cost
793 if (coeff_idx == 0) {
Jingning Handfd72322017-08-09 14:04:12 -0700794 return dc_sign_cost[dc_sign_ctx][sign];
Angie Chiang488f9212017-05-30 12:46:26 -0700795 } else {
Hui Su751a2332018-01-23 11:35:03 -0800796 return av1_cost_literal(1);
Angie Chiang488f9212017-05-30 12:46:26 -0700797 }
798}
799static INLINE int get_golomb_cost(int abs_qc) {
800 if (abs_qc >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
801 // residual cost
802 int r = abs_qc - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
803 int ri = r;
804 int length = 0;
805
806 while (ri) {
807 ri >>= 1;
808 ++length;
809 }
810
811 return av1_cost_literal(2 * length - 1);
812 } else {
813 return 0;
814 }
815}
816
Angie Chiang2affb3b2017-05-30 15:23:51 -0700817void gen_txb_cache(TxbCache *txb_cache, TxbInfo *txb_info) {
Angie Chiang481c01f2017-08-15 16:24:30 -0700818 // gen_nz_count_arr
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800819 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang481c01f2017-08-15 16:24:30 -0700820 const int bwl = txb_info->bwl;
821 const int height = txb_info->height;
Linfeng Zhang72e0b3f2017-10-18 13:32:12 -0700822 const tran_low_t *const qcoeff = txb_info->qcoeff;
Linfeng Zhangb6957c22017-10-25 13:17:28 -0700823 const uint8_t *const levels = txb_info->levels;
Angie Chiangdef11252017-08-18 14:37:32 -0700824 const BASE_CTX_TABLE *base_ctx_table =
825 txb_info->coeff_ctx_table->base_ctx_table;
Angie Chiang481c01f2017-08-15 16:24:30 -0700826 for (int c = 0; c < txb_info->eob; ++c) {
827 const int coeff_idx = scan[c]; // raster order
828 const int row = coeff_idx >> bwl;
829 const int col = coeff_idx - (row << bwl);
Jingning Han3422ac12017-10-25 20:37:53 -0700830
Linfeng Zhangf91f3ca2017-12-05 11:22:41 -0800831 txb_cache->nz_count_arr[coeff_idx] =
Linfeng Zhangd5647372017-12-05 17:06:07 -0800832 get_nz_count(levels + get_padded_idx(coeff_idx, bwl), bwl,
Linfeng Zhangf91f3ca2017-12-05 11:22:41 -0800833 tx_type_to_class[txb_info->tx_type]);
Dake Hea47cd6c2017-10-13 18:09:58 -0700834
Yaowu Xu102ef812017-12-12 11:31:03 -0800835 txb_cache->nz_ctx_arr[coeff_idx] =
836 get_nz_map_ctx_from_stats(0, coeff_idx, bwl, txb_info->tx_size,
837 tx_type_to_class[txb_info->tx_type]);
Angie Chiang481c01f2017-08-15 16:24:30 -0700838
839 // gen_base_count_mag_arr
840 if (!has_base(qcoeff[coeff_idx], 0)) continue;
841 int *base_mag = txb_cache->base_mag_arr[coeff_idx];
Angie Chiang9cde59f2017-08-16 15:24:55 -0700842 int count[NUM_BASE_LEVELS];
843 get_base_count_mag(base_mag, count, qcoeff, bwl, height, row, col);
Angie Chiang481c01f2017-08-15 16:24:30 -0700844
845 for (int i = 0; i < NUM_BASE_LEVELS; ++i) {
Angie Chiang9cde59f2017-08-16 15:24:55 -0700846 if (!has_base(qcoeff[coeff_idx], i)) break;
847 txb_cache->base_count_arr[i][coeff_idx] = count[i];
Angie Chiang481c01f2017-08-15 16:24:30 -0700848 const int level = i + 1;
Angie Chiang9cde59f2017-08-16 15:24:55 -0700849 txb_cache->base_ctx_arr[i][coeff_idx] =
Angie Chiangdef11252017-08-18 14:37:32 -0700850 base_ctx_table[row != 0][col != 0][base_mag[0] > level][count[i]];
Angie Chiang481c01f2017-08-15 16:24:30 -0700851 }
852
853 // gen_br_count_mag_arr
854 if (!has_br(qcoeff[coeff_idx])) continue;
855 int *br_count = txb_cache->br_count_arr + coeff_idx;
856 int *br_mag = txb_cache->br_mag_arr[coeff_idx];
Angie Chiangea8183b2017-08-17 14:36:35 -0700857 *br_count = get_br_count_mag(br_mag, qcoeff, bwl, height, row, col,
858 NUM_BASE_LEVELS);
Angie Chiang481c01f2017-08-15 16:24:30 -0700859 txb_cache->br_ctx_arr[coeff_idx] =
860 get_br_ctx_from_count_mag(row, col, *br_count, br_mag[0]);
861 }
Angie Chiang2affb3b2017-05-30 15:23:51 -0700862}
863
Jingning Handfd72322017-08-09 14:04:12 -0700864static INLINE const int *get_level_prob(int level, int coeff_idx,
865 const TxbCache *txb_cache,
866 const LV_MAP_COEFF_COST *txb_costs) {
Ola Hugosson13892102017-11-06 08:01:44 +0100867 if (level < 1 + NUM_BASE_LEVELS) {
868 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
869 return &txb_costs->base_cost[ctx][level];
Angie Chiang7afbba42017-05-30 15:59:15 -0700870 } else if (level >= 1 + NUM_BASE_LEVELS &&
871 level < 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700872 const int ctx = txb_cache->br_ctx_arr[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700873 return txb_costs->lps_cost[ctx];
Angie Chiang7afbba42017-05-30 15:59:15 -0700874 } else if (level >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Ola Hugosson13892102017-11-06 08:01:44 +0100875 // printf("get_level_prob does not support golomb\n");
Angie Chiang7afbba42017-05-30 15:59:15 -0700876 assert(0);
877 return 0;
878 } else {
879 assert(0);
880 return 0;
881 }
882}
883
Angie Chiangd19969e2017-05-30 18:02:33 -0700884static INLINE void update_mag_arr(int *mag_arr, int abs_qc) {
885 if (mag_arr[0] == abs_qc) {
886 mag_arr[1] -= 1;
887 assert(mag_arr[1] >= 0);
888 }
889}
890
Angie Chianga530ef42017-05-30 16:32:36 -0700891static INLINE int get_mag_from_mag_arr(const int *mag_arr) {
892 int mag;
893 if (mag_arr[1] > 0) {
894 mag = mag_arr[0];
895 } else if (mag_arr[0] > 0) {
896 mag = mag_arr[0] - 1;
897 } else {
898 // no neighbor
899 assert(mag_arr[0] == 0 && mag_arr[1] == 0);
900 mag = 0;
901 }
902 return mag;
903}
904
905static int neighbor_level_down_update(int *new_count, int *new_mag, int count,
906 const int *mag, int coeff_idx,
907 tran_low_t abs_nb_coeff, int nb_coeff_idx,
908 int level, const TxbInfo *txb_info) {
909 *new_count = count;
910 *new_mag = get_mag_from_mag_arr(mag);
911
912 int update = 0;
913 // check if br_count changes
914 if (abs_nb_coeff == level) {
915 update = 1;
916 *new_count -= 1;
917 assert(*new_count >= 0);
918 }
919 const int row = coeff_idx >> txb_info->bwl;
920 const int col = coeff_idx - (row << txb_info->bwl);
921 const int nb_row = nb_coeff_idx >> txb_info->bwl;
922 const int nb_col = nb_coeff_idx - (nb_row << txb_info->bwl);
923
924 // check if mag changes
925 if (nb_row >= row && nb_col >= col) {
926 if (abs_nb_coeff == mag[0]) {
927 assert(mag[1] > 0);
928 if (mag[1] == 1) {
929 // the nb is the only qc with max mag
930 *new_mag -= 1;
931 assert(*new_mag >= 0);
932 update = 1;
933 }
934 }
935 }
936 return update;
937}
938
939static int try_neighbor_level_down_br(int coeff_idx, int nb_coeff_idx,
940 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700941 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -0700942 const TxbInfo *txb_info) {
943 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
944 const tran_low_t abs_qc = abs(qc);
945 const int level = NUM_BASE_LEVELS + 1;
946 if (abs_qc < level) return 0;
947
948 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
949 const tran_low_t abs_nb_coeff = abs(nb_coeff);
950 const int count = txb_cache->br_count_arr[coeff_idx];
951 const int *mag = txb_cache->br_mag_arr[coeff_idx];
952 int new_count;
953 int new_mag;
954 const int update =
955 neighbor_level_down_update(&new_count, &new_mag, count, mag, coeff_idx,
956 abs_nb_coeff, nb_coeff_idx, level, txb_info);
957 if (update) {
958 const int row = coeff_idx >> txb_info->bwl;
959 const int col = coeff_idx - (row << txb_info->bwl);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -0700960 const int ctx = txb_cache->br_ctx_arr[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -0700961 const int org_cost = get_br_cost(abs_qc, ctx, txb_costs->lps_cost[ctx]);
Angie Chianga530ef42017-05-30 16:32:36 -0700962
963 const int new_ctx = get_br_ctx_from_count_mag(row, col, new_count, new_mag);
Jingning Handfd72322017-08-09 14:04:12 -0700964 const int new_cost =
965 get_br_cost(abs_qc, new_ctx, txb_costs->lps_cost[new_ctx]);
Angie Chianga530ef42017-05-30 16:32:36 -0700966 const int cost_diff = -org_cost + new_cost;
967 return cost_diff;
968 } else {
969 return 0;
970 }
971}
972
973static int try_neighbor_level_down_base(int coeff_idx, int nb_coeff_idx,
974 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700975 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -0700976 const TxbInfo *txb_info) {
Ola Hugosson13892102017-11-06 08:01:44 +0100977 // TODO(olah): not implemented yet
978 (void)coeff_idx;
979 (void)nb_coeff_idx;
980 (void)txb_cache;
981 (void)txb_costs;
982 (void)txb_info;
983 return 0;
Angie Chianga530ef42017-05-30 16:32:36 -0700984}
985
986static int try_neighbor_level_down_nz(int coeff_idx, int nb_coeff_idx,
987 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -0700988 const LV_MAP_COEFF_COST *txb_costs,
Angie Chianga530ef42017-05-30 16:32:36 -0700989 TxbInfo *txb_info) {
990 // assume eob doesn't change
991 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
992 const tran_low_t abs_qc = abs(qc);
993 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
994 const tran_low_t abs_nb_coeff = abs(nb_coeff);
995 if (abs_nb_coeff != 1) return 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -0800996 const int16_t *const iscan = txb_info->scan_order->iscan;
Angie Chianga530ef42017-05-30 16:32:36 -0700997 const int scan_idx = iscan[coeff_idx];
998 if (scan_idx == txb_info->seg_eob) return 0;
999 const int nb_scan_idx = iscan[nb_coeff_idx];
1000 if (nb_scan_idx < scan_idx) {
1001 const int count = txb_cache->nz_count_arr[coeff_idx];
Linfeng Zhang8ac45572017-11-29 11:39:51 -08001002 (void)count;
Angie Chianga530ef42017-05-30 16:32:36 -07001003 assert(count > 0);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001004 update_qcoeff(nb_coeff_idx, get_lower_coeff(nb_coeff), txb_info);
Linfeng Zhang8ac45572017-11-29 11:39:51 -08001005 const int new_ctx = get_nz_map_ctx_from_stats(
Yaowu Xu102ef812017-12-12 11:31:03 -08001006 0, coeff_idx, txb_info->bwl, txb_info->tx_size,
1007 tx_type_to_class[txb_info->tx_type]);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001008 update_qcoeff(nb_coeff_idx, nb_coeff, txb_info);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001009 const int ctx = txb_cache->nz_ctx_arr[coeff_idx];
Ola Hugosson13892102017-11-06 08:01:44 +01001010 const int org_cost = txb_costs->base_cost[ctx][AOMMIN(abs_qc, 3)];
1011 const int new_cost = txb_costs->base_cost[new_ctx][AOMMIN(abs_qc, 3)];
Angie Chianga530ef42017-05-30 16:32:36 -07001012 const int cost_diff = new_cost - org_cost;
1013 return cost_diff;
1014 } else {
1015 return 0;
1016 }
1017}
1018
1019static int try_self_level_down(tran_low_t *low_coeff, int coeff_idx,
1020 const TxbCache *txb_cache,
Jingning Handfd72322017-08-09 14:04:12 -07001021 const LV_MAP_COEFF_COST *txb_costs,
1022 TxbInfo *txb_info) {
Angie Chiang7afbba42017-05-30 15:59:15 -07001023 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1024 if (qc == 0) {
1025 *low_coeff = 0;
1026 return 0;
1027 }
1028 const tran_low_t abs_qc = abs(qc);
1029 *low_coeff = get_lower_coeff(qc);
1030 int cost_diff;
1031 if (*low_coeff == 0) {
1032 const int scan_idx = txb_info->scan_order->iscan[coeff_idx];
Jingning Handfd72322017-08-09 14:04:12 -07001033 const int *level_cost =
1034 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1035 const int *low_level_cost =
1036 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
Jingning Han3422ac12017-10-25 20:37:53 -07001037
Dake Hea47cd6c2017-10-13 18:09:58 -07001038 if (scan_idx < txb_info->eob - 1) {
Angie Chiang7afbba42017-05-30 15:59:15 -07001039 // When level-0, we code the binary of abs_qc > level
1040 // but when level-k k > 0 we code the binary of abs_qc == level
1041 // That's why wee need this special treatment for level-0 map
1042 // TODO(angiebird): make leve-0 consistent to other levels
Jingning Handfd72322017-08-09 14:04:12 -07001043 cost_diff = -level_cost[1] + low_level_cost[0] - low_level_cost[1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001044 } else {
Jingning Handfd72322017-08-09 14:04:12 -07001045 cost_diff = -level_cost[1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001046 }
1047
Angie Chiang7afbba42017-05-30 15:59:15 -07001048 const int sign_cost = get_sign_bit_cost(
Jingning Handfd72322017-08-09 14:04:12 -07001049 qc, coeff_idx, txb_costs->dc_sign_cost, txb_info->txb_ctx->dc_sign_ctx);
Angie Chiang7afbba42017-05-30 15:59:15 -07001050 cost_diff -= sign_cost;
Jingning Han772dee32017-09-15 08:53:18 -07001051 } else if (abs_qc <= NUM_BASE_LEVELS) {
1052 const int *level_cost =
1053 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1054 const int *low_level_cost =
1055 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1056 cost_diff = -level_cost[1] + low_level_cost[1] - low_level_cost[0];
1057 } else if (abs_qc == NUM_BASE_LEVELS + 1) {
1058 const int *level_cost =
1059 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1060 const int *low_level_cost =
1061 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1062 cost_diff = -level_cost[0] + low_level_cost[1] - low_level_cost[0];
Angie Chiang7afbba42017-05-30 15:59:15 -07001063 } else if (abs_qc < 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Jingning Handfd72322017-08-09 14:04:12 -07001064 const int *level_cost =
1065 get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
1066 const int *low_level_cost =
1067 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
1068
Jingning Han772dee32017-09-15 08:53:18 -07001069 cost_diff = -level_cost[abs_qc - 1 - NUM_BASE_LEVELS] +
1070 low_level_cost[abs(*low_coeff) - 1 - NUM_BASE_LEVELS];
Angie Chiang7afbba42017-05-30 15:59:15 -07001071 } else if (abs_qc == 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
Jingning Handfd72322017-08-09 14:04:12 -07001072 const int *low_level_cost =
1073 get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
Jingning Han772dee32017-09-15 08:53:18 -07001074 cost_diff = -get_golomb_cost(abs_qc) - low_level_cost[COEFF_BASE_RANGE] +
1075 low_level_cost[COEFF_BASE_RANGE - 1];
Angie Chiang7afbba42017-05-30 15:59:15 -07001076 } else {
1077 assert(abs_qc > 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE);
1078 const tran_low_t abs_low_coeff = abs(*low_coeff);
1079 cost_diff = -get_golomb_cost(abs_qc) + get_golomb_cost(abs_low_coeff);
1080 }
1081 return cost_diff;
1082}
1083
Angie Chianga530ef42017-05-30 16:32:36 -07001084#define COST_MAP_SIZE 5
1085#define COST_MAP_OFFSET 2
1086
1087static INLINE int check_nz_neighbor(tran_low_t qc) { return abs(qc) == 1; }
1088
1089static INLINE int check_base_neighbor(tran_low_t qc) {
1090 return abs(qc) <= 1 + NUM_BASE_LEVELS;
1091}
1092
1093static INLINE int check_br_neighbor(tran_low_t qc) {
1094 return abs(qc) > BR_MAG_OFFSET;
1095}
1096
Angie Chiang87278292017-10-18 09:59:47 -07001097#define FAST_OPTIMIZE_TXB 1
Angie Chiange80957f2017-09-05 10:48:00 -07001098
1099#if FAST_OPTIMIZE_TXB
1100#define ALNB_REF_OFFSET_NUM 2
Linfeng Zhang4afda452017-10-24 10:34:04 -07001101static const int alnb_ref_offset[ALNB_REF_OFFSET_NUM][2] = {
Johannb0ef6ff2018-02-08 14:32:21 -08001102 { -1, 0 },
1103 { 0, -1 },
Angie Chiange80957f2017-09-05 10:48:00 -07001104};
1105#define NB_REF_OFFSET_NUM 4
Linfeng Zhang4afda452017-10-24 10:34:04 -07001106static const int nb_ref_offset[NB_REF_OFFSET_NUM][2] = {
Johannb0ef6ff2018-02-08 14:32:21 -08001107 { -1, 0 },
1108 { 0, -1 },
1109 { 1, 0 },
1110 { 0, 1 },
Angie Chiange80957f2017-09-05 10:48:00 -07001111};
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 INLINE void set_eob(TxbInfo *txb_info, int eob) {
1255 txb_info->eob = eob;
Urvang Joshi80893152017-10-27 11:51:14 -07001256 txb_info->seg_eob = av1_get_max_eob(txb_info->tx_size);
Angie Chiangc77799b2017-05-30 17:08:17 -07001257}
1258
Angie Chiangd19969e2017-05-30 18:02:33 -07001259// TODO(angiebird): add static to this function it's called
Linfeng Zhang1015a342017-10-24 16:20:41 -07001260void update_level_down(const int coeff_idx, TxbCache *const txb_cache,
1261 TxbInfo *const txb_info) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001262 const tran_low_t qc = txb_info->qcoeff[coeff_idx];
1263 const int abs_qc = abs(qc);
1264 if (qc == 0) return;
1265 const tran_low_t low_coeff = get_lower_coeff(qc);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001266 update_coeff(coeff_idx, low_coeff, txb_info);
Angie Chiangd19969e2017-05-30 18:02:33 -07001267
1268 const int row = coeff_idx >> txb_info->bwl;
1269 const int col = coeff_idx - (row << txb_info->bwl);
1270 const int eob = txb_info->eob;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001271 const int16_t *const iscan = txb_info->scan_order->iscan;
Angie Chiangd19969e2017-05-30 18:02:33 -07001272 for (int i = 0; i < SIG_REF_OFFSET_NUM; ++i) {
1273 const int nb_row = row - sig_ref_offset[i][0];
1274 const int nb_col = col - sig_ref_offset[i][1];
Jingning Han3455e762017-06-13 21:15:44 -07001275
1276 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001277 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001278 continue;
1279
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001280 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiangd19969e2017-05-30 18:02:33 -07001281 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001282 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001283 const int scan_idx = iscan[coeff_idx];
1284 if (scan_idx < nb_scan_idx) {
1285 const int level = 1;
1286 if (abs_qc == level) {
1287 txb_cache->nz_count_arr[nb_coeff_idx] -= 1;
1288 assert(txb_cache->nz_count_arr[nb_coeff_idx] >= 0);
1289 }
Yaowu Xu102ef812017-12-12 11:31:03 -08001290 txb_cache->nz_ctx_arr[nb_coeff_idx] = get_nz_map_ctx_from_stats(
1291 0, nb_coeff_idx, txb_info->bwl, txb_info->tx_size,
1292 tx_type_to_class[txb_info->tx_type]);
Angie Chiangd19969e2017-05-30 18:02:33 -07001293 }
1294 }
1295 }
1296
Angie Chiangdef11252017-08-18 14:37:32 -07001297 const BASE_CTX_TABLE *base_ctx_table =
1298 txb_info->coeff_ctx_table->base_ctx_table;
Angie Chiangd19969e2017-05-30 18:02:33 -07001299 for (int i = 0; i < BASE_CONTEXT_POSITION_NUM; ++i) {
1300 const int nb_row = row - base_ref_offset[i][0];
1301 const int nb_col = col - base_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001302 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001303
1304 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001305 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001306 continue;
1307
Angie Chiangd19969e2017-05-30 18:02:33 -07001308 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
1309 if (!has_base(nb_coeff, 0)) continue;
1310 const int nb_scan_idx = iscan[nb_coeff_idx];
Jingning Han3455e762017-06-13 21:15:44 -07001311 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001312 if (row >= nb_row && col >= nb_col)
1313 update_mag_arr(txb_cache->base_mag_arr[nb_coeff_idx], abs_qc);
1314 const int mag =
1315 get_mag_from_mag_arr(txb_cache->base_mag_arr[nb_coeff_idx]);
1316 for (int base_idx = 0; base_idx < NUM_BASE_LEVELS; ++base_idx) {
1317 if (!has_base(nb_coeff, base_idx)) continue;
1318 const int level = base_idx + 1;
1319 if (abs_qc == level) {
1320 txb_cache->base_count_arr[base_idx][nb_coeff_idx] -= 1;
1321 assert(txb_cache->base_count_arr[base_idx][nb_coeff_idx] >= 0);
1322 }
1323 const int count = txb_cache->base_count_arr[base_idx][nb_coeff_idx];
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001324 txb_cache->base_ctx_arr[base_idx][nb_coeff_idx] =
Angie Chiangdef11252017-08-18 14:37:32 -07001325 base_ctx_table[nb_row != 0][nb_col != 0][mag > level][count];
Angie Chiangd19969e2017-05-30 18:02:33 -07001326 }
1327 }
1328 }
1329
1330 for (int i = 0; i < BR_CONTEXT_POSITION_NUM; ++i) {
1331 const int nb_row = row - br_ref_offset[i][0];
1332 const int nb_col = col - br_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001333 const int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Jingning Han3455e762017-06-13 21:15:44 -07001334
1335 if (!(nb_row >= 0 && nb_col >= 0 && nb_row < txb_info->height &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001336 nb_col < txb_info->width))
Jingning Han3455e762017-06-13 21:15:44 -07001337 continue;
1338
Angie Chiangd19969e2017-05-30 18:02:33 -07001339 const int nb_scan_idx = iscan[nb_coeff_idx];
1340 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
1341 if (!has_br(nb_coeff)) continue;
Jingning Han3455e762017-06-13 21:15:44 -07001342 if (nb_scan_idx < eob) {
Angie Chiangd19969e2017-05-30 18:02:33 -07001343 const int level = 1 + NUM_BASE_LEVELS;
1344 if (abs_qc == level) {
1345 txb_cache->br_count_arr[nb_coeff_idx] -= 1;
1346 assert(txb_cache->br_count_arr[nb_coeff_idx] >= 0);
1347 }
1348 if (row >= nb_row && col >= nb_col)
1349 update_mag_arr(txb_cache->br_mag_arr[nb_coeff_idx], abs_qc);
1350 const int count = txb_cache->br_count_arr[nb_coeff_idx];
1351 const int mag = get_mag_from_mag_arr(txb_cache->br_mag_arr[nb_coeff_idx]);
Angie Chiang1ae0ebf2017-08-15 15:16:47 -07001352 txb_cache->br_ctx_arr[nb_coeff_idx] =
Angie Chiangd19969e2017-05-30 18:02:33 -07001353 get_br_ctx_from_count_mag(nb_row, nb_col, count, mag);
Angie Chiangd19969e2017-05-30 18:02:33 -07001354 }
1355 }
1356}
1357
Linfeng Zhang1015a342017-10-24 16:20:41 -07001358static int get_coeff_cost(const tran_low_t qc, const int scan_idx,
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001359 const int is_eob, const TxbInfo *const txb_info,
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001360 const LV_MAP_COEFF_COST *const txb_costs,
1361 const int coeff_ctx) {
Angie Chiang488f9212017-05-30 12:46:26 -07001362 const TXB_CTX *txb_ctx = txb_info->txb_ctx;
1363 const int is_nz = (qc != 0);
1364 const tran_low_t abs_qc = abs(qc);
1365 int cost = 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001366 const int16_t *const scan = txb_info->scan_order->scan;
1367 const int pos = scan[scan_idx];
Dake He03a32922017-10-31 08:06:45 -07001368
Dake He3fe369c2017-11-16 17:56:44 -08001369 if (is_eob) {
Dake He4d447692017-12-15 09:10:06 -08001370 cost += txb_costs->base_eob_cost[coeff_ctx][AOMMIN(abs_qc, 3) - 1];
Dake He3fe369c2017-11-16 17:56:44 -08001371 } else {
1372 cost += txb_costs->base_cost[coeff_ctx][AOMMIN(abs_qc, 3)];
1373 }
Angie Chiang488f9212017-05-30 12:46:26 -07001374 if (is_nz) {
Jingning Handfd72322017-08-09 14:04:12 -07001375 cost += get_sign_bit_cost(qc, scan_idx, txb_costs->dc_sign_cost,
Angie Chiang488f9212017-05-30 12:46:26 -07001376 txb_ctx->dc_sign_ctx);
1377
Angie Chiang488f9212017-05-30 12:46:26 -07001378 if (abs_qc > NUM_BASE_LEVELS) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001379 const int row = pos >> txb_info->bwl;
1380 const int col = pos - (row << txb_info->bwl);
Dake He7d01ab52017-11-24 17:53:28 -08001381
Dake He7d01ab52017-11-24 17:53:28 -08001382 (void)col;
1383 const int count = 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001384 const int ctx = get_br_ctx(txb_info->levels, pos, txb_info->bwl, count,
1385 txb_info->tx_type);
Jingning Handfd72322017-08-09 14:04:12 -07001386 cost += get_br_cost(abs_qc, ctx, txb_costs->lps_cost[ctx]);
Angie Chiang488f9212017-05-30 12:46:26 -07001387 cost += get_golomb_cost(abs_qc);
1388 }
Angie Chiang488f9212017-05-30 12:46:26 -07001389 }
1390 return cost;
1391}
1392
Angie Chiang47e07072017-05-30 17:27:01 -07001393#if TEST_OPTIMIZE_TXB
Angie Chiang5e012fe2017-05-30 18:47:39 -07001394#define ALL_REF_OFFSET_NUM 17
Linfeng Zhang4afda452017-10-24 10:34:04 -07001395static const int all_ref_offset[ALL_REF_OFFSET_NUM][2] = {
Angie Chiang5e012fe2017-05-30 18:47:39 -07001396 { 0, 0 }, { -2, -1 }, { -2, 0 }, { -2, 1 }, { -1, -2 }, { -1, -1 },
1397 { -1, 0 }, { -1, 1 }, { 0, -2 }, { 0, -1 }, { 1, -2 }, { 1, -1 },
1398 { 1, 0 }, { 2, 0 }, { 0, 1 }, { 0, 2 }, { 1, 1 },
1399};
1400
Angie Chiang0b2795c2017-09-29 16:00:08 -07001401static int try_level_down_ref(int coeff_idx, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang5e012fe2017-05-30 18:47:39 -07001402 TxbInfo *txb_info,
1403 int (*cost_map)[COST_MAP_SIZE]) {
1404 if (cost_map) {
1405 for (int i = 0; i < COST_MAP_SIZE; ++i) av1_zero(cost_map[i]);
1406 }
1407 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1408 if (qc == 0) return 0;
1409 int row = coeff_idx >> txb_info->bwl;
1410 int col = coeff_idx - (row << txb_info->bwl);
1411 int org_cost = 0;
1412 for (int i = 0; i < ALL_REF_OFFSET_NUM; ++i) {
1413 int nb_row = row - all_ref_offset[i][0];
1414 int nb_col = col - all_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001415 int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001416 int nb_scan_idx = txb_info->scan_order->iscan[nb_coeff_idx];
1417 if (nb_scan_idx < txb_info->eob && nb_row >= 0 && nb_col >= 0 &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001418 nb_row < txb_info->height && nb_col < txb_info->width) {
Linfeng Zhang960e7002017-12-11 13:46:40 -08001419 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001420 const int coeff_ctx = get_nz_map_ctx(
1421 txb_info->levels, nb_coeff_idx, txb_info->bwl, txb_info->height,
1422 nb_scan_idx, is_eob, txb_info->tx_size, txb_info->tx_type);
1423 const int cost = get_coeff_cost(nb_coeff, nb_scan_idx, is_eob, txb_info,
1424 txb_costs, coeff_ctx);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001425 if (cost_map)
1426 cost_map[nb_row - row + COST_MAP_OFFSET]
1427 [nb_col - col + COST_MAP_OFFSET] -= cost;
1428 org_cost += cost;
1429 }
1430 }
Linfeng Zhang1015a342017-10-24 16:20:41 -07001431 update_qcoeff(coeff_idx, get_lower_coeff(qc), txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001432 int new_cost = 0;
1433 for (int i = 0; i < ALL_REF_OFFSET_NUM; ++i) {
1434 int nb_row = row - all_ref_offset[i][0];
1435 int nb_col = col - all_ref_offset[i][1];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001436 int nb_coeff_idx = nb_row * txb_info->width + nb_col;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001437 int nb_scan_idx = txb_info->scan_order->iscan[nb_coeff_idx];
1438 if (nb_scan_idx < txb_info->eob && nb_row >= 0 && nb_col >= 0 &&
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001439 nb_row < txb_info->height && nb_col < txb_info->width) {
Linfeng Zhang960e7002017-12-11 13:46:40 -08001440 const tran_low_t nb_coeff = txb_info->qcoeff[nb_coeff_idx];
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001441 const int coeff_ctx = get_nz_map_ctx(
1442 txb_info->levels, nb_coeff_idx, txb_info->bwl, txb_info->height,
1443 nb_scan_idx, is_eob, txb_info->tx_size, txb_info->tx_type);
1444 const int cost = get_coeff_cost(nb_coeff, nb_scan_idx, is_eob, txb_info,
1445 txb_costs, coeff_ctx);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001446 if (cost_map)
1447 cost_map[nb_row - row + COST_MAP_OFFSET]
1448 [nb_col - col + COST_MAP_OFFSET] += cost;
1449 new_cost += cost;
1450 }
1451 }
Linfeng Zhang1015a342017-10-24 16:20:41 -07001452 update_qcoeff(coeff_idx, qc, txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001453 return new_cost - org_cost;
1454}
1455
1456static void test_level_down(int coeff_idx, const TxbCache *txb_cache,
Angie Chiang0b2795c2017-09-29 16:00:08 -07001457 const LV_MAP_COEFF_COST *txb_costs,
1458 TxbInfo *txb_info) {
Angie Chiang47e07072017-05-30 17:27:01 -07001459 int cost_map[COST_MAP_SIZE][COST_MAP_SIZE];
1460 int ref_cost_map[COST_MAP_SIZE][COST_MAP_SIZE];
1461 const int cost_diff =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001462 try_level_down(coeff_idx, txb_cache, txb_costs, txb_info, cost_map, 0);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001463 const int cost_diff_ref =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001464 try_level_down_ref(coeff_idx, txb_costs, txb_info, ref_cost_map);
Angie Chiang47e07072017-05-30 17:27:01 -07001465 if (cost_diff != cost_diff_ref) {
1466 printf("qc %d cost_diff %d cost_diff_ref %d\n", txb_info->qcoeff[coeff_idx],
1467 cost_diff, cost_diff_ref);
1468 for (int r = 0; r < COST_MAP_SIZE; ++r) {
1469 for (int c = 0; c < COST_MAP_SIZE; ++c) {
1470 printf("%d:%d ", cost_map[r][c], ref_cost_map[r][c]);
1471 }
1472 printf("\n");
1473 }
1474 }
1475}
1476#endif
1477
Angie Chiang488f9212017-05-30 12:46:26 -07001478// TODO(angiebird): make this static once it's called
Jingning Handfd72322017-08-09 14:04:12 -07001479int get_txb_cost(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs) {
Angie Chiang488f9212017-05-30 12:46:26 -07001480 int cost = 0;
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001481 const int txb_skip_ctx = txb_info->txb_ctx->txb_skip_ctx;
1482 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang488f9212017-05-30 12:46:26 -07001483 if (txb_info->eob == 0) {
Jingning Handfd72322017-08-09 14:04:12 -07001484 cost = txb_costs->txb_skip_cost[txb_skip_ctx][1];
Angie Chiang488f9212017-05-30 12:46:26 -07001485 return cost;
1486 }
Jingning Handfd72322017-08-09 14:04:12 -07001487 cost = txb_costs->txb_skip_cost[txb_skip_ctx][0];
Angie Chiang488f9212017-05-30 12:46:26 -07001488 for (int c = 0; c < txb_info->eob; ++c) {
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001489 const int pos = scan[c];
1490 const tran_low_t qc = txb_info->qcoeff[pos];
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001491 const int coeff_ctx = get_nz_map_ctx(
1492 txb_info->levels, pos, txb_info->bwl, txb_info->height, c,
1493 c == txb_info->eob - 1, txb_info->tx_size, txb_info->tx_type);
1494 const int coeff_cost = get_coeff_cost(qc, c, c == txb_info->eob - 1,
Linfeng Zhang5f1b8ce2017-12-11 15:53:10 -08001495 txb_info, txb_costs, coeff_ctx);
Angie Chiang488f9212017-05-30 12:46:26 -07001496 cost += coeff_cost;
1497 }
1498 return cost;
1499}
1500
Angie Chiang5e012fe2017-05-30 18:47:39 -07001501#if TEST_OPTIMIZE_TXB
Angie Chiang0b2795c2017-09-29 16:00:08 -07001502void test_try_change_eob(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Angie Chiang5e012fe2017-05-30 18:47:39 -07001503 TxbCache *txb_cache) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001504 const int eob = txb_info->eob;
1505 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang5e012fe2017-05-30 18:47:39 -07001506 if (eob > 0) {
1507 int last_si = eob - 1;
1508 int last_ci = scan[last_si];
1509 int last_coeff = txb_info->qcoeff[last_ci];
1510 if (abs(last_coeff) == 1) {
1511 int new_eob;
1512 int cost_diff =
Angie Chiang0b2795c2017-09-29 16:00:08 -07001513 try_change_eob(&new_eob, last_ci, txb_cache, txb_costs, txb_info, 0);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001514 int org_eob = txb_info->eob;
Angie Chiang0b2795c2017-09-29 16:00:08 -07001515 int cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001516
Linfeng Zhang1015a342017-10-24 16:20:41 -07001517 update_qcoeff(last_ci, get_lower_coeff(last_coeff), txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001518 set_eob(txb_info, new_eob);
Angie Chiang0b2795c2017-09-29 16:00:08 -07001519 int new_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001520 set_eob(txb_info, org_eob);
Linfeng Zhang1015a342017-10-24 16:20:41 -07001521 update_qcoeff(last_ci, last_coeff, txb_info);
Angie Chiang5e012fe2017-05-30 18:47:39 -07001522
1523 int ref_cost_diff = -cost + new_cost;
1524 if (cost_diff != ref_cost_diff)
1525 printf("org_eob %d new_eob %d cost_diff %d ref_cost_diff %d\n", org_eob,
1526 new_eob, cost_diff, ref_cost_diff);
1527 }
1528 }
1529}
1530#endif
1531
Jingning Han3422ac12017-10-25 20:37:53 -07001532#if 1
Dake Hea47cd6c2017-10-13 18:09:58 -07001533static int optimize_txb(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Dake He0db7d0e2017-12-21 15:23:20 -08001534 const LV_MAP_EOB_COST *txb_eob_costs,
Cheng Chen82775f62018-01-18 12:09:54 -08001535 TxbCache *txb_cache, int dry_run, int fast_mode,
1536 int *rate_cost) {
Dake Hea47cd6c2017-10-13 18:09:58 -07001537 (void)fast_mode;
1538 (void)txb_cache;
1539 int update = 0;
Dake He59881772017-11-24 07:00:02 -08001540 // return update; // TODO(DKHE): training only.
Dake Hea47cd6c2017-10-13 18:09:58 -07001541 if (txb_info->eob == 0) return update;
Urvang Joshi80893152017-10-27 11:51:14 -07001542 const int max_eob = av1_get_max_eob(txb_info->tx_size);
Dake Hea47cd6c2017-10-13 18:09:58 -07001543
1544#if TEST_OPTIMIZE_TXB
1545 int64_t sse;
1546 int64_t org_dist =
1547 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1548 (1 << (2 * txb_info->shift));
1549 int org_cost = get_txb_cost(txb_info, txb_probs);
1550#endif
1551
1552 tran_low_t *org_qcoeff = txb_info->qcoeff;
1553 tran_low_t *org_dqcoeff = txb_info->dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001554 uint8_t *const org_levels = txb_info->levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001555
1556 tran_low_t tmp_qcoeff[MAX_TX_SQUARE];
1557 tran_low_t tmp_dqcoeff[MAX_TX_SQUARE];
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001558 uint8_t tmp_levels_buf[TX_PAD_2D];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001559 uint8_t *const tmp_levels = set_levels(tmp_levels_buf, txb_info->width);
Dake Hea47cd6c2017-10-13 18:09:58 -07001560 const int org_eob = txb_info->eob;
1561 if (dry_run) {
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001562 const int stride = txb_info->width + TX_PAD_HOR;
1563 const int levels_size =
1564
1565 (stride * (txb_info->height + TX_PAD_VER) + TX_PAD_END);
Dake Hea47cd6c2017-10-13 18:09:58 -07001566 memcpy(tmp_qcoeff, org_qcoeff, sizeof(org_qcoeff[0]) * max_eob);
1567 memcpy(tmp_dqcoeff, org_dqcoeff, sizeof(org_dqcoeff[0]) * max_eob);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001568 memcpy(tmp_levels, org_levels - TX_PAD_TOP * stride,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001569 sizeof(org_levels[0]) * levels_size);
Dake Hea47cd6c2017-10-13 18:09:58 -07001570 txb_info->qcoeff = tmp_qcoeff;
1571 txb_info->dqcoeff = tmp_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001572 txb_info->levels = tmp_levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001573 }
1574
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001575 const int16_t *const scan = txb_info->scan_order->scan;
Dake Hea47cd6c2017-10-13 18:09:58 -07001576
1577 // forward optimize the nz_map`
1578 const int init_eob = txb_info->eob;
1579 const int seg_eob = txb_info->seg_eob;
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001580 const int eob_cost = get_eob_cost(init_eob, seg_eob, txb_eob_costs, txb_costs,
Dake He0db7d0e2017-12-21 15:23:20 -08001581 txb_info->tx_type);
Dake Hea47cd6c2017-10-13 18:09:58 -07001582
1583 // backward optimize the level-k map
Cheng Chen82775f62018-01-18 12:09:54 -08001584 int accu_rate = eob_cost;
Dake Hea47cd6c2017-10-13 18:09:58 -07001585 int64_t accu_dist = 0;
1586 int64_t prev_eob_rd_cost = INT64_MAX;
1587 int64_t cur_eob_rd_cost = 0;
Jingning Han8be58fa2017-12-18 09:46:13 -08001588 int8_t has_nz_tail = 0;
Dake Hea47cd6c2017-10-13 18:09:58 -07001589
1590 for (int si = init_eob - 1; si >= 0; --si) {
1591 const int coeff_idx = scan[si];
1592 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1593
1594 LevelDownStats stats;
Sebastien Alaiwan78f7bb92018-01-11 11:02:43 +01001595 get_dist_cost_stats(&stats, si, si == init_eob - 1, txb_costs, txb_info,
1596 has_nz_tail);
Dake Hea47cd6c2017-10-13 18:09:58 -07001597
1598 if (qc == 0) {
1599 accu_rate += stats.rate;
1600 } else {
Jingning Han8be58fa2017-12-18 09:46:13 -08001601 if (has_nz_tail < 2) {
Cheng Chenec32a742018-01-12 19:09:39 -08001602 if (si == init_eob - 1) {
Dake He4d447692017-12-15 09:10:06 -08001603 if ((stats.rd_low < stats.rd) && (stats.low_qc != 0)) {
1604 update = 1;
1605 update_coeff(coeff_idx, stats.low_qc, txb_info);
1606 accu_rate += stats.rate_low;
1607 accu_dist += stats.dist_low;
1608 } else {
1609 accu_rate += stats.rate;
1610 accu_dist += stats.dist;
1611 }
Jingning Han8be58fa2017-12-18 09:46:13 -08001612 continue;
Cheng Chenec32a742018-01-12 19:09:39 -08001613 } else {
1614 // check if it is better to make this the last significant coefficient
1615 int cur_eob_rate = get_eob_cost(si + 1, seg_eob, txb_eob_costs,
1616 txb_costs, txb_info->tx_type);
1617 cur_eob_rd_cost = RDCOST(txb_info->rdmult, cur_eob_rate, 0);
1618 prev_eob_rd_cost =
1619 RDCOST(txb_info->rdmult, accu_rate, accu_dist) + stats.nz_rd;
1620 if (cur_eob_rd_cost <= prev_eob_rd_cost) {
1621 update = 1;
1622 for (int j = si + 1; j < txb_info->eob; j++) {
1623 const int coeff_pos_j = scan[j];
1624 update_coeff(coeff_pos_j, 0, txb_info);
1625 }
1626 txb_info->eob = si + 1;
1627
1628 // rerun cost calculation due to change of eob
1629 accu_rate = cur_eob_rate;
1630 accu_dist = 0;
1631 get_dist_cost_stats(&stats, si, 1, txb_costs, txb_info,
1632 has_nz_tail);
1633 if ((stats.rd_low < stats.rd) && (stats.low_qc != 0)) {
1634 update = 1;
1635 update_coeff(coeff_idx, stats.low_qc, txb_info);
1636 accu_rate += stats.rate_low;
1637 accu_dist += stats.dist_low;
1638 } else {
1639 accu_rate += stats.rate;
1640 accu_dist += stats.dist;
1641 }
1642
1643 // reset non zero tail when new eob is found
1644 has_nz_tail = 0;
1645 continue;
1646 }
Jingning Han8be58fa2017-12-18 09:46:13 -08001647 }
Dake Hea47cd6c2017-10-13 18:09:58 -07001648 }
1649
1650 int bUpdCoeff = 0;
1651 if (stats.rd_low < stats.rd) {
Dake He4d447692017-12-15 09:10:06 -08001652 if ((si < txb_info->eob - 1)) {
Dake Hea47cd6c2017-10-13 18:09:58 -07001653 bUpdCoeff = 1;
1654 update = 1;
1655 }
Jingning Han8be58fa2017-12-18 09:46:13 -08001656 } else {
1657 ++has_nz_tail;
Dake Hea47cd6c2017-10-13 18:09:58 -07001658 }
1659
1660 if (bUpdCoeff) {
1661 update_coeff(coeff_idx, stats.low_qc, txb_info);
1662 accu_rate += stats.rate_low;
1663 accu_dist += stats.dist_low;
1664 } else {
1665 accu_rate += stats.rate;
1666 accu_dist += stats.dist;
1667 }
1668 }
1669 } // for (si)
Jingning Hana7a6f4e2017-12-13 14:44:08 -08001670
Dake Hea47cd6c2017-10-13 18:09:58 -07001671 int non_zero_blk_rate =
1672 txb_costs->txb_skip_cost[txb_info->txb_ctx->txb_skip_ctx][0];
1673 prev_eob_rd_cost =
1674 RDCOST(txb_info->rdmult, accu_rate + non_zero_blk_rate, accu_dist);
1675
1676 int zero_blk_rate =
1677 txb_costs->txb_skip_cost[txb_info->txb_ctx->txb_skip_ctx][1];
1678 int64_t zero_blk_rd_cost = RDCOST(txb_info->rdmult, zero_blk_rate, 0);
1679 if (zero_blk_rd_cost <= prev_eob_rd_cost) {
1680 update = 1;
1681 for (int j = 0; j < txb_info->eob; j++) {
1682 const int coeff_pos_j = scan[j];
1683 update_coeff(coeff_pos_j, 0, txb_info);
1684 }
1685 txb_info->eob = 0;
1686 }
1687
Cheng Chen82775f62018-01-18 12:09:54 -08001688 // record total rate cost
1689 *rate_cost = zero_blk_rd_cost <= prev_eob_rd_cost
1690 ? zero_blk_rate
1691 : accu_rate + non_zero_blk_rate;
1692
Dake Hea47cd6c2017-10-13 18:09:58 -07001693#if TEST_OPTIMIZE_TXB
1694 int cost_diff = 0;
1695 int64_t dist_diff = 0;
1696 int64_t rd_diff = 0;
1697 int64_t new_dist =
1698 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1699 (1 << (2 * txb_info->shift));
1700 int new_cost = get_txb_cost(txb_info, txb_probs);
1701 int64_t ref_dist_diff = new_dist - org_dist;
1702 int ref_cost_diff = new_cost - org_cost;
1703 if (cost_diff != ref_cost_diff || dist_diff != ref_dist_diff)
1704 printf(
1705 "overall rd_diff %ld\ncost_diff %d ref_cost_diff%d\ndist_diff %ld "
1706 "ref_dist_diff %ld\neob %d new_eob %d\n\n",
1707 rd_diff, cost_diff, ref_cost_diff, dist_diff, ref_dist_diff, org_eob,
1708 txb_info->eob);
1709#endif
1710 if (dry_run) {
1711 txb_info->qcoeff = org_qcoeff;
1712 txb_info->dqcoeff = org_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001713 txb_info->levels = org_levels;
Dake Hea47cd6c2017-10-13 18:09:58 -07001714 set_eob(txb_info, org_eob);
1715 }
1716 return update;
1717}
1718
1719#else
Jingning Handfd72322017-08-09 14:04:12 -07001720static int optimize_txb(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Cheng Chen82775f62018-01-18 12:09:54 -08001721 TxbCache *txb_cache, int dry_run, int fast_mode,
1722 int *rate_cost) {
Angie Chiang07c57f32017-05-30 18:18:33 -07001723 int update = 0;
1724 if (txb_info->eob == 0) return update;
1725 int cost_diff = 0;
1726 int64_t dist_diff = 0;
1727 int64_t rd_diff = 0;
Urvang Joshi80893152017-10-27 11:51:14 -07001728 const int max_eob = av1_get_max_eob(txb_info->tx_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07001729
1730#if TEST_OPTIMIZE_TXB
1731 int64_t sse;
1732 int64_t org_dist =
1733 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1734 (1 << (2 * txb_info->shift));
Angie Chiang0b2795c2017-09-29 16:00:08 -07001735 int org_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang07c57f32017-05-30 18:18:33 -07001736#endif
1737
1738 tran_low_t *org_qcoeff = txb_info->qcoeff;
1739 tran_low_t *org_dqcoeff = txb_info->dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001740 uint8_t *const org_levels = txb_info->levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07001741
1742 tran_low_t tmp_qcoeff[MAX_TX_SQUARE];
1743 tran_low_t tmp_dqcoeff[MAX_TX_SQUARE];
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001744 uint8_t tmp_levels_buf[TX_PAD_2D];
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001745 uint8_t *const tmp_levels = set_levels(tmp_levels_buf, txb_info->width);
Angie Chiang07c57f32017-05-30 18:18:33 -07001746 const int org_eob = txb_info->eob;
1747 if (dry_run) {
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001748 const int stride = txb_info->width + TX_PAD_HOR;
1749 const int levels_size =
1750
1751 (stride * (txb_info->height + TX_PAD_VER) + TX_PAD_END);
Angie Chiang07c57f32017-05-30 18:18:33 -07001752 memcpy(tmp_qcoeff, org_qcoeff, sizeof(org_qcoeff[0]) * max_eob);
1753 memcpy(tmp_dqcoeff, org_dqcoeff, sizeof(org_dqcoeff[0]) * max_eob);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07001754 memcpy(tmp_levels, org_levels - TX_PAD_TOP * stride,
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07001755 sizeof(org_levels[0]) * levels_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07001756 txb_info->qcoeff = tmp_qcoeff;
1757 txb_info->dqcoeff = tmp_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001758 txb_info->levels = tmp_levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07001759 }
1760
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08001761 const int16_t *const scan = txb_info->scan_order->scan;
Angie Chiang07c57f32017-05-30 18:18:33 -07001762
1763 // forward optimize the nz_map
1764 const int cur_eob = txb_info->eob;
1765 for (int si = 0; si < cur_eob; ++si) {
1766 const int coeff_idx = scan[si];
1767 tran_low_t qc = txb_info->qcoeff[coeff_idx];
1768 if (abs(qc) == 1) {
1769 LevelDownStats stats;
Angie Chiang25645b72017-09-24 14:28:49 -07001770 try_level_down_facade(&stats, si, txb_cache, txb_costs, txb_info,
1771 fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07001772 if (stats.update) {
1773 update = 1;
1774 cost_diff += stats.cost_diff;
1775 dist_diff += stats.dist_diff;
1776 rd_diff += stats.rd_diff;
1777 update_level_down(coeff_idx, txb_cache, txb_info);
1778 set_eob(txb_info, stats.new_eob);
1779 }
1780 }
1781 }
1782
1783 // backward optimize the level-k map
Angie Chiang530b3042017-08-17 15:08:58 -07001784 int eob_fix = 0;
Angie Chiang07c57f32017-05-30 18:18:33 -07001785 for (int si = txb_info->eob - 1; si >= 0; --si) {
Angie Chiang530b3042017-08-17 15:08:58 -07001786 const int coeff_idx = scan[si];
1787 if (eob_fix == 1 && txb_info->qcoeff[coeff_idx] == 1) {
1788 // when eob is fixed, there is not need to optimize again when
1789 // abs(qc) == 1
1790 continue;
1791 }
Angie Chiang07c57f32017-05-30 18:18:33 -07001792 LevelDownStats stats;
Angie Chiang25645b72017-09-24 14:28:49 -07001793 try_level_down_facade(&stats, si, txb_cache, txb_costs, txb_info,
1794 fast_mode);
Angie Chiang07c57f32017-05-30 18:18:33 -07001795 if (stats.update) {
1796#if TEST_OPTIMIZE_TXB
1797// printf("si %d low_qc %d cost_diff %d dist_diff %ld rd_diff %ld eob %d new_eob
1798// %d\n", si, stats.low_qc, stats.cost_diff, stats.dist_diff, stats.rd_diff,
1799// txb_info->eob, stats.new_eob);
1800#endif
1801 update = 1;
1802 cost_diff += stats.cost_diff;
1803 dist_diff += stats.dist_diff;
1804 rd_diff += stats.rd_diff;
1805 update_level_down(coeff_idx, txb_cache, txb_info);
1806 set_eob(txb_info, stats.new_eob);
1807 }
Angie Chiang530b3042017-08-17 15:08:58 -07001808 if (eob_fix == 0 && txb_info->qcoeff[coeff_idx] != 0) eob_fix = 1;
Angie Chiang07c57f32017-05-30 18:18:33 -07001809 if (si > txb_info->eob) si = txb_info->eob;
1810 }
1811#if TEST_OPTIMIZE_TXB
1812 int64_t new_dist =
1813 av1_block_error_c(txb_info->tcoeff, txb_info->dqcoeff, max_eob, &sse) *
1814 (1 << (2 * txb_info->shift));
Angie Chiang0b2795c2017-09-29 16:00:08 -07001815 int new_cost = get_txb_cost(txb_info, txb_costs);
Angie Chiang07c57f32017-05-30 18:18:33 -07001816 int64_t ref_dist_diff = new_dist - org_dist;
1817 int ref_cost_diff = new_cost - org_cost;
1818 if (cost_diff != ref_cost_diff || dist_diff != ref_dist_diff)
1819 printf(
1820 "overall rd_diff %ld\ncost_diff %d ref_cost_diff%d\ndist_diff %ld "
1821 "ref_dist_diff %ld\neob %d new_eob %d\n\n",
1822 rd_diff, cost_diff, ref_cost_diff, dist_diff, ref_dist_diff, org_eob,
1823 txb_info->eob);
1824#endif
1825 if (dry_run) {
1826 txb_info->qcoeff = org_qcoeff;
1827 txb_info->dqcoeff = org_dqcoeff;
Linfeng Zhang1015a342017-10-24 16:20:41 -07001828 txb_info->levels = org_levels;
Angie Chiang07c57f32017-05-30 18:18:33 -07001829 set_eob(txb_info, org_eob);
1830 }
1831 return update;
1832}
Dake Hea47cd6c2017-10-13 18:09:58 -07001833#endif
Angie Chiang07c57f32017-05-30 18:18:33 -07001834
1835// These numbers are empirically obtained.
1836static const int plane_rd_mult[REF_TYPES][PLANE_TYPES] = {
Johannb0ef6ff2018-02-08 14:32:21 -08001837 { 17, 13 },
1838 { 16, 10 },
Angie Chiang07c57f32017-05-30 18:18:33 -07001839};
1840
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001841void hbt_init() {
1842 hbt_hash_table =
1843 aom_malloc(sizeof(OptTxbQcoeff) * HBT_TABLE_SIZE * HBT_ARRAY_LENGTH);
1844 memset(hbt_hash_table, 0,
1845 sizeof(OptTxbQcoeff) * HBT_TABLE_SIZE * HBT_ARRAY_LENGTH);
1846 av1_crc_calculator_init(&crc_calculator, 31, 0x5D6DCB); // 31 bit: qc & ctx
1847
1848 hbt_needs_init = 0;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001849}
1850
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001851void hbt_destroy() { aom_free(hbt_hash_table); }
1852
1853int hbt_hash_miss(uint32_t hbt_ctx_hash, uint32_t hbt_qc_hash,
1854 TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001855 const LV_MAP_EOB_COST *txb_eob_costs,
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001856 const struct macroblock_plane *p, int block, int fast_mode,
1857 int *rate_cost) {
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001858 const int16_t *scan = txb_info->scan_order->scan;
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001859 int prev_eob = txb_info->eob;
1860 assert(HBT_EOB <= 16); // Lengthen array if allowing longer eob.
1861 int32_t prev_coeff[16];
1862 for (int i = 0; i < prev_eob; i++) {
1863 prev_coeff[i] = txb_info->qcoeff[scan[i]];
1864 }
1865 for (int i = prev_eob; i < HBT_EOB; i++) {
1866 prev_coeff[i] = 0; // For compiler piece of mind.
1867 }
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001868
1869 av1_txb_init_levels(txb_info->qcoeff, txb_info->width, txb_info->height,
1870 txb_info->levels);
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001871
Cheng Chen82775f62018-01-18 12:09:54 -08001872 const int update = optimize_txb(txb_info, txb_costs, txb_eob_costs, NULL, 0,
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001873 fast_mode, rate_cost);
1874
1875 // Overwrite old entry
1876 uint16_t hbt_table_index = hbt_ctx_hash % HBT_TABLE_SIZE;
1877 uint16_t hbt_array_index = hbt_qc_hash % HBT_ARRAY_LENGTH;
1878 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1879 .rate_cost = *rate_cost;
1880 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index].init = 1;
1881 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1882 .hbt_qc_hash = hbt_qc_hash;
1883 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1884 .hbt_ctx_hash = hbt_ctx_hash;
1885 assert(prev_eob >= txb_info->eob); // eob can't get longer
1886 for (int i = 0; i < txb_info->eob; i++) {
1887 // Record how coeff changed. Convention: towards zero is negative.
1888 if (txb_info->qcoeff[scan[i]] > 0)
1889 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1890 .deltas[i] = txb_info->qcoeff[scan[i]] - prev_coeff[i];
1891 else
1892 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1893 .deltas[i] = prev_coeff[i] - txb_info->qcoeff[scan[i]];
1894 }
1895 for (int i = txb_info->eob; i < prev_eob; i++) {
1896 // If eob got shorter, record that all after it changed to zero.
1897 if (prev_coeff[i] > 0)
1898 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1899 .deltas[i] = -prev_coeff[i];
1900 else
1901 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1902 .deltas[i] = prev_coeff[i];
1903 }
1904 for (int i = prev_eob; i < HBT_EOB; i++) {
1905 // Record 'no change' after optimized coefficients run out.
1906 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1907 .deltas[i] = 0;
1908 }
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001909
1910 if (update) {
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001911 p->eobs[block] = txb_info->eob;
1912 p->txb_entropy_ctx[block] = av1_get_txb_entropy_context(
1913 txb_info->qcoeff, txb_info->scan_order, txb_info->eob);
1914 }
1915 return txb_info->eob;
1916}
1917
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001918int hbt_hash_hit(uint32_t hbt_table_index, int hbt_array_index,
1919 TxbInfo *txb_info, const struct macroblock_plane *p, int block,
1920 int *rate_cost) {
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001921 const int16_t *scan = txb_info->scan_order->scan;
1922 int new_eob = 0;
1923 int update = 0;
1924
1925 for (int i = 0; i < txb_info->eob; i++) {
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001926 // Delta convention is negatives go towards zero, so only apply those ones.
1927 if (hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1928 .deltas[i] < 0) {
1929 if (txb_info->qcoeff[scan[i]] > 0)
1930 txb_info->qcoeff[scan[i]] +=
1931 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1932 .deltas[i];
1933 else
1934 txb_info->qcoeff[scan[i]] -=
1935 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1936 .deltas[i];
1937
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001938 update = 1;
1939 update_coeff(scan[i], txb_info->qcoeff[scan[i]], txb_info);
1940 }
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001941 if (txb_info->qcoeff[scan[i]]) new_eob = i + 1;
1942 }
1943
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001944 // Rate_cost can be calculated here instead (av1_cost_coeffs_txb), but
1945 // it is expensive and gives little benefit as long as qc_hash is high bit
1946 *rate_cost =
1947 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1948 .rate_cost;
1949
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001950 if (update) {
1951 txb_info->eob = new_eob;
1952 p->eobs[block] = txb_info->eob;
1953 p->txb_entropy_ctx[block] = av1_get_txb_entropy_context(
1954 txb_info->qcoeff, txb_info->scan_order, txb_info->eob);
1955 }
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001956
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001957 return txb_info->eob;
1958}
1959
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001960int hbt_search_match(uint32_t hbt_ctx_hash, uint32_t hbt_qc_hash,
1961 TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
1962 const LV_MAP_EOB_COST *txb_eob_costs,
1963 const struct macroblock_plane *p, int block, int fast_mode,
1964 int *rate_cost) {
1965 // Check for qcoeff match
1966 int hbt_array_index = hbt_qc_hash % HBT_ARRAY_LENGTH;
1967 int hbt_table_index = hbt_ctx_hash % HBT_TABLE_SIZE;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001968
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001969 if (hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1970 .hbt_qc_hash == hbt_qc_hash &&
1971 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1972 .hbt_ctx_hash == hbt_ctx_hash &&
1973 hbt_hash_table[hbt_table_index * HBT_ARRAY_LENGTH + hbt_array_index]
1974 .init) {
1975 return hbt_hash_hit(hbt_table_index, hbt_array_index, txb_info, p, block,
1976 rate_cost);
1977 } else {
1978 return hbt_hash_miss(hbt_ctx_hash, hbt_qc_hash, txb_info, txb_costs,
1979 txb_eob_costs, p, block, fast_mode, rate_cost);
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001980 }
1981}
1982
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001983int hbt_create_hashes(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
1984 const LV_MAP_EOB_COST *txb_eob_costs,
1985 const struct macroblock_plane *p, int block,
1986 int fast_mode, int *rate_cost) {
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001987 // Initialize hash table if needed.
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001988 if (hbt_needs_init) {
1989 hbt_init();
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001990 }
1991
1992 //// Hash creation
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001993 uint8_t txb_hash_data[256]; // Asserts below to ensure enough space.
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001994 const int16_t *scan = txb_info->scan_order->scan;
1995 uint8_t chunk = 0;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001996 int hash_data_index = 0;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08001997
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08001998 // Make qc_hash.
1999 int packing_index = 0; // needed for packing.
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08002000 for (int i = 0; i < txb_info->eob; i++) {
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08002001 tran_low_t prechunk = txb_info->qcoeff[scan[i]];
2002
2003 // Softening: Improves speed. Aligns with signed deltas.
2004 if (prechunk < 0) prechunk *= -1;
2005
2006 // Early kick out: Don't apply feature if there are large coeffs:
2007 // If this kickout value is removed or raised beyond int8_t,
2008 // widen deltas type in OptTxbQcoeff struct.
2009 assert((int8_t)HBT_KICKOUT == HBT_KICKOUT); // If not, widen types.
2010 if (prechunk > HBT_KICKOUT) {
2011 av1_txb_init_levels(txb_info->qcoeff, txb_info->width, txb_info->height,
2012 txb_info->levels);
2013
2014 const int update = optimize_txb(txb_info, txb_costs, txb_eob_costs, NULL,
2015 0, fast_mode, rate_cost);
2016
2017 if (update) {
2018 p->eobs[block] = txb_info->eob;
2019 p->txb_entropy_ctx[block] = av1_get_txb_entropy_context(
2020 txb_info->qcoeff, txb_info->scan_order, txb_info->eob);
2021 }
2022 return txb_info->eob;
2023 }
2024
2025 // Since coeffs are 0 to 3, only 2 bits are needed: pack into bytes
2026 if (packing_index == 0) txb_hash_data[hash_data_index] = 0;
2027 chunk = prechunk << packing_index;
2028 packing_index += 2;
2029 txb_hash_data[hash_data_index] |= chunk;
2030
2031 // Full byte:
2032 if (packing_index == 8) {
2033 packing_index = 0;
2034 hash_data_index++;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08002035 }
2036 }
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08002037 // Needed when packing_index != 0, to include final byte.
2038 hash_data_index++;
2039 assert(hash_data_index <= 64);
2040 // 31 bit qc_hash: index to array
2041 uint32_t hbt_qc_hash =
2042 av1_get_crc_value(&crc_calculator, txb_hash_data, hash_data_index);
2043
2044 // Make ctx_hash.
2045 hash_data_index = 0;
2046 tran_low_t prechunk;
2047
2048 for (int i = 0; i < txb_info->eob; i++) {
2049 // Save as magnitudes towards or away from zero.
2050 if (txb_info->tcoeff[scan[i]] >= 0)
2051 prechunk = txb_info->tcoeff[scan[i]] - txb_info->dqcoeff[scan[i]];
2052 else
2053 prechunk = txb_info->dqcoeff[scan[i]] - txb_info->tcoeff[scan[i]];
2054
2055 chunk = prechunk & 0xff;
2056 txb_hash_data[hash_data_index++] = chunk;
2057 }
2058
2059 // Extra ctx data:
2060 // Include dequants.
2061 txb_hash_data[hash_data_index++] = txb_info->dequant[0] & 0xff;
2062 txb_hash_data[hash_data_index++] = txb_info->dequant[1] & 0xff;
2063 chunk = txb_info->txb_ctx->txb_skip_ctx & 0xff;
2064 txb_hash_data[hash_data_index++] = chunk;
2065 chunk = txb_info->txb_ctx->dc_sign_ctx & 0xff;
2066 txb_hash_data[hash_data_index++] = chunk;
2067 // eob
2068 chunk = txb_info->eob & 0xff;
2069 txb_hash_data[hash_data_index++] = chunk;
2070 // rdmult (int64)
2071 chunk = txb_info->rdmult & 0xff;
2072 txb_hash_data[hash_data_index++] = chunk;
2073 // tx_type
2074 chunk = txb_info->tx_type & 0xff;
2075 txb_hash_data[hash_data_index++] = chunk;
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08002076 // base_eob_cost
2077 for (int i = 1; i < 3; i++) { // i = 0 are softened away
2078 for (int j = 0; j < SIG_COEF_CONTEXTS_EOB; j++) {
2079 chunk = (txb_costs->base_eob_cost[j][i] & 0xff00) >> 8;
2080 txb_hash_data[hash_data_index++] = chunk;
2081 }
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08002082 }
2083 // eob_cost
2084 for (int i = 0; i < 11; i++) {
2085 for (int j = 0; j < 2; j++) {
2086 chunk = (txb_eob_costs->eob_cost[j][i] & 0xff00) >> 8;
2087 txb_hash_data[hash_data_index++] = chunk;
2088 }
2089 }
2090 // dc_sign_cost
2091 for (int i = 0; i < 2; i++) {
2092 for (int j = 0; j < DC_SIGN_CONTEXTS; j++) {
2093 chunk = (txb_costs->dc_sign_cost[j][i] & 0xff00) >> 8;
2094 txb_hash_data[hash_data_index++] = chunk;
2095 }
2096 }
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08002097
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08002098 assert(hash_data_index <= 256);
2099 // 31 bit ctx_hash: used to index table
2100 uint32_t hbt_ctx_hash =
2101 av1_get_crc_value(&crc_calculator, txb_hash_data, hash_data_index);
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08002102 //// End hash creation
2103
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08002104 return hbt_search_match(hbt_ctx_hash, hbt_qc_hash, txb_info, txb_costs,
2105 txb_eob_costs, p, block, fast_mode, rate_cost);
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08002106}
2107
Yaowu Xuefcf1e92018-01-12 17:05:46 -08002108int av1_optimize_txb(const struct AV1_COMP *cpi, MACROBLOCK *x, int plane,
Jingning Han7eab9ff2017-07-06 10:12:54 -07002109 int blk_row, int blk_col, int block, TX_SIZE tx_size,
Cheng Chen82775f62018-01-18 12:09:54 -08002110 TXB_CTX *txb_ctx, int fast_mode, int *rate_cost) {
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08002111 const AV1_COMMON *cm = &cpi->common;
Angie Chiang07c57f32017-05-30 18:18:33 -07002112 MACROBLOCKD *const xd = &x->e_mbd;
2113 const PLANE_TYPE plane_type = get_plane_type(plane);
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -08002114 const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
Sarah Parker7c71cc02018-01-29 12:27:58 -08002115 const TX_TYPE tx_type = av1_get_tx_type(plane_type, xd, blk_row, blk_col,
2116 tx_size, cm->reduced_tx_set_used);
Angie Chiang07c57f32017-05-30 18:18:33 -07002117 const MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
2118 const struct macroblock_plane *p = &x->plane[plane];
2119 struct macroblockd_plane *pd = &xd->plane[plane];
2120 const int eob = p->eobs[block];
2121 tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2122 tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
2123 const tran_low_t *tcoeff = BLOCK_OFFSET(p->coeff, block);
Monty Montgomery125c0fc2017-10-26 00:44:35 -04002124 const int16_t *dequant = p->dequant_QTX;
Urvang Joshi80893152017-10-27 11:51:14 -07002125 const int seg_eob = av1_get_max_eob(tx_size);
Angie Chianga9ba58e2017-12-01 19:22:43 -08002126 const int bwl = get_txb_bwl(tx_size);
2127 const int width = get_txb_wide(tx_size);
2128 const int height = get_txb_high(tx_size);
Angie Chiang07c57f32017-05-30 18:18:33 -07002129 const int is_inter = is_inter_block(mbmi);
Angie Chiangbd99b382017-06-20 15:11:16 -07002130 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Jingning Handfd72322017-08-09 14:04:12 -07002131 const LV_MAP_COEFF_COST txb_costs = x->coeff_costs[txs_ctx][plane_type];
Sarah Parker3d752092017-12-20 15:37:55 -08002132#if CONFIG_NEW_QUANT
Debargha Mukherjeee15b8ad2017-12-26 07:10:40 -08002133 int dq = get_dq_profile(cm->dq_type, x->qindex, is_inter, plane_type);
Sarah Parker98c8dd72018-01-12 15:42:24 -08002134#if !CONFIG_AOM_QM
Sarah Parker3d752092017-12-20 15:37:55 -08002135 const dequant_val_type_nuq *dequant_val = p->dequant_val_nuq_QTX[dq];
Sarah Parker98c8dd72018-01-12 15:42:24 -08002136#endif // !CONFIG_AOM_QM
Sarah Parker3d752092017-12-20 15:37:55 -08002137#endif // CONFIG_NEW_QUANT
Dake He0db7d0e2017-12-21 15:23:20 -08002138 const int eob_multi_size = txsize_log2_minus4[tx_size];
2139 const LV_MAP_EOB_COST txb_eob_costs =
2140 x->eob_costs[eob_multi_size][plane_type];
Angie Chiang07c57f32017-05-30 18:18:33 -07002141
2142 const int shift = av1_get_tx_scale(tx_size);
2143 const int64_t rdmult =
Jingning Hanb433f4c2017-11-17 15:43:59 -08002144 ((x->rdmult * plane_rd_mult[is_inter][plane_type] << (2 * (xd->bd - 8))) +
2145 2) >>
2146 2;
Linfeng Zhang679d81e2017-10-31 15:27:42 -07002147 uint8_t levels_buf[TX_PAD_2D];
2148 uint8_t *const levels = set_levels(levels_buf, width);
Angie Chiangb3167a62018-01-30 19:37:57 -08002149#if CONFIG_AOM_QM
2150 const TX_SIZE qm_tx_size = av1_get_adjusted_tx_size(tx_size);
2151 const qm_val_t *iqmatrix =
2152 IS_2D_TRANSFORM(tx_type)
2153 ? pd->seg_iqmatrix[mbmi->segment_id][qm_tx_size]
2154 : cm->giqmatrix[NUM_QM_LEVELS - 1][0][qm_tx_size];
2155#else
2156 const qm_val_t *iqmatrix = NULL;
2157#endif
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002158 assert(width == (1 << bwl));
Linfeng Zhang1015a342017-10-24 16:20:41 -07002159 TxbInfo txb_info = {
Sarah Parker3d752092017-12-20 15:37:55 -08002160 qcoeff,
2161 levels,
2162 dqcoeff,
2163 tcoeff,
2164 dequant,
2165#if CONFIG_NEW_QUANT
Sarah Parker98c8dd72018-01-12 15:42:24 -08002166#if CONFIG_AOM_QM
2167 dq,
2168#else
Sarah Parker3d752092017-12-20 15:37:55 -08002169 dequant_val,
Sarah Parker98c8dd72018-01-12 15:42:24 -08002170#endif // CONFIG_AOM_QM
Sarah Parker3d752092017-12-20 15:37:55 -08002171#endif // CONFIG_NEW_QUANT
2172 shift,
2173 tx_size,
2174 txs_ctx,
2175 tx_type,
2176 bwl,
2177 width,
2178 height,
2179 eob,
2180 seg_eob,
2181 scan_order,
2182 txb_ctx,
2183 rdmult,
Angie Chiangb3167a62018-01-30 19:37:57 -08002184 &cm->coeff_ctx_table,
2185 iqmatrix,
Linfeng Zhang1015a342017-10-24 16:20:41 -07002186 };
2187
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08002188 // Hash based trellis (hbt) speed feature: avoid expensive optimize_txb calls
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08002189 // by storing the coefficient deltas in a hash table.
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08002190 // Currently disabled in speedfeatures.c
Michelle Findlay-Olynykdea531d2017-12-13 14:10:56 -08002191 if (eob <= HBT_EOB && eob > 0 && cpi->sf.use_hash_based_trellis) {
2192 return hbt_create_hashes(&txb_info, &txb_costs, &txb_eob_costs, p, block,
2193 fast_mode, rate_cost);
Michelle Findlay-Olynykfbab0622017-12-13 14:10:56 -08002194 }
2195
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002196 av1_txb_init_levels(qcoeff, width, height, levels);
Urvang Joshi70006e42017-06-14 16:08:55 -07002197
Cheng Chen82775f62018-01-18 12:09:54 -08002198 const int update = optimize_txb(&txb_info, &txb_costs, &txb_eob_costs, NULL,
2199 0, fast_mode, rate_cost);
Angie Chiang07c57f32017-05-30 18:18:33 -07002200
Jingning Hand7e99112017-12-13 09:47:45 -08002201 if (update) {
2202 p->eobs[block] = txb_info.eob;
2203 p->txb_entropy_ctx[block] =
2204 av1_get_txb_entropy_context(qcoeff, scan_order, txb_info.eob);
2205 }
Angie Chiang07c57f32017-05-30 18:18:33 -07002206 return txb_info.eob;
2207}
Jingning Hand7e99112017-12-13 09:47:45 -08002208
Angie Chiang74e23072017-03-24 14:54:23 -07002209int av1_get_txb_entropy_context(const tran_low_t *qcoeff,
2210 const SCAN_ORDER *scan_order, int eob) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002211 const int16_t *const scan = scan_order->scan;
Angie Chiang74e23072017-03-24 14:54:23 -07002212 int cul_level = 0;
2213 int c;
Jingning Han339cf932017-09-18 10:17:02 -07002214
2215 if (eob == 0) return 0;
Angie Chiang74e23072017-03-24 14:54:23 -07002216 for (c = 0; c < eob; ++c) {
2217 cul_level += abs(qcoeff[scan[c]]);
2218 }
2219
2220 cul_level = AOMMIN(COEFF_CONTEXT_MASK, cul_level);
2221 set_dc_sign(&cul_level, qcoeff[0]);
2222
2223 return cul_level;
2224}
2225
Jingning Han4fe5f672017-05-19 15:46:07 -07002226void av1_update_txb_context_b(int plane, int block, int blk_row, int blk_col,
2227 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
2228 void *arg) {
Jingning Han6171ae72017-05-18 20:15:06 -07002229 struct tokenize_b_args *const args = arg;
Angie Chiang36d616b2017-03-22 13:58:36 -07002230 const AV1_COMP *cpi = args->cpi;
2231 const AV1_COMMON *cm = &cpi->common;
Angie Chiang0397eda2017-03-15 16:57:14 -07002232 ThreadData *const td = args->td;
2233 MACROBLOCK *const x = &td->mb;
2234 MACROBLOCKD *const xd = &x->e_mbd;
Angie Chiang36d616b2017-03-22 13:58:36 -07002235 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiang0397eda2017-03-15 16:57:14 -07002236 struct macroblock_plane *p = &x->plane[plane];
2237 struct macroblockd_plane *pd = &xd->plane[plane];
Angie Chiang36d616b2017-03-22 13:58:36 -07002238 const uint16_t eob = p->eobs[block];
2239 const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2240 const PLANE_TYPE plane_type = pd->plane_type;
Sarah Parker7c71cc02018-01-29 12:27:58 -08002241 const TX_TYPE tx_type = av1_get_tx_type(plane_type, xd, blk_row, blk_col,
2242 tx_size, cm->reduced_tx_set_used);
Angie Chiangbd99b382017-06-20 15:11:16 -07002243 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Angie Chiang0397eda2017-03-15 16:57:14 -07002244 (void)plane_bsize;
Angie Chiang36d616b2017-03-22 13:58:36 -07002245
Angie Chiang74e23072017-03-24 14:54:23 -07002246 int cul_level = av1_get_txb_entropy_context(qcoeff, scan_order, eob);
Angie Chiang36d616b2017-03-22 13:58:36 -07002247 av1_set_contexts(xd, pd, plane, tx_size, cul_level, blk_col, blk_row);
Angie Chiang0397eda2017-03-15 16:57:14 -07002248}
2249
Jingning Han4fe5f672017-05-19 15:46:07 -07002250void av1_update_and_record_txb_context(int plane, int block, int blk_row,
2251 int blk_col, BLOCK_SIZE plane_bsize,
2252 TX_SIZE tx_size, void *arg) {
Jingning Han6171ae72017-05-18 20:15:06 -07002253 struct tokenize_b_args *const args = arg;
Angie Chiang0397eda2017-03-15 16:57:14 -07002254 const AV1_COMP *cpi = args->cpi;
2255 const AV1_COMMON *cm = &cpi->common;
2256 ThreadData *const td = args->td;
2257 MACROBLOCK *const x = &td->mb;
2258 MACROBLOCKD *const xd = &x->e_mbd;
2259 struct macroblock_plane *p = &x->plane[plane];
2260 struct macroblockd_plane *pd = &xd->plane[plane];
2261 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Angie Chiang2cc5eb32018-02-14 18:37:22 -08002262 int eob = p->eobs[block];
Angie Chiang0397eda2017-03-15 16:57:14 -07002263 const PLANE_TYPE plane_type = pd->plane_type;
2264 const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
2265 tran_low_t *tcoeff = BLOCK_OFFSET(x->mbmi_ext->tcoeff[plane], block);
2266 const int segment_id = mbmi->segment_id;
Sarah Parker7c71cc02018-01-29 12:27:58 -08002267 const TX_TYPE tx_type = av1_get_tx_type(plane_type, xd, blk_row, blk_col,
2268 tx_size, cm->reduced_tx_set_used);
Angie Chiangbd99b382017-06-20 15:11:16 -07002269 const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002270 const int16_t *const scan = scan_order->scan;
hui suc0cf71d2017-07-20 16:38:50 -07002271 const int seg_eob = av1_get_tx_eob(&cpi->common.seg, segment_id, tx_size);
Linfeng Zhang1015a342017-10-24 16:20:41 -07002272 int c;
Angie Chiang85901562017-03-17 12:03:27 -07002273 TXB_CTX txb_ctx;
2274 get_txb_ctx(plane_bsize, tx_size, plane, pd->above_context + blk_col,
2275 pd->left_context + blk_row, &txb_ctx);
Angie Chianga9ba58e2017-12-01 19:22:43 -08002276 const int bwl = get_txb_bwl(tx_size);
2277 const int width = get_txb_wide(tx_size);
2278 const int height = get_txb_high(tx_size);
Linfeng Zhang679d81e2017-10-31 15:27:42 -07002279 uint8_t levels_buf[TX_PAD_2D];
2280 uint8_t *const levels = set_levels(levels_buf, width);
Linfeng Zhangae7b2f32017-11-08 15:46:57 -08002281 DECLARE_ALIGNED(16, uint8_t, level_counts[MAX_TX_SQUARE]);
Yunqing Wang0e141b52017-11-02 15:08:58 -07002282 const uint8_t allow_update_cdf = args->allow_update_cdf;
Angie Chiang0397eda2017-03-15 16:57:14 -07002283
Debargha Mukherjeeb3eda2f2017-11-28 16:00:20 -08002284 TX_SIZE txsize_ctx = get_txsize_entropy_ctx(tx_size);
Jingning Han8f661602017-08-19 08:16:50 -07002285 FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
Linfeng Zhangd67c13f2017-12-11 11:49:12 -08002286 DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
Jingning Han48be0e12017-06-13 12:12:01 -07002287
Angie Chiang0397eda2017-03-15 16:57:14 -07002288 memcpy(tcoeff, qcoeff, sizeof(*tcoeff) * seg_eob);
Hui Su1e959892018-01-22 12:14:43 -08002289#if CONFIG_ENTROPY_STATS
Jingning Han48be0e12017-06-13 12:12:01 -07002290 ++td->counts->txb_skip[txsize_ctx][txb_ctx.txb_skip_ctx][eob == 0];
Hui Su1e959892018-01-22 12:14:43 -08002291#endif // CONFIG_ENTROPY_STATS
Hui Su41d61522018-01-23 10:47:55 -08002292 if (allow_update_cdf) {
2293 update_cdf(ec_ctx->txb_skip_cdf[txsize_ctx][txb_ctx.txb_skip_ctx], eob == 0,
Yunqing Wang0e141b52017-11-02 15:08:58 -07002294 2);
Hui Su41d61522018-01-23 10:47:55 -08002295 }
Angie Chiang85901562017-03-17 12:03:27 -07002296 x->mbmi_ext->txb_skip_ctx[plane][block] = txb_ctx.txb_skip_ctx;
Angie Chiang0397eda2017-03-15 16:57:14 -07002297
2298 x->mbmi_ext->eobs[plane][block] = eob;
2299
2300 if (eob == 0) {
2301 av1_set_contexts(xd, pd, plane, tx_size, 0, blk_col, blk_row);
2302 return;
2303 }
2304
Linfeng Zhang1122d7d2017-10-31 15:30:28 -07002305 av1_txb_init_levels(tcoeff, width, height, levels);
Linfeng Zhangce065ca2017-10-17 16:49:30 -07002306
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002307#if CONFIG_TXK_SEL
Luc Trudeau2eb9b842017-12-13 11:19:16 -05002308 av1_update_tx_type_count(cm, xd, blk_row, blk_col, plane, mbmi->sb_type,
Debargha Mukherjee3ebb0d02017-12-14 05:05:18 -08002309 tx_size, td->counts, allow_update_cdf);
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002310#endif
Angie Chiang0397eda2017-03-15 16:57:14 -07002311
Jingning Han35deaa72017-10-26 15:36:30 -07002312 av1_update_eob_context(eob, seg_eob, tx_size, tx_type, plane_type, ec_ctx,
Yunqing Wang0e141b52017-11-02 15:08:58 -07002313 td->counts, allow_update_cdf);
Linfeng Zhangd67c13f2017-12-11 11:49:12 -08002314
2315 av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_type, coeff_contexts);
2316
Dake Hea47cd6c2017-10-13 18:09:58 -07002317 for (c = eob - 1; c >= 0; --c) {
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002318 const int pos = scan[c];
Linfeng Zhangd67c13f2017-12-11 11:49:12 -08002319 const int coeff_ctx = coeff_contexts[pos];
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002320 const tran_low_t v = qcoeff[pos];
Angie Chiang2cc5eb32018-02-14 18:37:22 -08002321 const tran_low_t level = abs(v);
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002322 const int is_nz = (v != 0);
Dake He03a32922017-10-31 08:06:45 -07002323
Ola Hugosson13892102017-11-06 08:01:44 +01002324 (void)is_nz;
Dake He4d447692017-12-15 09:10:06 -08002325 if (allow_update_cdf) {
2326 if (c == eob - 1) {
2327 assert(coeff_ctx < 4);
2328 update_cdf(
2329 ec_ctx->coeff_base_eob_cdf[txsize_ctx][plane_type][coeff_ctx],
Angie Chiang2cc5eb32018-02-14 18:37:22 -08002330 AOMMIN(level, 3) - 1, 3);
Dake He4d447692017-12-15 09:10:06 -08002331 } else {
2332 update_cdf(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][coeff_ctx],
Angie Chiang2cc5eb32018-02-14 18:37:22 -08002333 AOMMIN(level, 3), 4);
Dake He4d447692017-12-15 09:10:06 -08002334 }
Dake He3fe369c2017-11-16 17:56:44 -08002335 }
Dake He59881772017-11-24 07:00:02 -08002336 {
Dake He4d447692017-12-15 09:10:06 -08002337 if (c == eob - 1) {
2338 assert(coeff_ctx < 4);
2339 ++td->counts->coeff_base_eob_multi[txsize_ctx][plane_type][coeff_ctx]
Angie Chiang2cc5eb32018-02-14 18:37:22 -08002340 [AOMMIN(level, 3) - 1];
Dake He4d447692017-12-15 09:10:06 -08002341 } else {
2342 ++td->counts->coeff_base_multi[txsize_ctx][plane_type][coeff_ctx]
Angie Chiang2cc5eb32018-02-14 18:37:22 -08002343 [AOMMIN(level, 3)];
2344 }
2345 }
2346 if (level > NUM_BASE_LEVELS) {
2347 const int base_range = level - 1 - NUM_BASE_LEVELS;
Angie Chiang2cc5eb32018-02-14 18:37:22 -08002348 const int br_ctx =
2349 get_br_ctx(levels, pos, bwl, level_counts[pos], tx_type);
Angie Chiang2cc5eb32018-02-14 18:37:22 -08002350 for (int idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
2351 const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
2352 if (allow_update_cdf) {
Angie Chiang2cfb7142018-02-16 11:24:52 -08002353 update_cdf(ec_ctx->coeff_br_cdf[AOMMIN(txsize_ctx, TX_32X32)]
2354 [plane_type][br_ctx],
2355 k, BR_CDF_SIZE);
Angie Chiang2cc5eb32018-02-14 18:37:22 -08002356 }
2357 for (int lps = 0; lps < BR_CDF_SIZE - 1; lps++) {
2358#if CONFIG_ENTROPY_STATS
Angie Chiang2cc5eb32018-02-14 18:37:22 -08002359 ++td->counts->coeff_lps[AOMMIN(txsize_ctx, TX_32X32)][plane_type][lps]
2360 [br_ctx][lps == k];
Angie Chiang2cc5eb32018-02-14 18:37:22 -08002361#endif // CONFIG_ENTROPY_STATS
2362 if (lps == k) break;
2363 }
2364 ++td->counts->coeff_lps_multi[AOMMIN(txsize_ctx, TX_32X32)][plane_type]
2365 [br_ctx][k];
2366 if (k < BR_CDF_SIZE - 1) break;
Dake He59881772017-11-24 07:00:02 -08002367 }
2368 }
Dake Hea47cd6c2017-10-13 18:09:58 -07002369 }
Dake Hea47cd6c2017-10-13 18:09:58 -07002370
Linfeng Zhangdb41d1e2017-12-05 11:06:20 -08002371 // Update the context needed to code the DC sign (if applicable)
2372 const int sign = (tcoeff[0] < 0) ? 1 : 0;
2373 if (tcoeff[0] != 0) {
Dake He43edb762017-10-26 10:29:46 -07002374 int dc_sign_ctx = txb_ctx.dc_sign_ctx;
Hui Su1e959892018-01-22 12:14:43 -08002375#if CONFIG_ENTROPY_STATS
Dake He43edb762017-10-26 10:29:46 -07002376 ++td->counts->dc_sign[plane_type][dc_sign_ctx][sign];
Hui Su1e959892018-01-22 12:14:43 -08002377#endif // CONFIG_ENTROPY_STATS
Yunqing Wang0e141b52017-11-02 15:08:58 -07002378 if (allow_update_cdf)
Hui Su41d61522018-01-23 10:47:55 -08002379 update_cdf(ec_ctx->dc_sign_cdf[plane_type][dc_sign_ctx], sign, 2);
Dake He43edb762017-10-26 10:29:46 -07002380 x->mbmi_ext->dc_sign_ctx[plane][block] = dc_sign_ctx;
2381 }
2382
Angie Chiang63d190a2017-10-23 15:43:05 -07002383 int cul_level = av1_get_txb_entropy_context(tcoeff, scan_order, eob);
Angie Chiang0397eda2017-03-15 16:57:14 -07002384 av1_set_contexts(xd, pd, plane, tx_size, cul_level, blk_col, blk_row);
2385}
2386
2387void av1_update_txb_context(const AV1_COMP *cpi, ThreadData *td,
2388 RUN_TYPE dry_run, BLOCK_SIZE bsize, int *rate,
Yunqing Wang0e141b52017-11-02 15:08:58 -07002389 int mi_row, int mi_col, uint8_t allow_update_cdf) {
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +00002390 const AV1_COMMON *const cm = &cpi->common;
2391 const int num_planes = av1_num_planes(cm);
Angie Chiang0397eda2017-03-15 16:57:14 -07002392 MACROBLOCK *const x = &td->mb;
2393 MACROBLOCKD *const xd = &x->e_mbd;
2394 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yunqing Wang0e141b52017-11-02 15:08:58 -07002395 struct tokenize_b_args arg = { cpi, td, NULL, 0, allow_update_cdf };
Angie Chiang0397eda2017-03-15 16:57:14 -07002396 (void)rate;
2397 (void)mi_row;
2398 (void)mi_col;
2399 if (mbmi->skip) {
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +00002400 av1_reset_skip_context(xd, mi_row, mi_col, bsize, num_planes);
Angie Chiang0397eda2017-03-15 16:57:14 -07002401 return;
2402 }
2403
2404 if (!dry_run) {
Jingning Han94652b82017-04-04 09:45:02 -07002405 av1_foreach_transformed_block(xd, bsize, mi_row, mi_col,
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +00002406 av1_update_and_record_txb_context, &arg,
2407 num_planes);
Angie Chiangc8af6112017-03-16 16:11:22 -07002408 } else if (dry_run == DRY_RUN_NORMAL) {
Jingning Han4fe5f672017-05-19 15:46:07 -07002409 av1_foreach_transformed_block(xd, bsize, mi_row, mi_col,
Imdad Sardharwallaaf8e2642018-01-19 11:46:34 +00002410 av1_update_txb_context_b, &arg, num_planes);
Angie Chiangc8af6112017-03-16 16:11:22 -07002411 } else {
2412 printf("DRY_RUN_COSTCOEFFS is not supported yet\n");
2413 assert(0);
Angie Chiang0397eda2017-03-15 16:57:14 -07002414 }
2415}