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 g->buffer = g->buffer_end; \ 76 return 0; \ 77 } \ 78 return bytestream2_get_ ## name ## u(g); \ 79} \ 80static av_always_inline type bytestream2_peek_ ## name ## u(GetByteContext *g) \ 81{ \ 82 return read(g->buffer); \ 83} \ 84static 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 91DEF(uint64_t, le64, 8, AV_RL64, AV_WL64) 92DEF(unsigned int, le32, 4, AV_RL32, AV_WL32) 93DEF(unsigned int, le24, 3, AV_RL24, AV_WL24) 94DEF(unsigned int, le16, 2, AV_RL16, AV_WL16) 95DEF(uint64_t, be64, 8, AV_RB64, AV_WB64) 96DEF(unsigned int, be32, 4, AV_RB32, AV_WB32) 97DEF(unsigned int, be24, 3, AV_RB24, AV_WB24) 98DEF(unsigned int, be16, 2, AV_RB16, AV_WB16) 99DEF(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 137static 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 147static 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 158static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g) 159{ 160 return g->buffer_end - g->buffer; 161} 162 163static av_always_inline int bytestream2_get_bytes_left_p(PutByteContext *p) 164{ 165 return p->buffer_end - p->buffer; 166} 167 168static 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 174static av_always_inline void bytestream2_skipu(GetByteContext *g, 175 unsigned int size) 176{ 177 g->buffer += size; 178} 179 180static 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 192static av_always_inline int bytestream2_tell(GetByteContext *g) 193{ 194 return (int)(g->buffer - g->buffer_start); 195} 196 197static av_always_inline int bytestream2_tell_p(PutByteContext *p) 198{ 199 return (int)(p->buffer - p->buffer_start); 200} 201 202static av_always_inline int bytestream2_size(GetByteContext *g) 203{ 204 return (int)(g->buffer_end - g->buffer_start); 205} 206 207static av_always_inline int bytestream2_size_p(PutByteContext *p) 208{ 209 return (int)(p->buffer_end - p->buffer_start); 210} 211 212static 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 236static 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 267static 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 277static 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 286static 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 301static 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 310static 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 324static 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 332static av_always_inline unsigned int bytestream2_get_eof(PutByteContext *p) 333{ 334 return p->eof; 335} 336 337static 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 347static 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 363static 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 372static 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