Specify ANS window size at initialization

Change-Id: Ia1757d580dd230d9e743b1f8c3e87df164008684
diff --git a/aom_dsp/ansreader.h b/aom_dsp/ansreader.h
index 8a7788e..099d094 100644
--- a/aom_dsp/ansreader.h
+++ b/aom_dsp/ansreader.h
@@ -34,6 +34,7 @@
   uint32_t state;
 #if ANS_MAX_SYMBOLS
   int symbols_left;
+  int window_size;
 #endif
 #if CONFIG_ACCOUNTING
   Accounting *accounting;
@@ -134,6 +135,9 @@
 }
 
 static INLINE int ans_read_init(struct AnsDecoder *const ans,
+#if ANS_MAX_SYMBOLS
+                                int window_size,
+#endif
                                 const uint8_t *const buf, int offset) {
   unsigned x;
   if (offset < 1) return 1;
@@ -176,14 +180,19 @@
   ans->state += L_BASE;
   if (ans->state >= L_BASE * IO_BASE) return 1;
 #if ANS_MAX_SYMBOLS
-  ans->symbols_left = ANS_MAX_SYMBOLS;
+  ans->window_size = window_size;
+  ans->symbols_left = window_size;
 #endif
   return 0;
 }
 
 #if ANS_REVERSE
 static INLINE int ans_read_reinit(struct AnsDecoder *const ans) {
-  return ans_read_init(ans, ans->buf + ans->buf_offset, -ans->buf_offset);
+  return ans_read_init(ans,
+#if ANS_MAX_SYMBOLS
+                       ans->window_size,
+#endif
+                       ans->buf + ans->buf_offset, -ans->buf_offset);
 }
 #endif
 
diff --git a/aom_dsp/bitreader.h b/aom_dsp/bitreader.h
index 4ab8b5b..05216c8 100644
--- a/aom_dsp/bitreader.h
+++ b/aom_dsp/bitreader.h
@@ -68,13 +68,21 @@
 #endif
 
 static INLINE int aom_reader_init(aom_reader *r, const uint8_t *buffer,
-                                  size_t size, aom_decrypt_cb decrypt_cb,
+                                  size_t size,
+#if CONFIG_ANS && ANS_MAX_SYMBOLS
+                                  size_t window_size,
+#endif
+                                  aom_decrypt_cb decrypt_cb,
                                   void *decrypt_state) {
 #if CONFIG_ANS
   (void)decrypt_cb;
   (void)decrypt_state;
   if (size > INT_MAX) return 1;
-  return ans_read_init(r, buffer, (int)size);
+  return ans_read_init(r,
+#if ANS_MAX_SYMBOLS
+                       (int)window_size,
+#endif
+                       buffer, (int)size);
 #elif CONFIG_DAALA_EC
   (void)decrypt_cb;
   (void)decrypt_state;
diff --git a/aom_dsp/buf_ans.c b/aom_dsp/buf_ans.c
index c4ac643..c911983 100644
--- a/aom_dsp/buf_ans.c
+++ b/aom_dsp/buf_ans.c
@@ -16,9 +16,9 @@
 #include "aom/internal/aom_codec_internal.h"
 
 void aom_buf_ans_alloc(struct BufAnsCoder *c,
-                       struct aom_internal_error_info *error, int size_hint) {
+                       struct aom_internal_error_info *error, int size) {
   c->error = error;
-  c->size = size_hint;
+  c->size = size;
   AOM_CHECK_MEM_ERROR(error, c->buf, aom_malloc(c->size * sizeof(*c->buf)));
   // Initialize to overfull to trigger the assert in write.
   c->offset = c->size + 1;
@@ -30,6 +30,7 @@
   c->size = 0;
 }
 
+#if !ANS_MAX_SYMBOLS
 void aom_buf_ans_grow(struct BufAnsCoder *c) {
   struct buffered_ans_symbol *new_buf = NULL;
   int new_size = c->size * 2;
@@ -40,6 +41,7 @@
   c->buf = new_buf;
   c->size = new_size;
 }
+#endif
 
 void aom_buf_ans_flush(struct BufAnsCoder *const c) {
   int offset;
diff --git a/aom_dsp/buf_ans.h b/aom_dsp/buf_ans.h
index b315bd7..2a36a64 100644
--- a/aom_dsp/buf_ans.h
+++ b/aom_dsp/buf_ans.h
@@ -43,14 +43,24 @@
   int size;
   int offset;
   int output_bytes;
+#if ANS_MAX_SYMBOLS
+  int window_size;
+#endif
 };
 
+// Allocate a buffered ANS coder to store size symbols.
+// When ANS_MAX_SYMBOLS is turned on, the size is the fixed size of each ANS
+// partition.
+// When ANS_MAX_SYMBOLS is turned off, size is merely an initial hint and the
+// buffer will grow on demand
 void aom_buf_ans_alloc(struct BufAnsCoder *c,
-                       struct aom_internal_error_info *error, int size_hint);
+                       struct aom_internal_error_info *error, int hint);
 
 void aom_buf_ans_free(struct BufAnsCoder *c);
 
+#if !ANS_MAX_SYMBOLS
 void aom_buf_ans_grow(struct BufAnsCoder *c);
+#endif
 
 void aom_buf_ans_flush(struct BufAnsCoder *const c);
 
@@ -64,30 +74,34 @@
 static INLINE void buf_uabs_write(struct BufAnsCoder *const c, uint8_t val,
                                   AnsP8 prob) {
   assert(c->offset <= c->size);
+#if !ANS_MAX_SYMBOLS
   if (c->offset == c->size) {
     aom_buf_ans_grow(c);
   }
+#endif
   c->buf[c->offset].method = ANS_METHOD_UABS;
   c->buf[c->offset].val_start = val;
   c->buf[c->offset].prob = prob;
   ++c->offset;
 #if ANS_MAX_SYMBOLS
-  if (c->offset == ANS_MAX_SYMBOLS) aom_buf_ans_flush(c);
+  if (c->offset == c->size) aom_buf_ans_flush(c);
 #endif
 }
 
 static INLINE void buf_rans_write(struct BufAnsCoder *const c,
                                   const struct rans_sym *const sym) {
   assert(c->offset <= c->size);
+#if !ANS_MAX_SYMBOLS
   if (c->offset == c->size) {
     aom_buf_ans_grow(c);
   }
+#endif
   c->buf[c->offset].method = ANS_METHOD_RANS;
   c->buf[c->offset].val_start = sym->cum_prob;
   c->buf[c->offset].prob = sym->prob;
   ++c->offset;
 #if ANS_MAX_SYMBOLS
-  if (c->offset == ANS_MAX_SYMBOLS) aom_buf_ans_flush(c);
+  if (c->offset == c->size) aom_buf_ans_flush(c);
 #endif
 }
 
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 5f3b3b7..71160c7 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -2183,7 +2183,11 @@
     aom_internal_error(error_info, AOM_CODEC_CORRUPT_FRAME,
                        "Truncated packet or corrupt tile length");
 
-  if (aom_reader_init(r, data, read_size, decrypt_cb, decrypt_state))
+  if (aom_reader_init(r, data, read_size,
+#if CONFIG_ANS && ANS_MAX_SYMBOLS
+                      ANS_MAX_SYMBOLS,
+#endif
+                      decrypt_cb, decrypt_state))
     aom_internal_error(error_info, AOM_CODEC_MEM_ERROR,
                        "Failed to allocate bool decoder %d", 1);
 }
@@ -4149,8 +4153,11 @@
   int j;
 #endif
 
-  if (aom_reader_init(&r, data, partition_size, pbi->decrypt_cb,
-                      pbi->decrypt_state))
+  if (aom_reader_init(&r, data, partition_size,
+#if CONFIG_ANS && ANS_MAX_SYMBOLS
+                      ANS_MAX_SYMBOLS,
+#endif
+                      pbi->decrypt_cb, pbi->decrypt_state))
     aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
                        "Failed to allocate bool decoder 0");
 
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index f652fe0..a882a0b 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -791,7 +791,8 @@
     CHECK_MEM_ERROR(cm, cpi->tile_tok[0][0],
                     aom_calloc(tokens, sizeof(*cpi->tile_tok[0][0])));
 #if CONFIG_ANS
-    aom_buf_ans_alloc(&cpi->buf_ans, &cm->error, tokens);
+    aom_buf_ans_alloc(&cpi->buf_ans, &cm->error,
+                      ANS_MAX_SYMBOLS ? ANS_MAX_SYMBOLS : tokens);
 #endif  // CONFIG_ANS
   }
 
diff --git a/test/accounting_test.cc b/test/accounting_test.cc
index e0dfaa2..5f3defc 100644
--- a/test/accounting_test.cc
+++ b/test/accounting_test.cc
@@ -35,7 +35,11 @@
   }
   aom_stop_encode(&bw);
   aom_reader br;
-  aom_reader_init(&br, bw_buffer, bw.pos, NULL, NULL);
+  aom_reader_init(&br, bw_buffer, bw.pos,
+#if CONFIG_ANS && ANS_MAX_SYMBOLS
+                  1 << 16,
+#endif
+                  NULL, NULL);
 
   Accounting accounting;
   aom_accounting_init(&accounting);
diff --git a/test/ans_test.cc b/test/ans_test.cc
index 4c63352..760b541 100644
--- a/test/ans_test.cc
+++ b/test/ans_test.cc
@@ -26,6 +26,9 @@
 typedef std::vector<std::pair<uint8_t, bool> > PvVec;
 
 const int kPrintStats = 0;
+// When ANS is windowed use the window size, otherwise use a small value to
+// exercise the buffer growth code
+const int kBufAnsSize = ANS_MAX_SYMBOLS ? ANS_MAX_SYMBOLS : 100;
 
 PvVec abs_encode_build_vals(int iters) {
   PvVec ret;
@@ -49,7 +52,7 @@
 
 bool check_uabs(const PvVec &pv_vec, uint8_t *buf) {
   BufAnsCoder a;
-  aom_buf_ans_alloc(&a, NULL, 100);
+  aom_buf_ans_alloc(&a, NULL, kBufAnsSize);
   buf_ans_write_init(&a, buf);
 
   std::clock_t start = std::clock();
@@ -62,7 +65,12 @@
   aom_buf_ans_free(&a);
   bool okay = true;
   AnsDecoder d;
-  if (ans_read_init(&d, buf, offset)) return false;
+  if (ans_read_init(&d,
+#if ANS_MAX_SYMBOLS
+                    kBufAnsSize,
+#endif
+                    buf, offset))
+    return false;
   start = std::clock();
   for (PvVec::const_iterator it = pv_vec.begin(); it != pv_vec.end(); ++it) {
     okay = okay && (uabs_read(&d, 256 - it->first) != 0) == it->second;
@@ -115,7 +123,7 @@
 bool check_rans(const std::vector<int> &sym_vec, const rans_sym *const tab,
                 uint8_t *buf) {
   BufAnsCoder a;
-  aom_buf_ans_alloc(&a, NULL, 100);
+  aom_buf_ans_alloc(&a, NULL, kBufAnsSize);
   buf_ans_write_init(&a, buf);
   aom_cdf_prob dec_tab[kRansSymbols];
   rans_build_dec_tab(tab, dec_tab);
@@ -131,7 +139,12 @@
   aom_buf_ans_free(&a);
   bool okay = true;
   AnsDecoder d;
-  if (ans_read_init(&d, buf, offset)) return false;
+  if (ans_read_init(&d,
+#if ANS_MAX_SYMBOLS
+                    kBufAnsSize,
+#endif
+                    buf, offset))
+    return false;
   start = std::clock();
   for (std::vector<int>::const_iterator it = sym_vec.begin();
        it != sym_vec.end(); ++it) {