blob: e092b627820e5c1c21444e46945fbf9c05d42151 [file] [log] [blame]
Debargha Mukherjee47748b52017-03-24 12:20:49 -07001/*
2 * Copyright (c) 2017, 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#include "aom_dsp/bitwriter.h"
Sarah Parker3e579a62017-08-23 16:53:20 -070013#include "aom_dsp/binary_codes_writer.h"
Debargha Mukherjee47748b52017-03-24 12:20:49 -070014
15#include "av1/common/common.h"
16
17// Recenters a non-negative literal v around a reference r
18static uint16_t recenter_nonneg(uint16_t r, uint16_t v) {
19 if (v > (r << 1))
20 return v;
21 else if (v >= r)
22 return ((v - r) << 1);
23 else
24 return ((r - v) << 1) - 1;
25}
26
27// Recenters a non-negative literal v in [0, n-1] around a
28// reference r also in [0, n-1]
29static uint16_t recenter_finite_nonneg(uint16_t n, uint16_t r, uint16_t v) {
30 if ((r << 1) <= n) {
31 return recenter_nonneg(r, v);
32 } else {
33 return recenter_nonneg(n - 1 - r, n - 1 - v);
34 }
35}
36
37// Codes a symbol v in [-2^mag_bits, 2^mag_bits].
38// mag_bits is number of bits for magnitude. The alphabet is of size
39// 2 * 2^mag_bits + 1, symmetric around 0, where one bit is used to
40// indicate 0 or non-zero, mag_bits bits are used to indicate magnitide
41// and 1 more bit for the sign if non-zero.
42void aom_write_primitive_symmetric(aom_writer *w, int16_t v,
43 unsigned int abs_bits) {
44 if (v == 0) {
45 aom_write_bit(w, 0);
46 } else {
47 const int x = abs(v);
48 const int s = v < 0;
49 aom_write_bit(w, 1);
50 aom_write_bit(w, s);
51 aom_write_literal(w, x - 1, abs_bits);
52 }
53}
54
55int aom_count_primitive_symmetric(int16_t v, unsigned int abs_bits) {
56 return (v == 0 ? 1 : abs_bits + 2);
57}
58
59// Encodes a value v in [0, n-1] quasi-uniformly
60void aom_write_primitive_quniform(aom_writer *w, uint16_t n, uint16_t v) {
61 if (n <= 1) return;
62 const int l = get_msb(n - 1) + 1;
63 const int m = (1 << l) - n;
64 if (v < m) {
65 aom_write_literal(w, v, l - 1);
66 } else {
67 aom_write_literal(w, m + ((v - m) >> 1), l - 1);
68 aom_write_bit(w, (v - m) & 1);
69 }
70}
71
Sarah Parker3e579a62017-08-23 16:53:20 -070072static void aom_wb_write_primitive_quniform(struct aom_write_bit_buffer *wb,
73 uint16_t n, uint16_t v) {
74 if (n <= 1) return;
75 const int l = get_msb(n - 1) + 1;
76 const int m = (1 << l) - n;
77 if (v < m) {
78 aom_wb_write_literal(wb, v, l - 1);
79 } else {
80 aom_wb_write_literal(wb, m + ((v - m) >> 1), l - 1);
81 aom_wb_write_bit(wb, (v - m) & 1);
82 }
83}
84
Debargha Mukherjee47748b52017-03-24 12:20:49 -070085int aom_count_primitive_quniform(uint16_t n, uint16_t v) {
86 if (n <= 1) return 0;
87 const int l = get_msb(n - 1) + 1;
88 const int m = (1 << l) - n;
89 return v < m ? l - 1 : l;
90}
91
92// Encodes a value v in [0, n-1] based on a reference ref also in [0, n-1]
93// The closest p values of v from ref are coded using a p-ary quasi-unoform
94// short code while the remaining n-p values are coded with a longer code.
95void aom_write_primitive_refbilevel(aom_writer *w, uint16_t n, uint16_t p,
96 uint16_t ref, uint16_t v) {
97 if (n <= 1) return;
98 assert(p > 0 && p <= n);
99 assert(ref < n);
100 int lolimit = ref - p / 2;
101 int hilimit = lolimit + p - 1;
102 if (lolimit < 0) {
103 lolimit = 0;
104 hilimit = p - 1;
105 } else if (hilimit >= n) {
106 hilimit = n - 1;
107 lolimit = n - p;
108 }
109 if (v >= lolimit && v <= hilimit) {
110 aom_write_bit(w, 1);
111 v = v - lolimit;
112 aom_write_primitive_quniform(w, p, v);
113 } else {
114 aom_write_bit(w, 0);
115 if (v > hilimit) v -= p;
116 aom_write_primitive_quniform(w, n - p, v);
117 }
118}
119
120int aom_count_primitive_refbilevel(uint16_t n, uint16_t p, uint16_t ref,
121 uint16_t v) {
122 if (n <= 1) return 0;
123 assert(p > 0 && p <= n);
124 assert(ref < n);
125 int lolimit = ref - p / 2;
126 int hilimit = lolimit + p - 1;
127 if (lolimit < 0) {
128 lolimit = 0;
129 hilimit = p - 1;
130 } else if (hilimit >= n) {
131 hilimit = n - 1;
132 lolimit = n - p;
133 }
134 int count = 0;
135 if (v >= lolimit && v <= hilimit) {
136 count++;
137 v = v - lolimit;
138 count += aom_count_primitive_quniform(p, v);
139 } else {
140 count++;
141 if (v > hilimit) v -= p;
142 count += aom_count_primitive_quniform(n - p, v);
143 }
144 return count;
145}
146
147// Finite subexponential code that codes a symbol v in [0, n-1] with parameter k
148void aom_write_primitive_subexpfin(aom_writer *w, uint16_t n, uint16_t k,
149 uint16_t v) {
150 int i = 0;
151 int mk = 0;
152 while (1) {
153 int b = (i ? k + i - 1 : k);
154 int a = (1 << b);
155 if (n <= mk + 3 * a) {
156 aom_write_primitive_quniform(w, n - mk, v - mk);
157 break;
158 } else {
159 int t = (v >= mk + a);
160 aom_write_bit(w, t);
161 if (t) {
162 i = i + 1;
163 mk += a;
164 } else {
165 aom_write_literal(w, v - mk, b);
166 break;
167 }
168 }
169 }
170}
171
Sarah Parker3e579a62017-08-23 16:53:20 -0700172static void aom_wb_write_primitive_subexpfin(struct aom_write_bit_buffer *wb,
173 uint16_t n, uint16_t k,
174 uint16_t v) {
175 int i = 0;
176 int mk = 0;
177 while (1) {
178 int b = (i ? k + i - 1 : k);
179 int a = (1 << b);
180 if (n <= mk + 3 * a) {
181 aom_wb_write_primitive_quniform(wb, n - mk, v - mk);
182 break;
183 } else {
184 int t = (v >= mk + a);
185 aom_wb_write_bit(wb, t);
186 if (t) {
187 i = i + 1;
188 mk += a;
189 } else {
190 aom_wb_write_literal(wb, v - mk, b);
191 break;
192 }
193 }
194 }
195}
196
Debargha Mukherjee47748b52017-03-24 12:20:49 -0700197int aom_count_primitive_subexpfin(uint16_t n, uint16_t k, uint16_t v) {
198 int count = 0;
199 int i = 0;
200 int mk = 0;
201 while (1) {
202 int b = (i ? k + i - 1 : k);
203 int a = (1 << b);
204 if (n <= mk + 3 * a) {
205 count += aom_count_primitive_quniform(n - mk, v - mk);
206 break;
207 } else {
208 int t = (v >= mk + a);
209 count++;
210 if (t) {
211 i = i + 1;
212 mk += a;
213 } else {
214 count += b;
215 break;
216 }
217 }
218 }
219 return count;
220}
221
222// Finite subexponential code that codes a symbol v in [0, n-1] with parameter k
223// based on a reference ref also in [0, n-1].
224// Recenters symbol around r first and then uses a finite subexponential code.
225void aom_write_primitive_refsubexpfin(aom_writer *w, uint16_t n, uint16_t k,
Sarah Parker3e579a62017-08-23 16:53:20 -0700226 uint16_t ref, uint16_t v) {
Debargha Mukherjee47748b52017-03-24 12:20:49 -0700227 aom_write_primitive_subexpfin(w, n, k, recenter_finite_nonneg(n, ref, v));
228}
229
Sarah Parker3e579a62017-08-23 16:53:20 -0700230static void aom_wb_write_primitive_refsubexpfin(struct aom_write_bit_buffer *wb,
231 uint16_t n, uint16_t k,
232 uint16_t ref, uint16_t v) {
233 aom_wb_write_primitive_subexpfin(wb, n, k, recenter_finite_nonneg(n, ref, v));
234}
235
Sarah Parkerf1783292017-04-05 11:55:27 -0700236void aom_write_signed_primitive_refsubexpfin(aom_writer *w, uint16_t n,
Sarah Parker3e579a62017-08-23 16:53:20 -0700237 uint16_t k, int16_t ref,
238 int16_t v) {
Sarah Parkerf1783292017-04-05 11:55:27 -0700239 ref += n - 1;
240 v += n - 1;
241 const uint16_t scaled_n = (n << 1) - 1;
242 aom_write_primitive_refsubexpfin(w, scaled_n, k, ref, v);
243}
244
Sarah Parker3e579a62017-08-23 16:53:20 -0700245void aom_wb_write_signed_primitive_refsubexpfin(struct aom_write_bit_buffer *wb,
246 uint16_t n, uint16_t k,
247 int16_t ref, int16_t v) {
248 ref += n - 1;
249 v += n - 1;
250 const uint16_t scaled_n = (n << 1) - 1;
251 aom_wb_write_primitive_refsubexpfin(wb, scaled_n, k, ref, v);
252}
253
Debargha Mukherjee47748b52017-03-24 12:20:49 -0700254int aom_count_primitive_refsubexpfin(uint16_t n, uint16_t k, uint16_t ref,
255 uint16_t v) {
256 return aom_count_primitive_subexpfin(n, k, recenter_finite_nonneg(n, ref, v));
257}
Sarah Parkerf1783292017-04-05 11:55:27 -0700258
259int aom_count_signed_primitive_refsubexpfin(uint16_t n, uint16_t k, int16_t ref,
260 int16_t v) {
261 ref += n - 1;
262 v += n - 1;
263 const uint16_t scaled_n = (n << 1) - 1;
264 return aom_count_primitive_refsubexpfin(scaled_n, k, ref, v);
265}