blob: e50c63b2d1ace3bc82da3161fc139778f5e7556a [file] [log] [blame]
Alex Converse7fe2ae82016-09-28 11:33:20 -07001/*
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 Conversec54692b2017-01-25 16:41:05 -080014// An implementation of Asymmetric Numeral Systems
Alex Converse7fe2ae82016-09-28 11:33:20 -070015// http://arxiv.org/abs/1311.2540v2
Alex Conversec54692b2017-01-25 16:41:05 -080016// Implements decoding of:
17// * rABS (range Asymmetric Binary Systems), a boolean coder
18// * rANS (range Asymmetric Numeral Systems), a multi-symbol coder
Alex Converse7fe2ae82016-09-28 11:33:20 -070019
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 Barker01b16ba2016-10-25 16:07:53 +010026#if CONFIG_ACCOUNTING
Luc Trudeau83fbd572017-04-21 11:24:34 -040027#include "av1/decoder/accounting.h"
David Barker01b16ba2016-10-25 16:07:53 +010028#endif
Alex Converse7fe2ae82016-09-28 11:33:20 -070029
30#ifdef __cplusplus
31extern "C" {
32#endif // __cplusplus
33
34struct AnsDecoder {
35 const uint8_t *buf;
36 int buf_offset;
37 uint32_t state;
Alex Converseb0be6412016-11-30 15:51:50 -080038#if ANS_MAX_SYMBOLS
39 int symbols_left;
Alex Converse2cdf0d82016-12-13 13:53:09 -080040 int window_size;
Alex Converseb0be6412016-11-30 15:51:50 -080041#endif
David Barker01b16ba2016-10-25 16:07:53 +010042#if CONFIG_ACCOUNTING
43 Accounting *accounting;
44#endif
Alex Converse7fe2ae82016-09-28 11:33:20 -070045};
46
Alex Converseb0be6412016-11-30 15:51:50 -080047static INLINE int ans_read_reinit(struct AnsDecoder *const ans);
48
Alex Converse5943d412016-11-03 13:10:00 -070049static INLINE unsigned refill_state(struct AnsDecoder *const ans,
50 unsigned state) {
Alex Converseb0bbd602016-10-21 14:15:06 -070051#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 Converse5943d412016-11-03 13:10:00 -070056 while (state < L_BASE && ans->buf_offset > 0) {
57 state = state * IO_BASE + ans->buf[--ans->buf_offset];
58 }
Alex Converseb0bbd602016-10-21 14:15:06 -070059#endif
Alex Converse5943d412016-11-03 13:10:00 -070060 return state;
61}
62
Alex Conversec54692b2017-01-25 16:41:05 -080063// Decode one rABS encoded boolean where the probability of the value being zero
64// is p0.
65static INLINE int rabs_read(struct AnsDecoder *ans, AnsP8 p0) {
Alex Converseb0be6412016-11-30 15:51:50 -080066#if ANS_MAX_SYMBOLS
67 if (ans->symbols_left-- == 0) {
68 ans_read_reinit(ans);
69 ans->symbols_left--;
70 }
71#endif
Alex Converse39204062017-02-02 15:59:29 -080072 unsigned state = refill_state(ans, ans->state);
Alex Conversec54692b2017-01-25 16:41:05 -080073 const unsigned quotient = state / ANS_P8_PRECISION;
74 const unsigned remainder = state % ANS_P8_PRECISION;
75 const int value = remainder >= p0;
Alex Conversebff32ac2017-02-27 09:27:33 -080076 const unsigned qp0 = quotient * p0;
Alex Conversec54692b2017-01-25 16:41:05 -080077 if (value)
Alex Conversebff32ac2017-02-27 09:27:33 -080078 state = state - qp0 - p0;
Alex Converse7fe2ae82016-09-28 11:33:20 -070079 else
Alex Conversebff32ac2017-02-27 09:27:33 -080080 state = qp0 + remainder;
Alex Converse39204062017-02-02 15:59:29 -080081 ans->state = state;
Alex Conversec54692b2017-01-25 16:41:05 -080082 return value;
Alex Converse7fe2ae82016-09-28 11:33:20 -070083}
84
Alex Conversec54692b2017-01-25 16:41:05 -080085// Decode one rABS encoded boolean where the probability of the value being zero
86// is one half.
87static INLINE int rabs_read_bit(struct AnsDecoder *ans) {
Alex Converse7fdf2d22017-02-09 12:00:36 -080088#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 Converse7fe2ae82016-09-28 11:33:20 -070098}
99
100struct rans_dec_sym {
101 uint8_t val;
Alex Converse9ed1a2f2016-09-04 13:30:43 +0200102 aom_cdf_prob prob;
103 aom_cdf_prob cum_prob; // not-inclusive
Alex Converse7fe2ae82016-09-28 11:33:20 -0700104};
105
Alex Converse9ed1a2f2016-09-04 13:30:43 +0200106static INLINE void fetch_sym(struct rans_dec_sym *out, const aom_cdf_prob *cdf,
107 aom_cdf_prob rem) {
Alex Conversee9f70f82016-08-22 12:44:16 -0700108 int i;
Alex Converse9ed1a2f2016-09-04 13:30:43 +0200109 aom_cdf_prob cum_prob = 0, top_prob;
Alex Converse7fe2ae82016-09-28 11:33:20 -0700110 // TODO(skal): if critical, could be a binary search.
111 // Or, better, an O(1) alias-table.
Alex Conversee9f70f82016-08-22 12:44:16 -0700112 for (i = 0; rem >= (top_prob = cdf[i]); ++i) {
113 cum_prob = top_prob;
Alex Converse7fe2ae82016-09-28 11:33:20 -0700114 }
Alex Conversee9f70f82016-08-22 12:44:16 -0700115 out->val = i;
116 out->prob = top_prob - cum_prob;
117 out->cum_prob = cum_prob;
Alex Converse7fe2ae82016-09-28 11:33:20 -0700118}
119
Alex Converse9ed1a2f2016-09-04 13:30:43 +0200120static INLINE int rans_read(struct AnsDecoder *ans, const aom_cdf_prob *tab) {
Alex Converse7fe2ae82016-09-28 11:33:20 -0700121 unsigned rem;
122 unsigned quo;
123 struct rans_dec_sym sym;
Alex Converseb0be6412016-11-30 15:51:50 -0800124#if ANS_MAX_SYMBOLS
125 if (ans->symbols_left-- == 0) {
126 ans_read_reinit(ans);
127 ans->symbols_left--;
128 }
129#endif
Alex Converse39204062017-02-02 15:59:29 -0800130 ans->state = refill_state(ans, ans->state);
Alex Converse7fe2ae82016-09-28 11:33:20 -0700131 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
138static 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 Converseb0bbd602016-10-21 14:15:06 -0700142#if ANS_REVERSE
143 ans->buf = buf + offset;
144 ans->buf_offset = -offset;
145 x = buf[0];
Alex Converse822513c2017-01-25 16:41:46 -0800146 if ((x & 0x80) == 0) { // Marker is 0xxx xxxx
Alex Converseb0bbd602016-10-21 14:15:06 -0700147 if (offset < 2) return 1;
148 ans->buf_offset += 2;
149 ans->state = mem_get_be16(buf) & 0x7FFF;
Alex Converse822513c2017-01-25 16:41:46 -0800150#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 Converseb0bbd602016-10-21 14:15:06 -0700161 if (offset < 3) return 1;
162 ans->buf_offset += 3;
163 ans->state = mem_get_be24(buf) & 0x7FFFFF;
Alex Converse822513c2017-01-25 16:41:46 -0800164#endif
Alex Converseb0bbd602016-10-21 14:15:06 -0700165 }
166#else
Alex Converse7fe2ae82016-09-28 11:33:20 -0700167 ans->buf = buf;
Alex Conversefa9c9d12016-11-04 14:06:06 -0700168 x = buf[offset - 1];
Alex Converse822513c2017-01-25 16:41:46 -0800169 if ((x & 0x80) == 0) { // Marker is 0xxx xxxx
Alex Converse7fe2ae82016-09-28 11:33:20 -0700170 if (offset < 2) return 1;
171 ans->buf_offset = offset - 2;
Alex Conversefa9c9d12016-11-04 14:06:06 -0700172 ans->state = mem_get_le16(buf + offset - 2) & 0x7FFF;
Alex Converse822513c2017-01-25 16:41:46 -0800173 } else if ((x & 0xC0) == 0x80) { // Marker is 10xx xxxx
Alex Converse7fe2ae82016-09-28 11:33:20 -0700174 if (offset < 3) return 1;
175 ans->buf_offset = offset - 3;
176 ans->state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
Alex Converse822513c2017-01-25 16:41:46 -0800177 } else if ((x & 0xE0) == 0xE0) { // Marker is 111x xxxx
Alex Converse62a94a62016-09-09 10:51:48 -0700178 if (offset < 4) return 1;
179 ans->buf_offset = offset - 4;
180 ans->state = mem_get_le32(buf + offset - 4) & 0x1FFFFFFF;
Alex Converse7fe2ae82016-09-28 11:33:20 -0700181 } else {
Alex Converse822513c2017-01-25 16:41:46 -0800182 // Marker 110x xxxx implies this byte is a superframe marker
Alex Converse7fe2ae82016-09-28 11:33:20 -0700183 return 1;
184 }
Alex Converseb0bbd602016-10-21 14:15:06 -0700185#endif // ANS_REVERSE
David Barker01b16ba2016-10-25 16:07:53 +0100186#if CONFIG_ACCOUNTING
187 ans->accounting = NULL;
188#endif
Alex Converse7fe2ae82016-09-28 11:33:20 -0700189 ans->state += L_BASE;
190 if (ans->state >= L_BASE * IO_BASE) return 1;
Alex Converseb0be6412016-11-30 15:51:50 -0800191#if ANS_MAX_SYMBOLS
Alex Converseeb780e72016-12-13 12:46:41 -0800192 assert(ans->window_size > 1);
Alex Converse346440b2017-01-03 13:47:37 -0800193 ans->symbols_left = ans->window_size;
Alex Converseb0be6412016-11-30 15:51:50 -0800194#endif
Alex Converse7fe2ae82016-09-28 11:33:20 -0700195 return 0;
196}
197
Alex Converseb0be6412016-11-30 15:51:50 -0800198#if ANS_REVERSE
199static INLINE int ans_read_reinit(struct AnsDecoder *const ans) {
Alex Converse346440b2017-01-03 13:47:37 -0800200 return ans_read_init(ans, ans->buf + ans->buf_offset, -ans->buf_offset);
Alex Converseb0be6412016-11-30 15:51:50 -0800201}
202#endif
203
Alex Converse39204062017-02-02 15:59:29 -0800204static INLINE int ans_read_end(const struct AnsDecoder *const ans) {
205 return ans->buf_offset == 0 && ans->state < L_BASE;
Alex Converse7fe2ae82016-09-28 11:33:20 -0700206}
207
208static INLINE int ans_reader_has_error(const struct AnsDecoder *const ans) {
Alex Converse39204062017-02-02 15:59:29 -0800209 return ans->state < L_BASE / RANS_PRECISION;
Alex Converse7fe2ae82016-09-28 11:33:20 -0700210}
211#ifdef __cplusplus
212} // extern "C"
213#endif // __cplusplus
214#endif // AOM_DSP_ANSREADER_H_