Line data Source code
1 : /*
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"
13 :
14 : #include "av1/common/common.h"
15 :
16 : // Recenters a non-negative literal v around a reference r
17 0 : static uint16_t recenter_nonneg(uint16_t r, uint16_t v) {
18 0 : if (v > (r << 1))
19 0 : return v;
20 0 : else if (v >= r)
21 0 : return ((v - r) << 1);
22 : else
23 0 : return ((r - v) << 1) - 1;
24 : }
25 :
26 : // Recenters a non-negative literal v in [0, n-1] around a
27 : // reference r also in [0, n-1]
28 0 : static uint16_t recenter_finite_nonneg(uint16_t n, uint16_t r, uint16_t v) {
29 0 : if ((r << 1) <= n) {
30 0 : return recenter_nonneg(r, v);
31 : } else {
32 0 : return recenter_nonneg(n - 1 - r, n - 1 - v);
33 : }
34 : }
35 :
36 : // Codes a symbol v in [-2^mag_bits, 2^mag_bits].
37 : // mag_bits is number of bits for magnitude. The alphabet is of size
38 : // 2 * 2^mag_bits + 1, symmetric around 0, where one bit is used to
39 : // indicate 0 or non-zero, mag_bits bits are used to indicate magnitide
40 : // and 1 more bit for the sign if non-zero.
41 0 : void aom_write_primitive_symmetric(aom_writer *w, int16_t v,
42 : unsigned int abs_bits) {
43 0 : if (v == 0) {
44 0 : aom_write_bit(w, 0);
45 : } else {
46 0 : const int x = abs(v);
47 0 : const int s = v < 0;
48 0 : aom_write_bit(w, 1);
49 0 : aom_write_bit(w, s);
50 0 : aom_write_literal(w, x - 1, abs_bits);
51 : }
52 0 : }
53 :
54 0 : int aom_count_primitive_symmetric(int16_t v, unsigned int abs_bits) {
55 0 : return (v == 0 ? 1 : abs_bits + 2);
56 : }
57 :
58 : // Encodes a value v in [0, n-1] quasi-uniformly
59 0 : void aom_write_primitive_quniform(aom_writer *w, uint16_t n, uint16_t v) {
60 0 : if (n <= 1) return;
61 0 : const int l = get_msb(n - 1) + 1;
62 0 : const int m = (1 << l) - n;
63 0 : if (v < m) {
64 0 : aom_write_literal(w, v, l - 1);
65 : } else {
66 0 : aom_write_literal(w, m + ((v - m) >> 1), l - 1);
67 0 : aom_write_bit(w, (v - m) & 1);
68 : }
69 : }
70 :
71 0 : int aom_count_primitive_quniform(uint16_t n, uint16_t v) {
72 0 : if (n <= 1) return 0;
73 0 : const int l = get_msb(n - 1) + 1;
74 0 : const int m = (1 << l) - n;
75 0 : return v < m ? l - 1 : l;
76 : }
77 :
78 : // Encodes a value v in [0, n-1] based on a reference ref also in [0, n-1]
79 : // The closest p values of v from ref are coded using a p-ary quasi-unoform
80 : // short code while the remaining n-p values are coded with a longer code.
81 0 : void aom_write_primitive_refbilevel(aom_writer *w, uint16_t n, uint16_t p,
82 : uint16_t ref, uint16_t v) {
83 0 : if (n <= 1) return;
84 0 : assert(p > 0 && p <= n);
85 0 : assert(ref < n);
86 0 : int lolimit = ref - p / 2;
87 0 : int hilimit = lolimit + p - 1;
88 0 : if (lolimit < 0) {
89 0 : lolimit = 0;
90 0 : hilimit = p - 1;
91 0 : } else if (hilimit >= n) {
92 0 : hilimit = n - 1;
93 0 : lolimit = n - p;
94 : }
95 0 : if (v >= lolimit && v <= hilimit) {
96 0 : aom_write_bit(w, 1);
97 0 : v = v - lolimit;
98 0 : aom_write_primitive_quniform(w, p, v);
99 : } else {
100 0 : aom_write_bit(w, 0);
101 0 : if (v > hilimit) v -= p;
102 0 : aom_write_primitive_quniform(w, n - p, v);
103 : }
104 : }
105 :
106 0 : int aom_count_primitive_refbilevel(uint16_t n, uint16_t p, uint16_t ref,
107 : uint16_t v) {
108 0 : if (n <= 1) return 0;
109 0 : assert(p > 0 && p <= n);
110 0 : assert(ref < n);
111 0 : int lolimit = ref - p / 2;
112 0 : int hilimit = lolimit + p - 1;
113 0 : if (lolimit < 0) {
114 0 : lolimit = 0;
115 0 : hilimit = p - 1;
116 0 : } else if (hilimit >= n) {
117 0 : hilimit = n - 1;
118 0 : lolimit = n - p;
119 : }
120 0 : int count = 0;
121 0 : if (v >= lolimit && v <= hilimit) {
122 0 : count++;
123 0 : v = v - lolimit;
124 0 : count += aom_count_primitive_quniform(p, v);
125 : } else {
126 0 : count++;
127 0 : if (v > hilimit) v -= p;
128 0 : count += aom_count_primitive_quniform(n - p, v);
129 : }
130 0 : return count;
131 : }
132 :
133 : // Finite subexponential code that codes a symbol v in [0, n-1] with parameter k
134 0 : void aom_write_primitive_subexpfin(aom_writer *w, uint16_t n, uint16_t k,
135 : uint16_t v) {
136 0 : int i = 0;
137 0 : int mk = 0;
138 0 : while (1) {
139 0 : int b = (i ? k + i - 1 : k);
140 0 : int a = (1 << b);
141 0 : if (n <= mk + 3 * a) {
142 0 : aom_write_primitive_quniform(w, n - mk, v - mk);
143 0 : break;
144 : } else {
145 0 : int t = (v >= mk + a);
146 0 : aom_write_bit(w, t);
147 0 : if (t) {
148 0 : i = i + 1;
149 0 : mk += a;
150 : } else {
151 0 : aom_write_literal(w, v - mk, b);
152 0 : break;
153 : }
154 : }
155 : }
156 0 : }
157 :
158 0 : int aom_count_primitive_subexpfin(uint16_t n, uint16_t k, uint16_t v) {
159 0 : int count = 0;
160 0 : int i = 0;
161 0 : int mk = 0;
162 0 : while (1) {
163 0 : int b = (i ? k + i - 1 : k);
164 0 : int a = (1 << b);
165 0 : if (n <= mk + 3 * a) {
166 0 : count += aom_count_primitive_quniform(n - mk, v - mk);
167 0 : break;
168 : } else {
169 0 : int t = (v >= mk + a);
170 0 : count++;
171 0 : if (t) {
172 0 : i = i + 1;
173 0 : mk += a;
174 : } else {
175 0 : count += b;
176 0 : break;
177 : }
178 : }
179 : }
180 0 : return count;
181 : }
182 :
183 : // Finite subexponential code that codes a symbol v in [0, n-1] with parameter k
184 : // based on a reference ref also in [0, n-1].
185 : // Recenters symbol around r first and then uses a finite subexponential code.
186 0 : void aom_write_primitive_refsubexpfin(aom_writer *w, uint16_t n, uint16_t k,
187 : int16_t ref, int16_t v) {
188 0 : aom_write_primitive_subexpfin(w, n, k, recenter_finite_nonneg(n, ref, v));
189 0 : }
190 :
191 0 : void aom_write_signed_primitive_refsubexpfin(aom_writer *w, uint16_t n,
192 : uint16_t k, uint16_t ref,
193 : uint16_t v) {
194 0 : ref += n - 1;
195 0 : v += n - 1;
196 0 : const uint16_t scaled_n = (n << 1) - 1;
197 0 : aom_write_primitive_refsubexpfin(w, scaled_n, k, ref, v);
198 0 : }
199 :
200 0 : int aom_count_primitive_refsubexpfin(uint16_t n, uint16_t k, uint16_t ref,
201 : uint16_t v) {
202 0 : return aom_count_primitive_subexpfin(n, k, recenter_finite_nonneg(n, ref, v));
203 : }
204 :
205 0 : int aom_count_signed_primitive_refsubexpfin(uint16_t n, uint16_t k, int16_t ref,
206 : int16_t v) {
207 0 : ref += n - 1;
208 0 : v += n - 1;
209 0 : const uint16_t scaled_n = (n << 1) - 1;
210 0 : return aom_count_primitive_refsubexpfin(scaled_n, k, ref, v);
211 : }
|