bytestream.h (14911B)
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 33 typedef struct GetByteContext { 34 const uint8_t *buffer, *buffer_end, *buffer_start; 35 } GetByteContext; 36 37 typedef struct PutByteContext { 38 uint8_t *buffer, *buffer_end, *buffer_start; 39 int eof; 40 } PutByteContext; 41 42 #define DEF(type, name, bytes, read, write) \ 43 static av_always_inline type bytestream_get_ ## name(const uint8_t **b) \ 44 { \ 45 (*b) += bytes; \ 46 return read(*b - bytes); \ 47 } \ 48 static av_always_inline void bytestream_put_ ## name(uint8_t **b, \ 49 const type value) \ 50 { \ 51 write(*b, value); \ 52 (*b) += bytes; \ 53 } \ 54 static av_always_inline void bytestream2_put_ ## name ## u(PutByteContext *p, \ 55 const type value) \ 56 { \ 57 bytestream_put_ ## name(&p->buffer, value); \ 58 } \ 59 static 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 } \ 68 static av_always_inline type bytestream2_get_ ## name ## u(GetByteContext *g) \ 69 { \ 70 return bytestream_get_ ## name(&g->buffer); \ 71 } \ 72 static 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 } \ 80 static av_always_inline type bytestream2_peek_ ## name ## u(GetByteContext *g) \ 81 { \ 82 return read(g->buffer); \ 83 } \ 84 static 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 91 DEF(uint64_t, le64, 8, AV_RL64, AV_WL64) 92 DEF(unsigned int, le32, 4, AV_RL32, AV_WL32) 93 DEF(unsigned int, le24, 3, AV_RL24, AV_WL24) 94 DEF(unsigned int, le16, 2, AV_RL16, AV_WL16) 95 DEF(uint64_t, be64, 8, AV_RB64, AV_WB64) 96 DEF(unsigned int, be32, 4, AV_RB32, AV_WB32) 97 DEF(unsigned int, be24, 3, AV_RB24, AV_WB24) 98 DEF(unsigned int, be16, 2, AV_RB16, AV_WB16) 99 DEF(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 137 static 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 147 static 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 158 static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g) 159 { 160 return g->buffer_end - g->buffer; 161 } 162 163 static av_always_inline int bytestream2_get_bytes_left_p(PutByteContext *p) 164 { 165 return p->buffer_end - p->buffer; 166 } 167 168 static 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 174 static av_always_inline void bytestream2_skipu(GetByteContext *g, 175 unsigned int size) 176 { 177 g->buffer += size; 178 } 179 180 static av_always_inline void bytestream2_skip_p(PutByteContext *p, 181 unsigned int size) 182 { 183 unsigned 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 192 static av_always_inline int bytestream2_tell(GetByteContext *g) 193 { 194 return (int)(g->buffer - g->buffer_start); 195 } 196 197 static av_always_inline int bytestream2_tell_p(PutByteContext *p) 198 { 199 return (int)(p->buffer - p->buffer_start); 200 } 201 202 static av_always_inline int bytestream2_size(GetByteContext *g) 203 { 204 return (int)(g->buffer_end - g->buffer_start); 205 } 206 207 static av_always_inline int bytestream2_size_p(PutByteContext *p) 208 { 209 return (int)(p->buffer_end - p->buffer_start); 210 } 211 212 static 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 236 static 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 267 static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, 268 uint8_t *dst, 269 unsigned int size) 270 { 271 unsigned int size2 = FFMIN(g->buffer_end - g->buffer, size); 272 memcpy(dst, g->buffer, size2); 273 g->buffer += size2; 274 return size2; 275 } 276 277 static 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 286 static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p, 287 const uint8_t *src, 288 unsigned int size) 289 { 290 unsigned 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 301 static 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 310 static av_always_inline void bytestream2_set_buffer(PutByteContext *p, 311 const uint8_t c, 312 unsigned int size) 313 { 314 unsigned 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 324 static 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 332 static av_always_inline unsigned int bytestream2_get_eof(PutByteContext *p) 333 { 334 return p->eof; 335 } 336 337 static 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 347 static av_always_inline unsigned int bytestream2_copy_buffer(PutByteContext *p, 348 GetByteContext *g, 349 unsigned int size) 350 { 351 unsigned 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 363 static 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 372 static 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 */