1/* 2 * buffered I/O 3 * Copyright (c) 2000,2001 Fabrice Bellard 4 * 5 * This file is part of Libav. 6 * 7 * Libav 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 * Libav 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 Libav; 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/dict.h" 24#include "libavutil/intreadwrite.h" 25#include "libavutil/log.h" 26#include "libavutil/opt.h" 27#include "avformat.h" 28#include "avio.h" 29#include "avio_internal.h" 30#include "internal.h" 31#include "url.h" 32#include <stdarg.h> 33 34#define IO_BUFFER_SIZE 32768 35 36/** 37 * Do seeks within this distance ahead of the current buffer by skipping 38 * data instead of calling the protocol seek function, for seekable 39 * protocols. 40 */ 41#define SHORT_SEEK_THRESHOLD 4096 42 43#if !FF_API_OLD_AVIO 44static void *ffio_url_child_next(void *obj, void *prev) 45{ 46 AVIOContext *s = obj; 47 return prev ? NULL : s->opaque; 48} 49 50static const AVClass *ffio_url_child_class_next(const AVClass *prev) 51{ 52 return prev ? NULL : &ffurl_context_class; 53} 54 55static const AVOption ffio_url_options[] = { 56 { NULL }, 57}; 58 59const AVClass ffio_url_class = { 60 .class_name = "AVIOContext", 61 .item_name = av_default_item_name, 62 .version = LIBAVUTIL_VERSION_INT, 63 .option = ffio_url_options, 64 .child_next = ffio_url_child_next, 65 .child_class_next = ffio_url_child_class_next, 66}; 67#endif 68static void fill_buffer(AVIOContext *s); 69static int url_resetbuf(AVIOContext *s, int flags); 70 71int ffio_init_context(AVIOContext *s, 72 unsigned char *buffer, 73 int buffer_size, 74 int write_flag, 75 void *opaque, 76 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), 77 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), 78 int64_t (*seek)(void *opaque, int64_t offset, int whence)) 79{ 80 s->buffer = buffer; 81 s->buffer_size = buffer_size; 82 s->buf_ptr = buffer; 83 s->opaque = opaque; 84 url_resetbuf(s, write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ); 85 s->write_packet = write_packet; 86 s->read_packet = read_packet; 87 s->seek = seek; 88 s->pos = 0; 89 s->must_flush = 0; 90 s->eof_reached = 0; 91 s->error = 0; 92#if FF_API_OLD_AVIO 93 s->is_streamed = 0; 94#endif 95 s->seekable = AVIO_SEEKABLE_NORMAL; 96 s->max_packet_size = 0; 97 s->update_checksum= NULL; 98 if(!read_packet && !write_flag){ 99 s->pos = buffer_size; 100 s->buf_end = s->buffer + buffer_size; 101 } 102 s->read_pause = NULL; 103 s->read_seek = NULL; 104 return 0; 105} 106 107#if FF_API_OLD_AVIO 108int init_put_byte(AVIOContext *s, 109 unsigned char *buffer, 110 int buffer_size, 111 int write_flag, 112 void *opaque, 113 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), 114 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), 115 int64_t (*seek)(void *opaque, int64_t offset, int whence)) 116{ 117 return ffio_init_context(s, buffer, buffer_size, write_flag, opaque, 118 read_packet, write_packet, seek); 119} 120AVIOContext *av_alloc_put_byte( 121 unsigned char *buffer, 122 int buffer_size, 123 int write_flag, 124 void *opaque, 125 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), 126 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), 127 int64_t (*seek)(void *opaque, int64_t offset, int whence)) 128{ 129 return avio_alloc_context(buffer, buffer_size, write_flag, opaque, 130 read_packet, write_packet, seek); 131} 132#endif 133 134AVIOContext *avio_alloc_context( 135 unsigned char *buffer, 136 int buffer_size, 137 int write_flag, 138 void *opaque, 139 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), 140 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), 141 int64_t (*seek)(void *opaque, int64_t offset, int whence)) 142{ 143 AVIOContext *s = av_mallocz(sizeof(AVIOContext)); 144 if (!s) 145 return NULL; 146 ffio_init_context(s, buffer, buffer_size, write_flag, opaque, 147 read_packet, write_packet, seek); 148 return s; 149} 150 151static void flush_buffer(AVIOContext *s) 152{ 153 if (s->buf_ptr > s->buffer) { 154 if (s->write_packet && !s->error){ 155 int ret= s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer); 156 if(ret < 0){ 157 s->error = ret; 158 } 159 } 160 if(s->update_checksum){ 161 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr); 162 s->checksum_ptr= s->buffer; 163 } 164 s->pos += s->buf_ptr - s->buffer; 165 } 166 s->buf_ptr = s->buffer; 167} 168 169void avio_w8(AVIOContext *s, int b) 170{ 171 *s->buf_ptr++ = b; 172 if (s->buf_ptr >= s->buf_end) 173 flush_buffer(s); 174} 175 176void ffio_fill(AVIOContext *s, int b, int count) 177{ 178 while (count > 0) { 179 int len = FFMIN(s->buf_end - s->buf_ptr, count); 180 memset(s->buf_ptr, b, len); 181 s->buf_ptr += len; 182 183 if (s->buf_ptr >= s->buf_end) 184 flush_buffer(s); 185 186 count -= len; 187 } 188} 189 190void avio_write(AVIOContext *s, const unsigned char *buf, int size) 191{ 192 while (size > 0) { 193 int len = FFMIN(s->buf_end - s->buf_ptr, size); 194 memcpy(s->buf_ptr, buf, len); 195 s->buf_ptr += len; 196 197 if (s->buf_ptr >= s->buf_end) 198 flush_buffer(s); 199 200 buf += len; 201 size -= len; 202 } 203} 204 205void avio_flush(AVIOContext *s) 206{ 207 flush_buffer(s); 208 s->must_flush = 0; 209} 210 211int64_t avio_seek(AVIOContext *s, int64_t offset, int whence) 212{ 213 int64_t offset1; 214 int64_t pos; 215 int force = whence & AVSEEK_FORCE; 216 whence &= ~AVSEEK_FORCE; 217 218 if(!s) 219 return AVERROR(EINVAL); 220 221 pos = s->pos - (s->write_flag ? 0 : (s->buf_end - s->buffer)); 222 223 if (whence != SEEK_CUR && whence != SEEK_SET) 224 return AVERROR(EINVAL); 225 226 if (whence == SEEK_CUR) { 227 offset1 = pos + (s->buf_ptr - s->buffer); 228 if (offset == 0) 229 return offset1; 230 offset += offset1; 231 } 232 offset1 = offset - pos; 233 if (!s->must_flush && 234 offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) { 235 /* can do the seek inside the buffer */ 236 s->buf_ptr = s->buffer + offset1; 237 } else if ((!s->seekable || 238 offset1 <= s->buf_end + SHORT_SEEK_THRESHOLD - s->buffer) && 239 !s->write_flag && offset1 >= 0 && 240 (whence != SEEK_END || force)) { 241 while(s->pos < offset && !s->eof_reached) 242 fill_buffer(s); 243 if (s->eof_reached) 244 return AVERROR_EOF; 245 s->buf_ptr = s->buf_end + offset - s->pos; 246 } else { 247 int64_t res; 248 249#if CONFIG_MUXERS || CONFIG_NETWORK 250 if (s->write_flag) { 251 flush_buffer(s); 252 s->must_flush = 1; 253 } 254#endif /* CONFIG_MUXERS || CONFIG_NETWORK */ 255 if (!s->seek) 256 return AVERROR(EPIPE); 257 if ((res = s->seek(s->opaque, offset, SEEK_SET)) < 0) 258 return res; 259 if (!s->write_flag) 260 s->buf_end = s->buffer; 261 s->buf_ptr = s->buffer; 262 s->pos = offset; 263 } 264 s->eof_reached = 0; 265 return offset; 266} 267 268#if FF_API_OLD_AVIO 269int url_fskip(AVIOContext *s, int64_t offset) 270{ 271 int64_t ret = avio_seek(s, offset, SEEK_CUR); 272 return ret < 0 ? ret : 0; 273} 274 275int64_t url_ftell(AVIOContext *s) 276{ 277 return avio_seek(s, 0, SEEK_CUR); 278} 279#endif 280 281int64_t avio_size(AVIOContext *s) 282{ 283 int64_t size; 284 285 if(!s) 286 return AVERROR(EINVAL); 287 288 if (!s->seek) 289 return AVERROR(ENOSYS); 290 size = s->seek(s->opaque, 0, AVSEEK_SIZE); 291 if(size<0){ 292 if ((size = s->seek(s->opaque, -1, SEEK_END)) < 0) 293 return size; 294 size++; 295 s->seek(s->opaque, s->pos, SEEK_SET); 296 } 297 return size; 298} 299 300#if FF_API_OLD_AVIO 301int url_feof(AVIOContext *s) 302{ 303 if(!s) 304 return 0; 305 return s->eof_reached; 306} 307 308int url_ferror(AVIOContext *s) 309{ 310 if(!s) 311 return 0; 312 return s->error; 313} 314#endif 315 316void avio_wl32(AVIOContext *s, unsigned int val) 317{ 318 avio_w8(s, val); 319 avio_w8(s, val >> 8); 320 avio_w8(s, val >> 16); 321 avio_w8(s, val >> 24); 322} 323 324void avio_wb32(AVIOContext *s, unsigned int val) 325{ 326 avio_w8(s, val >> 24); 327 avio_w8(s, val >> 16); 328 avio_w8(s, val >> 8); 329 avio_w8(s, val); 330} 331 332#if FF_API_OLD_AVIO 333void put_strz(AVIOContext *s, const char *str) 334{ 335 avio_put_str(s, str); 336} 337 338#define GET(name, type) \ 339 type get_be ##name(AVIOContext *s) \ 340{\ 341 return avio_rb ##name(s);\ 342}\ 343 type get_le ##name(AVIOContext *s) \ 344{\ 345 return avio_rl ##name(s);\ 346} 347 348GET(16, unsigned int) 349GET(24, unsigned int) 350GET(32, unsigned int) 351GET(64, uint64_t) 352 353#undef GET 354 355#define PUT(name, type ) \ 356 void put_le ##name(AVIOContext *s, type val)\ 357{\ 358 avio_wl ##name(s, val);\ 359}\ 360 void put_be ##name(AVIOContext *s, type val)\ 361{\ 362 avio_wb ##name(s, val);\ 363} 364 365PUT(16, unsigned int) 366PUT(24, unsigned int) 367PUT(32, unsigned int) 368PUT(64, uint64_t) 369#undef PUT 370 371int get_byte(AVIOContext *s) 372{ 373 return avio_r8(s); 374} 375int get_buffer(AVIOContext *s, unsigned char *buf, int size) 376{ 377 return avio_read(s, buf, size); 378} 379int get_partial_buffer(AVIOContext *s, unsigned char *buf, int size) 380{ 381 return ffio_read_partial(s, buf, size); 382} 383void put_byte(AVIOContext *s, int val) 384{ 385 avio_w8(s, val); 386} 387void put_buffer(AVIOContext *s, const unsigned char *buf, int size) 388{ 389 avio_write(s, buf, size); 390} 391void put_nbyte(AVIOContext *s, int b, int count) 392{ 393 ffio_fill(s, b, count); 394} 395 396int url_fopen(AVIOContext **s, const char *filename, int flags) 397{ 398 return avio_open(s, filename, flags); 399} 400int url_fclose(AVIOContext *s) 401{ 402 return avio_close(s); 403} 404int64_t url_fseek(AVIOContext *s, int64_t offset, int whence) 405{ 406 return avio_seek(s, offset, whence); 407} 408int64_t url_fsize(AVIOContext *s) 409{ 410 return avio_size(s); 411} 412int url_setbufsize(AVIOContext *s, int buf_size) 413{ 414 return ffio_set_buf_size(s, buf_size); 415} 416int url_fprintf(AVIOContext *s, const char *fmt, ...) 417{ 418 va_list ap; 419 char buf[4096]; 420 int ret; 421 422 va_start(ap, fmt); 423 ret = vsnprintf(buf, sizeof(buf), fmt, ap); 424 va_end(ap); 425 avio_write(s, buf, strlen(buf)); 426 return ret; 427} 428void put_flush_packet(AVIOContext *s) 429{ 430 avio_flush(s); 431} 432int av_url_read_fpause(AVIOContext *s, int pause) 433{ 434 return avio_pause(s, pause); 435} 436int64_t av_url_read_fseek(AVIOContext *s, int stream_index, 437 int64_t timestamp, int flags) 438{ 439 return avio_seek_time(s, stream_index, timestamp, flags); 440} 441void init_checksum(AVIOContext *s, 442 unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), 443 unsigned long checksum) 444{ 445 ffio_init_checksum(s, update_checksum, checksum); 446} 447unsigned long get_checksum(AVIOContext *s) 448{ 449 return ffio_get_checksum(s); 450} 451int url_open_dyn_buf(AVIOContext **s) 452{ 453 return avio_open_dyn_buf(s); 454} 455int url_open_dyn_packet_buf(AVIOContext **s, int max_packet_size) 456{ 457 return ffio_open_dyn_packet_buf(s, max_packet_size); 458} 459int url_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer) 460{ 461 return avio_close_dyn_buf(s, pbuffer); 462} 463int url_fdopen(AVIOContext **s, URLContext *h) 464{ 465 return ffio_fdopen(s, h); 466} 467#endif 468 469int avio_put_str(AVIOContext *s, const char *str) 470{ 471 int len = 1; 472 if (str) { 473 len += strlen(str); 474 avio_write(s, (const unsigned char *) str, len); 475 } else 476 avio_w8(s, 0); 477 return len; 478} 479 480int avio_put_str16le(AVIOContext *s, const char *str) 481{ 482 const uint8_t *q = str; 483 int ret = 0; 484 485 while (*q) { 486 uint32_t ch; 487 uint16_t tmp; 488 489 GET_UTF8(ch, *q++, break;) 490 PUT_UTF16(ch, tmp, avio_wl16(s, tmp);ret += 2;) 491 } 492 avio_wl16(s, 0); 493 ret += 2; 494 return ret; 495} 496 497int ff_get_v_length(uint64_t val){ 498 int i=1; 499 500 while(val>>=7) 501 i++; 502 503 return i; 504} 505 506void ff_put_v(AVIOContext *bc, uint64_t val){ 507 int i= ff_get_v_length(val); 508 509 while(--i>0) 510 avio_w8(bc, 128 | (val>>(7*i))); 511 512 avio_w8(bc, val&127); 513} 514 515void avio_wl64(AVIOContext *s, uint64_t val) 516{ 517 avio_wl32(s, (uint32_t)(val & 0xffffffff)); 518 avio_wl32(s, (uint32_t)(val >> 32)); 519} 520 521void avio_wb64(AVIOContext *s, uint64_t val) 522{ 523 avio_wb32(s, (uint32_t)(val >> 32)); 524 avio_wb32(s, (uint32_t)(val & 0xffffffff)); 525} 526 527void avio_wl16(AVIOContext *s, unsigned int val) 528{ 529 avio_w8(s, val); 530 avio_w8(s, val >> 8); 531} 532 533void avio_wb16(AVIOContext *s, unsigned int val) 534{ 535 avio_w8(s, val >> 8); 536 avio_w8(s, val); 537} 538 539void avio_wl24(AVIOContext *s, unsigned int val) 540{ 541 avio_wl16(s, val & 0xffff); 542 avio_w8(s, val >> 16); 543} 544 545void avio_wb24(AVIOContext *s, unsigned int val) 546{ 547 avio_wb16(s, val >> 8); 548 avio_w8(s, val); 549} 550 551#if FF_API_OLD_AVIO 552void put_tag(AVIOContext *s, const char *tag) 553{ 554 while (*tag) { 555 avio_w8(s, *tag++); 556 } 557} 558#endif 559 560/* Input stream */ 561 562static void fill_buffer(AVIOContext *s) 563{ 564 uint8_t *dst= !s->max_packet_size && s->buf_end - s->buffer < s->buffer_size ? s->buf_end : s->buffer; 565 int len= s->buffer_size - (dst - s->buffer); 566 int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE; 567 568 /* can't fill the buffer without read_packet, just set EOF if appropiate */ 569 if (!s->read_packet && s->buf_ptr >= s->buf_end) 570 s->eof_reached = 1; 571 572 /* no need to do anything if EOF already reached */ 573 if (s->eof_reached) 574 return; 575 576 if(s->update_checksum && dst == s->buffer){ 577 if(s->buf_end > s->checksum_ptr) 578 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr); 579 s->checksum_ptr= s->buffer; 580 } 581 582 /* make buffer smaller in case it ended up large after probing */ 583 if (s->buffer_size > max_buffer_size) { 584 ffio_set_buf_size(s, max_buffer_size); 585 586 s->checksum_ptr = dst = s->buffer; 587 len = s->buffer_size; 588 } 589 590 if(s->read_packet) 591 len = s->read_packet(s->opaque, dst, len); 592 else 593 len = 0; 594 if (len <= 0) { 595 /* do not modify buffer if EOF reached so that a seek back can 596 be done without rereading data */ 597 s->eof_reached = 1; 598 if(len<0) 599 s->error= len; 600 } else { 601 s->pos += len; 602 s->buf_ptr = dst; 603 s->buf_end = dst + len; 604 } 605} 606 607unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, 608 unsigned int len) 609{ 610 return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len); 611} 612 613unsigned long ffio_get_checksum(AVIOContext *s) 614{ 615 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr); 616 s->update_checksum= NULL; 617 return s->checksum; 618} 619 620void ffio_init_checksum(AVIOContext *s, 621 unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), 622 unsigned long checksum) 623{ 624 s->update_checksum= update_checksum; 625 if(s->update_checksum){ 626 s->checksum= checksum; 627 s->checksum_ptr= s->buf_ptr; 628 } 629} 630 631/* XXX: put an inline version */ 632int avio_r8(AVIOContext *s) 633{ 634 if (s->buf_ptr >= s->buf_end) 635 fill_buffer(s); 636 if (s->buf_ptr < s->buf_end) 637 return *s->buf_ptr++; 638 return 0; 639} 640 641#if FF_API_OLD_AVIO 642int url_fgetc(AVIOContext *s) 643{ 644 if (s->buf_ptr >= s->buf_end) 645 fill_buffer(s); 646 if (s->buf_ptr < s->buf_end) 647 return *s->buf_ptr++; 648 return URL_EOF; 649} 650#endif 651 652int avio_read(AVIOContext *s, unsigned char *buf, int size) 653{ 654 int len, size1; 655 656 size1 = size; 657 while (size > 0) { 658 len = s->buf_end - s->buf_ptr; 659 if (len > size) 660 len = size; 661 if (len == 0) { 662 if(size > s->buffer_size && !s->update_checksum){ 663 if(s->read_packet) 664 len = s->read_packet(s->opaque, buf, size); 665 if (len <= 0) { 666 /* do not modify buffer if EOF reached so that a seek back can 667 be done without rereading data */ 668 s->eof_reached = 1; 669 if(len<0) 670 s->error= len; 671 break; 672 } else { 673 s->pos += len; 674 size -= len; 675 buf += len; 676 s->buf_ptr = s->buffer; 677 s->buf_end = s->buffer/* + len*/; 678 } 679 }else{ 680 fill_buffer(s); 681 len = s->buf_end - s->buf_ptr; 682 if (len == 0) 683 break; 684 } 685 } else { 686 memcpy(buf, s->buf_ptr, len); 687 buf += len; 688 s->buf_ptr += len; 689 size -= len; 690 } 691 } 692 if (size1 == size) { 693 if (s->error) return s->error; 694 if (s->eof_reached) return AVERROR_EOF; 695 } 696 return size1 - size; 697} 698 699int ffio_read_partial(AVIOContext *s, unsigned char *buf, int size) 700{ 701 int len; 702 703 if(size<0) 704 return -1; 705 706 len = s->buf_end - s->buf_ptr; 707 if (len == 0) { 708 fill_buffer(s); 709 len = s->buf_end - s->buf_ptr; 710 } 711 if (len > size) 712 len = size; 713 memcpy(buf, s->buf_ptr, len); 714 s->buf_ptr += len; 715 if (!len) { 716 if (s->error) return s->error; 717 if (s->eof_reached) return AVERROR_EOF; 718 } 719 return len; 720} 721 722unsigned int avio_rl16(AVIOContext *s) 723{ 724 unsigned int val; 725 val = avio_r8(s); 726 val |= avio_r8(s) << 8; 727 return val; 728} 729 730unsigned int avio_rl24(AVIOContext *s) 731{ 732 unsigned int val; 733 val = avio_rl16(s); 734 val |= avio_r8(s) << 16; 735 return val; 736} 737 738unsigned int avio_rl32(AVIOContext *s) 739{ 740 unsigned int val; 741 val = avio_rl16(s); 742 val |= avio_rl16(s) << 16; 743 return val; 744} 745 746uint64_t avio_rl64(AVIOContext *s) 747{ 748 uint64_t val; 749 val = (uint64_t)avio_rl32(s); 750 val |= (uint64_t)avio_rl32(s) << 32; 751 return val; 752} 753 754unsigned int avio_rb16(AVIOContext *s) 755{ 756 unsigned int val; 757 val = avio_r8(s) << 8; 758 val |= avio_r8(s); 759 return val; 760} 761 762unsigned int avio_rb24(AVIOContext *s) 763{ 764 unsigned int val; 765 val = avio_rb16(s) << 8; 766 val |= avio_r8(s); 767 return val; 768} 769unsigned int avio_rb32(AVIOContext *s) 770{ 771 unsigned int val; 772 val = avio_rb16(s) << 16; 773 val |= avio_rb16(s); 774 return val; 775} 776 777#if FF_API_OLD_AVIO 778char *get_strz(AVIOContext *s, char *buf, int maxlen) 779{ 780 avio_get_str(s, INT_MAX, buf, maxlen); 781 return buf; 782} 783#endif 784 785int ff_get_line(AVIOContext *s, char *buf, int maxlen) 786{ 787 int i = 0; 788 char c; 789 790 do { 791 c = avio_r8(s); 792 if (c && i < maxlen-1) 793 buf[i++] = c; 794 } while (c != '\n' && c); 795 796 buf[i] = 0; 797 return i; 798} 799 800int avio_get_str(AVIOContext *s, int maxlen, char *buf, int buflen) 801{ 802 int i; 803 804 if (buflen <= 0) 805 return AVERROR(EINVAL); 806 // reserve 1 byte for terminating 0 807 buflen = FFMIN(buflen - 1, maxlen); 808 for (i = 0; i < buflen; i++) 809 if (!(buf[i] = avio_r8(s))) 810 return i + 1; 811 buf[i] = 0; 812 for (; i < maxlen; i++) 813 if (!avio_r8(s)) 814 return i + 1; 815 return maxlen; 816} 817 818#define GET_STR16(type, read) \ 819 int avio_get_str16 ##type(AVIOContext *pb, int maxlen, char *buf, int buflen)\ 820{\ 821 char* q = buf;\ 822 int ret = 0;\ 823 if (buflen <= 0) \ 824 return AVERROR(EINVAL); \ 825 while (ret + 1 < maxlen) {\ 826 uint8_t tmp;\ 827 uint32_t ch;\ 828 GET_UTF16(ch, (ret += 2) <= maxlen ? read(pb) : 0, break;)\ 829 if (!ch)\ 830 break;\ 831 PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;)\ 832 }\ 833 *q = 0;\ 834 return ret;\ 835}\ 836 837GET_STR16(le, avio_rl16) 838GET_STR16(be, avio_rb16) 839 840#undef GET_STR16 841 842uint64_t avio_rb64(AVIOContext *s) 843{ 844 uint64_t val; 845 val = (uint64_t)avio_rb32(s) << 32; 846 val |= (uint64_t)avio_rb32(s); 847 return val; 848} 849 850uint64_t ffio_read_varlen(AVIOContext *bc){ 851 uint64_t val = 0; 852 int tmp; 853 854 do{ 855 tmp = avio_r8(bc); 856 val= (val<<7) + (tmp&127); 857 }while(tmp&128); 858 return val; 859} 860 861int ffio_fdopen(AVIOContext **s, URLContext *h) 862{ 863 uint8_t *buffer; 864 int buffer_size, max_packet_size; 865 866 max_packet_size = h->max_packet_size; 867 if (max_packet_size) { 868 buffer_size = max_packet_size; /* no need to bufferize more than one packet */ 869 } else { 870 buffer_size = IO_BUFFER_SIZE; 871 } 872 buffer = av_malloc(buffer_size); 873 if (!buffer) 874 return AVERROR(ENOMEM); 875 876 *s = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE, h, 877 ffurl_read, ffurl_write, ffurl_seek); 878 if (!*s) { 879 av_free(buffer); 880 return AVERROR(ENOMEM); 881 } 882#if FF_API_OLD_AVIO 883 (*s)->is_streamed = h->is_streamed; 884#endif 885 (*s)->seekable = h->is_streamed ? 0 : AVIO_SEEKABLE_NORMAL; 886 (*s)->max_packet_size = max_packet_size; 887 if(h->prot) { 888 (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause; 889 (*s)->read_seek = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek; 890 } 891#if !FF_API_OLD_AVIO 892 (*s)->av_class = &ffio_url_class; 893#endif 894 return 0; 895} 896 897int ffio_set_buf_size(AVIOContext *s, int buf_size) 898{ 899 uint8_t *buffer; 900 buffer = av_malloc(buf_size); 901 if (!buffer) 902 return AVERROR(ENOMEM); 903 904 av_free(s->buffer); 905 s->buffer = buffer; 906 s->buffer_size = buf_size; 907 s->buf_ptr = buffer; 908 url_resetbuf(s, s->write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ); 909 return 0; 910} 911 912static int url_resetbuf(AVIOContext *s, int flags) 913{ 914 assert(flags == AVIO_FLAG_WRITE || flags == AVIO_FLAG_READ); 915 916 if (flags & AVIO_FLAG_WRITE) { 917 s->buf_end = s->buffer + s->buffer_size; 918 s->write_flag = 1; 919 } else { 920 s->buf_end = s->buffer; 921 s->write_flag = 0; 922 } 923 return 0; 924} 925 926int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char *buf, int buf_size) 927{ 928 int64_t buffer_start; 929 int buffer_size; 930 int overlap, new_size, alloc_size; 931 932 if (s->write_flag) 933 return AVERROR(EINVAL); 934 935 buffer_size = s->buf_end - s->buffer; 936 937 /* the buffers must touch or overlap */ 938 if ((buffer_start = s->pos - buffer_size) > buf_size) 939 return AVERROR(EINVAL); 940 941 overlap = buf_size - buffer_start; 942 new_size = buf_size + buffer_size - overlap; 943 944 alloc_size = FFMAX(s->buffer_size, new_size); 945 if (alloc_size > buf_size) 946 if (!(buf = av_realloc(buf, alloc_size))) 947 return AVERROR(ENOMEM); 948 949 if (new_size > buf_size) { 950 memcpy(buf + buf_size, s->buffer + overlap, buffer_size - overlap); 951 buf_size = new_size; 952 } 953 954 av_free(s->buffer); 955 s->buf_ptr = s->buffer = buf; 956 s->buffer_size = alloc_size; 957 s->pos = buf_size; 958 s->buf_end = s->buf_ptr + buf_size; 959 s->eof_reached = 0; 960 s->must_flush = 0; 961 962 return 0; 963} 964 965int avio_open(AVIOContext **s, const char *filename, int flags) 966{ 967 return avio_open2(s, filename, flags, NULL, NULL); 968} 969 970int avio_open2(AVIOContext **s, const char *filename, int flags, 971 const AVIOInterruptCB *int_cb, AVDictionary **options) 972{ 973 URLContext *h; 974 int err; 975 976 err = ffurl_open(&h, filename, flags, int_cb, options); 977 if (err < 0) 978 return err; 979 err = ffio_fdopen(s, h); 980 if (err < 0) { 981 ffurl_close(h); 982 return err; 983 } 984 return 0; 985} 986 987int avio_close(AVIOContext *s) 988{ 989 URLContext *h = s->opaque; 990 991 av_free(s->buffer); 992 av_free(s); 993 return ffurl_close(h); 994} 995 996#if FF_API_OLD_AVIO 997URLContext *url_fileno(AVIOContext *s) 998{ 999 return s->opaque; 1000} 1001#endif 1002 1003int avio_printf(AVIOContext *s, const char *fmt, ...) 1004{ 1005 va_list ap; 1006 char buf[4096]; 1007 int ret; 1008 1009 va_start(ap, fmt); 1010 ret = vsnprintf(buf, sizeof(buf), fmt, ap); 1011 va_end(ap); 1012 avio_write(s, buf, strlen(buf)); 1013 return ret; 1014} 1015 1016#if FF_API_OLD_AVIO 1017char *url_fgets(AVIOContext *s, char *buf, int buf_size) 1018{ 1019 int c; 1020 char *q; 1021 1022 c = avio_r8(s); 1023 if (s->eof_reached) 1024 return NULL; 1025 q = buf; 1026 for(;;) { 1027 if (s->eof_reached || c == '\n') 1028 break; 1029 if ((q - buf) < buf_size - 1) 1030 *q++ = c; 1031 c = avio_r8(s); 1032 } 1033 if (buf_size > 0) 1034 *q = '\0'; 1035 return buf; 1036} 1037 1038int url_fget_max_packet_size(AVIOContext *s) 1039{ 1040 return s->max_packet_size; 1041} 1042#endif 1043 1044int avio_pause(AVIOContext *s, int pause) 1045{ 1046 if (!s->read_pause) 1047 return AVERROR(ENOSYS); 1048 return s->read_pause(s->opaque, pause); 1049} 1050 1051int64_t avio_seek_time(AVIOContext *s, int stream_index, 1052 int64_t timestamp, int flags) 1053{ 1054 URLContext *h = s->opaque; 1055 int64_t ret; 1056 if (!s->read_seek) 1057 return AVERROR(ENOSYS); 1058 ret = s->read_seek(h, stream_index, timestamp, flags); 1059 if(ret >= 0) { 1060 int64_t pos; 1061 s->buf_ptr = s->buf_end; // Flush buffer 1062 pos = s->seek(h, 0, SEEK_CUR); 1063 if (pos >= 0) 1064 s->pos = pos; 1065 else if (pos != AVERROR(ENOSYS)) 1066 ret = pos; 1067 } 1068 return ret; 1069} 1070 1071/* buffer handling */ 1072#if FF_API_OLD_AVIO 1073int url_open_buf(AVIOContext **s, uint8_t *buf, int buf_size, int flags) 1074{ 1075 int ret; 1076 *s = av_mallocz(sizeof(AVIOContext)); 1077 if(!*s) 1078 return AVERROR(ENOMEM); 1079 ret = ffio_init_context(*s, buf, buf_size, 1080 flags & AVIO_FLAG_WRITE, 1081 NULL, NULL, NULL, NULL); 1082 if(ret != 0) 1083 av_freep(s); 1084 return ret; 1085} 1086 1087int url_close_buf(AVIOContext *s) 1088{ 1089 avio_flush(s); 1090 return s->buf_ptr - s->buffer; 1091} 1092#endif 1093 1094/* output in a dynamic buffer */ 1095 1096typedef struct DynBuffer { 1097 int pos, size, allocated_size; 1098 uint8_t *buffer; 1099 int io_buffer_size; 1100 uint8_t io_buffer[1]; 1101} DynBuffer; 1102 1103static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size) 1104{ 1105 DynBuffer *d = opaque; 1106 unsigned new_size, new_allocated_size; 1107 1108 /* reallocate buffer if needed */ 1109 new_size = d->pos + buf_size; 1110 new_allocated_size = d->allocated_size; 1111 if(new_size < d->pos || new_size > INT_MAX/2) 1112 return -1; 1113 while (new_size > new_allocated_size) { 1114 if (!new_allocated_size) 1115 new_allocated_size = new_size; 1116 else 1117 new_allocated_size += new_allocated_size / 2 + 1; 1118 } 1119 1120 if (new_allocated_size > d->allocated_size) { 1121 d->buffer = av_realloc(d->buffer, new_allocated_size); 1122 if(d->buffer == NULL) 1123 return AVERROR(ENOMEM); 1124 d->allocated_size = new_allocated_size; 1125 } 1126 memcpy(d->buffer + d->pos, buf, buf_size); 1127 d->pos = new_size; 1128 if (d->pos > d->size) 1129 d->size = d->pos; 1130 return buf_size; 1131} 1132 1133static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size) 1134{ 1135 unsigned char buf1[4]; 1136 int ret; 1137 1138 /* packetized write: output the header */ 1139 AV_WB32(buf1, buf_size); 1140 ret= dyn_buf_write(opaque, buf1, 4); 1141 if(ret < 0) 1142 return ret; 1143 1144 /* then the data */ 1145 return dyn_buf_write(opaque, buf, buf_size); 1146} 1147 1148static int64_t dyn_buf_seek(void *opaque, int64_t offset, int whence) 1149{ 1150 DynBuffer *d = opaque; 1151 1152 if (whence == SEEK_CUR) 1153 offset += d->pos; 1154 else if (whence == SEEK_END) 1155 offset += d->size; 1156 if (offset < 0 || offset > 0x7fffffffLL) 1157 return -1; 1158 d->pos = offset; 1159 return 0; 1160} 1161 1162static int url_open_dyn_buf_internal(AVIOContext **s, int max_packet_size) 1163{ 1164 DynBuffer *d; 1165 unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024; 1166 1167 if(sizeof(DynBuffer) + io_buffer_size < io_buffer_size) 1168 return -1; 1169 d = av_mallocz(sizeof(DynBuffer) + io_buffer_size); 1170 if (!d) 1171 return AVERROR(ENOMEM); 1172 d->io_buffer_size = io_buffer_size; 1173 *s = avio_alloc_context(d->io_buffer, d->io_buffer_size, 1, d, NULL, 1174 max_packet_size ? dyn_packet_buf_write : dyn_buf_write, 1175 max_packet_size ? NULL : dyn_buf_seek); 1176 if(!*s) { 1177 av_free(d); 1178 return AVERROR(ENOMEM); 1179 } 1180 (*s)->max_packet_size = max_packet_size; 1181 return 0; 1182} 1183 1184int avio_open_dyn_buf(AVIOContext **s) 1185{ 1186 return url_open_dyn_buf_internal(s, 0); 1187} 1188 1189int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size) 1190{ 1191 if (max_packet_size <= 0) 1192 return -1; 1193 return url_open_dyn_buf_internal(s, max_packet_size); 1194} 1195 1196int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer) 1197{ 1198 DynBuffer *d = s->opaque; 1199 int size; 1200 static const char padbuf[FF_INPUT_BUFFER_PADDING_SIZE] = {0}; 1201 int padding = 0; 1202 1203 /* don't attempt to pad fixed-size packet buffers */ 1204 if (!s->max_packet_size) { 1205 avio_write(s, padbuf, sizeof(padbuf)); 1206 padding = FF_INPUT_BUFFER_PADDING_SIZE; 1207 } 1208 1209 avio_flush(s); 1210 1211 *pbuffer = d->buffer; 1212 size = d->size; 1213 av_free(d); 1214 av_free(s); 1215 return size - padding; 1216} 1217