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 Libav. 7 * 8 * Libav 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 * Libav 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 Libav; 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 <string.h> 27 28#include "libavutil/common.h" 29#include "libavutil/intreadwrite.h" 30 31typedef struct { 32 const uint8_t *buffer, *buffer_end, *buffer_start; 33} GetByteContext; 34 35typedef struct { 36 uint8_t *buffer, *buffer_end, *buffer_start; 37 int eof; 38} PutByteContext; 39 40#define DEF_T(type, name, bytes, read, write) \ 41static av_always_inline type bytestream_get_ ## name(const uint8_t **b) \ 42{ \ 43 (*b) += bytes; \ 44 return read(*b - bytes); \ 45} \ 46static av_always_inline void bytestream_put_ ## name(uint8_t **b, \ 47 const type value) \ 48{ \ 49 write(*b, value); \ 50 (*b) += bytes; \ 51} \ 52static av_always_inline void bytestream2_put_ ## name ## u(PutByteContext *p, \ 53 const type value) \ 54{ \ 55 bytestream_put_ ## name(&p->buffer, value); \ 56} \ 57static av_always_inline void bytestream2_put_ ## name(PutByteContext *p, \ 58 const type value) \ 59{ \ 60 if (!p->eof && (p->buffer_end - p->buffer >= bytes)) { \ 61 write(p->buffer, value); \ 62 p->buffer += bytes; \ 63 } else \ 64 p->eof = 1; \ 65} \ 66static av_always_inline type bytestream2_get_ ## name ## u(GetByteContext *g) \ 67{ \ 68 return bytestream_get_ ## name(&g->buffer); \ 69} \ 70static av_always_inline type bytestream2_get_ ## name(GetByteContext *g) \ 71{ \ 72 if (g->buffer_end - g->buffer < bytes) \ 73 return 0; \ 74 return bytestream2_get_ ## name ## u(g); \ 75} \ 76static av_always_inline type bytestream2_peek_ ## name(GetByteContext *g) \ 77{ \ 78 if (g->buffer_end - g->buffer < bytes) \ 79 return 0; \ 80 return read(g->buffer); \ 81} 82 83#define DEF(name, bytes, read, write) \ 84 DEF_T(unsigned int, name, bytes, read, write) 85#define DEF64(name, bytes, read, write) \ 86 DEF_T(uint64_t, name, bytes, read, write) 87 88DEF64(le64, 8, AV_RL64, AV_WL64) 89DEF (le32, 4, AV_RL32, AV_WL32) 90DEF (le24, 3, AV_RL24, AV_WL24) 91DEF (le16, 2, AV_RL16, AV_WL16) 92DEF64(be64, 8, AV_RB64, AV_WB64) 93DEF (be32, 4, AV_RB32, AV_WB32) 94DEF (be24, 3, AV_RB24, AV_WB24) 95DEF (be16, 2, AV_RB16, AV_WB16) 96DEF (byte, 1, AV_RB8 , AV_WB8 ) 97 98#undef DEF 99#undef DEF64 100#undef DEF_T 101 102#if HAVE_BIGENDIAN 103# define bytestream2_get_ne16 bytestream2_get_be16 104# define bytestream2_get_ne24 bytestream2_get_be24 105# define bytestream2_get_ne32 bytestream2_get_be32 106# define bytestream2_get_ne64 bytestream2_get_be64 107# define bytestream2_get_ne16u bytestream2_get_be16u 108# define bytestream2_get_ne24u bytestream2_get_be24u 109# define bytestream2_get_ne32u bytestream2_get_be32u 110# define bytestream2_get_ne64u bytestream2_get_be64u 111# define bytestream2_put_ne16 bytestream2_put_be16 112# define bytestream2_put_ne24 bytestream2_put_be24 113# define bytestream2_put_ne32 bytestream2_put_be32 114# define bytestream2_put_ne64 bytestream2_put_be64 115# define bytestream2_peek_ne16 bytestream2_peek_be16 116# define bytestream2_peek_ne24 bytestream2_peek_be24 117# define bytestream2_peek_ne32 bytestream2_peek_be32 118# define bytestream2_peek_ne64 bytestream2_peek_be64 119#else 120# define bytestream2_get_ne16 bytestream2_get_le16 121# define bytestream2_get_ne24 bytestream2_get_le24 122# define bytestream2_get_ne32 bytestream2_get_le32 123# define bytestream2_get_ne64 bytestream2_get_le64 124# define bytestream2_get_ne16u bytestream2_get_le16u 125# define bytestream2_get_ne24u bytestream2_get_le24u 126# define bytestream2_get_ne32u bytestream2_get_le32u 127# define bytestream2_get_ne64u bytestream2_get_le64u 128# define bytestream2_put_ne16 bytestream2_put_le16 129# define bytestream2_put_ne24 bytestream2_put_le24 130# define bytestream2_put_ne32 bytestream2_put_le32 131# define bytestream2_put_ne64 bytestream2_put_le64 132# define bytestream2_peek_ne16 bytestream2_peek_le16 133# define bytestream2_peek_ne24 bytestream2_peek_le24 134# define bytestream2_peek_ne32 bytestream2_peek_le32 135# define bytestream2_peek_ne64 bytestream2_peek_le64 136#endif 137 138static av_always_inline void bytestream2_init(GetByteContext *g, 139 const uint8_t *buf, 140 int buf_size) 141{ 142 g->buffer = buf; 143 g->buffer_start = buf; 144 g->buffer_end = buf + buf_size; 145} 146 147static av_always_inline void bytestream2_init_writer(PutByteContext *p, 148 uint8_t *buf, 149 int buf_size) 150{ 151 p->buffer = buf; 152 p->buffer_start = buf; 153 p->buffer_end = buf + buf_size; 154 p->eof = 0; 155} 156 157static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g) 158{ 159 return g->buffer_end - g->buffer; 160} 161 162static av_always_inline unsigned int bytestream2_get_bytes_left_p(PutByteContext *p) 163{ 164 return p->buffer_end - p->buffer; 165} 166 167static av_always_inline void bytestream2_skip(GetByteContext *g, 168 unsigned int size) 169{ 170 g->buffer += FFMIN(g->buffer_end - g->buffer, size); 171} 172 173static av_always_inline void bytestream2_skipu(GetByteContext *g, 174 unsigned int size) 175{ 176 g->buffer += size; 177} 178 179static av_always_inline void bytestream2_skip_p(PutByteContext *p, 180 unsigned int size) 181{ 182 int size2; 183 if (p->eof) 184 return; 185 size2 = FFMIN(p->buffer_end - p->buffer, size); 186 if (size2 != size) 187 p->eof = 1; 188 p->buffer += size2; 189} 190 191static av_always_inline int bytestream2_tell(GetByteContext *g) 192{ 193 return (int)(g->buffer - g->buffer_start); 194} 195 196static av_always_inline int bytestream2_tell_p(PutByteContext *p) 197{ 198 return (int)(p->buffer - p->buffer_start); 199} 200 201static av_always_inline int bytestream2_seek(GetByteContext *g, 202 int offset, 203 int whence) 204{ 205 switch (whence) { 206 case SEEK_CUR: 207 offset = av_clip(offset, -(g->buffer - g->buffer_start), 208 g->buffer_end - g->buffer); 209 g->buffer += offset; 210 break; 211 case SEEK_END: 212 offset = av_clip(offset, -(g->buffer_end - g->buffer_start), 0); 213 g->buffer = g->buffer_end + offset; 214 break; 215 case SEEK_SET: 216 offset = av_clip(offset, 0, g->buffer_end - g->buffer_start); 217 g->buffer = g->buffer_start + offset; 218 break; 219 default: 220 return AVERROR(EINVAL); 221 } 222 return bytestream2_tell(g); 223} 224 225static av_always_inline int bytestream2_seek_p(PutByteContext *p, 226 int offset, 227 int whence) 228{ 229 p->eof = 0; 230 switch (whence) { 231 case SEEK_CUR: 232 if (p->buffer_end - p->buffer < offset) 233 p->eof = 1; 234 offset = av_clip(offset, -(p->buffer - p->buffer_start), 235 p->buffer_end - p->buffer); 236 p->buffer += offset; 237 break; 238 case SEEK_END: 239 if (offset > 0) 240 p->eof = 1; 241 offset = av_clip(offset, -(p->buffer_end - p->buffer_start), 0); 242 p->buffer = p->buffer_end + offset; 243 break; 244 case SEEK_SET: 245 if (p->buffer_end - p->buffer_start < offset) 246 p->eof = 1; 247 offset = av_clip(offset, 0, p->buffer_end - p->buffer_start); 248 p->buffer = p->buffer_start + offset; 249 break; 250 default: 251 return AVERROR(EINVAL); 252 } 253 return bytestream2_tell_p(p); 254} 255 256static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, 257 uint8_t *dst, 258 unsigned int size) 259{ 260 int size2 = FFMIN(g->buffer_end - g->buffer, size); 261 memcpy(dst, g->buffer, size2); 262 g->buffer += size2; 263 return size2; 264} 265 266static av_always_inline unsigned int bytestream2_get_bufferu(GetByteContext *g, 267 uint8_t *dst, 268 unsigned int size) 269{ 270 memcpy(dst, g->buffer, size); 271 g->buffer += size; 272 return size; 273} 274 275static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p, 276 const uint8_t *src, 277 unsigned int size) 278{ 279 int size2; 280 if (p->eof) 281 return 0; 282 size2 = FFMIN(p->buffer_end - p->buffer, size); 283 if (size2 != size) 284 p->eof = 1; 285 memcpy(p->buffer, src, size2); 286 p->buffer += size2; 287 return size2; 288} 289 290static av_always_inline unsigned int bytestream2_put_bufferu(PutByteContext *p, 291 const uint8_t *src, 292 unsigned int size) 293{ 294 memcpy(p->buffer, src, size); 295 p->buffer += size; 296 return size; 297} 298 299static av_always_inline void bytestream2_set_buffer(PutByteContext *p, 300 const uint8_t c, 301 unsigned int size) 302{ 303 int size2; 304 if (p->eof) 305 return; 306 size2 = FFMIN(p->buffer_end - p->buffer, size); 307 if (size2 != size) 308 p->eof = 1; 309 memset(p->buffer, c, size2); 310 p->buffer += size2; 311} 312 313static av_always_inline void bytestream2_set_bufferu(PutByteContext *p, 314 const uint8_t c, 315 unsigned int size) 316{ 317 memset(p->buffer, c, size); 318 p->buffer += size; 319} 320 321static av_always_inline unsigned int bytestream2_get_eof(PutByteContext *p) 322{ 323 return p->eof; 324} 325 326static av_always_inline unsigned int bytestream_get_buffer(const uint8_t **b, 327 uint8_t *dst, 328 unsigned int size) 329{ 330 memcpy(dst, *b, size); 331 (*b) += size; 332 return size; 333} 334 335static av_always_inline void bytestream_put_buffer(uint8_t **b, 336 const uint8_t *src, 337 unsigned int size) 338{ 339 memcpy(*b, src, size); 340 (*b) += size; 341} 342 343#endif /* AVCODEC_BYTESTREAM_H */ 344