Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2016, Alliance for Open Media. All rights reserved |
| 3 | * |
| 4 | * This source code is subject to the terms of the BSD 2 Clause License and |
| 5 | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| 6 | * was not distributed with this source code in the LICENSE file, you can |
| 7 | * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| 8 | * Media Patent License 1.0 was not distributed with this source code in the |
| 9 | * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
| 10 | */ |
| 11 | |
| 12 | #ifndef AOM_DSP_ANSREADER_H_ |
| 13 | #define AOM_DSP_ANSREADER_H_ |
Alex Converse | c54692b | 2017-01-25 16:41:05 -0800 | [diff] [blame] | 14 | // An implementation of Asymmetric Numeral Systems |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 15 | // http://arxiv.org/abs/1311.2540v2 |
Alex Converse | c54692b | 2017-01-25 16:41:05 -0800 | [diff] [blame] | 16 | // Implements decoding of: |
| 17 | // * rABS (range Asymmetric Binary Systems), a boolean coder |
| 18 | // * rANS (range Asymmetric Numeral Systems), a multi-symbol coder |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 19 | |
| 20 | #include <assert.h> |
| 21 | #include "./aom_config.h" |
| 22 | #include "aom/aom_integer.h" |
| 23 | #include "aom_dsp/prob.h" |
| 24 | #include "aom_dsp/ans.h" |
| 25 | #include "aom_ports/mem_ops.h" |
David Barker | 01b16ba | 2016-10-25 16:07:53 +0100 | [diff] [blame] | 26 | #if CONFIG_ACCOUNTING |
Luc Trudeau | 83fbd57 | 2017-04-21 11:24:34 -0400 | [diff] [blame] | 27 | #include "av1/decoder/accounting.h" |
David Barker | 01b16ba | 2016-10-25 16:07:53 +0100 | [diff] [blame] | 28 | #endif |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 29 | |
| 30 | #ifdef __cplusplus |
| 31 | extern "C" { |
| 32 | #endif // __cplusplus |
| 33 | |
| 34 | struct AnsDecoder { |
| 35 | const uint8_t *buf; |
| 36 | int buf_offset; |
| 37 | uint32_t state; |
Alex Converse | b0be641 | 2016-11-30 15:51:50 -0800 | [diff] [blame] | 38 | #if ANS_MAX_SYMBOLS |
| 39 | int symbols_left; |
Alex Converse | 2cdf0d8 | 2016-12-13 13:53:09 -0800 | [diff] [blame] | 40 | int window_size; |
Alex Converse | b0be641 | 2016-11-30 15:51:50 -0800 | [diff] [blame] | 41 | #endif |
David Barker | 01b16ba | 2016-10-25 16:07:53 +0100 | [diff] [blame] | 42 | #if CONFIG_ACCOUNTING |
| 43 | Accounting *accounting; |
| 44 | #endif |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 45 | }; |
| 46 | |
Alex Converse | b0be641 | 2016-11-30 15:51:50 -0800 | [diff] [blame] | 47 | static INLINE int ans_read_reinit(struct AnsDecoder *const ans); |
| 48 | |
Alex Converse | 5943d41 | 2016-11-03 13:10:00 -0700 | [diff] [blame] | 49 | static INLINE unsigned refill_state(struct AnsDecoder *const ans, |
| 50 | unsigned state) { |
Alex Converse | b0bbd60 | 2016-10-21 14:15:06 -0700 | [diff] [blame] | 51 | #if ANS_REVERSE |
| 52 | while (state < L_BASE && ans->buf_offset < 0) { |
| 53 | state = state * IO_BASE + ans->buf[ans->buf_offset++]; |
| 54 | } |
| 55 | #else |
Alex Converse | 5943d41 | 2016-11-03 13:10:00 -0700 | [diff] [blame] | 56 | while (state < L_BASE && ans->buf_offset > 0) { |
| 57 | state = state * IO_BASE + ans->buf[--ans->buf_offset]; |
| 58 | } |
Alex Converse | b0bbd60 | 2016-10-21 14:15:06 -0700 | [diff] [blame] | 59 | #endif |
Alex Converse | 5943d41 | 2016-11-03 13:10:00 -0700 | [diff] [blame] | 60 | return state; |
| 61 | } |
| 62 | |
Alex Converse | c54692b | 2017-01-25 16:41:05 -0800 | [diff] [blame] | 63 | // Decode one rABS encoded boolean where the probability of the value being zero |
| 64 | // is p0. |
| 65 | static INLINE int rabs_read(struct AnsDecoder *ans, AnsP8 p0) { |
Alex Converse | b0be641 | 2016-11-30 15:51:50 -0800 | [diff] [blame] | 66 | #if ANS_MAX_SYMBOLS |
| 67 | if (ans->symbols_left-- == 0) { |
| 68 | ans_read_reinit(ans); |
| 69 | ans->symbols_left--; |
| 70 | } |
| 71 | #endif |
Alex Converse | 3920406 | 2017-02-02 15:59:29 -0800 | [diff] [blame] | 72 | unsigned state = refill_state(ans, ans->state); |
Alex Converse | c54692b | 2017-01-25 16:41:05 -0800 | [diff] [blame] | 73 | const unsigned quotient = state / ANS_P8_PRECISION; |
| 74 | const unsigned remainder = state % ANS_P8_PRECISION; |
| 75 | const int value = remainder >= p0; |
Alex Converse | bff32ac | 2017-02-27 09:27:33 -0800 | [diff] [blame] | 76 | const unsigned qp0 = quotient * p0; |
Alex Converse | c54692b | 2017-01-25 16:41:05 -0800 | [diff] [blame] | 77 | if (value) |
Alex Converse | bff32ac | 2017-02-27 09:27:33 -0800 | [diff] [blame] | 78 | state = state - qp0 - p0; |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 79 | else |
Alex Converse | bff32ac | 2017-02-27 09:27:33 -0800 | [diff] [blame] | 80 | state = qp0 + remainder; |
Alex Converse | 3920406 | 2017-02-02 15:59:29 -0800 | [diff] [blame] | 81 | ans->state = state; |
Alex Converse | c54692b | 2017-01-25 16:41:05 -0800 | [diff] [blame] | 82 | return value; |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 83 | } |
| 84 | |
Alex Converse | c54692b | 2017-01-25 16:41:05 -0800 | [diff] [blame] | 85 | // Decode one rABS encoded boolean where the probability of the value being zero |
| 86 | // is one half. |
| 87 | static INLINE int rabs_read_bit(struct AnsDecoder *ans) { |
Alex Converse | 7fdf2d2 | 2017-02-09 12:00:36 -0800 | [diff] [blame] | 88 | #if ANS_MAX_SYMBOLS |
| 89 | if (ans->symbols_left-- == 0) { |
| 90 | ans_read_reinit(ans); |
| 91 | ans->symbols_left--; |
| 92 | } |
| 93 | #endif |
| 94 | unsigned state = refill_state(ans, ans->state); |
| 95 | const int value = !!(state & 0x80); |
| 96 | ans->state = ((state >> 1) & ~0x7F) | (state & 0x7F); |
| 97 | return value; |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 98 | } |
| 99 | |
| 100 | struct rans_dec_sym { |
| 101 | uint8_t val; |
Alex Converse | 9ed1a2f | 2016-09-04 13:30:43 +0200 | [diff] [blame] | 102 | aom_cdf_prob prob; |
| 103 | aom_cdf_prob cum_prob; // not-inclusive |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 104 | }; |
| 105 | |
Alex Converse | 9ed1a2f | 2016-09-04 13:30:43 +0200 | [diff] [blame] | 106 | static INLINE void fetch_sym(struct rans_dec_sym *out, const aom_cdf_prob *cdf, |
| 107 | aom_cdf_prob rem) { |
Alex Converse | e9f70f8 | 2016-08-22 12:44:16 -0700 | [diff] [blame] | 108 | int i; |
Alex Converse | 9ed1a2f | 2016-09-04 13:30:43 +0200 | [diff] [blame] | 109 | aom_cdf_prob cum_prob = 0, top_prob; |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 110 | // TODO(skal): if critical, could be a binary search. |
| 111 | // Or, better, an O(1) alias-table. |
Alex Converse | e9f70f8 | 2016-08-22 12:44:16 -0700 | [diff] [blame] | 112 | for (i = 0; rem >= (top_prob = cdf[i]); ++i) { |
| 113 | cum_prob = top_prob; |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 114 | } |
Alex Converse | e9f70f8 | 2016-08-22 12:44:16 -0700 | [diff] [blame] | 115 | out->val = i; |
| 116 | out->prob = top_prob - cum_prob; |
| 117 | out->cum_prob = cum_prob; |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 118 | } |
| 119 | |
Alex Converse | 9ed1a2f | 2016-09-04 13:30:43 +0200 | [diff] [blame] | 120 | static INLINE int rans_read(struct AnsDecoder *ans, const aom_cdf_prob *tab) { |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 121 | unsigned rem; |
| 122 | unsigned quo; |
| 123 | struct rans_dec_sym sym; |
Alex Converse | b0be641 | 2016-11-30 15:51:50 -0800 | [diff] [blame] | 124 | #if ANS_MAX_SYMBOLS |
| 125 | if (ans->symbols_left-- == 0) { |
| 126 | ans_read_reinit(ans); |
| 127 | ans->symbols_left--; |
| 128 | } |
| 129 | #endif |
Alex Converse | 3920406 | 2017-02-02 15:59:29 -0800 | [diff] [blame] | 130 | ans->state = refill_state(ans, ans->state); |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 131 | quo = ans->state / RANS_PRECISION; |
| 132 | rem = ans->state % RANS_PRECISION; |
| 133 | fetch_sym(&sym, tab, rem); |
| 134 | ans->state = quo * sym.prob + rem - sym.cum_prob; |
| 135 | return sym.val; |
| 136 | } |
| 137 | |
| 138 | static INLINE int ans_read_init(struct AnsDecoder *const ans, |
| 139 | const uint8_t *const buf, int offset) { |
| 140 | unsigned x; |
| 141 | if (offset < 1) return 1; |
Alex Converse | b0bbd60 | 2016-10-21 14:15:06 -0700 | [diff] [blame] | 142 | #if ANS_REVERSE |
| 143 | ans->buf = buf + offset; |
| 144 | ans->buf_offset = -offset; |
| 145 | x = buf[0]; |
Alex Converse | 822513c | 2017-01-25 16:41:46 -0800 | [diff] [blame] | 146 | if ((x & 0x80) == 0) { // Marker is 0xxx xxxx |
Alex Converse | b0bbd60 | 2016-10-21 14:15:06 -0700 | [diff] [blame] | 147 | if (offset < 2) return 1; |
| 148 | ans->buf_offset += 2; |
| 149 | ans->state = mem_get_be16(buf) & 0x7FFF; |
Alex Converse | 822513c | 2017-01-25 16:41:46 -0800 | [diff] [blame] | 150 | #if L_BASE * IO_BASE > (1 << 23) |
| 151 | } else if ((x & 0xC0) == 0x80) { // Marker is 10xx xxxx |
| 152 | if (offset < 3) return 1; |
| 153 | ans->buf_offset += 3; |
| 154 | ans->state = mem_get_be24(buf) & 0x3FFFFF; |
| 155 | } else { // Marker is 11xx xxxx |
| 156 | if (offset < 4) return 1; |
| 157 | ans->buf_offset += 4; |
| 158 | ans->state = mem_get_be32(buf) & 0x3FFFFFFF; |
| 159 | #else |
| 160 | } else { // Marker is 1xxx xxxx |
Alex Converse | b0bbd60 | 2016-10-21 14:15:06 -0700 | [diff] [blame] | 161 | if (offset < 3) return 1; |
| 162 | ans->buf_offset += 3; |
| 163 | ans->state = mem_get_be24(buf) & 0x7FFFFF; |
Alex Converse | 822513c | 2017-01-25 16:41:46 -0800 | [diff] [blame] | 164 | #endif |
Alex Converse | b0bbd60 | 2016-10-21 14:15:06 -0700 | [diff] [blame] | 165 | } |
| 166 | #else |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 167 | ans->buf = buf; |
Alex Converse | fa9c9d1 | 2016-11-04 14:06:06 -0700 | [diff] [blame] | 168 | x = buf[offset - 1]; |
Alex Converse | 822513c | 2017-01-25 16:41:46 -0800 | [diff] [blame] | 169 | if ((x & 0x80) == 0) { // Marker is 0xxx xxxx |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 170 | if (offset < 2) return 1; |
| 171 | ans->buf_offset = offset - 2; |
Alex Converse | fa9c9d1 | 2016-11-04 14:06:06 -0700 | [diff] [blame] | 172 | ans->state = mem_get_le16(buf + offset - 2) & 0x7FFF; |
Alex Converse | 822513c | 2017-01-25 16:41:46 -0800 | [diff] [blame] | 173 | } else if ((x & 0xC0) == 0x80) { // Marker is 10xx xxxx |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 174 | if (offset < 3) return 1; |
| 175 | ans->buf_offset = offset - 3; |
| 176 | ans->state = mem_get_le24(buf + offset - 3) & 0x3FFFFF; |
Alex Converse | 822513c | 2017-01-25 16:41:46 -0800 | [diff] [blame] | 177 | } else if ((x & 0xE0) == 0xE0) { // Marker is 111x xxxx |
Alex Converse | 62a94a6 | 2016-09-09 10:51:48 -0700 | [diff] [blame] | 178 | if (offset < 4) return 1; |
| 179 | ans->buf_offset = offset - 4; |
| 180 | ans->state = mem_get_le32(buf + offset - 4) & 0x1FFFFFFF; |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 181 | } else { |
Alex Converse | 822513c | 2017-01-25 16:41:46 -0800 | [diff] [blame] | 182 | // Marker 110x xxxx implies this byte is a superframe marker |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 183 | return 1; |
| 184 | } |
Alex Converse | b0bbd60 | 2016-10-21 14:15:06 -0700 | [diff] [blame] | 185 | #endif // ANS_REVERSE |
David Barker | 01b16ba | 2016-10-25 16:07:53 +0100 | [diff] [blame] | 186 | #if CONFIG_ACCOUNTING |
| 187 | ans->accounting = NULL; |
| 188 | #endif |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 189 | ans->state += L_BASE; |
| 190 | if (ans->state >= L_BASE * IO_BASE) return 1; |
Alex Converse | b0be641 | 2016-11-30 15:51:50 -0800 | [diff] [blame] | 191 | #if ANS_MAX_SYMBOLS |
Alex Converse | eb780e7 | 2016-12-13 12:46:41 -0800 | [diff] [blame] | 192 | assert(ans->window_size > 1); |
Alex Converse | 346440b | 2017-01-03 13:47:37 -0800 | [diff] [blame] | 193 | ans->symbols_left = ans->window_size; |
Alex Converse | b0be641 | 2016-11-30 15:51:50 -0800 | [diff] [blame] | 194 | #endif |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 195 | return 0; |
| 196 | } |
| 197 | |
Alex Converse | b0be641 | 2016-11-30 15:51:50 -0800 | [diff] [blame] | 198 | #if ANS_REVERSE |
| 199 | static INLINE int ans_read_reinit(struct AnsDecoder *const ans) { |
Alex Converse | 346440b | 2017-01-03 13:47:37 -0800 | [diff] [blame] | 200 | return ans_read_init(ans, ans->buf + ans->buf_offset, -ans->buf_offset); |
Alex Converse | b0be641 | 2016-11-30 15:51:50 -0800 | [diff] [blame] | 201 | } |
| 202 | #endif |
| 203 | |
Alex Converse | 3920406 | 2017-02-02 15:59:29 -0800 | [diff] [blame] | 204 | static INLINE int ans_read_end(const struct AnsDecoder *const ans) { |
| 205 | return ans->buf_offset == 0 && ans->state < L_BASE; |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 206 | } |
| 207 | |
| 208 | static INLINE int ans_reader_has_error(const struct AnsDecoder *const ans) { |
Alex Converse | 3920406 | 2017-02-02 15:59:29 -0800 | [diff] [blame] | 209 | return ans->state < L_BASE / RANS_PRECISION; |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 210 | } |
| 211 | #ifdef __cplusplus |
| 212 | } // extern "C" |
| 213 | #endif // __cplusplus |
| 214 | #endif // AOM_DSP_ANSREADER_H_ |