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