Line | Count | Source |
1 | | /* |
2 | | * Copyright © 2018, VideoLAN and dav1d authors |
3 | | * Copyright © 2018, Two Orioles, LLC |
4 | | * All rights reserved. |
5 | | * |
6 | | * Redistribution and use in source and binary forms, with or without |
7 | | * modification, are permitted provided that the following conditions are met: |
8 | | * |
9 | | * 1. Redistributions of source code must retain the above copyright notice, this |
10 | | * list of conditions and the following disclaimer. |
11 | | * |
12 | | * 2. Redistributions in binary form must reproduce the above copyright notice, |
13 | | * this list of conditions and the following disclaimer in the documentation |
14 | | * and/or other materials provided with the distribution. |
15 | | * |
16 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
17 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR |
20 | | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
25 | | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | | */ |
27 | | |
28 | | #include "config.h" |
29 | | |
30 | | #include <limits.h> |
31 | | |
32 | | #include "common/intops.h" |
33 | | |
34 | | #include "src/msac.h" |
35 | | |
36 | 0 | #define EC_PROB_SHIFT 6 |
37 | 0 | #define EC_MIN_PROB 4 // must be <= (1<<EC_PROB_SHIFT)/16 |
38 | | |
39 | 0 | #define EC_WIN_SIZE (sizeof(ec_win) << 3) |
40 | | |
41 | 0 | static inline void ctx_refill(MsacContext *const s) { |
42 | 0 | const uint8_t *buf_pos = s->buf_pos; |
43 | 0 | const uint8_t *buf_end = s->buf_end; |
44 | 0 | int c = EC_WIN_SIZE - s->cnt - 24; |
45 | 0 | ec_win dif = s->dif; |
46 | 0 | do { |
47 | 0 | if (buf_pos >= buf_end) { |
48 | | // set remaining bits to 1; |
49 | 0 | dif |= ~(~(ec_win)0xff << c); |
50 | 0 | break; |
51 | 0 | } |
52 | 0 | dif |= (ec_win)(*buf_pos++ ^ 0xff) << c; |
53 | 0 | c -= 8; |
54 | 0 | } while (c >= 0); |
55 | 0 | s->dif = dif; |
56 | 0 | s->cnt = EC_WIN_SIZE - c - 24; |
57 | 0 | s->buf_pos = buf_pos; |
58 | 0 | } |
59 | | |
60 | | int dav1d_msac_decode_subexp(MsacContext *const s, const int ref, |
61 | | const int n, unsigned k) |
62 | 0 | { |
63 | 0 | assert(n >> k == 8); |
64 | | |
65 | 0 | unsigned a = 0; |
66 | 0 | if (dav1d_msac_decode_bool_equi(s)) { |
67 | 0 | if (dav1d_msac_decode_bool_equi(s)) |
68 | 0 | k += dav1d_msac_decode_bool_equi(s) + 1; |
69 | 0 | a = 1 << k; |
70 | 0 | } |
71 | 0 | const unsigned v = dav1d_msac_decode_bools(s, k) + a; |
72 | 0 | return ref * 2 <= n ? inv_recenter(ref, v) : |
73 | 0 | n - 1 - inv_recenter(n - 1 - ref, v); |
74 | 0 | } |
75 | | |
76 | | #if !(HAVE_ASM && TRIM_DSP_FUNCTIONS && ( \ |
77 | | ARCH_AARCH64 || \ |
78 | | (ARCH_ARM && (defined(__ARM_NEON) || defined(__APPLE__) || defined(_WIN32))) \ |
79 | | )) |
80 | | /* Takes updated dif and range values, renormalizes them so that |
81 | | * 32768 <= rng < 65536 (reading more bytes from the stream into dif if |
82 | | * necessary), and stores them back in the decoder context. |
83 | | * dif: The new value of dif. |
84 | | * rng: The new value of the range. */ |
85 | | static inline void ctx_norm(MsacContext *const s, const ec_win dif, |
86 | | const unsigned rng) |
87 | 0 | { |
88 | 0 | const int d = 15 ^ (31 ^ clz(rng)); |
89 | 0 | const int cnt = s->cnt; |
90 | 0 | assert(rng <= 65535U); |
91 | 0 | s->dif = dif << d; |
92 | 0 | s->rng = rng << d; |
93 | 0 | s->cnt = cnt - d; |
94 | | // unsigned compare avoids redundant refills at eob |
95 | 0 | if ((unsigned)cnt < (unsigned)d) |
96 | 0 | ctx_refill(s); |
97 | 0 | } |
98 | | |
99 | 0 | unsigned dav1d_msac_decode_bool_equi_c(MsacContext *const s) { |
100 | 0 | const unsigned r = s->rng; |
101 | 0 | ec_win dif = s->dif; |
102 | 0 | assert((dif >> (EC_WIN_SIZE - 16)) < r); |
103 | | // When the probability is 1/2, f = 16384 >> EC_PROB_SHIFT = 256 and we can |
104 | | // replace the multiply with a simple shift. |
105 | 0 | unsigned v = ((r >> 8) << 7) + EC_MIN_PROB; |
106 | 0 | const ec_win vw = (ec_win)v << (EC_WIN_SIZE - 16); |
107 | 0 | const unsigned ret = dif >= vw; |
108 | 0 | dif -= ret * vw; |
109 | 0 | v += ret * (r - 2 * v); |
110 | 0 | ctx_norm(s, dif, v); |
111 | 0 | return !ret; |
112 | 0 | } |
113 | | |
114 | | /* Decode a single binary value. |
115 | | * f: The probability that the bit is one |
116 | | * Return: The value decoded (0 or 1). */ |
117 | 0 | unsigned dav1d_msac_decode_bool_c(MsacContext *const s, const unsigned f) { |
118 | 0 | const unsigned r = s->rng; |
119 | 0 | ec_win dif = s->dif; |
120 | 0 | assert((dif >> (EC_WIN_SIZE - 16)) < r); |
121 | 0 | unsigned v = ((r >> 8) * (f >> EC_PROB_SHIFT) >> (7 - EC_PROB_SHIFT)) + EC_MIN_PROB; |
122 | 0 | const ec_win vw = (ec_win)v << (EC_WIN_SIZE - 16); |
123 | 0 | const unsigned ret = dif >= vw; |
124 | 0 | dif -= ret * vw; |
125 | 0 | v += ret * (r - 2 * v); |
126 | 0 | ctx_norm(s, dif, v); |
127 | 0 | return !ret; |
128 | 0 | } |
129 | | |
130 | | /* Decodes a symbol given an inverse cumulative distribution function (CDF) |
131 | | * table in Q15. */ |
132 | | unsigned dav1d_msac_decode_symbol_adapt_c(MsacContext *const s, |
133 | | uint16_t *const cdf, |
134 | | const size_t n_symbols) |
135 | 0 | { |
136 | 0 | const unsigned c = s->dif >> (EC_WIN_SIZE - 16), r = s->rng >> 8; |
137 | 0 | unsigned u, v = s->rng, val = -1; |
138 | |
|
139 | 0 | assert(n_symbols <= 15); |
140 | 0 | assert(cdf[n_symbols] <= 32); |
141 | | |
142 | 0 | do { |
143 | 0 | val++; |
144 | 0 | u = v; |
145 | 0 | v = r * (cdf[val] >> EC_PROB_SHIFT); |
146 | 0 | v >>= 7 - EC_PROB_SHIFT; |
147 | 0 | v += EC_MIN_PROB * ((unsigned)n_symbols - val); |
148 | 0 | } while (c < v); |
149 | |
|
150 | 0 | assert(u <= s->rng); |
151 | | |
152 | 0 | ctx_norm(s, s->dif - ((ec_win)v << (EC_WIN_SIZE - 16)), u - v); |
153 | |
|
154 | 0 | if (s->allow_update_cdf) { |
155 | 0 | const unsigned count = cdf[n_symbols]; |
156 | 0 | const unsigned rate = 4 + (count >> 4) + (n_symbols > 2); |
157 | 0 | unsigned i; |
158 | 0 | for (i = 0; i < val; i++) |
159 | 0 | cdf[i] += (32768 - cdf[i]) >> rate; |
160 | 0 | for (; i < n_symbols; i++) |
161 | 0 | cdf[i] -= cdf[i] >> rate; |
162 | 0 | cdf[n_symbols] = count + (count < 32); |
163 | 0 | } |
164 | |
|
165 | 0 | return val; |
166 | 0 | } |
167 | | |
168 | | unsigned dav1d_msac_decode_bool_adapt_c(MsacContext *const s, |
169 | | uint16_t *const cdf) |
170 | 0 | { |
171 | 0 | const unsigned bit = dav1d_msac_decode_bool(s, *cdf); |
172 | |
|
173 | 0 | if (s->allow_update_cdf) { |
174 | | // update_cdf() specialized for boolean CDFs |
175 | 0 | const unsigned count = cdf[1]; |
176 | 0 | const int rate = 4 + (count >> 4); |
177 | 0 | if (bit) |
178 | 0 | cdf[0] += (32768 - cdf[0]) >> rate; |
179 | 0 | else |
180 | 0 | cdf[0] -= cdf[0] >> rate; |
181 | 0 | cdf[1] = count + (count < 32); |
182 | 0 | } |
183 | |
|
184 | 0 | return bit; |
185 | 0 | } |
186 | | |
187 | 0 | unsigned dav1d_msac_decode_hi_tok_c(MsacContext *const s, uint16_t *const cdf) { |
188 | 0 | unsigned tok_br = dav1d_msac_decode_symbol_adapt4(s, cdf, 3); |
189 | 0 | unsigned tok = 3 + tok_br; |
190 | 0 | if (tok_br == 3) { |
191 | 0 | tok_br = dav1d_msac_decode_symbol_adapt4(s, cdf, 3); |
192 | 0 | tok = 6 + tok_br; |
193 | 0 | if (tok_br == 3) { |
194 | 0 | tok_br = dav1d_msac_decode_symbol_adapt4(s, cdf, 3); |
195 | 0 | tok = 9 + tok_br; |
196 | 0 | if (tok_br == 3) |
197 | 0 | tok = 12 + dav1d_msac_decode_symbol_adapt4(s, cdf, 3); |
198 | 0 | } |
199 | 0 | } |
200 | 0 | return tok; |
201 | 0 | } |
202 | | #endif |
203 | | |
204 | | void dav1d_msac_init(MsacContext *const s, const uint8_t *const data, |
205 | | const size_t sz, const int disable_cdf_update_flag) |
206 | 0 | { |
207 | 0 | s->buf_pos = data; |
208 | 0 | s->buf_end = data + sz; |
209 | 0 | s->dif = 0; |
210 | 0 | s->rng = 0x8000; |
211 | 0 | s->cnt = -15; |
212 | 0 | s->allow_update_cdf = !disable_cdf_update_flag; |
213 | 0 | ctx_refill(s); |
214 | |
|
215 | | #if ARCH_X86_64 && HAVE_ASM |
216 | | s->symbol_adapt16 = dav1d_msac_decode_symbol_adapt_c; |
217 | | |
218 | | msac_init_x86(s); |
219 | | #endif |
220 | 0 | } |