Bit accounting.

This patch adds bit account infrastructure to the bit reader API.
When configured with --enable-accounting, every bit reader API
function records the number of bits necessary to decoding a symbol.
Accounting symbol entries are collected in global accounting data
structure, that can be used to understand exactly where bits are
spent (http://aomanalyzer.org). The data structure is cleared and
reused each frame to reduce memory usage. When configured without
--enable-accounting, bit accounting does not incur any runtime
overhead.

All aom_read_xxx functions now have an additional string parameter
that specifies the symbol name. By default, the ACCT_STR macro is
used (which expands to __func__). For more precise accounting,
these should be replaced with more descriptive names.

Change-Id: Ia2e1343cb842c9391b12b77272587dfbe307a56d
diff --git a/aom_dsp/bitreader.h b/aom_dsp/bitreader.h
index ee34275..68e1339 100644
--- a/aom_dsp/bitreader.h
+++ b/aom_dsp/bitreader.h
@@ -28,6 +28,29 @@
 #include "aom_dsp/prob.h"
 #include "av1/common/odintrin.h"
 
+#if CONFIG_ACCOUNTING
+#include "av1/common/accounting.h"
+#define ACCT_STR_NAME acct_str
+#define ACCT_STR_PARAM , const char *ACCT_STR_NAME
+#define ACCT_STR_ARG(s) , s
+#else
+#define ACCT_STR_PARAM
+#define ACCT_STR_ARG(s)
+#endif
+
+#define aom_read(r, prob, ACCT_STR_NAME) \
+  aom_read_(r, prob ACCT_STR_ARG(ACCT_STR_NAME))
+#define aom_read_bit(r, ACCT_STR_NAME) \
+  aom_read_bit_(r ACCT_STR_ARG(ACCT_STR_NAME))
+#define aom_read_tree(r, tree, probs, ACCT_STR_NAME) \
+  aom_read_tree_(r, tree, probs ACCT_STR_ARG(ACCT_STR_NAME))
+#define aom_read_literal(r, bits, ACCT_STR_NAME) \
+  aom_read_literal_(r, bits ACCT_STR_ARG(ACCT_STR_NAME))
+#define aom_read_tree_bits(r, tree, probs, ACCT_STR_NAME) \
+  aom_read_tree_bits_(r, tree, probs ACCT_STR_ARG(ACCT_STR_NAME))
+#define aom_read_symbol(r, cdf, nsymbs, ACCT_STR_NAME) \
+  aom_read_symbol_(r, cdf, nsymbs ACCT_STR_ARG(ACCT_STR_NAME))
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -105,75 +128,100 @@
 #endif
 }
 
-static INLINE int aom_read(aom_reader *r, int prob) {
+#if CONFIG_ACCOUNTING
+static INLINE void aom_process_accounting(const aom_reader *r ACCT_STR_PARAM) {
+  if (r->accounting != NULL) {
+    uint32_t tell_frac;
+    tell_frac = aom_reader_tell_frac(r);
+    aom_accounting_record(r->accounting, ACCT_STR_NAME,
+                          tell_frac - r->accounting->last_tell_frac);
+    r->accounting->last_tell_frac = tell_frac;
+  }
+}
+#endif
+
+static INLINE int aom_read_(aom_reader *r, int prob ACCT_STR_PARAM) {
+  int ret;
 #if CONFIG_ANS
-  return uabs_read(r, prob);
+  ret = uabs_read(r, prob);
 #elif CONFIG_DAALA_EC
-  return aom_daala_read(r, prob);
+  ret = aom_daala_read(r, prob);
 #else
-  return aom_dk_read(r, prob);
+  ret = aom_dk_read(r, prob);
 #endif
+#if CONFIG_ACCOUNTING
+  if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
+#endif
+  return ret;
 }
 
-static INLINE int aom_read_bit(aom_reader *r) {
+static INLINE int aom_read_bit_(aom_reader *r ACCT_STR_PARAM) {
+  int ret;
 #if CONFIG_ANS
-  return uabs_read_bit(r);  // Non trivial optimization at half probability
+  ret = uabs_read_bit(r);  // Non trivial optimization at half probability
 #else
-  return aom_read(r, 128);  // aom_prob_half
+  ret = aom_read(r, 128, NULL);  // aom_prob_half
 #endif
+#if CONFIG_ACCOUNTING
+  if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
+#endif
+  return ret;
 }
 
-static INLINE int aom_read_literal(aom_reader *r, int bits) {
+static INLINE int aom_read_literal_(aom_reader *r, int bits ACCT_STR_PARAM) {
   int literal = 0, bit;
 
-  for (bit = bits - 1; bit >= 0; bit--) literal |= aom_read_bit(r) << bit;
-
+  for (bit = bits - 1; bit >= 0; bit--) literal |= aom_read_bit(r, NULL) << bit;
+#if CONFIG_ACCOUNTING
+  if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
+#endif
   return literal;
 }
 
-static INLINE int aom_read_tree_bits(aom_reader *r, const aom_tree_index *tree,
-                                     const aom_prob *probs) {
+static INLINE int aom_read_tree_bits_(aom_reader *r, const aom_tree_index *tree,
+                                      const aom_prob *probs ACCT_STR_PARAM) {
   aom_tree_index i = 0;
 
-  while ((i = tree[i + aom_read(r, probs[i >> 1])]) > 0) continue;
-
+  while ((i = tree[i + aom_read(r, probs[i >> 1], NULL)]) > 0) continue;
+#if CONFIG_ACCOUNTING
+  if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
+#endif
   return -i;
 }
 
-static INLINE int aom_read_tree(aom_reader *r, const aom_tree_index *tree,
-                                const aom_prob *probs) {
+static INLINE int aom_read_tree_(aom_reader *r, const aom_tree_index *tree,
+                                 const aom_prob *probs ACCT_STR_PARAM) {
+  int ret;
 #if CONFIG_DAALA_EC
-  return daala_read_tree_bits(r, tree, probs);
+  ret = daala_read_tree_bits(r, tree, probs);
 #else
-  return aom_read_tree_bits(r, tree, probs);
+  ret = aom_read_tree_bits(r, tree, probs, NULL);
 #endif
+#if CONFIG_ACCOUNTING
+  if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
+#endif
+  return ret;
 }
 
-static INLINE int aom_read_symbol(aom_reader *r, const aom_cdf_prob *cdf,
-                                  int nsymbs) {
+static INLINE int aom_read_symbol_(aom_reader *r, const aom_cdf_prob *cdf,
+                                   int nsymbs ACCT_STR_PARAM) {
+  int ret;
 #if CONFIG_ANS
   (void)nsymbs;
-  return rans_read(r, cdf);
+  ret = rans_read(r, cdf);
+#elif CONFIG_DAALA_EC
+  ret = daala_read_symbol(r, cdf, nsymbs);
 #else
   (void)r;
   (void)cdf;
   (void)nsymbs;
   assert(0 && "Unsupported bitreader operation");
-  return -1;
+  ret = -1;
 #endif
-}
-
-static INLINE int aom_read_tree_cdf(aom_reader *r, const uint16_t *cdf,
-                                    int nsymbs) {
-#if CONFIG_DAALA_EC
-  return daala_read_symbol(r, cdf, nsymbs);
-#else
-  (void)r;
-  (void)cdf;
-  (void)nsymbs;
-  assert(0 && "Unsupported bitreader operation");
-  return -1;
+#if CONFIG_ACCOUNTING
+  if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
 #endif
+  return ret;
 }
 
 #ifdef __cplusplus