• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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