ans: Allow compressed buffer reversal

The final ANS state gets further compacted because aliasing the super
frame marker is not an issue.

Change-Id: I26208accb117a6748abb6f1c32c28fadbc48de09
diff --git a/aom_dsp/ans.h b/aom_dsp/ans.h
index 08735bb..f84671c 100644
--- a/aom_dsp/ans.h
+++ b/aom_dsp/ans.h
@@ -23,6 +23,8 @@
 extern "C" {
 #endif  // __cplusplus
 
+#define ANS_REVERSE 0
+
 typedef uint8_t AnsP8;
 #define ANS_P8_PRECISION 256u
 #define ANS_P8_SHIFT 8
diff --git a/aom_dsp/ansreader.h b/aom_dsp/ansreader.h
index 5855789..e0b02f7 100644
--- a/aom_dsp/ansreader.h
+++ b/aom_dsp/ansreader.h
@@ -39,9 +39,15 @@
 
 static INLINE unsigned refill_state(struct AnsDecoder *const ans,
                                     unsigned state) {
+#if ANS_REVERSE
+  while (state < L_BASE && ans->buf_offset < 0) {
+    state = state * IO_BASE + ans->buf[ans->buf_offset++];
+  }
+#else
   while (state < L_BASE && ans->buf_offset > 0) {
     state = state * IO_BASE + ans->buf[--ans->buf_offset];
   }
+#endif
   return state;
 }
 
@@ -106,6 +112,20 @@
                                 const uint8_t *const buf, int offset) {
   unsigned x;
   if (offset < 1) return 1;
+#if ANS_REVERSE
+  ans->buf = buf + offset;
+  ans->buf_offset = -offset;
+  x = buf[0];
+  if ((x & 0x80) == 0) {
+    if (offset < 2) return 1;
+    ans->buf_offset += 2;
+    ans->state = mem_get_be16(buf) & 0x7FFF;
+  } else {
+    if (offset < 3) return 1;
+    ans->buf_offset += 3;
+    ans->state = mem_get_be24(buf) & 0x7FFFFF;
+  }
+#else
   ans->buf = buf;
   x = buf[offset - 1];
   if ((x & 0x80) == 0) {
@@ -124,6 +144,7 @@
     // 110xxxxx implies this byte is a superframe marker
     return 1;
   }
+#endif  // ANS_REVERSE
 #if CONFIG_ACCOUNTING
   ans->accounting = NULL;
 #endif
diff --git a/aom_dsp/answriter.h b/aom_dsp/answriter.h
index 23d7b41..b6ac6de 100644
--- a/aom_dsp/answriter.h
+++ b/aom_dsp/answriter.h
@@ -57,22 +57,41 @@
 
 static INLINE int ans_write_end(struct AnsCoder *const ans) {
   uint32_t state;
+  int ans_size;
   assert(ans->state >= L_BASE);
   assert(ans->state < L_BASE * IO_BASE);
   state = ans->state - L_BASE;
   if (state < (1u << 15)) {
     mem_put_le16(ans->buf + ans->buf_offset, (0x00u << 15) + state);
-    return ans->buf_offset + 2;
+    ans_size = ans->buf_offset + 2;
+#if ANS_REVERSE
+  } else if (state < (1u << 23)) {
+    mem_put_le24(ans->buf + ans->buf_offset, (0x01u << 23) + state);
+    ans_size = ans->buf_offset + 3;
+#else
   } else if (state < (1u << 22)) {
     mem_put_le24(ans->buf + ans->buf_offset, (0x02u << 22) + state);
-    return ans->buf_offset + 3;
+    ans_size = ans->buf_offset + 3;
   } else if (state < (1u << 29)) {
     mem_put_le32(ans->buf + ans->buf_offset, (0x07u << 29) + state);
-    return ans->buf_offset + 4;
+    ans_size = ans->buf_offset + 4;
+#endif
   } else {
     assert(0 && "State is too large to be serialized");
     return ans->buf_offset;
   }
+#if ANS_REVERSE
+  {
+    int i;
+    uint8_t tmp;
+    for (i = 0; i < (ans_size >> 1); i++) {
+      tmp = ans->buf[i];
+      ans->buf[i] = ans->buf[ans_size - 1 - i];
+      ans->buf[ans_size - 1 - i] = tmp;
+    }
+  }
+#endif
+  return ans_size;
 }
 
 // uABS with normalization
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 493e857..1bed65c 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -4554,5 +4554,9 @@
 #else
   data += data_size;
 #endif
+#if CONFIG_ANS && ANS_REVERSE
+  // Avoid aliasing the superframe index
+  *data++ = 0;
+#endif
   *size = data - dst;
 }