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
}