summaryrefslogtreecommitdiff
path: root/libavcodec/dirac_vlc.c (plain)
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
42int 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
82int 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 */
123static 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 */
168static 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 */
210static 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
227av_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
244av_cold void ff_dirac_golomb_reader_end(DiracGolombLUT **lut_ctx)
245{
246 av_freep(lut_ctx);
247}
248