libavcodec/bytestream.h
Go to the documentation of this file.
00001 /*
00002  * Bytestream functions
00003  * copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@free.fr>
00004  * Copyright (c) 2012 Aneesh Dogra (lionaneesh) <lionaneesh@gmail.com>
00005  *
00006  * This file is part of Libav.
00007  *
00008  * Libav is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * Libav is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with Libav; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00021  */
00022 
00023 #ifndef AVCODEC_BYTESTREAM_H
00024 #define AVCODEC_BYTESTREAM_H
00025 
00026 #include <string.h>
00027 
00028 #include "libavutil/common.h"
00029 #include "libavutil/intreadwrite.h"
00030 
00031 typedef struct {
00032     const uint8_t *buffer, *buffer_end, *buffer_start;
00033 } GetByteContext;
00034 
00035 typedef struct {
00036     uint8_t *buffer, *buffer_end, *buffer_start;
00037     int eof;
00038 } PutByteContext;
00039 
00040 #define DEF_T(type, name, bytes, read, write)                                  \
00041 static av_always_inline type bytestream_get_ ## name(const uint8_t **b)        \
00042 {                                                                              \
00043     (*b) += bytes;                                                             \
00044     return read(*b - bytes);                                                   \
00045 }                                                                              \
00046 static av_always_inline void bytestream_put_ ## name(uint8_t **b,              \
00047                                                      const type value)         \
00048 {                                                                              \
00049     write(*b, value);                                                          \
00050     (*b) += bytes;                                                             \
00051 }                                                                              \
00052 static av_always_inline void bytestream2_put_ ## name ## u(PutByteContext *p,  \
00053                                                            const type value)   \
00054 {                                                                              \
00055     bytestream_put_ ## name(&p->buffer, value);                                \
00056 }                                                                              \
00057 static av_always_inline void bytestream2_put_ ## name(PutByteContext *p,       \
00058                                                       const type value)        \
00059 {                                                                              \
00060     if (!p->eof && (p->buffer_end - p->buffer >= bytes)) {                     \
00061         write(p->buffer, value);                                               \
00062         p->buffer += bytes;                                                    \
00063     } else                                                                     \
00064         p->eof = 1;                                                            \
00065 }                                                                              \
00066 static av_always_inline type bytestream2_get_ ## name ## u(GetByteContext *g)  \
00067 {                                                                              \
00068     return bytestream_get_ ## name(&g->buffer);                                \
00069 }                                                                              \
00070 static av_always_inline type bytestream2_get_ ## name(GetByteContext *g)       \
00071 {                                                                              \
00072     if (g->buffer_end - g->buffer < bytes)                                     \
00073         return 0;                                                              \
00074     return bytestream2_get_ ## name ## u(g);                                   \
00075 }                                                                              \
00076 static av_always_inline type bytestream2_peek_ ## name(GetByteContext *g)      \
00077 {                                                                              \
00078     if (g->buffer_end - g->buffer < bytes)                                     \
00079         return 0;                                                              \
00080     return read(g->buffer);                                                    \
00081 }
00082 
00083 #define DEF(name, bytes, read, write)                                          \
00084     DEF_T(unsigned int, name, bytes, read, write)
00085 #define DEF64(name, bytes, read, write)                                        \
00086     DEF_T(uint64_t, name, bytes, read, write)
00087 
00088 DEF64(le64, 8, AV_RL64, AV_WL64)
00089 DEF  (le32, 4, AV_RL32, AV_WL32)
00090 DEF  (le24, 3, AV_RL24, AV_WL24)
00091 DEF  (le16, 2, AV_RL16, AV_WL16)
00092 DEF64(be64, 8, AV_RB64, AV_WB64)
00093 DEF  (be32, 4, AV_RB32, AV_WB32)
00094 DEF  (be24, 3, AV_RB24, AV_WB24)
00095 DEF  (be16, 2, AV_RB16, AV_WB16)
00096 DEF  (byte, 1, AV_RB8 , AV_WB8 )
00097 
00098 #undef DEF
00099 #undef DEF64
00100 #undef DEF_T
00101 
00102 #if HAVE_BIGENDIAN
00103 #   define bytestream2_get_ne16  bytestream2_get_be16
00104 #   define bytestream2_get_ne24  bytestream2_get_be24
00105 #   define bytestream2_get_ne32  bytestream2_get_be32
00106 #   define bytestream2_get_ne64  bytestream2_get_be64
00107 #   define bytestream2_get_ne16u bytestream2_get_be16u
00108 #   define bytestream2_get_ne24u bytestream2_get_be24u
00109 #   define bytestream2_get_ne32u bytestream2_get_be32u
00110 #   define bytestream2_get_ne64u bytestream2_get_be64u
00111 #   define bytestream2_put_ne16  bytestream2_put_be16
00112 #   define bytestream2_put_ne24  bytestream2_put_be24
00113 #   define bytestream2_put_ne32  bytestream2_put_be32
00114 #   define bytestream2_put_ne64  bytestream2_put_be64
00115 #   define bytestream2_peek_ne16 bytestream2_peek_be16
00116 #   define bytestream2_peek_ne24 bytestream2_peek_be24
00117 #   define bytestream2_peek_ne32 bytestream2_peek_be32
00118 #   define bytestream2_peek_ne64 bytestream2_peek_be64
00119 #else
00120 #   define bytestream2_get_ne16  bytestream2_get_le16
00121 #   define bytestream2_get_ne24  bytestream2_get_le24
00122 #   define bytestream2_get_ne32  bytestream2_get_le32
00123 #   define bytestream2_get_ne64  bytestream2_get_le64
00124 #   define bytestream2_get_ne16u bytestream2_get_le16u
00125 #   define bytestream2_get_ne24u bytestream2_get_le24u
00126 #   define bytestream2_get_ne32u bytestream2_get_le32u
00127 #   define bytestream2_get_ne64u bytestream2_get_le64u
00128 #   define bytestream2_put_ne16  bytestream2_put_le16
00129 #   define bytestream2_put_ne24  bytestream2_put_le24
00130 #   define bytestream2_put_ne32  bytestream2_put_le32
00131 #   define bytestream2_put_ne64  bytestream2_put_le64
00132 #   define bytestream2_peek_ne16 bytestream2_peek_le16
00133 #   define bytestream2_peek_ne24 bytestream2_peek_le24
00134 #   define bytestream2_peek_ne32 bytestream2_peek_le32
00135 #   define bytestream2_peek_ne64 bytestream2_peek_le64
00136 #endif
00137 
00138 static av_always_inline void bytestream2_init(GetByteContext *g,
00139                                               const uint8_t *buf,
00140                                               int buf_size)
00141 {
00142     g->buffer       = buf;
00143     g->buffer_start = buf;
00144     g->buffer_end   = buf + buf_size;
00145 }
00146 
00147 static av_always_inline void bytestream2_init_writer(PutByteContext *p,
00148                                                      uint8_t *buf,
00149                                                      int buf_size)
00150 {
00151     p->buffer       = buf;
00152     p->buffer_start = buf;
00153     p->buffer_end   = buf + buf_size;
00154     p->eof          = 0;
00155 }
00156 
00157 static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
00158 {
00159     return g->buffer_end - g->buffer;
00160 }
00161 
00162 static av_always_inline unsigned int bytestream2_get_bytes_left_p(PutByteContext *p)
00163 {
00164     return p->buffer_end - p->buffer;
00165 }
00166 
00167 static av_always_inline void bytestream2_skip(GetByteContext *g,
00168                                               unsigned int size)
00169 {
00170     g->buffer += FFMIN(g->buffer_end - g->buffer, size);
00171 }
00172 
00173 static av_always_inline void bytestream2_skipu(GetByteContext *g,
00174                                                unsigned int size)
00175 {
00176     g->buffer += size;
00177 }
00178 
00179 static av_always_inline void bytestream2_skip_p(PutByteContext *p,
00180                                                 unsigned int size)
00181 {
00182     int size2;
00183     if (p->eof)
00184         return;
00185     size2 = FFMIN(p->buffer_end - p->buffer, size);
00186     if (size2 != size)
00187         p->eof = 1;
00188     p->buffer += size2;
00189 }
00190 
00191 static av_always_inline int bytestream2_tell(GetByteContext *g)
00192 {
00193     return (int)(g->buffer - g->buffer_start);
00194 }
00195 
00196 static av_always_inline int bytestream2_tell_p(PutByteContext *p)
00197 {
00198     return (int)(p->buffer - p->buffer_start);
00199 }
00200 
00201 static av_always_inline int bytestream2_size(GetByteContext *g)
00202 {
00203     return (int)(g->buffer_end - g->buffer_start);
00204 }
00205 
00206 static av_always_inline int bytestream2_size_p(PutByteContext *p)
00207 {
00208     return (int)(p->buffer_end - p->buffer_start);
00209 }
00210 
00211 static av_always_inline int bytestream2_seek(GetByteContext *g,
00212                                              int offset,
00213                                              int whence)
00214 {
00215     switch (whence) {
00216     case SEEK_CUR:
00217         offset     = av_clip(offset, -(g->buffer - g->buffer_start),
00218                              g->buffer_end - g->buffer);
00219         g->buffer += offset;
00220         break;
00221     case SEEK_END:
00222         offset    = av_clip(offset, -(g->buffer_end - g->buffer_start), 0);
00223         g->buffer = g->buffer_end + offset;
00224         break;
00225     case SEEK_SET:
00226         offset    = av_clip(offset, 0, g->buffer_end - g->buffer_start);
00227         g->buffer = g->buffer_start + offset;
00228         break;
00229     default:
00230         return AVERROR(EINVAL);
00231     }
00232     return bytestream2_tell(g);
00233 }
00234 
00235 static av_always_inline int bytestream2_seek_p(PutByteContext *p,
00236                                                int offset,
00237                                                int whence)
00238 {
00239     p->eof = 0;
00240     switch (whence) {
00241     case SEEK_CUR:
00242         if (p->buffer_end - p->buffer < offset)
00243             p->eof = 1;
00244         offset     = av_clip(offset, -(p->buffer - p->buffer_start),
00245                              p->buffer_end - p->buffer);
00246         p->buffer += offset;
00247         break;
00248     case SEEK_END:
00249         if (offset > 0)
00250             p->eof = 1;
00251         offset    = av_clip(offset, -(p->buffer_end - p->buffer_start), 0);
00252         p->buffer = p->buffer_end + offset;
00253         break;
00254     case SEEK_SET:
00255         if (p->buffer_end - p->buffer_start < offset)
00256             p->eof = 1;
00257         offset    = av_clip(offset, 0, p->buffer_end - p->buffer_start);
00258         p->buffer = p->buffer_start + offset;
00259         break;
00260     default:
00261         return AVERROR(EINVAL);
00262     }
00263     return bytestream2_tell_p(p);
00264 }
00265 
00266 static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g,
00267                                                             uint8_t *dst,
00268                                                             unsigned int size)
00269 {
00270     int size2 = FFMIN(g->buffer_end - g->buffer, size);
00271     memcpy(dst, g->buffer, size2);
00272     g->buffer += size2;
00273     return size2;
00274 }
00275 
00276 static av_always_inline unsigned int bytestream2_get_bufferu(GetByteContext *g,
00277                                                              uint8_t *dst,
00278                                                              unsigned int size)
00279 {
00280     memcpy(dst, g->buffer, size);
00281     g->buffer += size;
00282     return size;
00283 }
00284 
00285 static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p,
00286                                                             const uint8_t *src,
00287                                                             unsigned int size)
00288 {
00289     int size2;
00290     if (p->eof)
00291         return 0;
00292     size2 = FFMIN(p->buffer_end - p->buffer, size);
00293     if (size2 != size)
00294         p->eof = 1;
00295     memcpy(p->buffer, src, size2);
00296     p->buffer += size2;
00297     return size2;
00298 }
00299 
00300 static av_always_inline unsigned int bytestream2_put_bufferu(PutByteContext *p,
00301                                                              const uint8_t *src,
00302                                                              unsigned int size)
00303 {
00304     memcpy(p->buffer, src, size);
00305     p->buffer += size;
00306     return size;
00307 }
00308 
00309 static av_always_inline void bytestream2_set_buffer(PutByteContext *p,
00310                                                     const uint8_t c,
00311                                                     unsigned int size)
00312 {
00313     int size2;
00314     if (p->eof)
00315         return;
00316     size2 = FFMIN(p->buffer_end - p->buffer, size);
00317     if (size2 != size)
00318         p->eof = 1;
00319     memset(p->buffer, c, size2);
00320     p->buffer += size2;
00321 }
00322 
00323 static av_always_inline void bytestream2_set_bufferu(PutByteContext *p,
00324                                                      const uint8_t c,
00325                                                      unsigned int size)
00326 {
00327     memset(p->buffer, c, size);
00328     p->buffer += size;
00329 }
00330 
00331 static av_always_inline unsigned int bytestream2_get_eof(PutByteContext *p)
00332 {
00333     return p->eof;
00334 }
00335 
00336 static av_always_inline unsigned int bytestream2_copy_bufferu(PutByteContext *p,
00337                                                               GetByteContext *g,
00338                                                               unsigned int size)
00339 {
00340     memcpy(p->buffer, g->buffer, size);
00341     p->buffer += size;
00342     g->buffer += size;
00343     return size;
00344 }
00345 
00346 static av_always_inline unsigned int bytestream2_copy_buffer(PutByteContext *p,
00347                                                              GetByteContext *g,
00348                                                              unsigned int size)
00349 {
00350     int size2;
00351 
00352     if (p->eof)
00353         return 0;
00354     size  = FFMIN(g->buffer_end - g->buffer, size);
00355     size2 = FFMIN(p->buffer_end - p->buffer, size);
00356     if (size2 != size)
00357         p->eof = 1;
00358 
00359     return bytestream2_copy_bufferu(p, g, size2);
00360 }
00361 
00362 static av_always_inline unsigned int bytestream_get_buffer(const uint8_t **b,
00363                                                            uint8_t *dst,
00364                                                            unsigned int size)
00365 {
00366     memcpy(dst, *b, size);
00367     (*b) += size;
00368     return size;
00369 }
00370 
00371 static av_always_inline void bytestream_put_buffer(uint8_t **b,
00372                                                    const uint8_t *src,
00373                                                    unsigned int size)
00374 {
00375     memcpy(*b, src, size);
00376     (*b) += size;
00377 }
00378 
00379 #endif /* AVCODEC_BYTESTREAM_H */