Add forward probability update for lv_map

The feature is implemented in the following two functions.
av1_write_txb_probs
av1_read_txb_probs

Change-Id: I0b646e17ec54d7a10a77a6853439217091455af1
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 8adcb15..3bbce0f 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -2849,6 +2849,7 @@
 #endif
 }
 
+#if !CONFIG_LV_MAP
 #if !CONFIG_PVQ && !(CONFIG_EC_ADAPT && CONFIG_NEW_TOKENSET)
 static void build_tree_distribution(AV1_COMP *cpi, TX_SIZE tx_size,
                                     av1_coeff_stats *coef_branch_ct,
@@ -3325,8 +3326,9 @@
   }
 #endif  // CONFIG_SUBFRAME_PROB_UPDATE
 }
-#endif
+#endif  // !(CONFIG_EC_ADAPT && CONFIG_NEW_TOKENSET)
 #endif  // !CONFIG_EC_ADAPT
+#endif  // !CONFIG_LV_MAP
 
 #if CONFIG_LOOP_RESTORATION
 static void encode_restoration_mode(AV1_COMMON *cm,
@@ -4601,11 +4603,16 @@
 #if !CONFIG_EC_ADAPT
   update_txfm_probs(cm, header_bc, counts);
 #endif
+#if CONFIG_LV_MAP
+  av1_write_txb_probs(cpi, header_bc);
+#else
 #if !CONFIG_PVQ
 #if !(CONFIG_EC_ADAPT && CONFIG_NEW_TOKENSET)
   update_coef_probs(cpi, header_bc);
 #endif  // !(CONFIG_EC_ADAPT && CONFIG_NEW_TOKENSET)
 #endif  // CONFIG_PVQ
+#endif  // CONFIG_LV_MAP
+
 #if CONFIG_VAR_TX
   update_txfm_partition_probs(cm, header_bc, counts, probwt);
 #endif
diff --git a/av1/encoder/encodetxb.c b/av1/encoder/encodetxb.c
index a1c8412..0971818 100644
--- a/av1/encoder/encodetxb.c
+++ b/av1/encoder/encodetxb.c
@@ -14,6 +14,7 @@
 #include "av1/common/pred_common.h"
 #include "av1/encoder/cost.h"
 #include "av1/encoder/encodetxb.h"
+#include "av1/encoder/subexp.h"
 #include "av1/encoder/tokenize.h"
 
 void av1_alloc_txb_buf(AV1_COMP *cpi) {
@@ -565,3 +566,133 @@
     assert(0);
   }
 }
+
+static void find_new_prob(unsigned int *branch_cnt, aom_prob *oldp,
+                          int *savings, int *update, aom_writer *const bc) {
+  const aom_prob upd = DIFF_UPDATE_PROB;
+  int u = 0;
+  aom_prob newp = get_binary_prob(branch_cnt[0], branch_cnt[1]);
+  int s = av1_prob_diff_update_savings_search(branch_cnt, *oldp, &newp, upd, 1);
+
+  if (s > 0 && newp != *oldp) u = 1;
+
+  if (u)
+    *savings += s - (int)(av1_cost_zero(upd));  // TODO(jingning): 1?
+  else
+    *savings -= (int)(av1_cost_zero(upd));
+
+  if (update) {
+    ++update[u];
+    return;
+  }
+
+  aom_write(bc, u, upd);
+  if (u) {
+    /* send/use new probability */
+    av1_write_prob_diff_update(bc, newp, *oldp);
+    *oldp = newp;
+  }
+}
+
+static void write_txb_probs(aom_writer *const bc, AV1_COMP *cpi,
+                            TX_SIZE tx_size) {
+  FRAME_CONTEXT *fc = cpi->common.fc;
+  FRAME_COUNTS *counts = cpi->td.counts;
+  int savings = 0;
+  int update[2] = { 0, 0 };
+  int plane, ctx, level;
+
+  for (ctx = 0; ctx < TXB_SKIP_CONTEXTS; ++ctx) {
+    find_new_prob(counts->txb_skip[tx_size][ctx], &fc->txb_skip[tx_size][ctx],
+                  &savings, update, bc);
+  }
+
+  for (plane = 0; plane < PLANE_TYPES; ++plane) {
+    for (ctx = 0; ctx < SIG_COEF_CONTEXTS; ++ctx) {
+      find_new_prob(counts->nz_map[tx_size][plane][ctx],
+                    &fc->nz_map[tx_size][plane][ctx], &savings, update, bc);
+    }
+  }
+
+  for (plane = 0; plane < PLANE_TYPES; ++plane) {
+    for (ctx = 0; ctx < EOB_COEF_CONTEXTS; ++ctx) {
+      find_new_prob(counts->eob_flag[tx_size][plane][ctx],
+                    &fc->eob_flag[tx_size][plane][ctx], &savings, update, bc);
+    }
+  }
+
+  for (level = 0; level < NUM_BASE_LEVELS; ++level) {
+    for (plane = 0; plane < PLANE_TYPES; ++plane) {
+      for (ctx = 0; ctx < COEFF_BASE_CONTEXTS; ++ctx) {
+        find_new_prob(counts->coeff_base[tx_size][plane][level][ctx],
+                      &fc->coeff_base[tx_size][plane][level][ctx], &savings,
+                      update, bc);
+      }
+    }
+  }
+
+  for (plane = 0; plane < PLANE_TYPES; ++plane) {
+    for (ctx = 0; ctx < LEVEL_CONTEXTS; ++ctx) {
+      find_new_prob(counts->coeff_lps[tx_size][plane][ctx],
+                    &fc->coeff_lps[tx_size][plane][ctx], &savings, update, bc);
+    }
+  }
+
+  // Decide if to update the model for this tx_size
+  if (update[1] == 0 || savings < 0) {
+    aom_write_bit(bc, 0);
+    return;
+  }
+  aom_write_bit(bc, 1);
+
+  for (ctx = 0; ctx < TXB_SKIP_CONTEXTS; ++ctx) {
+    find_new_prob(counts->txb_skip[tx_size][ctx], &fc->txb_skip[tx_size][ctx],
+                  &savings, NULL, bc);
+  }
+
+  for (plane = 0; plane < PLANE_TYPES; ++plane) {
+    for (ctx = 0; ctx < SIG_COEF_CONTEXTS; ++ctx) {
+      find_new_prob(counts->nz_map[tx_size][plane][ctx],
+                    &fc->nz_map[tx_size][plane][ctx], &savings, NULL, bc);
+    }
+  }
+
+  for (plane = 0; plane < PLANE_TYPES; ++plane) {
+    for (ctx = 0; ctx < EOB_COEF_CONTEXTS; ++ctx) {
+      find_new_prob(counts->eob_flag[tx_size][plane][ctx],
+                    &fc->eob_flag[tx_size][plane][ctx], &savings, NULL, bc);
+    }
+  }
+
+  for (level = 0; level < NUM_BASE_LEVELS; ++level) {
+    for (plane = 0; plane < PLANE_TYPES; ++plane) {
+      for (ctx = 0; ctx < COEFF_BASE_CONTEXTS; ++ctx) {
+        find_new_prob(counts->coeff_base[tx_size][plane][level][ctx],
+                      &fc->coeff_base[tx_size][plane][level][ctx], &savings,
+                      NULL, bc);
+      }
+    }
+  }
+
+  for (plane = 0; plane < PLANE_TYPES; ++plane) {
+    for (ctx = 0; ctx < LEVEL_CONTEXTS; ++ctx) {
+      find_new_prob(counts->coeff_lps[tx_size][plane][ctx],
+                    &fc->coeff_lps[tx_size][plane][ctx], &savings, NULL, bc);
+    }
+  }
+}
+
+void av1_write_txb_probs(AV1_COMP *cpi, aom_writer *w) {
+  const TX_MODE tx_mode = cpi->common.tx_mode;
+  const TX_SIZE max_tx_size = tx_mode_to_biggest_tx_size[tx_mode];
+  TX_SIZE tx_size;
+  int ctx, plane;
+
+  for (plane = 0; plane < PLANE_TYPES; ++plane)
+    for (ctx = 0; ctx < DC_SIGN_CONTEXTS; ++ctx)
+      av1_cond_prob_diff_update(w, &cpi->common.fc->dc_sign[plane][ctx],
+                                cpi->td.counts->dc_sign[plane][ctx], 1);
+
+  for (tx_size = TX_4X4; tx_size <= max_tx_size; ++tx_size)
+    write_txb_probs(w, cpi, tx_size);
+}
diff --git a/av1/encoder/encodetxb.h b/av1/encoder/encodetxb.h
index 15977b2..aee2e89 100644
--- a/av1/encoder/encodetxb.h
+++ b/av1/encoder/encodetxb.h
@@ -33,6 +33,7 @@
 void av1_update_txb_context(const AV1_COMP *cpi, ThreadData *td,
                             RUN_TYPE dry_run, BLOCK_SIZE bsize, int *rate,
                             const int mi_row, const int mi_col);
+void av1_write_txb_probs(AV1_COMP *cpi, aom_writer *w);
 #ifdef __cplusplus
 }
 #endif