xine-lib 1.2.13-20230125hg15249
vdec_hw_bits_reader.h
Go to the documentation of this file.
1/* kate: tab-indent on; indent-width 4; mixedindent off; indent-mode cstyle; remove-trailing-space on; */
2/*
3 * Copyright (C) 2008-2021 the xine project
4 *
5 * This file is part of xine, a free video player.
6 *
7 * xine is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * xine 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
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
20 *
21 */
22
23#ifndef ALTERH264_BITS_READER_H
24#define ALTERH264_BITS_READER_H
25#include <sys/types.h>
26#include <inttypes.h>
27#include <stdio.h>
28
29typedef struct {
30 const uint32_t *read;
31 const uint8_t *start, *end;
32 uint32_t val, bits, oflow;
34
35static void bits_set_buf (bits_reader_t *br, const uint8_t *buf, uint32_t len) {
36 const union {
37 uint32_t word;
38 uint8_t little;
39 } endian_is = {1};
40 uint32_t v;
41
42 br->start = buf;
43 br->end = buf + len;
44 br->read = (const uint32_t *)((uintptr_t)buf & ~(uintptr_t)3);
45 br->bits = 32 - (buf - (const uint8_t *)br->read) * 8;
46 v = *br->read++;
47 if (endian_is.little)
48 v = (v >> 24) | ((v >> 8) & 0x0000ff00) | ((v << 8) & 0x00ff0000) | (v << 24);
49 br->val = v << (32 - br->bits);
50 br->oflow = 0;
51}
52
53static inline uint32_t bits_tell (bits_reader_t *br) {
54 return ((const uint8_t *)br->read - br->start) * 8 - br->bits;
55}
56
57/* NOTE: mathematically, uint32_t << 32 yields 0.
58 * however, real life truncates the shift width to 5 bits (32 == 0),
59 * and thus has no effect. lets use some paranoia that gcc will
60 * optimize away in most cases where width is constant. */
61
63static uint32_t _bits_read_slow (bits_reader_t *br, uint32_t bits) {
64 const union {
65 uint32_t word;
66 uint8_t little;
67 } endian_is = {1};
68 uint32_t v1, v2;
69 int left = (br->end - (const uint8_t *)br->read) * 8;
70
71 if (br->bits) {
72 v1 = br->val >> (32 - br->bits);
73 bits -= br->bits;
74 v1 <<= bits;
75 } else {
76 v1 = 0;
77 }
78 if (left < 32) {
79 if (left < (int)bits) {
80 br->read = (const uint32_t *)(((uintptr_t)br->end + 3) & ~(uintptr_t)3);
81 br->bits = 0;
82 br->oflow = 1;
83 return 0;
84 }
85 } else {
86 left = 32;
87 }
88 v2 = *br->read++;
89 if (endian_is.little)
90 v2 = (v2 >> 24) | ((v2 >> 8) & 0x0000ff00) | ((v2 << 8) & 0x00ff0000) | (v2 << 24);
91 /* bits > 0 is sure here. */
92 v1 |= v2 >> (32 - bits);
93 br->val = v2 << bits;
94 br->bits = left - bits;
95 return v1;
96}
97
99static inline uint32_t bits_read (bits_reader_t *br, const uint32_t bits) {
100 uint32_t v;
101
102 if (!bits)
103 return 0;
104 if (br->bits >= bits) {
105 v = br->val >> (32 - bits);
106 br->val <<= bits;
107 br->bits -= bits;
108 return v;
109 }
110 return _bits_read_slow (br, bits);
111}
112
113static void _bits_skip_slow (bits_reader_t *br, uint32_t bits) {
114 const union {
115 uint32_t word;
116 uint8_t little;
117 } endian_is = {1};
118 uint32_t v2;
119 int left = (br->end - (const uint8_t *)br->read) * 8;
120
121 bits -= br->bits;
122 left -= bits;
123 if (left < 0) {
124 br->read = (const uint32_t *)(((uintptr_t)br->end + 3) & ~(uintptr_t)3);
125 br->bits = 0;
126 br->oflow = 1;
127 return;
128 }
129 br->read += bits >> 5;
130 v2 = *br->read++;
131 if (endian_is.little)
132 v2 = (v2 >> 24) | ((v2 >> 8) & 0x0000ff00) | ((v2 << 8) & 0x00ff0000) | (v2 << 24);
133 bits &= 31;
134 br->val = v2 << bits;
135 br->bits = (left >= 32 ? 32 : left) - bits;
136}
137
139static inline void bits_skip (bits_reader_t *br, const uint32_t bits) {
140 if (!bits)
141 return;
142 if (br->bits >= bits) {
143 br->val <<= bits;
144 br->bits -= bits;
145 } else {
146 _bits_skip_slow (br, bits);
147 }
148}
149
150/* needing this func at all is a nasty kludge.
151 * h.264 PPS has an optional extension that has been added without defining
152 * a presence flag earlier... */
154static uint32_t bits_valid_left (bits_reader_t *br) {
155 static const uint32_t mask[4] = {0x00000000, 0xff000000, 0xffff0000, 0xffffff00};
156 const union {
157 uint32_t word;
158 uint8_t little;
159 } endian_is = {1};
160 uint32_t v;
161 int n;
162
163 do {
164 /* search yet unread bits for last "1". */
165 if ((const uint8_t *)br->read < br->end) {
166 const uint32_t *p = (const uint32_t *)((uintptr_t)br->end & ~(uintptr_t)3);
167
168 n = br->end - (const uint8_t *)p;
169 if (n > 0) {
170 v = *p;
171 if (endian_is.little)
172 v = (v >> 24) | ((v >> 8) & 0x0000ff00) | ((v << 8) & 0x00ff0000) | (v << 24);
173 v &= mask[n];
174 } else {
175 v = 0;
176 }
177
178 while (!v && (p > br->read)) {
179 v = *--p;
180 if (endian_is.little)
181 v = (v >> 24) | ((v >> 8) & 0x0000ff00) | ((v << 8) & 0x00ff0000) | (v << 24);
182 }
183 n = (p - br->read) * 32 + br->bits;
184 if (v)
185 break;
186 }
187 /* well, only value cache is left to test. */
188 if (!br->bits)
189 return 0;
190 /* for performance, we dont end mask br->val generally. */
191 n = 32 - br->bits;
192 v = br->val >> n << n;
193 n = 0;
194 } while (0);
195
196 while (v)
197 n++, v <<= 1;
198 return n;
199}
200
201static uint32_t bits_exp_ue (bits_reader_t * br) {
202 const union {
203 uint32_t word;
204 uint8_t little;
205 } endian_is = {1};
206 uint32_t size;
207 /* count leading 0 bits */
208 if (br->bits && br->val) {
209 uint32_t v1 = br->val;
210
211 size = 0;
212 while (!(v1 & 0x80000000))
213 v1 <<= 1, size++;
214 br->val = v1;
215 br->bits -= size;
216 } else {
217 int left = (br->end - (const uint8_t *)br->read) * 8;
218 uint32_t v2, rest;
219
220 if (left <= 0) {
221 br->read = (const uint32_t *)(((uintptr_t)br->end + 3) & ~(uintptr_t)3);
222 br->bits = 0;
223 br->oflow = 1;
224 return 0;
225 }
226 size = br->bits;
227 rest = 32 - size;
228 if (rest > (uint32_t)left)
229 rest = left;
230 v2 = *br->read++;
231 if (endian_is.little)
232 v2 = (v2 >> 24) | ((v2 >> 8) & 0x0000ff00) | ((v2 << 8) & 0x00ff0000) | (v2 << 24);
233 if (v2 & (0xffffffff << (32 - rest))) {
234 while (!(v2 & 0x80000000))
235 v2 <<= 1, size++;
236 } else {
237 v2 <<= rest;
238 size += rest;
239 }
240 br->val = v2;
241 br->bits = (left > 32 ? 32 : left) + br->bits - size;
242 }
243 /* get sized value */
244 size++;
245 if (br->bits >= size) {
246 uint32_t res = br->val >> (32 - size);
247
248 br->val <<= size;
249 br->bits -= size;
250 return res - 1;
251 } else {
252 uint32_t v2, res;
253 int left = (br->end - (const uint8_t *)br->read) * 8;
254
255 size -= br->bits;
256 if (left < (int)size) {
257 br->read = (const uint32_t *)(((uintptr_t)br->end + 3) & ~(uintptr_t)3);
258 br->bits = 0;
259 br->oflow = 1;
260 return 0;
261 }
262 res = br->bits ? br->val >> (32 - br->bits) : 0;
263 v2 = *br->read++;
264 if (endian_is.little)
265 v2 = (v2 >> 24) | ((v2 >> 8) & 0x0000ff00) | ((v2 << 8) & 0x00ff0000) | (v2 << 24);
266 res = (res << size) + (v2 >> (32 - size));
267 br->val = v2 << size;
268 br->bits = (left > 32 ? 32 : left) - size;
269 return res - 1;
270 }
271}
272
273static inline int32_t bits_exp_se (bits_reader_t * br) {
274 uint32_t res = bits_exp_ue (br);
275
276 return (res & 1) ? (int32_t)((res + 1) >> 1) : -(int32_t)(res >> 1);
277}
278
279#ifdef TEST_THIS_FILE
280# include <stdio.h>
281
282int main (int argc, char **argv) {
283 static const uint8_t test[] = "\x75\x99\xfb\x07\x55\xd8\xff\x23\x11\xab\xa8";
284 bits_reader_t br;
285 unsigned int v1, v2, v3, v4, v5, v6, v7, v8, v9, m;
286
287 (void)argc;
288 (void)argv;
289 bits_set_buf (&br, test + 1, sizeof (test) - 1);
290 bits_skip (&br, 1);
291 v1 = bits_read (&br, 3);
292 v2 = bits_read (&br, 7);
293 v3 = bits_read (&br, 5);
294 bits_skip (&br, 8);
295 v4 = bits_read (&br, 8);
296 bits_skip (&br, 7);
297 v5 = bits_read (&br, 1);
298 m = bits_valid_left (&br);
299 v6 = bits_read (&br, 12);
300 v7 = bits_read (&br, 4);
301 v8 = bits_read (&br, 23);
302 v9 = bits_read (&br, 9);
303 printf ("%s\n", __FILE__);
304 printf ("(1) 3 7 5 (8) 8 (7) 1 12 4 23 9\n");
305 printf ("--- %08x %08x %08x --- %08x --- %08x %08x %08x %08x %08x\n", v1, v2, v3, v4, v5, v6, v7, v8, v9);
306 printf ("more: %08x\n", m);
307 return 0;
308}
309
310#endif
311#endif /* ALTERH264_BITS_READER_H */
312
#define bits
Definition bits_reader.h:26
const uint8_t * start
Definition bits_reader.h:27
int oflow
Definition bits_reader.h:28
uint32_t bits
Definition vdec_hw_bits_reader.h:32
const uint32_t * read
Definition vdec_hw_bits_reader.h:30
uint32_t val
Definition vdec_hw_bits_reader.h:32
const uint8_t * end
Definition vdec_hw_bits_reader.h:31
uint32_t v
Definition utils.c:1157
static uint32_t bits_exp_ue(bits_reader_t *br)
Definition vdec_hw_bits_reader.h:201
static int32_t bits_exp_se(bits_reader_t *br)
Definition vdec_hw_bits_reader.h:273
static void _bits_skip_slow(bits_reader_t *br, uint32_t bits)
Definition vdec_hw_bits_reader.h:113
static uint32_t bits_tell(bits_reader_t *br)
Definition vdec_hw_bits_reader.h:53
static uint32_t bits_read(bits_reader_t *br, const uint32_t bits)
Definition vdec_hw_bits_reader.h:99
static void bits_set_buf(bits_reader_t *br, const uint8_t *buf, uint32_t len)
Definition vdec_hw_bits_reader.h:35
static void bits_skip(bits_reader_t *br, const uint32_t bits)
Definition vdec_hw_bits_reader.h:139
static uint32_t bits_valid_left(bits_reader_t *br)
Definition vdec_hw_bits_reader.h:154
static uint32_t _bits_read_slow(bits_reader_t *br, uint32_t bits)
Definition vdec_hw_bits_reader.h:63