blob: 7be7fc22fc8e3451b49211841b8870152ea198e0
1 | /* |
2 | * Bytestream functions |
3 | * copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@free.fr> |
4 | * Copyright (c) 2012 Aneesh Dogra (lionaneesh) <lionaneesh@gmail.com> |
5 | * |
6 | * This file is part of FFmpeg. |
7 | * |
8 | * FFmpeg is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU Lesser General Public |
10 | * License as published by the Free Software Foundation; either |
11 | * version 2.1 of the License, or (at your option) any later version. |
12 | * |
13 | * FFmpeg is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | * Lesser General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU Lesser General Public |
19 | * License along with FFmpeg; if not, write to the Free Software |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | */ |
22 | |
23 | #ifndef AVCODEC_BYTESTREAM_H |
24 | #define AVCODEC_BYTESTREAM_H |
25 | |
26 | #include <stdint.h> |
27 | #include <string.h> |
28 | |
29 | #include "libavutil/avassert.h" |
30 | #include "libavutil/common.h" |
31 | #include "libavutil/intreadwrite.h" |
32 | |
33 | typedef struct GetByteContext { |
34 | const uint8_t *buffer, *buffer_end, *buffer_start; |
35 | } GetByteContext; |
36 | |
37 | typedef struct PutByteContext { |
38 | uint8_t *buffer, *buffer_end, *buffer_start; |
39 | int eof; |
40 | } PutByteContext; |
41 | |
42 | #define DEF(type, name, bytes, read, write) \ |
43 | static av_always_inline type bytestream_get_ ## name(const uint8_t **b) \ |
44 | { \ |
45 | (*b) += bytes; \ |
46 | return read(*b - bytes); \ |
47 | } \ |
48 | static av_always_inline void bytestream_put_ ## name(uint8_t **b, \ |
49 | const type value) \ |
50 | { \ |
51 | write(*b, value); \ |
52 | (*b) += bytes; \ |
53 | } \ |
54 | static av_always_inline void bytestream2_put_ ## name ## u(PutByteContext *p, \ |
55 | const type value) \ |
56 | { \ |
57 | bytestream_put_ ## name(&p->buffer, value); \ |
58 | } \ |
59 | static av_always_inline void bytestream2_put_ ## name(PutByteContext *p, \ |
60 | const type value) \ |
61 | { \ |
62 | if (!p->eof && (p->buffer_end - p->buffer >= bytes)) { \ |
63 | write(p->buffer, value); \ |
64 | p->buffer += bytes; \ |
65 | } else \ |
66 | p->eof = 1; \ |
67 | } \ |
68 | static av_always_inline type bytestream2_get_ ## name ## u(GetByteContext *g) \ |
69 | { \ |
70 | return bytestream_get_ ## name(&g->buffer); \ |
71 | } \ |
72 | static av_always_inline type bytestream2_get_ ## name(GetByteContext *g) \ |
73 | { \ |
74 | if (g->buffer_end - g->buffer < bytes) { \ |
75 | g->buffer = g->buffer_end; \ |
76 | return 0; \ |
77 | } \ |
78 | return bytestream2_get_ ## name ## u(g); \ |
79 | } \ |
80 | static av_always_inline type bytestream2_peek_ ## name(GetByteContext *g) \ |
81 | { \ |
82 | if (g->buffer_end - g->buffer < bytes) \ |
83 | return 0; \ |
84 | return read(g->buffer); \ |
85 | } |
86 | |
87 | DEF(uint64_t, le64, 8, AV_RL64, AV_WL64) |
88 | DEF(unsigned int, le32, 4, AV_RL32, AV_WL32) |
89 | DEF(unsigned int, le24, 3, AV_RL24, AV_WL24) |
90 | DEF(unsigned int, le16, 2, AV_RL16, AV_WL16) |
91 | DEF(uint64_t, be64, 8, AV_RB64, AV_WB64) |
92 | DEF(unsigned int, be32, 4, AV_RB32, AV_WB32) |
93 | DEF(unsigned int, be24, 3, AV_RB24, AV_WB24) |
94 | DEF(unsigned int, be16, 2, AV_RB16, AV_WB16) |
95 | DEF(unsigned int, byte, 1, AV_RB8 , AV_WB8) |
96 | |
97 | #if AV_HAVE_BIGENDIAN |
98 | # define bytestream2_get_ne16 bytestream2_get_be16 |
99 | # define bytestream2_get_ne24 bytestream2_get_be24 |
100 | # define bytestream2_get_ne32 bytestream2_get_be32 |
101 | # define bytestream2_get_ne64 bytestream2_get_be64 |
102 | # define bytestream2_get_ne16u bytestream2_get_be16u |
103 | # define bytestream2_get_ne24u bytestream2_get_be24u |
104 | # define bytestream2_get_ne32u bytestream2_get_be32u |
105 | # define bytestream2_get_ne64u bytestream2_get_be64u |
106 | # define bytestream2_put_ne16 bytestream2_put_be16 |
107 | # define bytestream2_put_ne24 bytestream2_put_be24 |
108 | # define bytestream2_put_ne32 bytestream2_put_be32 |
109 | # define bytestream2_put_ne64 bytestream2_put_be64 |
110 | # define bytestream2_peek_ne16 bytestream2_peek_be16 |
111 | # define bytestream2_peek_ne24 bytestream2_peek_be24 |
112 | # define bytestream2_peek_ne32 bytestream2_peek_be32 |
113 | # define bytestream2_peek_ne64 bytestream2_peek_be64 |
114 | #else |
115 | # define bytestream2_get_ne16 bytestream2_get_le16 |
116 | # define bytestream2_get_ne24 bytestream2_get_le24 |
117 | # define bytestream2_get_ne32 bytestream2_get_le32 |
118 | # define bytestream2_get_ne64 bytestream2_get_le64 |
119 | # define bytestream2_get_ne16u bytestream2_get_le16u |
120 | # define bytestream2_get_ne24u bytestream2_get_le24u |
121 | # define bytestream2_get_ne32u bytestream2_get_le32u |
122 | # define bytestream2_get_ne64u bytestream2_get_le64u |
123 | # define bytestream2_put_ne16 bytestream2_put_le16 |
124 | # define bytestream2_put_ne24 bytestream2_put_le24 |
125 | # define bytestream2_put_ne32 bytestream2_put_le32 |
126 | # define bytestream2_put_ne64 bytestream2_put_le64 |
127 | # define bytestream2_peek_ne16 bytestream2_peek_le16 |
128 | # define bytestream2_peek_ne24 bytestream2_peek_le24 |
129 | # define bytestream2_peek_ne32 bytestream2_peek_le32 |
130 | # define bytestream2_peek_ne64 bytestream2_peek_le64 |
131 | #endif |
132 | |
133 | static av_always_inline void bytestream2_init(GetByteContext *g, |
134 | const uint8_t *buf, |
135 | int buf_size) |
136 | { |
137 | av_assert0(buf_size >= 0); |
138 | g->buffer = buf; |
139 | g->buffer_start = buf; |
140 | g->buffer_end = buf + buf_size; |
141 | } |
142 | |
143 | static av_always_inline void bytestream2_init_writer(PutByteContext *p, |
144 | uint8_t *buf, |
145 | int buf_size) |
146 | { |
147 | av_assert0(buf_size >= 0); |
148 | p->buffer = buf; |
149 | p->buffer_start = buf; |
150 | p->buffer_end = buf + buf_size; |
151 | p->eof = 0; |
152 | } |
153 | |
154 | static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g) |
155 | { |
156 | return g->buffer_end - g->buffer; |
157 | } |
158 | |
159 | static av_always_inline unsigned int bytestream2_get_bytes_left_p(PutByteContext *p) |
160 | { |
161 | return p->buffer_end - p->buffer; |
162 | } |
163 | |
164 | static av_always_inline void bytestream2_skip(GetByteContext *g, |
165 | unsigned int size) |
166 | { |
167 | g->buffer += FFMIN(g->buffer_end - g->buffer, size); |
168 | } |
169 | |
170 | static av_always_inline void bytestream2_skipu(GetByteContext *g, |
171 | unsigned int size) |
172 | { |
173 | g->buffer += size; |
174 | } |
175 | |
176 | static av_always_inline void bytestream2_skip_p(PutByteContext *p, |
177 | unsigned int size) |
178 | { |
179 | int size2; |
180 | if (p->eof) |
181 | return; |
182 | size2 = FFMIN(p->buffer_end - p->buffer, size); |
183 | if (size2 != size) |
184 | p->eof = 1; |
185 | p->buffer += size2; |
186 | } |
187 | |
188 | static av_always_inline int bytestream2_tell(GetByteContext *g) |
189 | { |
190 | return (int)(g->buffer - g->buffer_start); |
191 | } |
192 | |
193 | static av_always_inline int bytestream2_tell_p(PutByteContext *p) |
194 | { |
195 | return (int)(p->buffer - p->buffer_start); |
196 | } |
197 | |
198 | static av_always_inline int bytestream2_size(GetByteContext *g) |
199 | { |
200 | return (int)(g->buffer_end - g->buffer_start); |
201 | } |
202 | |
203 | static av_always_inline int bytestream2_size_p(PutByteContext *p) |
204 | { |
205 | return (int)(p->buffer_end - p->buffer_start); |
206 | } |
207 | |
208 | static av_always_inline int bytestream2_seek(GetByteContext *g, |
209 | int offset, |
210 | int whence) |
211 | { |
212 | switch (whence) { |
213 | case SEEK_CUR: |
214 | offset = av_clip(offset, -(g->buffer - g->buffer_start), |
215 | g->buffer_end - g->buffer); |
216 | g->buffer += offset; |
217 | break; |
218 | case SEEK_END: |
219 | offset = av_clip(offset, -(g->buffer_end - g->buffer_start), 0); |
220 | g->buffer = g->buffer_end + offset; |
221 | break; |
222 | case SEEK_SET: |
223 | offset = av_clip(offset, 0, g->buffer_end - g->buffer_start); |
224 | g->buffer = g->buffer_start + offset; |
225 | break; |
226 | default: |
227 | return AVERROR(EINVAL); |
228 | } |
229 | return bytestream2_tell(g); |
230 | } |
231 | |
232 | static av_always_inline int bytestream2_seek_p(PutByteContext *p, |
233 | int offset, |
234 | int whence) |
235 | { |
236 | p->eof = 0; |
237 | switch (whence) { |
238 | case SEEK_CUR: |
239 | if (p->buffer_end - p->buffer < offset) |
240 | p->eof = 1; |
241 | offset = av_clip(offset, -(p->buffer - p->buffer_start), |
242 | p->buffer_end - p->buffer); |
243 | p->buffer += offset; |
244 | break; |
245 | case SEEK_END: |
246 | if (offset > 0) |
247 | p->eof = 1; |
248 | offset = av_clip(offset, -(p->buffer_end - p->buffer_start), 0); |
249 | p->buffer = p->buffer_end + offset; |
250 | break; |
251 | case SEEK_SET: |
252 | if (p->buffer_end - p->buffer_start < offset) |
253 | p->eof = 1; |
254 | offset = av_clip(offset, 0, p->buffer_end - p->buffer_start); |
255 | p->buffer = p->buffer_start + offset; |
256 | break; |
257 | default: |
258 | return AVERROR(EINVAL); |
259 | } |
260 | return bytestream2_tell_p(p); |
261 | } |
262 | |
263 | static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, |
264 | uint8_t *dst, |
265 | unsigned int size) |
266 | { |
267 | int size2 = FFMIN(g->buffer_end - g->buffer, size); |
268 | memcpy(dst, g->buffer, size2); |
269 | g->buffer += size2; |
270 | return size2; |
271 | } |
272 | |
273 | static av_always_inline unsigned int bytestream2_get_bufferu(GetByteContext *g, |
274 | uint8_t *dst, |
275 | unsigned int size) |
276 | { |
277 | memcpy(dst, g->buffer, size); |
278 | g->buffer += size; |
279 | return size; |
280 | } |
281 | |
282 | static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p, |
283 | const uint8_t *src, |
284 | unsigned int size) |
285 | { |
286 | int size2; |
287 | if (p->eof) |
288 | return 0; |
289 | size2 = FFMIN(p->buffer_end - p->buffer, size); |
290 | if (size2 != size) |
291 | p->eof = 1; |
292 | memcpy(p->buffer, src, size2); |
293 | p->buffer += size2; |
294 | return size2; |
295 | } |
296 | |
297 | static av_always_inline unsigned int bytestream2_put_bufferu(PutByteContext *p, |
298 | const uint8_t *src, |
299 | unsigned int size) |
300 | { |
301 | memcpy(p->buffer, src, size); |
302 | p->buffer += size; |
303 | return size; |
304 | } |
305 | |
306 | static av_always_inline void bytestream2_set_buffer(PutByteContext *p, |
307 | const uint8_t c, |
308 | unsigned int size) |
309 | { |
310 | int size2; |
311 | if (p->eof) |
312 | return; |
313 | size2 = FFMIN(p->buffer_end - p->buffer, size); |
314 | if (size2 != size) |
315 | p->eof = 1; |
316 | memset(p->buffer, c, size2); |
317 | p->buffer += size2; |
318 | } |
319 | |
320 | static av_always_inline void bytestream2_set_bufferu(PutByteContext *p, |
321 | const uint8_t c, |
322 | unsigned int size) |
323 | { |
324 | memset(p->buffer, c, size); |
325 | p->buffer += size; |
326 | } |
327 | |
328 | static av_always_inline unsigned int bytestream2_get_eof(PutByteContext *p) |
329 | { |
330 | return p->eof; |
331 | } |
332 | |
333 | static av_always_inline unsigned int bytestream2_copy_bufferu(PutByteContext *p, |
334 | GetByteContext *g, |
335 | unsigned int size) |
336 | { |
337 | memcpy(p->buffer, g->buffer, size); |
338 | p->buffer += size; |
339 | g->buffer += size; |
340 | return size; |
341 | } |
342 | |
343 | static av_always_inline unsigned int bytestream2_copy_buffer(PutByteContext *p, |
344 | GetByteContext *g, |
345 | unsigned int size) |
346 | { |
347 | int size2; |
348 | |
349 | if (p->eof) |
350 | return 0; |
351 | size = FFMIN(g->buffer_end - g->buffer, size); |
352 | size2 = FFMIN(p->buffer_end - p->buffer, size); |
353 | if (size2 != size) |
354 | p->eof = 1; |
355 | |
356 | return bytestream2_copy_bufferu(p, g, size2); |
357 | } |
358 | |
359 | static av_always_inline unsigned int bytestream_get_buffer(const uint8_t **b, |
360 | uint8_t *dst, |
361 | unsigned int size) |
362 | { |
363 | memcpy(dst, *b, size); |
364 | (*b) += size; |
365 | return size; |
366 | } |
367 | |
368 | static av_always_inline void bytestream_put_buffer(uint8_t **b, |
369 | const uint8_t *src, |
370 | unsigned int size) |
371 | { |
372 | memcpy(*b, src, size); |
373 | (*b) += size; |
374 | } |
375 | |
376 | #endif /* AVCODEC_BYTESTREAM_H */ |
377 |