]> git.sesse.net Git - ffmpeg/blob - libavcodec/dirac_vlc.c
Merge commit '3152058bf1dca318898550efacf0286f4836cae6'
[ffmpeg] / libavcodec / dirac_vlc.c
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  = (N ## _bits + (M ## _bits)) & 0x3F
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_bits = off;
220         if (off) {
221             l->preamble  = CONVERT_TO_RESIDUE(res >> (RSIZE_BITS - off), off);
222             l->sign      = ((l->preamble >> (RSIZE_BITS - l->preamble_bits)) & 1) ? -1 : +1;
223         } else {
224             l->preamble  = 0;
225             l->sign = 1;
226         }
227
228         search_for_golomb(l, res << off, LUT_BITS - off);
229     }
230 }
231
232 av_cold int ff_dirac_golomb_reader_init(DiracGolombLUT **lut_ctx)
233 {
234     DiracGolombLUT *lut;
235
236     if (!(lut = av_calloc(4*LUT_SIZE, sizeof(DiracGolombLUT))))
237         return AVERROR(ENOMEM);
238
239     generate_parity_lut(&lut[0*LUT_SIZE], 0);
240     generate_parity_lut(&lut[1*LUT_SIZE], 1);
241     generate_offset_lut(&lut[2*LUT_SIZE], 0);
242     generate_offset_lut(&lut[3*LUT_SIZE], 1);
243
244     *lut_ctx = lut;
245
246     return 0;
247 }
248
249 av_cold void ff_dirac_golomb_reader_end(DiracGolombLUT **lut_ctx)
250 {
251     av_freep(lut_ctx);
252 }