Add av1_cost_coeffs_txb() for lv_map experiment
Change-Id: I44842387207b19f8e0c3894d3f4e8d0646a4cafd
diff --git a/av1/encoder/encodetxb.c b/av1/encoder/encodetxb.c
index 62db8cb..4128d50 100644
--- a/av1/encoder/encodetxb.c
+++ b/av1/encoder/encodetxb.c
@@ -10,6 +10,7 @@
*/
#include "av1/common/scan.h"
+#include "av1/encoder/cost.h"
#include "av1/encoder/encodetxb.h"
static void write_golomb(aom_writer *w, int level) {
@@ -131,3 +132,171 @@
write_golomb(w, level - COEFF_BASE_RANGE - 1 - NUM_BASE_LEVELS);
}
}
+
+static INLINE void get_base_ctx_set(const tran_low_t *tcoeffs,
+ int c, // raster order
+ const int bwl,
+ int ctx_set[NUM_BASE_LEVELS]) {
+ const int row = c >> bwl;
+ const int col = c - (row << bwl);
+ const int stride = 1 << bwl;
+ int mag[NUM_BASE_LEVELS] = { 0 };
+ int idx;
+ tran_low_t abs_coeff;
+ int i;
+
+ for (idx = 0; idx < BASE_CONTEXT_POSITION_NUM; ++idx) {
+ int ref_row = row + base_ref_offset[idx][0];
+ int ref_col = col + base_ref_offset[idx][1];
+ int pos = (ref_row << bwl) + ref_col;
+
+ if (ref_row < 0 || ref_col < 0 || ref_row >= stride || ref_col >= stride)
+ continue;
+
+ abs_coeff = abs(tcoeffs[pos]);
+
+ for (i = 0; i < NUM_BASE_LEVELS; ++i) {
+ ctx_set[i] += abs_coeff > i;
+ if (base_ref_offset[idx][0] >= 0 && base_ref_offset[idx][1] >= 0)
+ mag[i] |= abs_coeff > (i + 1);
+ }
+ }
+
+ for (i = 0; i < NUM_BASE_LEVELS; ++i) {
+ ctx_set[i] = (ctx_set[i] + 1) >> 1;
+
+ if (row == 0 && col == 0)
+ ctx_set[i] = (ctx_set[i] << 1) + mag[i];
+ else if (row == 0)
+ ctx_set[i] = 8 + (ctx_set[i] << 1) + mag[i];
+ else if (col == 0)
+ ctx_set[i] = 18 + (ctx_set[i] << 1) + mag[i];
+ else
+ ctx_set[i] = 28 + (ctx_set[i] << 1) + mag[i];
+ }
+ return;
+}
+
+int av1_cost_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCK *x, int plane,
+ int block, TXB_CTX *txb_ctx, int *cul_level) {
+ MACROBLOCKD *const xd = &x->e_mbd;
+ const TX_SIZE tx_size = get_tx_size(plane, xd);
+ const PLANE_TYPE plane_type = get_plane_type(plane);
+ const TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
+ MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
+ const struct macroblock_plane *p = &x->plane[plane];
+ const int eob = p->eobs[block];
+ const tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
+ int c, cost;
+ const int seg_eob = AOMMIN(eob, (16 << (tx_size << 1)) - 1);
+ int txb_skip_ctx = txb_ctx->txb_skip_ctx;
+ aom_prob *nz_map = xd->fc->nz_map[tx_size][plane_type];
+
+ const int bwl = b_width_log2_lookup[txsize_to_bsize[tx_size]] + 2;
+ *cul_level = 0;
+ // txb_mask is only initialized for once here. After that, it will be set when
+ // coding zero map and then reset when coding level 1 info.
+ uint8_t txb_mask[32 * 32] = { 0 };
+ aom_prob(*coeff_base)[COEFF_BASE_CONTEXTS] =
+ xd->fc->coeff_base[tx_size][plane_type];
+
+ const SCAN_ORDER *const scan_order =
+ get_scan(cm, tx_size, tx_type, is_inter_block(mbmi));
+ const int16_t *scan = scan_order->scan;
+
+ cost = 0;
+
+ if (eob == 0) {
+ cost = av1_cost_bit(xd->fc->txb_skip[tx_size][txb_skip_ctx], 1);
+ return cost;
+ }
+
+ cost = av1_cost_bit(xd->fc->txb_skip[tx_size][txb_skip_ctx], 0);
+
+ for (c = 0; c < eob; ++c) {
+ tran_low_t v = qcoeff[scan[c]];
+ int is_nz = (v != 0);
+ int level = abs(v);
+
+ if (c < seg_eob) {
+ int coeff_ctx = get_nz_map_ctx(qcoeff, txb_mask, scan[c], bwl);
+ cost += av1_cost_bit(nz_map[coeff_ctx], is_nz);
+ }
+
+ if (is_nz) {
+ int ctx_ls[NUM_BASE_LEVELS] = { 0 };
+ int sign = (v < 0) ? 1 : 0;
+
+ // sign bit cost
+ if (c == 0) {
+ int dc_sign_ctx = txb_ctx->dc_sign_ctx;
+
+ cost += av1_cost_bit(xd->fc->dc_sign[plane_type][dc_sign_ctx], sign);
+ } else {
+ cost += av1_cost_bit(128, sign);
+ }
+
+ get_base_ctx_set(qcoeff, scan[c], bwl, ctx_ls);
+
+ int i;
+ for (i = 0; i < NUM_BASE_LEVELS; ++i) {
+ if (level <= i) continue;
+
+ if (level == i + 1) {
+ cost += av1_cost_bit(coeff_base[i][ctx_ls[i]], 1);
+ *cul_level += level;
+ continue;
+ }
+ cost += av1_cost_bit(coeff_base[i][ctx_ls[i]], 0);
+ }
+
+ if (level > NUM_BASE_LEVELS) {
+ int idx;
+ int ctx;
+ *cul_level += level;
+
+ ctx = get_level_ctx(qcoeff, scan[c], bwl);
+
+ for (idx = 0; idx < COEFF_BASE_RANGE; ++idx) {
+ if (level == (idx + 1 + NUM_BASE_LEVELS)) {
+ cost +=
+ av1_cost_bit(xd->fc->coeff_lps[tx_size][plane_type][ctx], 1);
+ break;
+ }
+ cost += av1_cost_bit(xd->fc->coeff_lps[tx_size][plane_type][ctx], 0);
+ }
+
+ if (idx >= COEFF_BASE_RANGE) {
+ // residual cost
+ int r = level - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
+ int ri = r;
+ int length = 0;
+
+ while (ri) {
+ ri >>= 1;
+ ++length;
+ }
+
+ for (ri = 0; ri < length - 1; ++ri) cost += av1_cost_bit(128, 0);
+
+ for (ri = length - 1; ri >= 0; --ri)
+ cost += av1_cost_bit(128, (r >> ri) & 0x01);
+ }
+ }
+
+ if (c < seg_eob) {
+ int eob_ctx = get_eob_ctx(qcoeff, scan[c], bwl);
+ cost += av1_cost_bit(xd->fc->eob_flag[tx_size][plane_type][eob_ctx],
+ c == (eob - 1));
+ }
+ }
+
+ txb_mask[scan[c]] = 1;
+ }
+
+ *cul_level = AOMMIN(63, *cul_level);
+ // DC value
+ set_dc_sign(cul_level, qcoeff[0]);
+
+ return cost;
+}
diff --git a/av1/encoder/encodetxb.h b/av1/encoder/encodetxb.h
index b6675f1..b3fe8e6 100644
--- a/av1/encoder/encodetxb.h
+++ b/av1/encoder/encodetxb.h
@@ -16,6 +16,7 @@
#include "av1/common/blockd.h"
#include "av1/common/onyxc_int.h"
#include "av1/common/txb_common.h"
+#include "av1/encoder/block.h"
#include "aom_dsp/bitwriter.h"
#ifdef __cplusplus
extern "C" {