Use uABS instead of duck bool in the ANS experiment.

Change-Id: I3ba5f7061f7a76a76e5c906132f33d4110a0dd87
diff --git a/aom_dsp/bitreader.h b/aom_dsp/bitreader.h
index 0b7930f..6055200 100644
--- a/aom_dsp/bitreader.h
+++ b/aom_dsp/bitreader.h
@@ -18,7 +18,9 @@
 #include "./aom_config.h"
 #include "aom/aomdx.h"
 #include "aom/aom_integer.h"
-#if CONFIG_DAALA_EC
+#if CONFIG_ANS
+#include "aom_dsp/ansreader.h"
+#elif CONFIG_DAALA_EC
 #include "aom_dsp/daalaboolreader.h"
 #else
 #include "aom_dsp/dkboolreader.h"
@@ -30,7 +32,9 @@
 extern "C" {
 #endif
 
-#if CONFIG_DAALA_EC
+#if CONFIG_ANS
+typedef struct AnsDecoder aom_reader;
+#elif CONFIG_DAALA_EC
 typedef struct daala_reader aom_reader;
 #else
 typedef struct aom_dk_reader aom_reader;
@@ -39,7 +43,12 @@
 static INLINE int aom_reader_init(aom_reader *r, const uint8_t *buffer,
                                   size_t size, aom_decrypt_cb decrypt_cb,
                                   void *decrypt_state) {
-#if CONFIG_DAALA_EC
+#if CONFIG_ANS
+  (void)decrypt_cb;
+  (void)decrypt_state;
+  assert(size <= INT_MAX);
+  return ans_read_init(r, buffer, size);
+#elif CONFIG_DAALA_EC
   (void)decrypt_cb;
   (void)decrypt_state;
   return aom_daala_reader_init(r, buffer, size);
@@ -49,7 +58,11 @@
 }
 
 static INLINE const uint8_t *aom_reader_find_end(aom_reader *r) {
-#if CONFIG_DAALA_EC
+#if CONFIG_ANS
+  (void)r;
+  assert(0 && "Use the raw buffer size with ANS");
+  return NULL;
+#elif CONFIG_DAALA_EC
   return aom_daala_reader_find_end(r);
 #else
   return aom_dk_reader_find_end(r);
@@ -57,7 +70,9 @@
 }
 
 static INLINE int aom_reader_has_error(aom_reader *r) {
-#if CONFIG_DAALA_EC
+#if CONFIG_ANS
+  return ans_reader_has_error(r);
+#elif CONFIG_DAALA_EC
   return aom_daala_reader_has_error(r);
 #else
   return aom_dk_reader_has_error(r);
@@ -65,7 +80,9 @@
 }
 
 static INLINE int aom_read(aom_reader *r, int prob) {
-#if CONFIG_DAALA_EC
+#if CONFIG_ANS
+  return uabs_read(r, prob);
+#elif CONFIG_DAALA_EC
   return aom_daala_read(r, prob);
 #else
   return aom_dk_read(r, prob);
@@ -73,7 +90,11 @@
 }
 
 static INLINE int aom_read_bit(aom_reader *r) {
+#if CONFIG_ANS
+  return uabs_read_bit(r);  // Non trivial optimization at half probability
+#else
   return aom_read(r, 128);  // aom_prob_half
+#endif
 }
 
 static INLINE int aom_read_literal(aom_reader *r, int bits) {
diff --git a/aom_dsp/bitwriter.h b/aom_dsp/bitwriter.h
index da17f9c..b8b9d84 100644
--- a/aom_dsp/bitwriter.h
+++ b/aom_dsp/bitwriter.h
@@ -14,7 +14,9 @@
 
 #include <assert.h>
 #include "./aom_config.h"
-#if CONFIG_DAALA_EC
+#if CONFIG_ANS
+#include "aom_dsp/buf_ans.h"
+#elif CONFIG_DAALA_EC
 #include "aom_dsp/daalaboolwriter.h"
 #else
 #include "aom_dsp/dkboolwriter.h"
@@ -25,14 +27,20 @@
 extern "C" {
 #endif
 
-#if CONFIG_DAALA_EC
+#if CONFIG_ANS
+typedef struct BufAnsCoder aom_writer;
+#elif CONFIG_DAALA_EC
 typedef struct daala_writer aom_writer;
 #else
 typedef struct aom_dk_writer aom_writer;
 #endif
 
 static INLINE void aom_start_encode(aom_writer *bc, uint8_t *buffer) {
-#if CONFIG_DAALA_EC
+#if CONFIG_ANS
+  (void)bc;
+  (void)buffer;
+  assert(0 && "buf_ans requires a more complicated startup procedure");
+#elif CONFIG_DAALA_EC
   aom_daala_start_encode(bc, buffer);
 #else
   aom_dk_start_encode(bc, buffer);
@@ -40,7 +48,10 @@
 }
 
 static INLINE void aom_stop_encode(aom_writer *bc) {
-#if CONFIG_DAALA_EC
+#if CONFIG_ANS
+  (void)bc;
+  assert(0 && "buf_ans requires a more complicated shutdown procedure");
+#elif CONFIG_DAALA_EC
   aom_daala_stop_encode(bc);
 #else
   aom_dk_stop_encode(bc);
@@ -48,7 +59,9 @@
 }
 
 static INLINE void aom_write(aom_writer *br, int bit, int probability) {
-#if CONFIG_DAALA_EC
+#if CONFIG_ANS
+  buf_uabs_write(br, bit, probability);
+#elif CONFIG_DAALA_EC
   aom_daala_write(br, bit, probability);
 #else
   aom_dk_write(br, bit, probability);
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 6066dfd..912c3e5 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -1329,7 +1329,11 @@
 
   if (cm->frame_parallel_decode)
     av1_frameworker_broadcast(pbi->cur_buf, INT_MAX);
+#if CONFIG_ANS
+  return data_end;
+#else
   return aom_reader_find_end(&tile_data->bit_reader);
+#endif
 }
 
 static int tile_worker_hook(TileWorkerData *const tile_data,
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 3ef0374..e5f3659 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -1332,7 +1332,12 @@
 static size_t encode_tiles(AV1_COMP *cpi, uint8_t *data_ptr,
                            unsigned int *max_tile_sz) {
   AV1_COMMON *const cm = &cpi->common;
+#if CONFIG_ANS
+  struct AnsCoder ans;
+  struct BufAnsCoder *buf_ans = &cpi->buf_ans;
+#else
   aom_writer residual_bc;
+#endif  // CONFIG_ANS
   int tile_row, tile_col;
   TOKENEXTRA *tok_end;
   size_t total_size = 0;
@@ -1345,33 +1350,40 @@
 
   for (tile_row = 0; tile_row < tile_rows; tile_row++) {
     for (tile_col = 0; tile_col < tile_cols; tile_col++) {
-      int tile_idx = tile_row * tile_cols + tile_col;
+      const int tile_idx = tile_row * tile_cols + tile_col;
+      const int is_last_tile = tile_idx == tile_rows * tile_cols - 1;
+      unsigned int tile_size;
       TOKENEXTRA *tok = cpi->tile_tok[tile_row][tile_col];
 
       tok_end = cpi->tile_tok[tile_row][tile_col] +
                 cpi->tok_count[tile_row][tile_col];
 
-      if (tile_col < tile_cols - 1 || tile_row < tile_rows - 1)
-        aom_start_encode(&residual_bc, data_ptr + total_size + 4);
-      else
-        aom_start_encode(&residual_bc, data_ptr + total_size);
+#if CONFIG_ANS
+      buf_ans_write_reset(buf_ans);
+      write_modes(cpi, &cpi->tile_data[tile_idx].tile_info, buf_ans, &tok,
+                  tok_end);
+      assert(tok == tok_end);
+      ans_write_init(&ans, data_ptr + total_size + 4 * !is_last_tile);
+      buf_ans_flush(buf_ans, &ans);
+      tile_size = ans_write_end(&ans) - CONFIG_MISC_FIXES;
+#else
+      aom_start_encode(&residual_bc, data_ptr + total_size + 4 * !is_last_tile);
 
       write_modes(cpi, &cpi->tile_data[tile_idx].tile_info, &residual_bc, &tok,
                   tok_end);
       assert(tok == tok_end);
       aom_stop_encode(&residual_bc);
-      if (tile_col < tile_cols - 1 || tile_row < tile_rows - 1) {
-        unsigned int tile_sz;
-
+      tile_size = residual_bc.pos - CONFIG_MISC_FIXES;
+#endif
+      assert(tile_size > 0);
+      if (!is_last_tile) {
         // size of this tile
-        assert(residual_bc.pos > 0);
-        tile_sz = residual_bc.pos - CONFIG_MISC_FIXES;
-        mem_put_le32(data_ptr + total_size, tile_sz);
-        max_tile = max_tile > tile_sz ? max_tile : tile_sz;
+        mem_put_le32(data_ptr + total_size, tile_size);
+        max_tile = max_tile > tile_size ? max_tile : tile_size;
         total_size += 4;
       }
 
-      total_size += residual_bc.pos;
+      total_size += tile_size;
     }
   }
   *max_tile_sz = max_tile;
@@ -1652,10 +1664,17 @@
   FRAME_COUNTS *counts = cpi->td.counts;
   aom_writer *header_bc;
   int i, j;
-  aom_writer real_header_bc;
 
+#if CONFIG_ANS
+  struct AnsCoder header_ans;
+  int header_size;
+  header_bc = &cpi->buf_ans;
+  buf_ans_write_reset(header_bc);
+#else
+  aom_writer real_header_bc;
   header_bc = &real_header_bc;
   aom_start_encode(header_bc, data);
+#endif
 
 #if !CONFIG_MISC_FIXES
   if (cpi->td.mb.e_mbd.lossless[0]) {
@@ -1772,10 +1791,17 @@
     update_ext_tx_probs(cm, header_bc);
   }
 
+#if CONFIG_ANS
+  ans_write_init(&header_ans, data);
+  buf_ans_flush(header_bc, &header_ans);
+  header_size = ans_write_end(&header_ans);
+  assert(header_size <= 0xffff);
+  return header_size;
+#else
   aom_stop_encode(header_bc);
   assert(header_bc->pos <= 0xffff);
-
   return header_bc->pos;
+#endif  // CONFIG_ANS
 }
 
 #if CONFIG_MISC_FIXES
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 12b655e..761c638 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -56,6 +56,9 @@
 #endif
 #include "aom_dsp/aom_dsp_common.h"
 #include "aom_dsp/aom_filter.h"
+#if CONFIG_ANS
+#include "aom_dsp/buf_ans.h"
+#endif  // CONFIG_ANS
 #include "aom_ports/aom_timer.h"
 #include "aom_ports/mem.h"
 #include "aom_ports/system_state.h"
@@ -422,6 +425,9 @@
     aom_free(cpi->source_diff_var);
     cpi->source_diff_var = NULL;
   }
+#if CONFIG_ANS
+  aom_buf_ans_free(&cpi->buf_ans);
+#endif  // CONFIG_ANS
 }
 
 static void save_coding_context(AV1_COMP *cpi) {
@@ -741,6 +747,9 @@
     unsigned int tokens = get_token_alloc(cm->mb_rows, cm->mb_cols);
     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);
+#endif  // CONFIG_ANS
   }
 
   av1_setup_pc_tree(&cpi->common, &cpi->td);
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 1055970..6f0cdec 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -35,6 +35,9 @@
 #include "av1/encoder/speed_features.h"
 #include "av1/encoder/tokenize.h"
 
+#if CONFIG_ANS
+#include "aom_dsp/buf_ans.h"
+#endif  // CONFIG_ANS
 #if CONFIG_INTERNAL_STATS
 #include "aom_dsp/ssim.h"
 #endif
@@ -531,6 +534,9 @@
   AVxWorker *workers;
   struct EncWorkerData *tile_thr_data;
   AV1LfSync lf_row_sync;
+#if CONFIG_ANS
+  struct BufAnsCoder buf_ans;
+#endif  // CONFIG_ANS
 } AV1_COMP;
 
 void av1_initialize_enc(void);
diff --git a/test/superframe_test.cc b/test/superframe_test.cc
index ec0d9fe..385537c 100644
--- a/test/superframe_test.cc
+++ b/test/superframe_test.cc
@@ -99,8 +99,22 @@
   EXPECT_EQ(sf_count_, 1);
 }
 
+#if CONFIG_ANS
+// TODO(aconverse@google.com): Because the ANS decoder starts reading from the
+// end of the buffer, it can't find the end of the first frame of the
+// superframe. This can be ameliorated by reversing the order of the frames in
+// the superframe or reversing the bytes of each ANS buffer.
+INSTANTIATE_TEST_CASE_P(
+    DISABLED_AV1, SuperframeTest,
+    ::testing::Combine(
+        ::testing::Values(
+            static_cast<const libaom_test::CodecFactory *>(&libaom_test::kAV1)),
+        ::testing::Combine(::testing::Values(::libaom_test::kTwoPassGood),
+                           ::testing::Values(CONFIG_MISC_FIXES))));
+#else
 AV1_INSTANTIATE_TEST_CASE(
     SuperframeTest,
     ::testing::Combine(::testing::Values(::libaom_test::kTwoPassGood),
                        ::testing::Values(CONFIG_MISC_FIXES)));
+#endif
 }  // namespace
diff --git a/test/test.mk b/test/test.mk
index dac9c7b..ecb9aaf 100644
--- a/test/test.mk
+++ b/test/test.mk
@@ -91,8 +91,11 @@
 LIBAOM_TEST_SRCS-yes                   += partial_idct_test.cc
 LIBAOM_TEST_SRCS-yes                   += superframe_test.cc
 LIBAOM_TEST_SRCS-yes                   += tile_independence_test.cc
-LIBAOM_TEST_SRCS-$(CONFIG_ANS)         += ans_test.cc
+ifeq ($(CONFIG_ANS),yes)
+LIBAOM_TEST_SRCS-yes                   += ans_test.cc
+else
 LIBAOM_TEST_SRCS-yes                   += boolcoder_test.cc
+endif
 LIBAOM_TEST_SRCS-yes                   += divu_small_test.cc
 LIBAOM_TEST_SRCS-yes                   += encoder_parms_get_to_decoder.cc
 endif