]> granicus.if.org Git - libvpx/commitdiff
Compress the final ANS state.
authorAlex Converse <aconverse@google.com>
Tue, 12 Jan 2016 00:16:19 +0000 (16:16 -0800)
committerAlex Converse <aconverse@google.com>
Tue, 12 Jan 2016 23:11:17 +0000 (23:11 +0000)
The '110' prefix on a final byte indicates a superframe marker. Coded
data is not allowed to use this pattern on a final byte.

Code |state - l_base| little endian with the following prefix scheme:
Prefix '00': Single byte coded state.
Prefix '01': Two bytes le coded state.
Prefix '10': Three bytes le coded state.

Change-Id: Ibc953b67675b567394b93de39b7cb22cadc47435

vp10/common/ans.h

index fbc9a45caa62b3da7b1c4e5d194804f239738408..a1862f30d057273db5d2c3d87cab949db0676453 100644 (file)
@@ -13,6 +13,7 @@
 // An implementation of Asymmetric Numeral Systems
 // http://arxiv.org/abs/1311.2540v2
 
+#include <assert.h>
 #include "./vpx_config.h"
 #include "vpx/vpx_integer.h"
 #include "vpx_ports/mem_ops.h"
@@ -68,8 +69,20 @@ static INLINE void ans_write_init(struct AnsCoder *const ans,
 }
 
 static INLINE int ans_write_end(struct AnsCoder *const ans) {
-  mem_put_le24(ans->buf + ans->buf_offset, ans->state);
-  return ans->buf_offset + 3;
+  uint32_t state;
+  assert(ans->state >= l_base);
+  assert(ans->state < l_base * io_base);
+  state = ans->state - l_base;
+  if (state < (1 << 6)) {
+    ans->buf[ans->buf_offset] = (0 << 6) + state;
+    return ans->buf_offset + 1;
+  } else if (state < (1 << 14)) {
+    mem_put_le16(ans->buf + ans->buf_offset, (1 << 14) + state);
+    return ans->buf_offset + 2;
+  } else {
+    mem_put_le24(ans->buf + ans->buf_offset, (1 << 23) + state);
+    return ans->buf_offset + 3;
+  }
 }
 
 // rABS with descending spread
@@ -281,11 +294,28 @@ static INLINE int rans_read(struct AnsDecoder *ans,
 static INLINE int ans_read_init(struct AnsDecoder *const ans,
                                 const uint8_t *const buf,
                                 int offset) {
-  if (offset < 3)
-    return 1;
+  unsigned x;
+  if (offset < 1) return 1;
   ans->buf = buf;
-  ans->buf_offset = offset - 3;
-  ans->state = mem_get_le24(buf + offset - 3);
+  x = buf[offset - 1] >> 6;
+  if (x == 0) {
+    ans->buf_offset = offset - 1;
+    ans->state = buf[offset - 1] & 0x3F;
+  } else if (x == 1) {
+    if (offset < 2) return 1;
+    ans->buf_offset = offset - 2;
+    ans->state = mem_get_le16(buf + offset - 2) & 0x3FFF;
+  } else if (x == 2) {
+    if (offset < 3) return 1;
+    ans->buf_offset = offset - 3;
+    ans->state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
+  } else {
+    // x == 3 implies this byte is a superframe marker
+    return 1;
+  }
+  ans->state += l_base;
+  if (ans->state >= l_base * io_base)
+    return 1;
   return 0;
 }