Fix tree to cdf index mapping

This fixes the mis-aligned cdf model derived from tree based
model. It resolves the compression performance regression in
dual filter, intra mode, inter mode, and transform block type
coding, when ec-multisymbol is enabled by default.

With dual filter enabled, the performance regression was 3.6%
loss for lowres. This fix brings the performance gains back to 1%
gains.

Change-Id: I80f5485386045908c152c9c11eeacbc650f1e324
diff --git a/aom_dsp/prob.c b/aom_dsp/prob.c
index 75a0d3f..9fbf0d1 100644
--- a/aom_dsp/prob.c
+++ b/aom_dsp/prob.c
@@ -215,16 +215,25 @@
 /* This code assumes that tree contains as unique leaf nodes the integer values
     0 to len - 1 and produces the forward and inverse mapping tables in ind[]
     and inv[] respectively. */
-void av1_indices_from_tree(int *ind, int *inv, int len,
-                           const aom_tree_index *tree) {
-  int i;
-  int index;
-  for (i = index = 0; i < TREE_SIZE(len); i++) {
-    const aom_tree_index j = tree[i];
-    if (j <= 0) {
-      inv[index] = -j;
-      ind[-j] = index++;
+static void tree_to_index(int *stack_index, int *ind, int *inv,
+                          const aom_tree_index *tree, int value, int index) {
+  value *= 2;
+
+  do {
+    const aom_tree_index content = tree[index];
+    ++index;
+    if (content <= 0) {
+      inv[*stack_index] = -content;
+      ind[-content] = *stack_index;
+      ++(*stack_index);
+    } else {
+      tree_to_index(stack_index, ind, inv, tree, value, content);
     }
-  }
+  } while (++value & 1);
+}
+
+void av1_indices_from_tree(int *ind, int *inv, const aom_tree_index *tree) {
+  int stack_index = 0;
+  tree_to_index(&stack_index, ind, inv, tree, 0, 0);
 }
 #endif
diff --git a/aom_dsp/prob.h b/aom_dsp/prob.h
index a7fc544..9921623 100644
--- a/aom_dsp/prob.h
+++ b/aom_dsp/prob.h
@@ -139,8 +139,7 @@
     }                                                  \
   } while (0)
 
-void av1_indices_from_tree(int *ind, int *inv, int len,
-                           const aom_tree_index *tree);
+void av1_indices_from_tree(int *ind, int *inv, const aom_tree_index *tree);
 #endif
 
 DECLARE_ALIGNED(16, extern const uint8_t, aom_norm[256]);
diff --git a/av1/decoder/decoder.c b/av1/decoder/decoder.c
index 5a74a3b..1bd9108 100644
--- a/av1/decoder/decoder.c
+++ b/av1/decoder/decoder.c
@@ -51,23 +51,22 @@
 #endif  // CONFIG_EXT_INTER
     init_done = 1;
 #if CONFIG_EC_MULTISYMBOL
-    av1_indices_from_tree(av1_intra_mode_ind, av1_intra_mode_inv, INTRA_MODES,
+    av1_indices_from_tree(av1_intra_mode_ind, av1_intra_mode_inv,
                           av1_intra_mode_tree);
     av1_indices_from_tree(av1_switchable_interp_ind, av1_switchable_interp_inv,
-                          SWITCHABLE_FILTERS, av1_switchable_interp_tree);
+                          av1_switchable_interp_tree);
 #if CONFIG_EXT_TX
     int s;
     for (s = 1; s < EXT_TX_SETS_INTRA; ++s)
       av1_indices_from_tree(av1_ext_tx_intra_ind[s], av1_ext_tx_intra_inv[s],
-                            ext_tx_cnt_intra[s], av1_ext_tx_intra_tree[s]);
+                            av1_ext_tx_intra_tree[s]);
     for (s = 1; s < EXT_TX_SETS_INTER; ++s)
       av1_indices_from_tree(av1_ext_tx_inter_ind[s], av1_ext_tx_inter_inv[s],
-                            ext_tx_cnt_inter[s], av1_ext_tx_inter_tree[s]);
+                            av1_ext_tx_inter_tree[s]);
 #else
-    av1_indices_from_tree(av1_ext_tx_ind, av1_ext_tx_inv, TX_TYPES,
-                          av1_ext_tx_tree);
+    av1_indices_from_tree(av1_ext_tx_ind, av1_ext_tx_inv, av1_ext_tx_tree);
 #endif
-    av1_indices_from_tree(av1_inter_mode_ind, av1_inter_mode_inv, INTER_MODES,
+    av1_indices_from_tree(av1_inter_mode_ind, av1_inter_mode_inv,
                           av1_inter_mode_tree);
 #endif
   }
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 2d79031..55fdbec 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -192,24 +192,23 @@
       SWITCHABLE_FILTERS are not consecutive, e.g., 0, 1, 2, 3, 4, when doing
       an in-order traversal of the av1_switchable_interp_tree structure. */
   av1_indices_from_tree(av1_switchable_interp_ind, av1_switchable_interp_inv,
-                        SWITCHABLE_FILTERS, av1_switchable_interp_tree);
+                        av1_switchable_interp_tree);
 /* This hack is necessary because the four TX_TYPES are not consecutive,
     e.g., 0, 1, 2, 3, when doing an in-order traversal of the av1_ext_tx_tree
     structure. */
 #if CONFIG_EXT_TX
   for (s = 1; s < EXT_TX_SETS_INTRA; ++s)
     av1_indices_from_tree(av1_ext_tx_intra_ind[s], av1_ext_tx_intra_inv[s],
-                          ext_tx_cnt_intra[s], av1_ext_tx_intra_tree[s]);
+                          av1_ext_tx_intra_tree[s]);
   for (s = 1; s < EXT_TX_SETS_INTER; ++s)
     av1_indices_from_tree(av1_ext_tx_inter_ind[s], av1_ext_tx_inter_inv[s],
-                          ext_tx_cnt_inter[s], av1_ext_tx_inter_tree[s]);
+                          av1_ext_tx_inter_tree[s]);
 #else
-  av1_indices_from_tree(av1_ext_tx_ind, av1_ext_tx_inv, TX_TYPES,
-                        av1_ext_tx_tree);
+  av1_indices_from_tree(av1_ext_tx_ind, av1_ext_tx_inv, av1_ext_tx_tree);
 #endif
-  av1_indices_from_tree(av1_intra_mode_ind, av1_intra_mode_inv, INTRA_MODES,
+  av1_indices_from_tree(av1_intra_mode_ind, av1_intra_mode_inv,
                         av1_intra_mode_tree);
-  av1_indices_from_tree(av1_inter_mode_ind, av1_inter_mode_inv, INTER_MODES,
+  av1_indices_from_tree(av1_inter_mode_ind, av1_inter_mode_inv,
                         av1_inter_mode_tree);
 #endif
 }