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_seek(GetByteContext *g,
00202                                              int offset,
00203                                              int whence)
00204 {
00205     switch (whence) {
00206     case SEEK_CUR:
00207         offset     = av_clip(offset, -(g->buffer - g->buffer_start),
00208                              g->buffer_end - g->buffer);
00209         g->buffer += offset;
00210         break;
00211     case SEEK_END:
00212         offset    = av_clip(offset, -(g->buffer_end - g->buffer_start), 0);
00213         g->buffer = g->buffer_end + offset;
00214         break;
00215     case SEEK_SET:
00216         offset    = av_clip(offset, 0, g->buffer_end - g->buffer_start);
00217         g->buffer = g->buffer_start + offset;
00218         break;
00219     default:
00220         return AVERROR(EINVAL);
00221     }
00222     return bytestream2_tell(g);
00223 }
00224 
00225 static av_always_inline int bytestream2_seek_p(PutByteContext *p,
00226                                                int offset,
00227                                                int whence)
00228 {
00229     p->eof = 0;
00230     switch (whence) {
00231     case SEEK_CUR:
00232         if (p->buffer_end - p->buffer < offset)
00233             p->eof = 1;
00234         offset     = av_clip(offset, -(p->buffer - p->buffer_start),
00235                              p->buffer_end - p->buffer);
00236         p->buffer += offset;
00237         break;
00238     case SEEK_END:
00239         if (offset > 0)
00240             p->eof = 1;
00241         offset    = av_clip(offset, -(p->buffer_end - p->buffer_start), 0);
00242         p->buffer = p->buffer_end + offset;
00243         break;
00244     case SEEK_SET:
00245         if (p->buffer_end - p->buffer_start < offset)
00246             p->eof = 1;
00247         offset    = av_clip(offset, 0, p->buffer_end - p->buffer_start);
00248         p->buffer = p->buffer_start + offset;
00249         break;
00250     default:
00251         return AVERROR(EINVAL);
00252     }
00253     return bytestream2_tell_p(p);
00254 }
00255 
00256 static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g,
00257                                                             uint8_t *dst,
00258                                                             unsigned int size)
00259 {
00260     int size2 = FFMIN(g->buffer_end - g->buffer, size);
00261     memcpy(dst, g->buffer, size2);
00262     g->buffer += size2;
00263     return size2;
00264 }
00265 
00266 static av_always_inline unsigned int bytestream2_get_bufferu(GetByteContext *g,
00267                                                              uint8_t *dst,
00268                                                              unsigned int size)
00269 {
00270     memcpy(dst, g->buffer, size);
00271     g->buffer += size;
00272     return size;
00273 }
00274 
00275 static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p,
00276                                                             const uint8_t *src,
00277                                                             unsigned int size)
00278 {
00279     int size2;
00280     if (p->eof)
00281         return 0;
00282     size2 = FFMIN(p->buffer_end - p->buffer, size);
00283     if (size2 != size)
00284         p->eof = 1;
00285     memcpy(p->buffer, src, size2);
00286     p->buffer += size2;
00287     return size2;
00288 }
00289 
00290 static av_always_inline unsigned int bytestream2_put_bufferu(PutByteContext *p,
00291                                                              const uint8_t *src,
00292                                                              unsigned int size)
00293 {
00294     memcpy(p->buffer, src, size);
00295     p->buffer += size;
00296     return size;
00297 }
00298 
00299 static av_always_inline void bytestream2_set_buffer(PutByteContext *p,
00300                                                     const uint8_t c,
00301                                                     unsigned int size)
00302 {
00303     int size2;
00304     if (p->eof)
00305         return;
00306     size2 = FFMIN(p->buffer_end - p->buffer, size);
00307     if (size2 != size)
00308         p->eof = 1;
00309     memset(p->buffer, c, size2);
00310     p->buffer += size2;
00311 }
00312 
00313 static av_always_inline void bytestream2_set_bufferu(PutByteContext *p,
00314                                                      const uint8_t c,
00315                                                      unsigned int size)
00316 {
00317     memset(p->buffer, c, size);
00318     p->buffer += size;
00319 }
00320 
00321 static av_always_inline unsigned int bytestream2_get_eof(PutByteContext *p)
00322 {
00323     return p->eof;
00324 }
00325 
00326 static av_always_inline unsigned int bytestream_get_buffer(const uint8_t **b,
00327                                                            uint8_t *dst,
00328                                                            unsigned int size)
00329 {
00330     memcpy(dst, *b, size);
00331     (*b) += size;
00332     return size;
00333 }
00334 
00335 static av_always_inline void bytestream_put_buffer(uint8_t **b,
00336                                                    const uint8_t *src,
00337                                                    unsigned int size)
00338 {
00339     memcpy(*b, src, size);
00340     (*b) += size;
00341 }
00342 
00343 #endif /* AVCODEC_BYTESTREAM_H */