Refactor lv-map rate cost estimation

Use the rate cost to replace the probability fetch. This improves
the encoding speed of level map by 10%. No coding stats change.

Change-Id: Iab0beac5da291eed50f657549667d4edffb4ead8
diff --git a/av1/encoder/block.h b/av1/encoder/block.h
index 2bdfff3..12d2aef 100644
--- a/av1/encoder/block.h
+++ b/av1/encoder/block.h
@@ -63,6 +63,17 @@
 typedef int av1_coeff_cost[PLANE_TYPES][REF_TYPES][COEF_BANDS][COEFF_CONTEXTS]
                           [TAIL_TOKENS];
 
+#if CONFIG_LV_MAP
+typedef struct {
+  int txb_skip_cost[TXB_SKIP_CONTEXTS][2];
+  int nz_map_cost[SIG_COEF_CONTEXTS][2];
+  int eob_cost[EOB_COEF_CONTEXTS][2];
+  int dc_sign_cost[DC_SIGN_CONTEXTS][2];
+  int base_cost[NUM_BASE_LEVELS][COEFF_BASE_CONTEXTS][2];
+  int lps_cost[LEVEL_CONTEXTS][2];
+} LV_MAP_COEFF_COST;
+#endif
+
 typedef struct {
   int_mv ref_mvs[MODE_CTX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
   int16_t mode_context[MODE_CTX_REF_FRAMES];
@@ -163,6 +174,10 @@
   int skip_chroma_rd;
 #endif
 
+#if CONFIG_LV_MAP
+  LV_MAP_COEFF_COST coeff_costs[TX_SIZES][PLANE_TYPES];
+#endif
+
   av1_coeff_cost token_head_costs[TX_SIZES];
   av1_coeff_cost token_tail_costs[TX_SIZES];
 
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index b157a69..b903884 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -4872,6 +4872,10 @@
 
   av1_setup_across_tile_boundary_info(cm, tile_info);
 
+#if CONFIG_LV_MAP
+  av1_fill_coeff_costs(&td->mb, cm->fc);
+#endif
+
   for (mi_row = tile_info->mi_row_start; mi_row < tile_info->mi_row_end;
        mi_row += cm->mib_size) {
     encode_rd_sb_row(cpi, td, this_tile, mi_row, &tok);
diff --git a/av1/encoder/encodetxb.c b/av1/encoder/encodetxb.c
index 68a39b3..f6ea47e 100644
--- a/av1/encoder/encodetxb.c
+++ b/av1/encoder/encodetxb.c
@@ -262,12 +262,13 @@
 }
 
 static INLINE int get_br_cost(tran_low_t abs_qc, int ctx,
-                              const aom_prob *coeff_lps) {
+                              const int coeff_lps[2]) {
   const tran_low_t min_level = 1 + NUM_BASE_LEVELS;
   const tran_low_t max_level = 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE;
+  (void)ctx;
   if (abs_qc >= min_level) {
-    const int cost0 = av1_cost_bit(coeff_lps[ctx], 0);
-    const int cost1 = av1_cost_bit(coeff_lps[ctx], 1);
+    const int cost0 = coeff_lps[0];
+    const int cost1 = coeff_lps[1];
     if (abs_qc >= max_level)
       return COEFF_BASE_RANGE * cost0;
     else
@@ -278,13 +279,13 @@
 }
 
 static INLINE int get_base_cost(tran_low_t abs_qc, int ctx,
-                                aom_prob (*coeff_base)[COEFF_BASE_CONTEXTS],
-                                int base_idx) {
+                                const int coeff_base[2], int base_idx) {
   const int level = base_idx + 1;
+  (void)ctx;
   if (abs_qc < level)
     return 0;
   else
-    return av1_cost_bit(coeff_base[base_idx][ctx], abs_qc == level);
+    return coeff_base[abs_qc == level];
 }
 
 int av1_cost_coeffs_txb(const AV1_COMP *const cpi, MACROBLOCK *x, int plane,
@@ -303,26 +304,23 @@
   int c, cost;
   const int seg_eob = AOMMIN(eob, tx_size_2d[tx_size] - 1);
   int txb_skip_ctx = txb_ctx->txb_skip_ctx;
-  aom_prob *nz_map = xd->fc->nz_map[txs_ctx][plane_type];
 
   const int bwl = b_width_log2_lookup[txsize_to_bsize[tx_size]] + 2;
   const int height = tx_size_high[tx_size];
 
-  aom_prob(*coeff_base)[COEFF_BASE_CONTEXTS] =
-      xd->fc->coeff_base[txs_ctx][plane_type];
-
   const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
   const int16_t *scan = scan_order->scan;
   const int16_t *iscan = scan_order->iscan;
 
+  LV_MAP_COEFF_COST *coeff_costs = &x->coeff_costs[txs_ctx][plane_type];
+
   cost = 0;
 
   if (eob == 0) {
-    cost = av1_cost_bit(xd->fc->txb_skip[txs_ctx][txb_skip_ctx], 1);
+    cost = coeff_costs->txb_skip_cost[txb_skip_ctx][1];
     return cost;
   }
-
-  cost = av1_cost_bit(xd->fc->txb_skip[txs_ctx][txb_skip_ctx], 0);
+  cost = coeff_costs->txb_skip_cost[txb_skip_ctx][0];
 
 #if CONFIG_TXK_SEL
   cost += av1_tx_type_cost(cm, x, xd, mbmi->sb_type, plane, tx_size, tx_type);
@@ -335,7 +333,7 @@
 
     if (c < seg_eob) {
       int coeff_ctx = get_nz_map_ctx(qcoeff, scan[c], bwl, height, iscan);
-      cost += av1_cost_bit(nz_map[coeff_ctx], is_nz);
+      cost += coeff_costs->nz_map_cost[coeff_ctx][is_nz];
     }
 
     if (is_nz) {
@@ -345,8 +343,7 @@
       // 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);
+        cost += coeff_costs->dc_sign_cost[dc_sign_ctx][sign];
       } else {
         cost += av1_cost_bit(128, sign);
       }
@@ -358,10 +355,10 @@
         if (level <= i) continue;
 
         if (level == i + 1) {
-          cost += av1_cost_bit(coeff_base[i][ctx_ls[i]], 1);
+          cost += coeff_costs->base_cost[i][ctx_ls[i]][1];
           continue;
         }
-        cost += av1_cost_bit(coeff_base[i][ctx_ls[i]], 0);
+        cost += coeff_costs->base_cost[i][ctx_ls[i]][0];
       }
 
       if (level > NUM_BASE_LEVELS) {
@@ -372,11 +369,10 @@
 
         for (idx = 0; idx < COEFF_BASE_RANGE; ++idx) {
           if (level == (idx + 1 + NUM_BASE_LEVELS)) {
-            cost +=
-                av1_cost_bit(xd->fc->coeff_lps[txs_ctx][plane_type][ctx], 1);
+            cost += coeff_costs->lps_cost[ctx][1];
             break;
           }
-          cost += av1_cost_bit(xd->fc->coeff_lps[txs_ctx][plane_type][ctx], 0);
+          cost += coeff_costs->lps_cost[ctx][0];
         }
 
         if (idx >= COEFF_BASE_RANGE) {
@@ -399,8 +395,7 @@
 
       if (c < seg_eob) {
         int eob_ctx = get_eob_ctx(qcoeff, scan[c], txs_ctx);
-        cost += av1_cost_bit(xd->fc->eob_flag[txs_ctx][plane_type][eob_ctx],
-                             c == (eob - 1));
+        cost += coeff_costs->eob_cost[eob_ctx][c == (eob - 1)];
       }
     }
   }
@@ -519,12 +514,12 @@
 }
 
 static INLINE int get_sign_bit_cost(tran_low_t qc, int coeff_idx,
-                                    const aom_prob *dc_sign_prob,
+                                    const int (*dc_sign_cost)[2],
                                     int dc_sign_ctx) {
   const int sign = (qc < 0) ? 1 : 0;
   // sign bit cost
   if (coeff_idx == 0) {
-    return av1_cost_bit(dc_sign_prob[dc_sign_ctx], sign);
+    return dc_sign_cost[dc_sign_ctx][sign];
   } else {
     return av1_cost_bit(128, sign);
   }
@@ -569,20 +564,20 @@
                  txb_info->eob, scan);
 }
 
-static INLINE aom_prob get_level_prob(int level, int coeff_idx,
-                                      const TxbCache *txb_cache,
-                                      const TxbProbs *txb_probs) {
+static INLINE const int *get_level_prob(int level, int coeff_idx,
+                                        const TxbCache *txb_cache,
+                                        const LV_MAP_COEFF_COST *txb_costs) {
   if (level == 0) {
     const int ctx = txb_cache->nz_ctx_arr[coeff_idx][0];
-    return txb_probs->nz_map[ctx];
+    return txb_costs->nz_map_cost[ctx];
   } else if (level >= 1 && level < 1 + NUM_BASE_LEVELS) {
     const int idx = level - 1;
     const int ctx = txb_cache->base_ctx_arr[idx][coeff_idx][0];
-    return txb_probs->coeff_base[idx][ctx];
+    return txb_costs->base_cost[idx][ctx];
   } else if (level >= 1 + NUM_BASE_LEVELS &&
              level < 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
     const int ctx = txb_cache->br_ctx_arr[coeff_idx][0];
-    return txb_probs->coeff_lps[ctx];
+    return txb_costs->lps_cost[ctx];
   } else if (level >= 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
     printf("get_level_prob does not support golomb\n");
     assert(0);
@@ -657,7 +652,7 @@
 
 static int try_neighbor_level_down_br(int coeff_idx, int nb_coeff_idx,
                                       const TxbCache *txb_cache,
-                                      const TxbProbs *txb_probs,
+                                      const LV_MAP_COEFF_COST *txb_costs,
                                       const TxbInfo *txb_info) {
   const tran_low_t qc = txb_info->qcoeff[coeff_idx];
   const tran_low_t abs_qc = abs(qc);
@@ -677,10 +672,11 @@
     const int row = coeff_idx >> txb_info->bwl;
     const int col = coeff_idx - (row << txb_info->bwl);
     const int ctx = txb_cache->br_ctx_arr[coeff_idx][0];
-    const int org_cost = get_br_cost(abs_qc, ctx, txb_probs->coeff_lps);
+    const int org_cost = get_br_cost(abs_qc, ctx, txb_costs->lps_cost[ctx]);
 
     const int new_ctx = get_br_ctx_from_count_mag(row, col, new_count, new_mag);
-    const int new_cost = get_br_cost(abs_qc, new_ctx, txb_probs->coeff_lps);
+    const int new_cost =
+        get_br_cost(abs_qc, new_ctx, txb_costs->lps_cost[new_ctx]);
     const int cost_diff = -org_cost + new_cost;
     return cost_diff;
   } else {
@@ -690,7 +686,7 @@
 
 static int try_neighbor_level_down_base(int coeff_idx, int nb_coeff_idx,
                                         const TxbCache *txb_cache,
-                                        const TxbProbs *txb_probs,
+                                        const LV_MAP_COEFF_COST *txb_costs,
                                         const TxbInfo *txb_info) {
   const tran_low_t qc = txb_info->qcoeff[coeff_idx];
   const tran_low_t abs_qc = abs(qc);
@@ -714,13 +710,13 @@
       const int row = coeff_idx >> txb_info->bwl;
       const int col = coeff_idx - (row << txb_info->bwl);
       const int ctx = txb_cache->base_ctx_arr[base_idx][coeff_idx][0];
-      const int org_cost =
-          get_base_cost(abs_qc, ctx, txb_probs->coeff_base, base_idx);
+      const int org_cost = get_base_cost(
+          abs_qc, ctx, txb_costs->base_cost[base_idx][ctx], base_idx);
 
       const int new_ctx =
           get_base_ctx_from_count_mag(row, col, new_count, new_mag, level);
-      const int new_cost =
-          get_base_cost(abs_qc, new_ctx, txb_probs->coeff_base, base_idx);
+      const int new_cost = get_base_cost(
+          abs_qc, new_ctx, txb_costs->base_cost[base_idx][new_ctx], base_idx);
       cost_diff += -org_cost + new_cost;
     }
   }
@@ -729,7 +725,7 @@
 
 static int try_neighbor_level_down_nz(int coeff_idx, int nb_coeff_idx,
                                       const TxbCache *txb_cache,
-                                      const TxbProbs *txb_probs,
+                                      const LV_MAP_COEFF_COST *txb_costs,
                                       TxbInfo *txb_info) {
   // assume eob doesn't change
   const tran_low_t qc = txb_info->qcoeff[coeff_idx];
@@ -750,8 +746,8 @@
     txb_info->qcoeff[nb_coeff_idx] = nb_coeff;
     const int ctx = txb_cache->nz_ctx_arr[coeff_idx][0];
     const int is_nz = abs_qc > 0;
-    const int org_cost = av1_cost_bit(txb_probs->nz_map[ctx], is_nz);
-    const int new_cost = av1_cost_bit(txb_probs->nz_map[new_ctx], is_nz);
+    const int org_cost = txb_costs->nz_map_cost[ctx][is_nz];
+    const int new_cost = txb_costs->nz_map_cost[new_ctx][is_nz];
     const int cost_diff = new_cost - org_cost;
     return cost_diff;
   } else {
@@ -761,7 +757,8 @@
 
 static int try_self_level_down(tran_low_t *low_coeff, int coeff_idx,
                                const TxbCache *txb_cache,
-                               const TxbProbs *txb_probs, TxbInfo *txb_info) {
+                               const LV_MAP_COEFF_COST *txb_costs,
+                               TxbInfo *txb_info) {
   const tran_low_t qc = txb_info->qcoeff[coeff_idx];
   if (qc == 0) {
     *low_coeff = 0;
@@ -772,44 +769,42 @@
   int cost_diff;
   if (*low_coeff == 0) {
     const int scan_idx = txb_info->scan_order->iscan[coeff_idx];
-    const aom_prob level_prob =
-        get_level_prob(abs_qc, coeff_idx, txb_cache, txb_probs);
-    const aom_prob low_level_prob =
-        get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_probs);
+    const int *level_cost =
+        get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
+    const int *low_level_cost =
+        get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
     if (scan_idx < txb_info->seg_eob) {
       // When level-0, we code the binary of abs_qc > level
       // but when level-k k > 0 we code the binary of abs_qc == level
       // That's why wee need this special treatment for level-0 map
       // TODO(angiebird): make leve-0 consistent to other levels
-      cost_diff = -av1_cost_bit(level_prob, 1) +
-                  av1_cost_bit(low_level_prob, 0) -
-                  av1_cost_bit(low_level_prob, 1);
+      cost_diff = -level_cost[1] + low_level_cost[0] - low_level_cost[1];
     } else {
-      cost_diff = -av1_cost_bit(level_prob, 1);
+      cost_diff = -level_cost[1];
     }
 
     if (scan_idx < txb_info->seg_eob) {
       const int eob_ctx =
           get_eob_ctx(txb_info->qcoeff, coeff_idx, txb_info->txs_ctx);
-      cost_diff -= av1_cost_bit(txb_probs->eob_flag[eob_ctx],
-                                scan_idx == (txb_info->eob - 1));
+      cost_diff -=
+          txb_costs->eob_cost[eob_ctx][scan_idx == (txb_info->eob - 1)];
     }
 
     const int sign_cost = get_sign_bit_cost(
-        qc, coeff_idx, txb_probs->dc_sign_prob, txb_info->txb_ctx->dc_sign_ctx);
+        qc, coeff_idx, txb_costs->dc_sign_cost, txb_info->txb_ctx->dc_sign_ctx);
     cost_diff -= sign_cost;
   } else if (abs_qc < 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
-    const aom_prob level_prob =
-        get_level_prob(abs_qc, coeff_idx, txb_cache, txb_probs);
-    const aom_prob low_level_prob =
-        get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_probs);
-    cost_diff = -av1_cost_bit(level_prob, 1) + av1_cost_bit(low_level_prob, 1) -
-                av1_cost_bit(low_level_prob, 0);
+    const int *level_cost =
+        get_level_prob(abs_qc, coeff_idx, txb_cache, txb_costs);
+    const int *low_level_cost =
+        get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
+
+    cost_diff = -level_cost[1] + low_level_cost[1] - low_level_cost[0];
   } else if (abs_qc == 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE) {
-    const aom_prob low_level_prob =
-        get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_probs);
-    cost_diff = -get_golomb_cost(abs_qc) + av1_cost_bit(low_level_prob, 1) -
-                av1_cost_bit(low_level_prob, 0);
+    const int *low_level_cost =
+        get_level_prob(abs(*low_coeff), coeff_idx, txb_cache, txb_costs);
+    cost_diff =
+        -get_golomb_cost(abs_qc) + low_level_cost[1] - low_level_cost[0];
   } else {
     assert(abs_qc > 1 + NUM_BASE_LEVELS + COEFF_BASE_RANGE);
     const tran_low_t abs_low_coeff = abs(*low_coeff);
@@ -833,7 +828,7 @@
 
 // TODO(angiebird): add static to this function once it's called
 int try_level_down(int coeff_idx, const TxbCache *txb_cache,
-                   const TxbProbs *txb_probs, TxbInfo *txb_info,
+                   const LV_MAP_COEFF_COST *txb_costs, TxbInfo *txb_info,
                    int (*cost_map)[COST_MAP_SIZE]) {
   if (cost_map) {
     for (int i = 0; i < COST_MAP_SIZE; ++i) av1_zero(cost_map[i]);
@@ -849,7 +844,7 @@
   const int scan_idx = iscan[coeff_idx];
   if (scan_idx < eob) {
     const int cost_diff = try_self_level_down(&low_coeff, coeff_idx, txb_cache,
-                                              txb_probs, txb_info);
+                                              txb_costs, txb_info);
     if (cost_map)
       cost_map[0 + COST_MAP_OFFSET][0 + COST_MAP_OFFSET] = cost_diff;
     accu_cost_diff += cost_diff;
@@ -870,7 +865,7 @@
       const int nb_scan_idx = iscan[nb_coeff_idx];
       if (nb_scan_idx < eob) {
         const int cost_diff = try_neighbor_level_down_nz(
-            nb_coeff_idx, coeff_idx, txb_cache, txb_probs, txb_info);
+            nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
         if (cost_map)
           cost_map[nb_row - row + COST_MAP_OFFSET]
                   [nb_col - col + COST_MAP_OFFSET] += cost_diff;
@@ -892,7 +887,7 @@
       const int nb_scan_idx = iscan[nb_coeff_idx];
       if (nb_scan_idx < eob) {
         const int cost_diff = try_neighbor_level_down_base(
-            nb_coeff_idx, coeff_idx, txb_cache, txb_probs, txb_info);
+            nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
         if (cost_map)
           cost_map[nb_row - row + COST_MAP_OFFSET]
                   [nb_col - col + COST_MAP_OFFSET] += cost_diff;
@@ -914,7 +909,7 @@
       const int nb_scan_idx = iscan[nb_coeff_idx];
       if (nb_scan_idx < eob) {
         const int cost_diff = try_neighbor_level_down_br(
-            nb_coeff_idx, coeff_idx, txb_cache, txb_probs, txb_info);
+            nb_coeff_idx, coeff_idx, txb_cache, txb_costs, txb_info);
         if (cost_map)
           cost_map[nb_row - row + COST_MAP_OFFSET]
                   [nb_col - col + COST_MAP_OFFSET] += cost_diff;
@@ -927,7 +922,7 @@
 }
 
 static int get_low_coeff_cost(int coeff_idx, const TxbCache *txb_cache,
-                              const TxbProbs *txb_probs,
+                              const LV_MAP_COEFF_COST *txb_costs,
                               const TxbInfo *txb_info) {
   const tran_low_t qc = txb_info->qcoeff[coeff_idx];
   const int abs_qc = abs(qc);
@@ -935,22 +930,21 @@
   int cost = 0;
   const int scan_idx = txb_info->scan_order->iscan[coeff_idx];
   if (scan_idx < txb_info->seg_eob) {
-    const aom_prob level_prob =
-        get_level_prob(0, coeff_idx, txb_cache, txb_probs);
-    cost += av1_cost_bit(level_prob, qc != 0);
+    const int *level_cost = get_level_prob(0, coeff_idx, txb_cache, txb_costs);
+    cost += level_cost[qc != 0];
   }
 
   if (qc != 0) {
     const int base_idx = 0;
     const int ctx = txb_cache->base_ctx_arr[base_idx][coeff_idx][0];
-    cost += get_base_cost(abs_qc, ctx, txb_probs->coeff_base, base_idx);
+    cost += get_base_cost(abs_qc, ctx, txb_costs->base_cost[base_idx][ctx],
+                          base_idx);
     if (scan_idx < txb_info->seg_eob) {
       const int eob_ctx =
           get_eob_ctx(txb_info->qcoeff, coeff_idx, txb_info->txs_ctx);
-      cost += av1_cost_bit(txb_probs->eob_flag[eob_ctx],
-                           scan_idx == (txb_info->eob - 1));
+      cost += txb_costs->eob_cost[eob_ctx][scan_idx == (txb_info->eob - 1)];
     }
-    cost += get_sign_bit_cost(qc, coeff_idx, txb_probs->dc_sign_prob,
+    cost += get_sign_bit_cost(qc, coeff_idx, txb_costs->dc_sign_cost,
                               txb_info->txb_ctx->dc_sign_ctx);
   }
   return cost;
@@ -963,7 +957,7 @@
 
 // TODO(angiebird): add static to this function once it's called
 int try_change_eob(int *new_eob, int coeff_idx, const TxbCache *txb_cache,
-                   const TxbProbs *txb_probs, TxbInfo *txb_info) {
+                   const LV_MAP_COEFF_COST *txb_costs, TxbInfo *txb_info) {
   assert(txb_info->eob > 0);
   const tran_low_t qc = txb_info->qcoeff[coeff_idx];
   const int abs_qc = abs(qc);
@@ -976,7 +970,7 @@
   const int scan_idx = iscan[coeff_idx];
   *new_eob = 0;
   int cost_diff = 0;
-  cost_diff -= get_low_coeff_cost(coeff_idx, txb_cache, txb_probs, txb_info);
+  cost_diff -= get_low_coeff_cost(coeff_idx, txb_cache, txb_costs, txb_info);
   // int coeff_cost =
   //     get_coeff_cost(qc, scan_idx, txb_info, txb_probs);
   // if (-cost_diff != coeff_cost) {
@@ -990,13 +984,13 @@
       *new_eob = si + 1;
       break;
     } else {
-      cost_diff -= get_low_coeff_cost(ci, txb_cache, txb_probs, txb_info);
+      cost_diff -= get_low_coeff_cost(ci, txb_cache, txb_costs, txb_info);
     }
   }
 
   const int org_eob = txb_info->eob;
   set_eob(txb_info, *new_eob);
-  cost_diff += try_level_down(coeff_idx, txb_cache, txb_probs, txb_info, NULL);
+  cost_diff += try_level_down(coeff_idx, txb_cache, txb_costs, txb_info, NULL);
   set_eob(txb_info, org_eob);
 
   if (*new_eob > 0) {
@@ -1004,12 +998,12 @@
     // need to lower down the qcoeff here
     const int eob_ctx =
         get_eob_ctx(txb_info->qcoeff, scan[*new_eob - 1], txb_info->txs_ctx);
-    cost_diff -= av1_cost_bit(txb_probs->eob_flag[eob_ctx], 0);
-    cost_diff += av1_cost_bit(txb_probs->eob_flag[eob_ctx], 1);
+    cost_diff -= txb_costs->eob_cost[eob_ctx][0];
+    cost_diff += txb_costs->eob_cost[eob_ctx][1];
   } else {
     const int txb_skip_ctx = txb_info->txb_ctx->txb_skip_ctx;
-    cost_diff -= av1_cost_bit(txb_probs->txb_skip[txb_skip_ctx], 0);
-    cost_diff += av1_cost_bit(txb_probs->txb_skip[txb_skip_ctx], 1);
+    cost_diff -= txb_costs->txb_skip_cost[txb_skip_ctx][0];
+    cost_diff += txb_costs->txb_skip_cost[txb_skip_ctx][1];
   }
   return cost_diff;
 }
@@ -1136,7 +1130,7 @@
 }
 
 static int get_coeff_cost(tran_low_t qc, int scan_idx, TxbInfo *txb_info,
-                          const TxbProbs *txb_probs) {
+                          const LV_MAP_COEFF_COST *txb_costs) {
   const TXB_CTX *txb_ctx = txb_info->txb_ctx;
   const int is_nz = (qc != 0);
   const tran_low_t abs_qc = abs(qc);
@@ -1147,11 +1141,11 @@
   if (scan_idx < txb_info->seg_eob) {
     int coeff_ctx = get_nz_map_ctx(txb_info->qcoeff, scan[scan_idx],
                                    txb_info->bwl, txb_info->height, iscan);
-    cost += av1_cost_bit(txb_probs->nz_map[coeff_ctx], is_nz);
+    cost += txb_costs->nz_map_cost[coeff_ctx][is_nz];
   }
 
   if (is_nz) {
-    cost += get_sign_bit_cost(qc, scan_idx, txb_probs->dc_sign_prob,
+    cost += get_sign_bit_cost(qc, scan_idx, txb_costs->dc_sign_cost,
                               txb_ctx->dc_sign_ctx);
 
     int ctx_ls[NUM_BASE_LEVELS] = { 0 };
@@ -1160,21 +1154,21 @@
 
     int i;
     for (i = 0; i < NUM_BASE_LEVELS; ++i) {
-      cost += get_base_cost(abs_qc, ctx_ls[i], txb_probs->coeff_base, i);
+      cost += get_base_cost(abs_qc, ctx_ls[i],
+                            txb_costs->base_cost[i][ctx_ls[i]], i);
     }
 
     if (abs_qc > NUM_BASE_LEVELS) {
       int ctx = get_br_ctx(txb_info->qcoeff, scan[scan_idx], txb_info->bwl,
                            txb_info->height);
-      cost += get_br_cost(abs_qc, ctx, txb_probs->coeff_lps);
+      cost += get_br_cost(abs_qc, ctx, txb_costs->lps_cost[ctx]);
       cost += get_golomb_cost(abs_qc);
     }
 
     if (scan_idx < txb_info->seg_eob) {
       int eob_ctx =
           get_eob_ctx(txb_info->qcoeff, scan[scan_idx], txb_info->txs_ctx);
-      cost += av1_cost_bit(txb_probs->eob_flag[eob_ctx],
-                           scan_idx == (txb_info->eob - 1));
+      cost += txb_costs->eob_cost[eob_ctx][scan_idx == (txb_info->eob - 1)];
     }
   }
   return cost;
@@ -1257,18 +1251,18 @@
 #endif
 
 // TODO(angiebird): make this static once it's called
-int get_txb_cost(TxbInfo *txb_info, const TxbProbs *txb_probs) {
+int get_txb_cost(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs) {
   int cost = 0;
   int txb_skip_ctx = txb_info->txb_ctx->txb_skip_ctx;
   const int16_t *scan = txb_info->scan_order->scan;
   if (txb_info->eob == 0) {
-    cost = av1_cost_bit(txb_probs->txb_skip[txb_skip_ctx], 1);
+    cost = txb_costs->txb_skip_cost[txb_skip_ctx][1];
     return cost;
   }
-  cost = av1_cost_bit(txb_probs->txb_skip[txb_skip_ctx], 0);
+  cost = txb_costs->txb_skip_cost[txb_skip_ctx][0];
   for (int c = 0; c < txb_info->eob; ++c) {
     tran_low_t qc = txb_info->qcoeff[scan[c]];
-    int coeff_cost = get_coeff_cost(qc, c, txb_info, txb_probs);
+    int coeff_cost = get_coeff_cost(qc, c, txb_info, txb_costs);
     cost += coeff_cost;
   }
   return cost;
@@ -1323,7 +1317,8 @@
 } LevelDownStats;
 
 void try_level_down_facade(LevelDownStats *stats, int scan_idx,
-                           const TxbCache *txb_cache, const TxbProbs *txb_probs,
+                           const TxbCache *txb_cache,
+                           const LV_MAP_COEFF_COST *txb_costs,
                            TxbInfo *txb_info) {
   const int16_t *scan = txb_info->scan_order->scan;
   const int coeff_idx = scan[scan_idx];
@@ -1350,10 +1345,10 @@
   stats->new_eob = txb_info->eob;
   if (scan_idx == txb_info->eob - 1 && abs(qc) == 1) {
     stats->cost_diff = try_change_eob(&stats->new_eob, coeff_idx, txb_cache,
-                                      txb_probs, txb_info);
+                                      txb_costs, txb_info);
   } else {
     stats->cost_diff =
-        try_level_down(coeff_idx, txb_cache, txb_probs, txb_info, NULL);
+        try_level_down(coeff_idx, txb_cache, txb_costs, txb_info, NULL);
 #if TEST_OPTIMIZE_TXB
     test_level_down(coeff_idx, txb_cache, txb_probs, txb_info);
 #endif
@@ -1363,7 +1358,7 @@
   return;
 }
 
-static int optimize_txb(TxbInfo *txb_info, const TxbProbs *txb_probs,
+static int optimize_txb(TxbInfo *txb_info, const LV_MAP_COEFF_COST *txb_costs,
                         TxbCache *txb_cache, int dry_run) {
   int update = 0;
   if (txb_info->eob == 0) return update;
@@ -1402,7 +1397,7 @@
     tran_low_t qc = txb_info->qcoeff[coeff_idx];
     if (abs(qc) == 1) {
       LevelDownStats stats;
-      try_level_down_facade(&stats, si, txb_cache, txb_probs, txb_info);
+      try_level_down_facade(&stats, si, txb_cache, txb_costs, txb_info);
       if (stats.update) {
         update = 1;
         cost_diff += stats.cost_diff;
@@ -1417,7 +1412,7 @@
   // backward optimize the level-k map
   for (int si = txb_info->eob - 1; si >= 0; --si) {
     LevelDownStats stats;
-    try_level_down_facade(&stats, si, txb_cache, txb_probs, txb_info);
+    try_level_down_facade(&stats, si, txb_cache, txb_costs, txb_info);
     const int coeff_idx = scan[si];
     if (stats.update) {
 #if TEST_OPTIMIZE_TXB
@@ -1478,25 +1473,12 @@
   const tran_low_t *tcoeff = BLOCK_OFFSET(p->coeff, block);
   const int16_t *dequant = pd->dequant;
   const int seg_eob = AOMMIN(eob, tx_size_2d[tx_size] - 1);
-  const aom_prob *nz_map = xd->fc->nz_map[txs_ctx][plane_type];
-
   const int bwl = b_width_log2_lookup[txsize_to_bsize[tx_size]] + 2;
   const int stride = 1 << bwl;
   const int height = tx_size_high[tx_size];
-  aom_prob(*coeff_base)[COEFF_BASE_CONTEXTS] =
-      xd->fc->coeff_base[txs_ctx][plane_type];
-
-  const aom_prob *coeff_lps = xd->fc->coeff_lps[txs_ctx][plane_type];
-
   const int is_inter = is_inter_block(mbmi);
   const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
-
-  const TxbProbs txb_probs = { xd->fc->dc_sign[plane_type],
-                               nz_map,
-                               coeff_base,
-                               coeff_lps,
-                               xd->fc->eob_flag[txs_ctx][plane_type],
-                               xd->fc->txb_skip[txs_ctx] };
+  const LV_MAP_COEFF_COST txb_costs = x->coeff_costs[txs_ctx][plane_type];
 
   const int shift = av1_get_tx_scale(tx_size);
   const int64_t rdmult =
@@ -1509,7 +1491,7 @@
   TxbCache txb_cache;
   gen_txb_cache(&txb_cache, &txb_info);
 
-  const int update = optimize_txb(&txb_info, &txb_probs, &txb_cache, 0);
+  const int update = optimize_txb(&txb_info, &txb_costs, &txb_cache, 0);
   if (update) p->eobs[block] = txb_info.eob;
   return txb_info.eob;
 }
diff --git a/av1/encoder/rd.c b/av1/encoder/rd.c
index 073b714..056d093 100644
--- a/av1/encoder/rd.c
+++ b/av1/encoder/rd.c
@@ -430,6 +430,41 @@
   x->nmvjointcost = x->nmv_vec_cost[nmv_ctx];
 }
 
+#if CONFIG_LV_MAP
+static void get_rate_cost(aom_prob p, int cost[2]) {
+  cost[0] = av1_cost_bit(p, 0);
+  cost[1] = av1_cost_bit(p, 1);
+}
+
+void av1_fill_coeff_costs(MACROBLOCK *x, FRAME_CONTEXT *fc) {
+  for (TX_SIZE tx_size = 0; tx_size < TX_SIZES; ++tx_size) {
+    for (int plane = 0; plane < PLANE_TYPES; ++plane) {
+      LV_MAP_COEFF_COST *pcost = &x->coeff_costs[tx_size][plane];
+
+      for (int ctx = 0; ctx < TXB_SKIP_CONTEXTS; ++ctx)
+        get_rate_cost(fc->txb_skip[tx_size][ctx], pcost->txb_skip_cost[ctx]);
+
+      for (int ctx = 0; ctx < SIG_COEF_CONTEXTS; ++ctx)
+        get_rate_cost(fc->nz_map[tx_size][plane][ctx], pcost->nz_map_cost[ctx]);
+
+      for (int ctx = 0; ctx < EOB_COEF_CONTEXTS; ++ctx)
+        get_rate_cost(fc->eob_flag[tx_size][plane][ctx], pcost->eob_cost[ctx]);
+
+      for (int ctx = 0; ctx < DC_SIGN_CONTEXTS; ++ctx)
+        get_rate_cost(fc->dc_sign[plane][ctx], pcost->dc_sign_cost[ctx]);
+
+      for (int layer = 0; layer < NUM_BASE_LEVELS; ++layer)
+        for (int ctx = 0; ctx < COEFF_BASE_CONTEXTS; ++ctx)
+          get_rate_cost(fc->coeff_base[tx_size][plane][layer][ctx],
+                        pcost->base_cost[layer][ctx]);
+
+      for (int ctx = 0; ctx < LEVEL_CONTEXTS; ++ctx)
+        get_rate_cost(fc->coeff_lps[tx_size][plane][ctx], pcost->lps_cost[ctx]);
+    }
+  }
+}
+#endif
+
 void av1_fill_token_costs_from_cdf(av1_coeff_cost *cost,
                                    coeff_cdf_model (*cdf)[PLANE_TYPES]) {
   for (int tx = 0; tx < TX_SIZES; ++tx) {
diff --git a/av1/encoder/rd.h b/av1/encoder/rd.h
index 3c9646f..dbafc7b 100644
--- a/av1/encoder/rd.h
+++ b/av1/encoder/rd.h
@@ -712,6 +712,10 @@
 void av1_fill_mode_rates(AV1_COMMON *const cm, MACROBLOCK *x,
                          FRAME_CONTEXT *fc);
 
+#if CONFIG_LV_MAP
+void av1_fill_coeff_costs(MACROBLOCK *x, FRAME_CONTEXT *fc);
+#endif
+
 void av1_fill_token_costs_from_cdf(av1_coeff_cost *cost,
                                    coeff_cdf_model (*cdf)[PLANE_TYPES]);