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 ## u(GetByteContext *g) \
81 { \
82 return read(g->buffer); \
83 } \
84 static av_always_inline type bytestream2_peek_ ## name(GetByteContext *g) \
85 { \
86 if (g->buffer_end - g->buffer < bytes) \
87 return 0; \
88 return bytestream2_peek_ ## name ## u(g); \
89 }
90
91 DEF(uint64_t, le64, 8, AV_RL64, AV_WL64)
92 DEF(unsigned int, le32, 4, AV_RL32, AV_WL32)
93 DEF(unsigned int, le24, 3, AV_RL24, AV_WL24)
94 DEF(unsigned int, le16, 2, AV_RL16, AV_WL16)
95 DEF(uint64_t, be64, 8, AV_RB64, AV_WB64)
96 DEF(unsigned int, be32, 4, AV_RB32, AV_WB32)
97 DEF(unsigned int, be24, 3, AV_RB24, AV_WB24)
98 DEF(unsigned int, be16, 2, AV_RB16, AV_WB16)
99 DEF(unsigned int, byte, 1, AV_RB8 , AV_WB8)
100
101 #if AV_HAVE_BIGENDIAN
102 # define bytestream2_get_ne16 bytestream2_get_be16
103 # define bytestream2_get_ne24 bytestream2_get_be24
104 # define bytestream2_get_ne32 bytestream2_get_be32
105 # define bytestream2_get_ne64 bytestream2_get_be64
106 # define bytestream2_get_ne16u bytestream2_get_be16u
107 # define bytestream2_get_ne24u bytestream2_get_be24u
108 # define bytestream2_get_ne32u bytestream2_get_be32u
109 # define bytestream2_get_ne64u bytestream2_get_be64u
110 # define bytestream2_put_ne16 bytestream2_put_be16
111 # define bytestream2_put_ne24 bytestream2_put_be24
112 # define bytestream2_put_ne32 bytestream2_put_be32
113 # define bytestream2_put_ne64 bytestream2_put_be64
114 # define bytestream2_peek_ne16 bytestream2_peek_be16
115 # define bytestream2_peek_ne24 bytestream2_peek_be24
116 # define bytestream2_peek_ne32 bytestream2_peek_be32
117 # define bytestream2_peek_ne64 bytestream2_peek_be64
118 #else
119 # define bytestream2_get_ne16 bytestream2_get_le16
120 # define bytestream2_get_ne24 bytestream2_get_le24
121 # define bytestream2_get_ne32 bytestream2_get_le32
122 # define bytestream2_get_ne64 bytestream2_get_le64
123 # define bytestream2_get_ne16u bytestream2_get_le16u
124 # define bytestream2_get_ne24u bytestream2_get_le24u
125 # define bytestream2_get_ne32u bytestream2_get_le32u
126 # define bytestream2_get_ne64u bytestream2_get_le64u
127 # define bytestream2_put_ne16 bytestream2_put_le16
128 # define bytestream2_put_ne24 bytestream2_put_le24
129 # define bytestream2_put_ne32 bytestream2_put_le32
130 # define bytestream2_put_ne64 bytestream2_put_le64
131 # define bytestream2_peek_ne16 bytestream2_peek_le16
132 # define bytestream2_peek_ne24 bytestream2_peek_le24
133 # define bytestream2_peek_ne32 bytestream2_peek_le32
134 # define bytestream2_peek_ne64 bytestream2_peek_le64
135 #endif
136
bytestream2_init(GetByteContext * g,const uint8_t * buf,int buf_size)137 static av_always_inline void bytestream2_init(GetByteContext *g,
138 const uint8_t *buf,
139 int buf_size)
140 {
141 av_assert0(buf_size >= 0);
142 g->buffer = buf;
143 g->buffer_start = buf;
144 g->buffer_end = buf + buf_size;
145 }
146
bytestream2_init_writer(PutByteContext * p,uint8_t * buf,int buf_size)147 static av_always_inline void bytestream2_init_writer(PutByteContext *p,
148 uint8_t *buf,
149 int buf_size)
150 {
151 av_assert0(buf_size >= 0);
152 p->buffer = buf;
153 p->buffer_start = buf;
154 p->buffer_end = buf + buf_size;
155 p->eof = 0;
156 }
157
bytestream2_get_bytes_left(GetByteContext * g)158 static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
159 {
160 return g->buffer_end - g->buffer;
161 }
162
bytestream2_get_bytes_left_p(PutByteContext * p)163 static av_always_inline int bytestream2_get_bytes_left_p(PutByteContext *p)
164 {
165 return p->buffer_end - p->buffer;
166 }
167
bytestream2_skip(GetByteContext * g,unsigned int size)168 static av_always_inline void bytestream2_skip(GetByteContext *g,
169 unsigned int size)
170 {
171 g->buffer += FFMIN(g->buffer_end - g->buffer, size);
172 }
173
bytestream2_skipu(GetByteContext * g,unsigned int size)174 static av_always_inline void bytestream2_skipu(GetByteContext *g,
175 unsigned int size)
176 {
177 g->buffer += size;
178 }
179
bytestream2_skip_p(PutByteContext * p,unsigned int size)180 static av_always_inline void bytestream2_skip_p(PutByteContext *p,
181 unsigned int size)
182 {
183 int size2;
184 if (p->eof)
185 return;
186 size2 = FFMIN(p->buffer_end - p->buffer, size);
187 if (size2 != size)
188 p->eof = 1;
189 p->buffer += size2;
190 }
191
bytestream2_tell(GetByteContext * g)192 static av_always_inline int bytestream2_tell(GetByteContext *g)
193 {
194 return (int)(g->buffer - g->buffer_start);
195 }
196
bytestream2_tell_p(PutByteContext * p)197 static av_always_inline int bytestream2_tell_p(PutByteContext *p)
198 {
199 return (int)(p->buffer - p->buffer_start);
200 }
201
bytestream2_size(GetByteContext * g)202 static av_always_inline int bytestream2_size(GetByteContext *g)
203 {
204 return (int)(g->buffer_end - g->buffer_start);
205 }
206
bytestream2_size_p(PutByteContext * p)207 static av_always_inline int bytestream2_size_p(PutByteContext *p)
208 {
209 return (int)(p->buffer_end - p->buffer_start);
210 }
211
bytestream2_seek(GetByteContext * g,int offset,int whence)212 static av_always_inline int bytestream2_seek(GetByteContext *g,
213 int offset,
214 int whence)
215 {
216 switch (whence) {
217 case SEEK_CUR:
218 offset = av_clip(offset, -(g->buffer - g->buffer_start),
219 g->buffer_end - g->buffer);
220 g->buffer += offset;
221 break;
222 case SEEK_END:
223 offset = av_clip(offset, -(g->buffer_end - g->buffer_start), 0);
224 g->buffer = g->buffer_end + offset;
225 break;
226 case SEEK_SET:
227 offset = av_clip(offset, 0, g->buffer_end - g->buffer_start);
228 g->buffer = g->buffer_start + offset;
229 break;
230 default:
231 return AVERROR(EINVAL);
232 }
233 return bytestream2_tell(g);
234 }
235
bytestream2_seek_p(PutByteContext * p,int offset,int whence)236 static av_always_inline int bytestream2_seek_p(PutByteContext *p,
237 int offset,
238 int whence)
239 {
240 p->eof = 0;
241 switch (whence) {
242 case SEEK_CUR:
243 if (p->buffer_end - p->buffer < offset)
244 p->eof = 1;
245 offset = av_clip(offset, -(p->buffer - p->buffer_start),
246 p->buffer_end - p->buffer);
247 p->buffer += offset;
248 break;
249 case SEEK_END:
250 if (offset > 0)
251 p->eof = 1;
252 offset = av_clip(offset, -(p->buffer_end - p->buffer_start), 0);
253 p->buffer = p->buffer_end + offset;
254 break;
255 case SEEK_SET:
256 if (p->buffer_end - p->buffer_start < offset)
257 p->eof = 1;
258 offset = av_clip(offset, 0, p->buffer_end - p->buffer_start);
259 p->buffer = p->buffer_start + offset;
260 break;
261 default:
262 return AVERROR(EINVAL);
263 }
264 return bytestream2_tell_p(p);
265 }
266
bytestream2_get_buffer(GetByteContext * g,uint8_t * dst,unsigned int size)267 static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g,
268 uint8_t *dst,
269 unsigned int size)
270 {
271 int size2 = FFMIN(g->buffer_end - g->buffer, size);
272 memcpy(dst, g->buffer, size2);
273 g->buffer += size2;
274 return size2;
275 }
276
bytestream2_get_bufferu(GetByteContext * g,uint8_t * dst,unsigned int size)277 static av_always_inline unsigned int bytestream2_get_bufferu(GetByteContext *g,
278 uint8_t *dst,
279 unsigned int size)
280 {
281 memcpy(dst, g->buffer, size);
282 g->buffer += size;
283 return size;
284 }
285
bytestream2_put_buffer(PutByteContext * p,const uint8_t * src,unsigned int size)286 static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p,
287 const uint8_t *src,
288 unsigned int size)
289 {
290 int size2;
291 if (p->eof)
292 return 0;
293 size2 = FFMIN(p->buffer_end - p->buffer, size);
294 if (size2 != size)
295 p->eof = 1;
296 memcpy(p->buffer, src, size2);
297 p->buffer += size2;
298 return size2;
299 }
300
bytestream2_put_bufferu(PutByteContext * p,const uint8_t * src,unsigned int size)301 static av_always_inline unsigned int bytestream2_put_bufferu(PutByteContext *p,
302 const uint8_t *src,
303 unsigned int size)
304 {
305 memcpy(p->buffer, src, size);
306 p->buffer += size;
307 return size;
308 }
309
bytestream2_set_buffer(PutByteContext * p,const uint8_t c,unsigned int size)310 static av_always_inline void bytestream2_set_buffer(PutByteContext *p,
311 const uint8_t c,
312 unsigned int size)
313 {
314 int size2;
315 if (p->eof)
316 return;
317 size2 = FFMIN(p->buffer_end - p->buffer, size);
318 if (size2 != size)
319 p->eof = 1;
320 memset(p->buffer, c, size2);
321 p->buffer += size2;
322 }
323
bytestream2_set_bufferu(PutByteContext * p,const uint8_t c,unsigned int size)324 static av_always_inline void bytestream2_set_bufferu(PutByteContext *p,
325 const uint8_t c,
326 unsigned int size)
327 {
328 memset(p->buffer, c, size);
329 p->buffer += size;
330 }
331
bytestream2_get_eof(PutByteContext * p)332 static av_always_inline unsigned int bytestream2_get_eof(PutByteContext *p)
333 {
334 return p->eof;
335 }
336
bytestream2_copy_bufferu(PutByteContext * p,GetByteContext * g,unsigned int size)337 static av_always_inline unsigned int bytestream2_copy_bufferu(PutByteContext *p,
338 GetByteContext *g,
339 unsigned int size)
340 {
341 memcpy(p->buffer, g->buffer, size);
342 p->buffer += size;
343 g->buffer += size;
344 return size;
345 }
346
bytestream2_copy_buffer(PutByteContext * p,GetByteContext * g,unsigned int size)347 static av_always_inline unsigned int bytestream2_copy_buffer(PutByteContext *p,
348 GetByteContext *g,
349 unsigned int size)
350 {
351 int size2;
352
353 if (p->eof)
354 return 0;
355 size = FFMIN(g->buffer_end - g->buffer, size);
356 size2 = FFMIN(p->buffer_end - p->buffer, size);
357 if (size2 != size)
358 p->eof = 1;
359
360 return bytestream2_copy_bufferu(p, g, size2);
361 }
362
bytestream_get_buffer(const uint8_t ** b,uint8_t * dst,unsigned int size)363 static av_always_inline unsigned int bytestream_get_buffer(const uint8_t **b,
364 uint8_t *dst,
365 unsigned int size)
366 {
367 memcpy(dst, *b, size);
368 (*b) += size;
369 return size;
370 }
371
bytestream_put_buffer(uint8_t ** b,const uint8_t * src,unsigned int size)372 static av_always_inline void bytestream_put_buffer(uint8_t **b,
373 const uint8_t *src,
374 unsigned int size)
375 {
376 memcpy(*b, src, size);
377 (*b) += size;
378 }
379
380 #endif /* AVCODEC_BYTESTREAM_H */
381