blob: 336d22a18298961d93e655839206a43dd6e4316e
1 | /* |
2 | * Copyright (C) 2016 Open Broadcast Systems Ltd. |
3 | * Author 2016 Rostislav Pehlivanov <rpehlivanov@obe.tv> |
4 | * |
5 | * This file is part of FFmpeg. |
6 | * |
7 | * FFmpeg is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 of the License, or (at your option) any later version. |
11 | * |
12 | * FFmpeg is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with FFmpeg; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ |
21 | |
22 | #include "dirac_vlc.h" |
23 | |
24 | #define LUT_SIZE (1 << LUT_BITS) |
25 | #define RSIZE_BITS (CHAR_BIT*sizeof(residual)) |
26 | |
27 | #define CONVERT_TO_RESIDUE(a, b) \ |
28 | (((residual)(a)) << (RSIZE_BITS - (b))) |
29 | |
30 | #define INIT_RESIDUE(N) \ |
31 | residual N = 0; \ |
32 | av_unused int32_t N ## _bits = 0 |
33 | |
34 | #define SET_RESIDUE(N, I, B) \ |
35 | N = CONVERT_TO_RESIDUE(I, B); \ |
36 | N ## _bits = B |
37 | |
38 | #define APPEND_RESIDUE(N, M) \ |
39 | N |= M >> (N ## _bits); \ |
40 | N ## _bits += (M ## _bits) |
41 | |
42 | int ff_dirac_golomb_read_32bit(DiracGolombLUT *lut_ctx, const uint8_t *buf, |
43 | int bytes, uint8_t *_dst, int coeffs) |
44 | { |
45 | int i, b, c_idx = 0; |
46 | int32_t *dst = (int32_t *)_dst; |
47 | DiracGolombLUT *future[4], *l = &lut_ctx[2*LUT_SIZE + buf[0]]; |
48 | INIT_RESIDUE(res); |
49 | |
50 | for (b = 1; b <= bytes; b++) { |
51 | future[0] = &lut_ctx[buf[b]]; |
52 | future[1] = future[0] + 1*LUT_SIZE; |
53 | future[2] = future[0] + 2*LUT_SIZE; |
54 | future[3] = future[0] + 3*LUT_SIZE; |
55 | |
56 | if ((c_idx + 1) > coeffs) |
57 | return c_idx; |
58 | |
59 | /* res_bits is a hint for better branch prediction */ |
60 | if (res_bits && l->sign) { |
61 | int32_t coeff = 1; |
62 | APPEND_RESIDUE(res, l->preamble); |
63 | for (i = 0; i < (res_bits >> 1) - 1; i++) { |
64 | coeff <<= 1; |
65 | coeff |= (res >> (RSIZE_BITS - 2*i - 2)) & 1; |
66 | } |
67 | dst[c_idx++] = l->sign * (coeff - 1); |
68 | res_bits = res = 0; |
69 | } |
70 | |
71 | memcpy(&dst[c_idx], l->ready, LUT_BITS*sizeof(int32_t)); |
72 | c_idx += l->ready_num; |
73 | |
74 | APPEND_RESIDUE(res, l->leftover); |
75 | |
76 | l = future[l->need_s ? 3 : !res_bits ? 2 : res_bits & 1]; |
77 | } |
78 | |
79 | return c_idx; |
80 | } |
81 | |
82 | int ff_dirac_golomb_read_16bit(DiracGolombLUT *lut_ctx, const uint8_t *buf, |
83 | int bytes, uint8_t *_dst, int coeffs) |
84 | { |
85 | int i, b, c_idx = 0; |
86 | int16_t *dst = (int16_t *)_dst; |
87 | DiracGolombLUT *future[4], *l = &lut_ctx[2*LUT_SIZE + buf[0]]; |
88 | INIT_RESIDUE(res); |
89 | |
90 | for (b = 1; b <= bytes; b++) { |
91 | future[0] = &lut_ctx[buf[b]]; |
92 | future[1] = future[0] + 1*LUT_SIZE; |
93 | future[2] = future[0] + 2*LUT_SIZE; |
94 | future[3] = future[0] + 3*LUT_SIZE; |
95 | |
96 | if ((c_idx + 1) > coeffs) |
97 | return c_idx; |
98 | |
99 | if (res_bits && l->sign) { |
100 | int32_t coeff = 1; |
101 | APPEND_RESIDUE(res, l->preamble); |
102 | for (i = 0; i < (res_bits >> 1) - 1; i++) { |
103 | coeff <<= 1; |
104 | coeff |= (res >> (RSIZE_BITS - 2*i - 2)) & 1; |
105 | } |
106 | dst[c_idx++] = l->sign * (coeff - 1); |
107 | res_bits = res = 0; |
108 | } |
109 | |
110 | for (i = 0; i < LUT_BITS; i++) |
111 | dst[c_idx + i] = l->ready[i]; |
112 | c_idx += l->ready_num; |
113 | |
114 | APPEND_RESIDUE(res, l->leftover); |
115 | |
116 | l = future[l->need_s ? 3 : !res_bits ? 2 : res_bits & 1]; |
117 | } |
118 | |
119 | return c_idx; |
120 | } |
121 | |
122 | /* Searches for golomb codes in a residue */ |
123 | static inline void search_for_golomb(DiracGolombLUT *l, residual r, int bits) |
124 | { |
125 | int r_count = RSIZE_BITS - 1; |
126 | int bits_start, bits_tot = bits, need_sign = 0; |
127 | |
128 | #define READ_BIT(N) (((N) >> (N ## _count--)) & 1) |
129 | |
130 | while (1) { |
131 | int32_t coef = 1; |
132 | bits_start = (RSIZE_BITS - 1) - r_count; |
133 | |
134 | while (1) { |
135 | if (!bits--) |
136 | goto leftover; |
137 | if (READ_BIT(r)) |
138 | break; |
139 | |
140 | coef <<= 1; |
141 | |
142 | if (!bits--) |
143 | goto leftover; |
144 | coef |= READ_BIT(r); |
145 | } |
146 | |
147 | l->ready[l->ready_num] = coef - 1; |
148 | if (l->ready[l->ready_num]) { |
149 | if (!bits--) { |
150 | need_sign = 1; |
151 | goto leftover; |
152 | } |
153 | l->ready[l->ready_num] *= READ_BIT(r) ? -1 : +1; |
154 | } |
155 | l->ready_num++; |
156 | |
157 | if (!bits) |
158 | return; |
159 | } |
160 | |
161 | leftover: |
162 | l->leftover = r << bits_start; |
163 | l->leftover_bits = bits_tot - bits_start; |
164 | l->need_s = need_sign; |
165 | } |
166 | |
167 | /* Parity LUTs - even and odd bit end positions */ |
168 | static void generate_parity_lut(DiracGolombLUT *lut, int even) |
169 | { |
170 | int idx; |
171 | for (idx = 0; idx < LUT_SIZE; idx++) { |
172 | DiracGolombLUT *l = &lut[idx]; |
173 | int symbol_end_loc = -1; |
174 | uint32_t code; |
175 | int i; |
176 | |
177 | INIT_RESIDUE(res); |
178 | SET_RESIDUE(res, idx, LUT_BITS); |
179 | |
180 | for (i = 0; i < LUT_BITS; i++) { |
181 | const int cond = even ? (i & 1) : !(i & 1); |
182 | if (((res >> (RSIZE_BITS - i - 1)) & 1) && cond) { |
183 | symbol_end_loc = i + 2; |
184 | break; |
185 | } |
186 | } |
187 | |
188 | if (symbol_end_loc < 0 || symbol_end_loc > LUT_BITS) { |
189 | l->preamble = 0; |
190 | l->preamble_bits = 0; |
191 | l->leftover_bits = LUT_BITS; |
192 | l->leftover = CONVERT_TO_RESIDUE(idx, l->leftover_bits); |
193 | if (even) |
194 | l->need_s = idx & 1; |
195 | continue; |
196 | } |
197 | |
198 | /* Gets bits 0 through to (symbol_end_loc - 1) inclusive */ |
199 | code = idx >> ((LUT_BITS - 1) - (symbol_end_loc - 1)); |
200 | code &= ((1 << LUT_BITS) - 1) >> (LUT_BITS - symbol_end_loc); |
201 | l->preamble_bits = symbol_end_loc; |
202 | l->preamble = CONVERT_TO_RESIDUE(code, l->preamble_bits); |
203 | l->sign = ((l->preamble >> (RSIZE_BITS - l->preamble_bits)) & 1) ? -1 : +1; |
204 | |
205 | search_for_golomb(l, res << symbol_end_loc, LUT_BITS - symbol_end_loc); |
206 | } |
207 | } |
208 | |
209 | /* Reset (off == 0) and needs-one-more-bit (off == 1) LUTs */ |
210 | static void generate_offset_lut(DiracGolombLUT *lut, int off) |
211 | { |
212 | int idx; |
213 | for (idx = 0; idx < LUT_SIZE; idx++) { |
214 | DiracGolombLUT *l = &lut[idx]; |
215 | |
216 | INIT_RESIDUE(res); |
217 | SET_RESIDUE(res, idx, LUT_BITS); |
218 | |
219 | l->preamble = CONVERT_TO_RESIDUE(res >> (RSIZE_BITS - off), off); |
220 | l->preamble_bits = off; |
221 | l->sign = ((l->preamble >> (RSIZE_BITS - l->preamble_bits)) & 1) ? -1 : +1; |
222 | |
223 | search_for_golomb(l, res << off, LUT_BITS - off); |
224 | } |
225 | } |
226 | |
227 | av_cold int ff_dirac_golomb_reader_init(DiracGolombLUT **lut_ctx) |
228 | { |
229 | DiracGolombLUT *lut; |
230 | |
231 | if (!(lut = av_calloc(4*LUT_SIZE, sizeof(DiracGolombLUT)))) |
232 | return AVERROR(ENOMEM); |
233 | |
234 | generate_parity_lut(&lut[0*LUT_SIZE], 0); |
235 | generate_parity_lut(&lut[1*LUT_SIZE], 1); |
236 | generate_offset_lut(&lut[2*LUT_SIZE], 0); |
237 | generate_offset_lut(&lut[3*LUT_SIZE], 1); |
238 | |
239 | *lut_ctx = lut; |
240 | |
241 | return 0; |
242 | } |
243 | |
244 | av_cold void ff_dirac_golomb_reader_end(DiracGolombLUT **lut_ctx) |
245 | { |
246 | av_freep(lut_ctx); |
247 | } |
248 |