1/* 2 * Buffered I/O for ffmpeg system 3 * Copyright (c) 2000,2001 Fabrice Bellard 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#include "libavutil/crc.h" 23#include "libavutil/intreadwrite.h" 24#include "avformat.h" 25#include "avio.h" 26#include <stdarg.h> 27 28#define IO_BUFFER_SIZE 32768 29 30static void fill_buffer(ByteIOContext *s); 31#if LIBAVFORMAT_VERSION_MAJOR >= 53 32static int url_resetbuf(ByteIOContext *s, int flags); 33#endif 34 35int init_put_byte(ByteIOContext *s, 36 unsigned char *buffer, 37 int buffer_size, 38 int write_flag, 39 void *opaque, 40 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), 41 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), 42 int64_t (*seek)(void *opaque, int64_t offset, int whence)) 43{ 44 s->buffer = buffer; 45 s->buffer_size = buffer_size; 46 s->buf_ptr = buffer; 47 s->opaque = opaque; 48 url_resetbuf(s, write_flag ? URL_WRONLY : URL_RDONLY); 49 s->write_packet = write_packet; 50 s->read_packet = read_packet; 51 s->seek = seek; 52 s->pos = 0; 53 s->must_flush = 0; 54 s->eof_reached = 0; 55 s->error = 0; 56 s->is_streamed = 0; 57 s->max_packet_size = 0; 58 s->update_checksum= NULL; 59 if(!read_packet && !write_flag){ 60 s->pos = buffer_size; 61 s->buf_end = s->buffer + buffer_size; 62 } 63 s->read_pause = NULL; 64 s->read_seek = NULL; 65 return 0; 66} 67 68ByteIOContext *av_alloc_put_byte( 69 unsigned char *buffer, 70 int buffer_size, 71 int write_flag, 72 void *opaque, 73 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), 74 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), 75 int64_t (*seek)(void *opaque, int64_t offset, int whence)) 76{ 77 ByteIOContext *s = av_mallocz(sizeof(ByteIOContext)); 78 init_put_byte(s, buffer, buffer_size, write_flag, opaque, 79 read_packet, write_packet, seek); 80 return s; 81} 82 83static void flush_buffer(ByteIOContext *s) 84{ 85 if (s->buf_ptr > s->buffer) { 86 if (s->write_packet && !s->error){ 87 int ret= s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer); 88 if(ret < 0){ 89 s->error = ret; 90 } 91 } 92 if(s->update_checksum){ 93 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr); 94 s->checksum_ptr= s->buffer; 95 } 96 s->pos += s->buf_ptr - s->buffer; 97 } 98 s->buf_ptr = s->buffer; 99} 100 101void put_byte(ByteIOContext *s, int b) 102{ 103 *(s->buf_ptr)++ = b; 104 if (s->buf_ptr >= s->buf_end) 105 flush_buffer(s); 106} 107 108void put_buffer(ByteIOContext *s, const unsigned char *buf, int size) 109{ 110 while (size > 0) { 111 int len = FFMIN(s->buf_end - s->buf_ptr, size); 112 memcpy(s->buf_ptr, buf, len); 113 s->buf_ptr += len; 114 115 if (s->buf_ptr >= s->buf_end) 116 flush_buffer(s); 117 118 buf += len; 119 size -= len; 120 } 121} 122 123void put_flush_packet(ByteIOContext *s) 124{ 125 flush_buffer(s); 126 s->must_flush = 0; 127} 128 129int64_t url_fseek(ByteIOContext *s, int64_t offset, int whence) 130{ 131 int64_t offset1; 132 int64_t pos; 133 int force = whence & AVSEEK_FORCE; 134 whence &= ~AVSEEK_FORCE; 135 136 if(!s) 137 return AVERROR(EINVAL); 138 139 pos = s->pos - (s->write_flag ? 0 : (s->buf_end - s->buffer)); 140 141 if (whence != SEEK_CUR && whence != SEEK_SET) 142 return AVERROR(EINVAL); 143 144 if (whence == SEEK_CUR) { 145 offset1 = pos + (s->buf_ptr - s->buffer); 146 if (offset == 0) 147 return offset1; 148 offset += offset1; 149 } 150 offset1 = offset - pos; 151 if (!s->must_flush && 152 offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) { 153 /* can do the seek inside the buffer */ 154 s->buf_ptr = s->buffer + offset1; 155 } else if(s->is_streamed && !s->write_flag && offset1 >= 0 && 156 (whence != SEEK_END || force)) { 157 while(s->pos < offset && !s->eof_reached) 158 fill_buffer(s); 159 if (s->eof_reached) 160 return AVERROR_EOF; 161 s->buf_ptr = s->buf_end + offset - s->pos; 162 } else { 163 int64_t res; 164 165#if CONFIG_MUXERS || CONFIG_NETWORK 166 if (s->write_flag) { 167 flush_buffer(s); 168 s->must_flush = 1; 169 } 170#endif /* CONFIG_MUXERS || CONFIG_NETWORK */ 171 if (!s->seek) 172 return AVERROR(EPIPE); 173 if ((res = s->seek(s->opaque, offset, SEEK_SET)) < 0) 174 return res; 175 if (!s->write_flag) 176 s->buf_end = s->buffer; 177 s->buf_ptr = s->buffer; 178 s->pos = offset; 179 } 180 s->eof_reached = 0; 181 return offset; 182} 183 184void url_fskip(ByteIOContext *s, int64_t offset) 185{ 186 url_fseek(s, offset, SEEK_CUR); 187} 188 189int64_t url_ftell(ByteIOContext *s) 190{ 191 return url_fseek(s, 0, SEEK_CUR); 192} 193 194int64_t url_fsize(ByteIOContext *s) 195{ 196 int64_t size; 197 198 if(!s) 199 return AVERROR(EINVAL); 200 201 if (!s->seek) 202 return AVERROR(ENOSYS); 203 size = s->seek(s->opaque, 0, AVSEEK_SIZE); 204 if(size<0){ 205 if ((size = s->seek(s->opaque, -1, SEEK_END)) < 0) 206 return size; 207 size++; 208 s->seek(s->opaque, s->pos, SEEK_SET); 209 } 210 return size; 211} 212 213int url_feof(ByteIOContext *s) 214{ 215 if(!s) 216 return 0; 217 return s->eof_reached; 218} 219 220int url_ferror(ByteIOContext *s) 221{ 222 if(!s) 223 return 0; 224 return s->error; 225} 226 227void put_le32(ByteIOContext *s, unsigned int val) 228{ 229 put_byte(s, val); 230 put_byte(s, val >> 8); 231 put_byte(s, val >> 16); 232 put_byte(s, val >> 24); 233} 234 235void put_be32(ByteIOContext *s, unsigned int val) 236{ 237 put_byte(s, val >> 24); 238 put_byte(s, val >> 16); 239 put_byte(s, val >> 8); 240 put_byte(s, val); 241} 242 243void put_strz(ByteIOContext *s, const char *str) 244{ 245 if (str) 246 put_buffer(s, (const unsigned char *) str, strlen(str) + 1); 247 else 248 put_byte(s, 0); 249} 250 251void put_le64(ByteIOContext *s, uint64_t val) 252{ 253 put_le32(s, (uint32_t)(val & 0xffffffff)); 254 put_le32(s, (uint32_t)(val >> 32)); 255} 256 257void put_be64(ByteIOContext *s, uint64_t val) 258{ 259 put_be32(s, (uint32_t)(val >> 32)); 260 put_be32(s, (uint32_t)(val & 0xffffffff)); 261} 262 263void put_le16(ByteIOContext *s, unsigned int val) 264{ 265 put_byte(s, val); 266 put_byte(s, val >> 8); 267} 268 269void put_be16(ByteIOContext *s, unsigned int val) 270{ 271 put_byte(s, val >> 8); 272 put_byte(s, val); 273} 274 275void put_le24(ByteIOContext *s, unsigned int val) 276{ 277 put_le16(s, val & 0xffff); 278 put_byte(s, val >> 16); 279} 280 281void put_be24(ByteIOContext *s, unsigned int val) 282{ 283 put_be16(s, val >> 8); 284 put_byte(s, val); 285} 286 287void put_tag(ByteIOContext *s, const char *tag) 288{ 289 while (*tag) { 290 put_byte(s, *tag++); 291 } 292} 293 294/* Input stream */ 295 296static void fill_buffer(ByteIOContext *s) 297{ 298 uint8_t *dst= !s->max_packet_size && s->buf_end - s->buffer < s->buffer_size ? s->buf_ptr : s->buffer; 299 int len= s->buffer_size - (dst - s->buffer); 300 int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE; 301 302 assert(s->buf_ptr == s->buf_end); 303 304 /* no need to do anything if EOF already reached */ 305 if (s->eof_reached) 306 return; 307 308 if(s->update_checksum && dst == s->buffer){ 309 if(s->buf_end > s->checksum_ptr) 310 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr); 311 s->checksum_ptr= s->buffer; 312 } 313 314 /* make buffer smaller in case it ended up large after probing */ 315 if (s->buffer_size > max_buffer_size) { 316 url_setbufsize(s, max_buffer_size); 317 318 s->checksum_ptr = dst = s->buffer; 319 len = s->buffer_size; 320 } 321 322 if(s->read_packet) 323 len = s->read_packet(s->opaque, dst, len); 324 else 325 len = 0; 326 if (len <= 0) { 327 /* do not modify buffer if EOF reached so that a seek back can 328 be done without rereading data */ 329 s->eof_reached = 1; 330 if(len<0) 331 s->error= len; 332 } else { 333 s->pos += len; 334 s->buf_ptr = dst; 335 s->buf_end = dst + len; 336 } 337} 338 339unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, 340 unsigned int len) 341{ 342 return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len); 343} 344 345unsigned long get_checksum(ByteIOContext *s) 346{ 347 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr); 348 s->update_checksum= NULL; 349 return s->checksum; 350} 351 352void init_checksum(ByteIOContext *s, 353 unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), 354 unsigned long checksum) 355{ 356 s->update_checksum= update_checksum; 357 if(s->update_checksum){ 358 s->checksum= checksum; 359 s->checksum_ptr= s->buf_ptr; 360 } 361} 362 363/* XXX: put an inline version */ 364int get_byte(ByteIOContext *s) 365{ 366 if (s->buf_ptr < s->buf_end) { 367 return *s->buf_ptr++; 368 } else { 369 fill_buffer(s); 370 if (s->buf_ptr < s->buf_end) 371 return *s->buf_ptr++; 372 else 373 return 0; 374 } 375} 376 377int url_fgetc(ByteIOContext *s) 378{ 379 if (s->buf_ptr < s->buf_end) { 380 return *s->buf_ptr++; 381 } else { 382 fill_buffer(s); 383 if (s->buf_ptr < s->buf_end) 384 return *s->buf_ptr++; 385 else 386 return URL_EOF; 387 } 388} 389 390int get_buffer(ByteIOContext *s, unsigned char *buf, int size) 391{ 392 int len, size1; 393 394 size1 = size; 395 while (size > 0) { 396 len = s->buf_end - s->buf_ptr; 397 if (len > size) 398 len = size; 399 if (len == 0) { 400 if(size > s->buffer_size && !s->update_checksum){ 401 if(s->read_packet) 402 len = s->read_packet(s->opaque, buf, size); 403 if (len <= 0) { 404 /* do not modify buffer if EOF reached so that a seek back can 405 be done without rereading data */ 406 s->eof_reached = 1; 407 if(len<0) 408 s->error= len; 409 break; 410 } else { 411 s->pos += len; 412 size -= len; 413 buf += len; 414 s->buf_ptr = s->buffer; 415 s->buf_end = s->buffer/* + len*/; 416 } 417 }else{ 418 fill_buffer(s); 419 len = s->buf_end - s->buf_ptr; 420 if (len == 0) 421 break; 422 } 423 } else { 424 memcpy(buf, s->buf_ptr, len); 425 buf += len; 426 s->buf_ptr += len; 427 size -= len; 428 } 429 } 430 if (size1 == size) { 431 if (url_ferror(s)) return url_ferror(s); 432 if (url_feof(s)) return AVERROR_EOF; 433 } 434 return size1 - size; 435} 436 437int get_partial_buffer(ByteIOContext *s, unsigned char *buf, int size) 438{ 439 int len; 440 441 if(size<0) 442 return -1; 443 444 len = s->buf_end - s->buf_ptr; 445 if (len == 0) { 446 fill_buffer(s); 447 len = s->buf_end - s->buf_ptr; 448 } 449 if (len > size) 450 len = size; 451 memcpy(buf, s->buf_ptr, len); 452 s->buf_ptr += len; 453 if (!len) { 454 if (url_ferror(s)) return url_ferror(s); 455 if (url_feof(s)) return AVERROR_EOF; 456 } 457 return len; 458} 459 460unsigned int get_le16(ByteIOContext *s) 461{ 462 unsigned int val; 463 val = get_byte(s); 464 val |= get_byte(s) << 8; 465 return val; 466} 467 468unsigned int get_le24(ByteIOContext *s) 469{ 470 unsigned int val; 471 val = get_le16(s); 472 val |= get_byte(s) << 16; 473 return val; 474} 475 476unsigned int get_le32(ByteIOContext *s) 477{ 478 unsigned int val; 479 val = get_le16(s); 480 val |= get_le16(s) << 16; 481 return val; 482} 483 484uint64_t get_le64(ByteIOContext *s) 485{ 486 uint64_t val; 487 val = (uint64_t)get_le32(s); 488 val |= (uint64_t)get_le32(s) << 32; 489 return val; 490} 491 492unsigned int get_be16(ByteIOContext *s) 493{ 494 unsigned int val; 495 val = get_byte(s) << 8; 496 val |= get_byte(s); 497 return val; 498} 499 500unsigned int get_be24(ByteIOContext *s) 501{ 502 unsigned int val; 503 val = get_be16(s) << 8; 504 val |= get_byte(s); 505 return val; 506} 507unsigned int get_be32(ByteIOContext *s) 508{ 509 unsigned int val; 510 val = get_be16(s) << 16; 511 val |= get_be16(s); 512 return val; 513} 514 515char *get_strz(ByteIOContext *s, char *buf, int maxlen) 516{ 517 int i = 0; 518 char c; 519 520 while ((c = get_byte(s))) { 521 if (i < maxlen-1) 522 buf[i++] = c; 523 } 524 525 buf[i] = 0; /* Ensure null terminated, but may be truncated */ 526 527 return buf; 528} 529 530uint64_t get_be64(ByteIOContext *s) 531{ 532 uint64_t val; 533 val = (uint64_t)get_be32(s) << 32; 534 val |= (uint64_t)get_be32(s); 535 return val; 536} 537 538uint64_t ff_get_v(ByteIOContext *bc){ 539 uint64_t val = 0; 540 int tmp; 541 542 do{ 543 tmp = get_byte(bc); 544 val= (val<<7) + (tmp&127); 545 }while(tmp&128); 546 return val; 547} 548 549int url_fdopen(ByteIOContext **s, URLContext *h) 550{ 551 uint8_t *buffer; 552 int buffer_size, max_packet_size; 553 554 max_packet_size = url_get_max_packet_size(h); 555 if (max_packet_size) { 556 buffer_size = max_packet_size; /* no need to bufferize more than one packet */ 557 } else { 558 buffer_size = IO_BUFFER_SIZE; 559 } 560 buffer = av_malloc(buffer_size); 561 if (!buffer) 562 return AVERROR(ENOMEM); 563 564 *s = av_mallocz(sizeof(ByteIOContext)); 565 if(!*s) { 566 av_free(buffer); 567 return AVERROR(ENOMEM); 568 } 569 570 if (init_put_byte(*s, buffer, buffer_size, 571 (h->flags & URL_WRONLY || h->flags & URL_RDWR), h, 572 url_read, url_write, url_seek) < 0) { 573 av_free(buffer); 574 av_freep(s); 575 return AVERROR(EIO); 576 } 577 (*s)->is_streamed = h->is_streamed; 578 (*s)->max_packet_size = max_packet_size; 579 if(h->prot) { 580 (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause; 581 (*s)->read_seek = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek; 582 } 583 return 0; 584} 585 586int url_setbufsize(ByteIOContext *s, int buf_size) 587{ 588 uint8_t *buffer; 589 buffer = av_malloc(buf_size); 590 if (!buffer) 591 return AVERROR(ENOMEM); 592 593 av_free(s->buffer); 594 s->buffer = buffer; 595 s->buffer_size = buf_size; 596 s->buf_ptr = buffer; 597 url_resetbuf(s, s->write_flag ? URL_WRONLY : URL_RDONLY); 598 return 0; 599} 600 601#if LIBAVFORMAT_VERSION_MAJOR < 53 602int url_resetbuf(ByteIOContext *s, int flags) 603#else 604static int url_resetbuf(ByteIOContext *s, int flags) 605#endif 606{ 607#if LIBAVFORMAT_VERSION_MAJOR < 53 608 URLContext *h = s->opaque; 609 if ((flags & URL_RDWR) || (h && h->flags != flags && !h->flags & URL_RDWR)) 610 return AVERROR(EINVAL); 611#else 612 assert(flags == URL_WRONLY || flags == URL_RDONLY); 613#endif 614 615 if (flags & URL_WRONLY) { 616 s->buf_end = s->buffer + s->buffer_size; 617 s->write_flag = 1; 618 } else { 619 s->buf_end = s->buffer; 620 s->write_flag = 0; 621 } 622 return 0; 623} 624 625int ff_rewind_with_probe_data(ByteIOContext *s, unsigned char *buf, int buf_size) 626{ 627 int64_t buffer_start; 628 int buffer_size; 629 int overlap, new_size; 630 631 if (s->write_flag) 632 return AVERROR(EINVAL); 633 634 buffer_size = s->buf_end - s->buffer; 635 636 /* the buffers must touch or overlap */ 637 if ((buffer_start = s->pos - buffer_size) > buf_size) 638 return AVERROR(EINVAL); 639 640 overlap = buf_size - buffer_start; 641 new_size = buf_size + buffer_size - overlap; 642 643 if (new_size > buf_size) { 644 if (!(buf = av_realloc(buf, new_size))) 645 return AVERROR(ENOMEM); 646 647 memcpy(buf + buf_size, s->buffer + overlap, buffer_size - overlap); 648 buf_size = new_size; 649 } 650 651 av_free(s->buffer); 652 s->buf_ptr = s->buffer = buf; 653 s->pos = s->buffer_size = buf_size; 654 s->buf_end = s->buf_ptr + buf_size; 655 s->eof_reached = 0; 656 s->must_flush = 0; 657 658 return 0; 659} 660 661int url_fopen(ByteIOContext **s, const char *filename, int flags) 662{ 663 URLContext *h; 664 int err; 665 666 err = url_open(&h, filename, flags); 667 if (err < 0) 668 return err; 669 err = url_fdopen(s, h); 670 if (err < 0) { 671 url_close(h); 672 return err; 673 } 674 return 0; 675} 676 677int url_fclose(ByteIOContext *s) 678{ 679 URLContext *h = s->opaque; 680 681 av_free(s->buffer); 682 av_free(s); 683 return url_close(h); 684} 685 686URLContext *url_fileno(ByteIOContext *s) 687{ 688 return s->opaque; 689} 690 691#if CONFIG_MUXERS 692int url_fprintf(ByteIOContext *s, const char *fmt, ...) 693{ 694 va_list ap; 695 char buf[4096]; 696 int ret; 697 698 va_start(ap, fmt); 699 ret = vsnprintf(buf, sizeof(buf), fmt, ap); 700 va_end(ap); 701 put_buffer(s, buf, strlen(buf)); 702 return ret; 703} 704#endif //CONFIG_MUXERS 705 706char *url_fgets(ByteIOContext *s, char *buf, int buf_size) 707{ 708 int c; 709 char *q; 710 711 c = url_fgetc(s); 712 if (c == EOF) 713 return NULL; 714 q = buf; 715 for(;;) { 716 if (c == EOF || c == '\n') 717 break; 718 if ((q - buf) < buf_size - 1) 719 *q++ = c; 720 c = url_fgetc(s); 721 } 722 if (buf_size > 0) 723 *q = '\0'; 724 return buf; 725} 726 727int url_fget_max_packet_size(ByteIOContext *s) 728{ 729 return s->max_packet_size; 730} 731 732int av_url_read_fpause(ByteIOContext *s, int pause) 733{ 734 if (!s->read_pause) 735 return AVERROR(ENOSYS); 736 return s->read_pause(s->opaque, pause); 737} 738 739int64_t av_url_read_fseek(ByteIOContext *s, int stream_index, 740 int64_t timestamp, int flags) 741{ 742 URLContext *h = s->opaque; 743 int64_t ret; 744 if (!s->read_seek) 745 return AVERROR(ENOSYS); 746 ret = s->read_seek(h, stream_index, timestamp, flags); 747 if(ret >= 0) { 748 int64_t pos; 749 s->buf_ptr = s->buf_end; // Flush buffer 750 pos = s->seek(h, 0, SEEK_CUR); 751 if (pos >= 0) 752 s->pos = pos; 753 else if (pos != AVERROR(ENOSYS)) 754 ret = pos; 755 } 756 return ret; 757} 758 759/* url_open_dyn_buf and url_close_dyn_buf are used in rtp.c to send a response 760 * back to the server even if CONFIG_MUXERS is false. */ 761#if CONFIG_MUXERS || CONFIG_NETWORK 762/* buffer handling */ 763int url_open_buf(ByteIOContext **s, uint8_t *buf, int buf_size, int flags) 764{ 765 int ret; 766 *s = av_mallocz(sizeof(ByteIOContext)); 767 if(!*s) 768 return AVERROR(ENOMEM); 769 ret = init_put_byte(*s, buf, buf_size, 770 (flags & URL_WRONLY || flags & URL_RDWR), 771 NULL, NULL, NULL, NULL); 772 if(ret != 0) 773 av_freep(s); 774 return ret; 775} 776 777int url_close_buf(ByteIOContext *s) 778{ 779 put_flush_packet(s); 780 return s->buf_ptr - s->buffer; 781} 782 783/* output in a dynamic buffer */ 784 785typedef struct DynBuffer { 786 int pos, size, allocated_size; 787 uint8_t *buffer; 788 int io_buffer_size; 789 uint8_t io_buffer[1]; 790} DynBuffer; 791 792static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size) 793{ 794 DynBuffer *d = opaque; 795 unsigned new_size, new_allocated_size; 796 797 /* reallocate buffer if needed */ 798 new_size = d->pos + buf_size; 799 new_allocated_size = d->allocated_size; 800 if(new_size < d->pos || new_size > INT_MAX/2) 801 return -1; 802 while (new_size > new_allocated_size) { 803 if (!new_allocated_size) 804 new_allocated_size = new_size; 805 else 806 new_allocated_size += new_allocated_size / 2 + 1; 807 } 808 809 if (new_allocated_size > d->allocated_size) { 810 d->buffer = av_realloc(d->buffer, new_allocated_size); 811 if(d->buffer == NULL) 812 return AVERROR(ENOMEM); 813 d->allocated_size = new_allocated_size; 814 } 815 memcpy(d->buffer + d->pos, buf, buf_size); 816 d->pos = new_size; 817 if (d->pos > d->size) 818 d->size = d->pos; 819 return buf_size; 820} 821 822static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size) 823{ 824 unsigned char buf1[4]; 825 int ret; 826 827 /* packetized write: output the header */ 828 AV_WB32(buf1, buf_size); 829 ret= dyn_buf_write(opaque, buf1, 4); 830 if(ret < 0) 831 return ret; 832 833 /* then the data */ 834 return dyn_buf_write(opaque, buf, buf_size); 835} 836 837static int64_t dyn_buf_seek(void *opaque, int64_t offset, int whence) 838{ 839 DynBuffer *d = opaque; 840 841 if (whence == SEEK_CUR) 842 offset += d->pos; 843 else if (whence == SEEK_END) 844 offset += d->size; 845 if (offset < 0 || offset > 0x7fffffffLL) 846 return -1; 847 d->pos = offset; 848 return 0; 849} 850 851static int url_open_dyn_buf_internal(ByteIOContext **s, int max_packet_size) 852{ 853 DynBuffer *d; 854 int ret; 855 unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024; 856 857 if(sizeof(DynBuffer) + io_buffer_size < io_buffer_size) 858 return -1; 859 d = av_mallocz(sizeof(DynBuffer) + io_buffer_size); 860 if (!d) 861 return AVERROR(ENOMEM); 862 *s = av_mallocz(sizeof(ByteIOContext)); 863 if(!*s) { 864 av_free(d); 865 return AVERROR(ENOMEM); 866 } 867 d->io_buffer_size = io_buffer_size; 868 ret = init_put_byte(*s, d->io_buffer, io_buffer_size, 869 1, d, NULL, 870 max_packet_size ? dyn_packet_buf_write : dyn_buf_write, 871 max_packet_size ? NULL : dyn_buf_seek); 872 if (ret == 0) { 873 (*s)->max_packet_size = max_packet_size; 874 } else { 875 av_free(d); 876 av_freep(s); 877 } 878 return ret; 879} 880 881int url_open_dyn_buf(ByteIOContext **s) 882{ 883 return url_open_dyn_buf_internal(s, 0); 884} 885 886int url_open_dyn_packet_buf(ByteIOContext **s, int max_packet_size) 887{ 888 if (max_packet_size <= 0) 889 return -1; 890 return url_open_dyn_buf_internal(s, max_packet_size); 891} 892 893int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer) 894{ 895 DynBuffer *d = s->opaque; 896 int size; 897 898 put_flush_packet(s); 899 900 *pbuffer = d->buffer; 901 size = d->size; 902 av_free(d); 903 av_free(s); 904 return size; 905} 906#endif /* CONFIG_MUXERS || CONFIG_NETWORK */ 907