Libav 0.7.1
|
00001 /* 00002 * Buffered I/O for ffmpeg system 00003 * Copyright (c) 2000,2001 Fabrice Bellard 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include "libavutil/crc.h" 00023 #include "libavutil/intreadwrite.h" 00024 #include "avformat.h" 00025 #include "avio.h" 00026 #include "avio_internal.h" 00027 #include "internal.h" 00028 #include "url.h" 00029 #include <stdarg.h> 00030 00031 #define IO_BUFFER_SIZE 32768 00032 00038 #define SHORT_SEEK_THRESHOLD 4096 00039 00040 static void fill_buffer(AVIOContext *s); 00041 static int url_resetbuf(AVIOContext *s, int flags); 00042 00043 int ffio_init_context(AVIOContext *s, 00044 unsigned char *buffer, 00045 int buffer_size, 00046 int write_flag, 00047 void *opaque, 00048 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), 00049 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), 00050 int64_t (*seek)(void *opaque, int64_t offset, int whence)) 00051 { 00052 s->buffer = buffer; 00053 s->buffer_size = buffer_size; 00054 s->buf_ptr = buffer; 00055 s->opaque = opaque; 00056 url_resetbuf(s, write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ); 00057 s->write_packet = write_packet; 00058 s->read_packet = read_packet; 00059 s->seek = seek; 00060 s->pos = 0; 00061 s->must_flush = 0; 00062 s->eof_reached = 0; 00063 s->error = 0; 00064 #if FF_API_OLD_AVIO 00065 s->is_streamed = 0; 00066 #endif 00067 s->seekable = AVIO_SEEKABLE_NORMAL; 00068 s->max_packet_size = 0; 00069 s->update_checksum= NULL; 00070 if(!read_packet && !write_flag){ 00071 s->pos = buffer_size; 00072 s->buf_end = s->buffer + buffer_size; 00073 } 00074 s->read_pause = NULL; 00075 s->read_seek = NULL; 00076 return 0; 00077 } 00078 00079 #if FF_API_OLD_AVIO 00080 int init_put_byte(AVIOContext *s, 00081 unsigned char *buffer, 00082 int buffer_size, 00083 int write_flag, 00084 void *opaque, 00085 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), 00086 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), 00087 int64_t (*seek)(void *opaque, int64_t offset, int whence)) 00088 { 00089 return ffio_init_context(s, buffer, buffer_size, write_flag, opaque, 00090 read_packet, write_packet, seek); 00091 } 00092 AVIOContext *av_alloc_put_byte( 00093 unsigned char *buffer, 00094 int buffer_size, 00095 int write_flag, 00096 void *opaque, 00097 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), 00098 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), 00099 int64_t (*seek)(void *opaque, int64_t offset, int whence)) 00100 { 00101 return avio_alloc_context(buffer, buffer_size, write_flag, opaque, 00102 read_packet, write_packet, seek); 00103 } 00104 #endif 00105 00106 AVIOContext *avio_alloc_context( 00107 unsigned char *buffer, 00108 int buffer_size, 00109 int write_flag, 00110 void *opaque, 00111 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), 00112 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), 00113 int64_t (*seek)(void *opaque, int64_t offset, int whence)) 00114 { 00115 AVIOContext *s = av_mallocz(sizeof(AVIOContext)); 00116 if (!s) 00117 return NULL; 00118 ffio_init_context(s, buffer, buffer_size, write_flag, opaque, 00119 read_packet, write_packet, seek); 00120 return s; 00121 } 00122 00123 static void flush_buffer(AVIOContext *s) 00124 { 00125 if (s->buf_ptr > s->buffer) { 00126 if (s->write_packet && !s->error){ 00127 int ret= s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer); 00128 if(ret < 0){ 00129 s->error = ret; 00130 } 00131 } 00132 if(s->update_checksum){ 00133 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr); 00134 s->checksum_ptr= s->buffer; 00135 } 00136 s->pos += s->buf_ptr - s->buffer; 00137 } 00138 s->buf_ptr = s->buffer; 00139 } 00140 00141 void avio_w8(AVIOContext *s, int b) 00142 { 00143 *(s->buf_ptr)++ = b; 00144 if (s->buf_ptr >= s->buf_end) 00145 flush_buffer(s); 00146 } 00147 00148 void ffio_fill(AVIOContext *s, int b, int count) 00149 { 00150 while (count > 0) { 00151 int len = FFMIN(s->buf_end - s->buf_ptr, count); 00152 memset(s->buf_ptr, b, len); 00153 s->buf_ptr += len; 00154 00155 if (s->buf_ptr >= s->buf_end) 00156 flush_buffer(s); 00157 00158 count -= len; 00159 } 00160 } 00161 00162 void avio_write(AVIOContext *s, const unsigned char *buf, int size) 00163 { 00164 while (size > 0) { 00165 int len = FFMIN(s->buf_end - s->buf_ptr, size); 00166 memcpy(s->buf_ptr, buf, len); 00167 s->buf_ptr += len; 00168 00169 if (s->buf_ptr >= s->buf_end) 00170 flush_buffer(s); 00171 00172 buf += len; 00173 size -= len; 00174 } 00175 } 00176 00177 void avio_flush(AVIOContext *s) 00178 { 00179 flush_buffer(s); 00180 s->must_flush = 0; 00181 } 00182 00183 int64_t avio_seek(AVIOContext *s, int64_t offset, int whence) 00184 { 00185 int64_t offset1; 00186 int64_t pos; 00187 int force = whence & AVSEEK_FORCE; 00188 whence &= ~AVSEEK_FORCE; 00189 00190 if(!s) 00191 return AVERROR(EINVAL); 00192 00193 pos = s->pos - (s->write_flag ? 0 : (s->buf_end - s->buffer)); 00194 00195 if (whence != SEEK_CUR && whence != SEEK_SET) 00196 return AVERROR(EINVAL); 00197 00198 if (whence == SEEK_CUR) { 00199 offset1 = pos + (s->buf_ptr - s->buffer); 00200 if (offset == 0) 00201 return offset1; 00202 offset += offset1; 00203 } 00204 offset1 = offset - pos; 00205 if (!s->must_flush && 00206 offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) { 00207 /* can do the seek inside the buffer */ 00208 s->buf_ptr = s->buffer + offset1; 00209 } else if ((!s->seekable || 00210 offset1 <= s->buf_end + SHORT_SEEK_THRESHOLD - s->buffer) && 00211 !s->write_flag && offset1 >= 0 && 00212 (whence != SEEK_END || force)) { 00213 while(s->pos < offset && !s->eof_reached) 00214 fill_buffer(s); 00215 if (s->eof_reached) 00216 return AVERROR_EOF; 00217 s->buf_ptr = s->buf_end + offset - s->pos; 00218 } else { 00219 int64_t res; 00220 00221 #if CONFIG_MUXERS || CONFIG_NETWORK 00222 if (s->write_flag) { 00223 flush_buffer(s); 00224 s->must_flush = 1; 00225 } 00226 #endif /* CONFIG_MUXERS || CONFIG_NETWORK */ 00227 if (!s->seek) 00228 return AVERROR(EPIPE); 00229 if ((res = s->seek(s->opaque, offset, SEEK_SET)) < 0) 00230 return res; 00231 if (!s->write_flag) 00232 s->buf_end = s->buffer; 00233 s->buf_ptr = s->buffer; 00234 s->pos = offset; 00235 } 00236 s->eof_reached = 0; 00237 return offset; 00238 } 00239 00240 #if FF_API_OLD_AVIO 00241 int url_fskip(AVIOContext *s, int64_t offset) 00242 { 00243 int64_t ret = avio_seek(s, offset, SEEK_CUR); 00244 return ret < 0 ? ret : 0; 00245 } 00246 00247 int64_t url_ftell(AVIOContext *s) 00248 { 00249 return avio_seek(s, 0, SEEK_CUR); 00250 } 00251 #endif 00252 00253 int64_t avio_size(AVIOContext *s) 00254 { 00255 int64_t size; 00256 00257 if(!s) 00258 return AVERROR(EINVAL); 00259 00260 if (!s->seek) 00261 return AVERROR(ENOSYS); 00262 size = s->seek(s->opaque, 0, AVSEEK_SIZE); 00263 if(size<0){ 00264 if ((size = s->seek(s->opaque, -1, SEEK_END)) < 0) 00265 return size; 00266 size++; 00267 s->seek(s->opaque, s->pos, SEEK_SET); 00268 } 00269 return size; 00270 } 00271 00272 #if FF_API_OLD_AVIO 00273 int url_feof(AVIOContext *s) 00274 { 00275 if(!s) 00276 return 0; 00277 return s->eof_reached; 00278 } 00279 00280 int url_ferror(AVIOContext *s) 00281 { 00282 if(!s) 00283 return 0; 00284 return s->error; 00285 } 00286 #endif 00287 00288 void avio_wl32(AVIOContext *s, unsigned int val) 00289 { 00290 avio_w8(s, val); 00291 avio_w8(s, val >> 8); 00292 avio_w8(s, val >> 16); 00293 avio_w8(s, val >> 24); 00294 } 00295 00296 void avio_wb32(AVIOContext *s, unsigned int val) 00297 { 00298 avio_w8(s, val >> 24); 00299 avio_w8(s, val >> 16); 00300 avio_w8(s, val >> 8); 00301 avio_w8(s, val); 00302 } 00303 00304 #if FF_API_OLD_AVIO 00305 void put_strz(AVIOContext *s, const char *str) 00306 { 00307 avio_put_str(s, str); 00308 } 00309 00310 #define GET(name, type) \ 00311 type get_be ##name(AVIOContext *s) \ 00312 {\ 00313 return avio_rb ##name(s);\ 00314 }\ 00315 type get_le ##name(AVIOContext *s) \ 00316 {\ 00317 return avio_rl ##name(s);\ 00318 } 00319 00320 GET(16, unsigned int) 00321 GET(24, unsigned int) 00322 GET(32, unsigned int) 00323 GET(64, uint64_t) 00324 00325 #undef GET 00326 00327 #define PUT(name, type ) \ 00328 void put_le ##name(AVIOContext *s, type val)\ 00329 {\ 00330 avio_wl ##name(s, val);\ 00331 }\ 00332 void put_be ##name(AVIOContext *s, type val)\ 00333 {\ 00334 avio_wb ##name(s, val);\ 00335 } 00336 00337 PUT(16, unsigned int) 00338 PUT(24, unsigned int) 00339 PUT(32, unsigned int) 00340 PUT(64, uint64_t) 00341 #undef PUT 00342 00343 int get_byte(AVIOContext *s) 00344 { 00345 return avio_r8(s); 00346 } 00347 int get_buffer(AVIOContext *s, unsigned char *buf, int size) 00348 { 00349 return avio_read(s, buf, size); 00350 } 00351 int get_partial_buffer(AVIOContext *s, unsigned char *buf, int size) 00352 { 00353 return ffio_read_partial(s, buf, size); 00354 } 00355 void put_byte(AVIOContext *s, int val) 00356 { 00357 avio_w8(s, val); 00358 } 00359 void put_buffer(AVIOContext *s, const unsigned char *buf, int size) 00360 { 00361 avio_write(s, buf, size); 00362 } 00363 void put_nbyte(AVIOContext *s, int b, int count) 00364 { 00365 ffio_fill(s, b, count); 00366 } 00367 00368 int url_fopen(AVIOContext **s, const char *filename, int flags) 00369 { 00370 return avio_open(s, filename, flags); 00371 } 00372 int url_fclose(AVIOContext *s) 00373 { 00374 return avio_close(s); 00375 } 00376 int64_t url_fseek(AVIOContext *s, int64_t offset, int whence) 00377 { 00378 return avio_seek(s, offset, whence); 00379 } 00380 int64_t url_fsize(AVIOContext *s) 00381 { 00382 return avio_size(s); 00383 } 00384 int url_setbufsize(AVIOContext *s, int buf_size) 00385 { 00386 return ffio_set_buf_size(s, buf_size); 00387 } 00388 int url_fprintf(AVIOContext *s, const char *fmt, ...) 00389 { 00390 va_list ap; 00391 char buf[4096]; 00392 int ret; 00393 00394 va_start(ap, fmt); 00395 ret = vsnprintf(buf, sizeof(buf), fmt, ap); 00396 va_end(ap); 00397 avio_write(s, buf, strlen(buf)); 00398 return ret; 00399 } 00400 void put_flush_packet(AVIOContext *s) 00401 { 00402 avio_flush(s); 00403 } 00404 int av_url_read_fpause(AVIOContext *s, int pause) 00405 { 00406 return avio_pause(s, pause); 00407 } 00408 int64_t av_url_read_fseek(AVIOContext *s, int stream_index, 00409 int64_t timestamp, int flags) 00410 { 00411 return avio_seek_time(s, stream_index, timestamp, flags); 00412 } 00413 void init_checksum(AVIOContext *s, 00414 unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), 00415 unsigned long checksum) 00416 { 00417 ffio_init_checksum(s, update_checksum, checksum); 00418 } 00419 unsigned long get_checksum(AVIOContext *s) 00420 { 00421 return ffio_get_checksum(s); 00422 } 00423 int url_open_dyn_buf(AVIOContext **s) 00424 { 00425 return avio_open_dyn_buf(s); 00426 } 00427 int url_open_dyn_packet_buf(AVIOContext **s, int max_packet_size) 00428 { 00429 return ffio_open_dyn_packet_buf(s, max_packet_size); 00430 } 00431 int url_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer) 00432 { 00433 return avio_close_dyn_buf(s, pbuffer); 00434 } 00435 int url_fdopen(AVIOContext **s, URLContext *h) 00436 { 00437 return ffio_fdopen(s, h); 00438 } 00439 #endif 00440 00441 int avio_put_str(AVIOContext *s, const char *str) 00442 { 00443 int len = 1; 00444 if (str) { 00445 len += strlen(str); 00446 avio_write(s, (const unsigned char *) str, len); 00447 } else 00448 avio_w8(s, 0); 00449 return len; 00450 } 00451 00452 int avio_put_str16le(AVIOContext *s, const char *str) 00453 { 00454 const uint8_t *q = str; 00455 int ret = 0; 00456 00457 while (*q) { 00458 uint32_t ch; 00459 uint16_t tmp; 00460 00461 GET_UTF8(ch, *q++, break;) 00462 PUT_UTF16(ch, tmp, avio_wl16(s, tmp);ret += 2;) 00463 } 00464 avio_wl16(s, 0); 00465 ret += 2; 00466 return ret; 00467 } 00468 00469 int ff_get_v_length(uint64_t val){ 00470 int i=1; 00471 00472 while(val>>=7) 00473 i++; 00474 00475 return i; 00476 } 00477 00478 void ff_put_v(AVIOContext *bc, uint64_t val){ 00479 int i= ff_get_v_length(val); 00480 00481 while(--i>0) 00482 avio_w8(bc, 128 | (val>>(7*i))); 00483 00484 avio_w8(bc, val&127); 00485 } 00486 00487 void avio_wl64(AVIOContext *s, uint64_t val) 00488 { 00489 avio_wl32(s, (uint32_t)(val & 0xffffffff)); 00490 avio_wl32(s, (uint32_t)(val >> 32)); 00491 } 00492 00493 void avio_wb64(AVIOContext *s, uint64_t val) 00494 { 00495 avio_wb32(s, (uint32_t)(val >> 32)); 00496 avio_wb32(s, (uint32_t)(val & 0xffffffff)); 00497 } 00498 00499 void avio_wl16(AVIOContext *s, unsigned int val) 00500 { 00501 avio_w8(s, val); 00502 avio_w8(s, val >> 8); 00503 } 00504 00505 void avio_wb16(AVIOContext *s, unsigned int val) 00506 { 00507 avio_w8(s, val >> 8); 00508 avio_w8(s, val); 00509 } 00510 00511 void avio_wl24(AVIOContext *s, unsigned int val) 00512 { 00513 avio_wl16(s, val & 0xffff); 00514 avio_w8(s, val >> 16); 00515 } 00516 00517 void avio_wb24(AVIOContext *s, unsigned int val) 00518 { 00519 avio_wb16(s, val >> 8); 00520 avio_w8(s, val); 00521 } 00522 00523 #if FF_API_OLD_AVIO 00524 void put_tag(AVIOContext *s, const char *tag) 00525 { 00526 while (*tag) { 00527 avio_w8(s, *tag++); 00528 } 00529 } 00530 #endif 00531 00532 /* Input stream */ 00533 00534 static void fill_buffer(AVIOContext *s) 00535 { 00536 uint8_t *dst= !s->max_packet_size && s->buf_end - s->buffer < s->buffer_size ? s->buf_end : s->buffer; 00537 int len= s->buffer_size - (dst - s->buffer); 00538 int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE; 00539 00540 /* no need to do anything if EOF already reached */ 00541 if (s->eof_reached) 00542 return; 00543 00544 if(s->update_checksum && dst == s->buffer){ 00545 if(s->buf_end > s->checksum_ptr) 00546 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr); 00547 s->checksum_ptr= s->buffer; 00548 } 00549 00550 /* make buffer smaller in case it ended up large after probing */ 00551 if (s->buffer_size > max_buffer_size) { 00552 ffio_set_buf_size(s, max_buffer_size); 00553 00554 s->checksum_ptr = dst = s->buffer; 00555 len = s->buffer_size; 00556 } 00557 00558 if(s->read_packet) 00559 len = s->read_packet(s->opaque, dst, len); 00560 else 00561 len = 0; 00562 if (len <= 0) { 00563 /* do not modify buffer if EOF reached so that a seek back can 00564 be done without rereading data */ 00565 s->eof_reached = 1; 00566 if(len<0) 00567 s->error= len; 00568 } else { 00569 s->pos += len; 00570 s->buf_ptr = dst; 00571 s->buf_end = dst + len; 00572 } 00573 } 00574 00575 unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, 00576 unsigned int len) 00577 { 00578 return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len); 00579 } 00580 00581 unsigned long ffio_get_checksum(AVIOContext *s) 00582 { 00583 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr); 00584 s->update_checksum= NULL; 00585 return s->checksum; 00586 } 00587 00588 void ffio_init_checksum(AVIOContext *s, 00589 unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), 00590 unsigned long checksum) 00591 { 00592 s->update_checksum= update_checksum; 00593 if(s->update_checksum){ 00594 s->checksum= checksum; 00595 s->checksum_ptr= s->buf_ptr; 00596 } 00597 } 00598 00599 /* XXX: put an inline version */ 00600 int avio_r8(AVIOContext *s) 00601 { 00602 if (s->buf_ptr >= s->buf_end) 00603 fill_buffer(s); 00604 if (s->buf_ptr < s->buf_end) 00605 return *s->buf_ptr++; 00606 return 0; 00607 } 00608 00609 #if FF_API_OLD_AVIO 00610 int url_fgetc(AVIOContext *s) 00611 { 00612 if (s->buf_ptr >= s->buf_end) 00613 fill_buffer(s); 00614 if (s->buf_ptr < s->buf_end) 00615 return *s->buf_ptr++; 00616 return URL_EOF; 00617 } 00618 #endif 00619 00620 int avio_read(AVIOContext *s, unsigned char *buf, int size) 00621 { 00622 int len, size1; 00623 00624 size1 = size; 00625 while (size > 0) { 00626 len = s->buf_end - s->buf_ptr; 00627 if (len > size) 00628 len = size; 00629 if (len == 0) { 00630 if(size > s->buffer_size && !s->update_checksum){ 00631 if(s->read_packet) 00632 len = s->read_packet(s->opaque, buf, size); 00633 if (len <= 0) { 00634 /* do not modify buffer if EOF reached so that a seek back can 00635 be done without rereading data */ 00636 s->eof_reached = 1; 00637 if(len<0) 00638 s->error= len; 00639 break; 00640 } else { 00641 s->pos += len; 00642 size -= len; 00643 buf += len; 00644 s->buf_ptr = s->buffer; 00645 s->buf_end = s->buffer/* + len*/; 00646 } 00647 }else{ 00648 fill_buffer(s); 00649 len = s->buf_end - s->buf_ptr; 00650 if (len == 0) 00651 break; 00652 } 00653 } else { 00654 memcpy(buf, s->buf_ptr, len); 00655 buf += len; 00656 s->buf_ptr += len; 00657 size -= len; 00658 } 00659 } 00660 if (size1 == size) { 00661 if (s->error) return s->error; 00662 if (s->eof_reached) return AVERROR_EOF; 00663 } 00664 return size1 - size; 00665 } 00666 00667 int ffio_read_partial(AVIOContext *s, unsigned char *buf, int size) 00668 { 00669 int len; 00670 00671 if(size<0) 00672 return -1; 00673 00674 len = s->buf_end - s->buf_ptr; 00675 if (len == 0) { 00676 fill_buffer(s); 00677 len = s->buf_end - s->buf_ptr; 00678 } 00679 if (len > size) 00680 len = size; 00681 memcpy(buf, s->buf_ptr, len); 00682 s->buf_ptr += len; 00683 if (!len) { 00684 if (s->error) return s->error; 00685 if (s->eof_reached) return AVERROR_EOF; 00686 } 00687 return len; 00688 } 00689 00690 unsigned int avio_rl16(AVIOContext *s) 00691 { 00692 unsigned int val; 00693 val = avio_r8(s); 00694 val |= avio_r8(s) << 8; 00695 return val; 00696 } 00697 00698 unsigned int avio_rl24(AVIOContext *s) 00699 { 00700 unsigned int val; 00701 val = avio_rl16(s); 00702 val |= avio_r8(s) << 16; 00703 return val; 00704 } 00705 00706 unsigned int avio_rl32(AVIOContext *s) 00707 { 00708 unsigned int val; 00709 val = avio_rl16(s); 00710 val |= avio_rl16(s) << 16; 00711 return val; 00712 } 00713 00714 uint64_t avio_rl64(AVIOContext *s) 00715 { 00716 uint64_t val; 00717 val = (uint64_t)avio_rl32(s); 00718 val |= (uint64_t)avio_rl32(s) << 32; 00719 return val; 00720 } 00721 00722 unsigned int avio_rb16(AVIOContext *s) 00723 { 00724 unsigned int val; 00725 val = avio_r8(s) << 8; 00726 val |= avio_r8(s); 00727 return val; 00728 } 00729 00730 unsigned int avio_rb24(AVIOContext *s) 00731 { 00732 unsigned int val; 00733 val = avio_rb16(s) << 8; 00734 val |= avio_r8(s); 00735 return val; 00736 } 00737 unsigned int avio_rb32(AVIOContext *s) 00738 { 00739 unsigned int val; 00740 val = avio_rb16(s) << 16; 00741 val |= avio_rb16(s); 00742 return val; 00743 } 00744 00745 #if FF_API_OLD_AVIO 00746 char *get_strz(AVIOContext *s, char *buf, int maxlen) 00747 { 00748 avio_get_str(s, INT_MAX, buf, maxlen); 00749 return buf; 00750 } 00751 #endif 00752 00753 int ff_get_line(AVIOContext *s, char *buf, int maxlen) 00754 { 00755 int i = 0; 00756 char c; 00757 00758 do { 00759 c = avio_r8(s); 00760 if (c && i < maxlen-1) 00761 buf[i++] = c; 00762 } while (c != '\n' && c); 00763 00764 buf[i] = 0; 00765 return i; 00766 } 00767 00768 int avio_get_str(AVIOContext *s, int maxlen, char *buf, int buflen) 00769 { 00770 int i; 00771 00772 // reserve 1 byte for terminating 0 00773 buflen = FFMIN(buflen - 1, maxlen); 00774 for (i = 0; i < buflen; i++) 00775 if (!(buf[i] = avio_r8(s))) 00776 return i + 1; 00777 if (buflen) 00778 buf[i] = 0; 00779 for (; i < maxlen; i++) 00780 if (!avio_r8(s)) 00781 return i + 1; 00782 return maxlen; 00783 } 00784 00785 #define GET_STR16(type, read) \ 00786 int avio_get_str16 ##type(AVIOContext *pb, int maxlen, char *buf, int buflen)\ 00787 {\ 00788 char* q = buf;\ 00789 int ret = 0;\ 00790 while (ret + 1 < maxlen) {\ 00791 uint8_t tmp;\ 00792 uint32_t ch;\ 00793 GET_UTF16(ch, (ret += 2) <= maxlen ? read(pb) : 0, break;)\ 00794 if (!ch)\ 00795 break;\ 00796 PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;)\ 00797 }\ 00798 *q = 0;\ 00799 return ret;\ 00800 }\ 00801 00802 GET_STR16(le, avio_rl16) 00803 GET_STR16(be, avio_rb16) 00804 00805 #undef GET_STR16 00806 00807 uint64_t avio_rb64(AVIOContext *s) 00808 { 00809 uint64_t val; 00810 val = (uint64_t)avio_rb32(s) << 32; 00811 val |= (uint64_t)avio_rb32(s); 00812 return val; 00813 } 00814 00815 uint64_t ffio_read_varlen(AVIOContext *bc){ 00816 uint64_t val = 0; 00817 int tmp; 00818 00819 do{ 00820 tmp = avio_r8(bc); 00821 val= (val<<7) + (tmp&127); 00822 }while(tmp&128); 00823 return val; 00824 } 00825 00826 int ffio_fdopen(AVIOContext **s, URLContext *h) 00827 { 00828 uint8_t *buffer; 00829 int buffer_size, max_packet_size; 00830 00831 max_packet_size = h->max_packet_size; 00832 if (max_packet_size) { 00833 buffer_size = max_packet_size; /* no need to bufferize more than one packet */ 00834 } else { 00835 buffer_size = IO_BUFFER_SIZE; 00836 } 00837 buffer = av_malloc(buffer_size); 00838 if (!buffer) 00839 return AVERROR(ENOMEM); 00840 00841 *s = av_mallocz(sizeof(AVIOContext)); 00842 if(!*s) { 00843 av_free(buffer); 00844 return AVERROR(ENOMEM); 00845 } 00846 00847 if (ffio_init_context(*s, buffer, buffer_size, 00848 h->flags & AVIO_FLAG_WRITE, h, 00849 ffurl_read, ffurl_write, ffurl_seek) < 0) { 00850 av_free(buffer); 00851 av_freep(s); 00852 return AVERROR(EIO); 00853 } 00854 #if FF_API_OLD_AVIO 00855 (*s)->is_streamed = h->is_streamed; 00856 #endif 00857 (*s)->seekable = h->is_streamed ? 0 : AVIO_SEEKABLE_NORMAL; 00858 (*s)->max_packet_size = max_packet_size; 00859 if(h->prot) { 00860 (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause; 00861 (*s)->read_seek = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek; 00862 } 00863 return 0; 00864 } 00865 00866 int ffio_set_buf_size(AVIOContext *s, int buf_size) 00867 { 00868 uint8_t *buffer; 00869 buffer = av_malloc(buf_size); 00870 if (!buffer) 00871 return AVERROR(ENOMEM); 00872 00873 av_free(s->buffer); 00874 s->buffer = buffer; 00875 s->buffer_size = buf_size; 00876 s->buf_ptr = buffer; 00877 url_resetbuf(s, s->write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ); 00878 return 0; 00879 } 00880 00881 static int url_resetbuf(AVIOContext *s, int flags) 00882 { 00883 assert(flags == AVIO_FLAG_WRITE || flags == AVIO_FLAG_READ); 00884 00885 if (flags & AVIO_FLAG_WRITE) { 00886 s->buf_end = s->buffer + s->buffer_size; 00887 s->write_flag = 1; 00888 } else { 00889 s->buf_end = s->buffer; 00890 s->write_flag = 0; 00891 } 00892 return 0; 00893 } 00894 00895 int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char *buf, int buf_size) 00896 { 00897 int64_t buffer_start; 00898 int buffer_size; 00899 int overlap, new_size, alloc_size; 00900 00901 if (s->write_flag) 00902 return AVERROR(EINVAL); 00903 00904 buffer_size = s->buf_end - s->buffer; 00905 00906 /* the buffers must touch or overlap */ 00907 if ((buffer_start = s->pos - buffer_size) > buf_size) 00908 return AVERROR(EINVAL); 00909 00910 overlap = buf_size - buffer_start; 00911 new_size = buf_size + buffer_size - overlap; 00912 00913 alloc_size = FFMAX(s->buffer_size, new_size); 00914 if (alloc_size > buf_size) 00915 if (!(buf = av_realloc(buf, alloc_size))) 00916 return AVERROR(ENOMEM); 00917 00918 if (new_size > buf_size) { 00919 memcpy(buf + buf_size, s->buffer + overlap, buffer_size - overlap); 00920 buf_size = new_size; 00921 } 00922 00923 av_free(s->buffer); 00924 s->buf_ptr = s->buffer = buf; 00925 s->buffer_size = alloc_size; 00926 s->pos = buf_size; 00927 s->buf_end = s->buf_ptr + buf_size; 00928 s->eof_reached = 0; 00929 s->must_flush = 0; 00930 00931 return 0; 00932 } 00933 00934 int avio_open(AVIOContext **s, const char *filename, int flags) 00935 { 00936 URLContext *h; 00937 int err; 00938 00939 err = ffurl_open(&h, filename, flags); 00940 if (err < 0) 00941 return err; 00942 err = ffio_fdopen(s, h); 00943 if (err < 0) { 00944 ffurl_close(h); 00945 return err; 00946 } 00947 return 0; 00948 } 00949 00950 int avio_close(AVIOContext *s) 00951 { 00952 URLContext *h = s->opaque; 00953 00954 av_free(s->buffer); 00955 av_free(s); 00956 return ffurl_close(h); 00957 } 00958 00959 #if FF_API_OLD_AVIO 00960 URLContext *url_fileno(AVIOContext *s) 00961 { 00962 return s->opaque; 00963 } 00964 #endif 00965 00966 int avio_printf(AVIOContext *s, const char *fmt, ...) 00967 { 00968 va_list ap; 00969 char buf[4096]; 00970 int ret; 00971 00972 va_start(ap, fmt); 00973 ret = vsnprintf(buf, sizeof(buf), fmt, ap); 00974 va_end(ap); 00975 avio_write(s, buf, strlen(buf)); 00976 return ret; 00977 } 00978 00979 #if FF_API_OLD_AVIO 00980 char *url_fgets(AVIOContext *s, char *buf, int buf_size) 00981 { 00982 int c; 00983 char *q; 00984 00985 c = avio_r8(s); 00986 if (s->eof_reached) 00987 return NULL; 00988 q = buf; 00989 for(;;) { 00990 if (s->eof_reached || c == '\n') 00991 break; 00992 if ((q - buf) < buf_size - 1) 00993 *q++ = c; 00994 c = avio_r8(s); 00995 } 00996 if (buf_size > 0) 00997 *q = '\0'; 00998 return buf; 00999 } 01000 01001 int url_fget_max_packet_size(AVIOContext *s) 01002 { 01003 return s->max_packet_size; 01004 } 01005 #endif 01006 01007 int avio_pause(AVIOContext *s, int pause) 01008 { 01009 if (!s->read_pause) 01010 return AVERROR(ENOSYS); 01011 return s->read_pause(s->opaque, pause); 01012 } 01013 01014 int64_t avio_seek_time(AVIOContext *s, int stream_index, 01015 int64_t timestamp, int flags) 01016 { 01017 URLContext *h = s->opaque; 01018 int64_t ret; 01019 if (!s->read_seek) 01020 return AVERROR(ENOSYS); 01021 ret = s->read_seek(h, stream_index, timestamp, flags); 01022 if(ret >= 0) { 01023 int64_t pos; 01024 s->buf_ptr = s->buf_end; // Flush buffer 01025 pos = s->seek(h, 0, SEEK_CUR); 01026 if (pos >= 0) 01027 s->pos = pos; 01028 else if (pos != AVERROR(ENOSYS)) 01029 ret = pos; 01030 } 01031 return ret; 01032 } 01033 01034 /* buffer handling */ 01035 #if FF_API_OLD_AVIO 01036 int url_open_buf(AVIOContext **s, uint8_t *buf, int buf_size, int flags) 01037 { 01038 int ret; 01039 *s = av_mallocz(sizeof(AVIOContext)); 01040 if(!*s) 01041 return AVERROR(ENOMEM); 01042 ret = ffio_init_context(*s, buf, buf_size, 01043 flags & AVIO_FLAG_WRITE, 01044 NULL, NULL, NULL, NULL); 01045 if(ret != 0) 01046 av_freep(s); 01047 return ret; 01048 } 01049 01050 int url_close_buf(AVIOContext *s) 01051 { 01052 avio_flush(s); 01053 return s->buf_ptr - s->buffer; 01054 } 01055 #endif 01056 01057 /* output in a dynamic buffer */ 01058 01059 typedef struct DynBuffer { 01060 int pos, size, allocated_size; 01061 uint8_t *buffer; 01062 int io_buffer_size; 01063 uint8_t io_buffer[1]; 01064 } DynBuffer; 01065 01066 static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size) 01067 { 01068 DynBuffer *d = opaque; 01069 unsigned new_size, new_allocated_size; 01070 01071 /* reallocate buffer if needed */ 01072 new_size = d->pos + buf_size; 01073 new_allocated_size = d->allocated_size; 01074 if(new_size < d->pos || new_size > INT_MAX/2) 01075 return -1; 01076 while (new_size > new_allocated_size) { 01077 if (!new_allocated_size) 01078 new_allocated_size = new_size; 01079 else 01080 new_allocated_size += new_allocated_size / 2 + 1; 01081 } 01082 01083 if (new_allocated_size > d->allocated_size) { 01084 d->buffer = av_realloc(d->buffer, new_allocated_size); 01085 if(d->buffer == NULL) 01086 return AVERROR(ENOMEM); 01087 d->allocated_size = new_allocated_size; 01088 } 01089 memcpy(d->buffer + d->pos, buf, buf_size); 01090 d->pos = new_size; 01091 if (d->pos > d->size) 01092 d->size = d->pos; 01093 return buf_size; 01094 } 01095 01096 static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size) 01097 { 01098 unsigned char buf1[4]; 01099 int ret; 01100 01101 /* packetized write: output the header */ 01102 AV_WB32(buf1, buf_size); 01103 ret= dyn_buf_write(opaque, buf1, 4); 01104 if(ret < 0) 01105 return ret; 01106 01107 /* then the data */ 01108 return dyn_buf_write(opaque, buf, buf_size); 01109 } 01110 01111 static int64_t dyn_buf_seek(void *opaque, int64_t offset, int whence) 01112 { 01113 DynBuffer *d = opaque; 01114 01115 if (whence == SEEK_CUR) 01116 offset += d->pos; 01117 else if (whence == SEEK_END) 01118 offset += d->size; 01119 if (offset < 0 || offset > 0x7fffffffLL) 01120 return -1; 01121 d->pos = offset; 01122 return 0; 01123 } 01124 01125 static int url_open_dyn_buf_internal(AVIOContext **s, int max_packet_size) 01126 { 01127 DynBuffer *d; 01128 unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024; 01129 01130 if(sizeof(DynBuffer) + io_buffer_size < io_buffer_size) 01131 return -1; 01132 d = av_mallocz(sizeof(DynBuffer) + io_buffer_size); 01133 if (!d) 01134 return AVERROR(ENOMEM); 01135 d->io_buffer_size = io_buffer_size; 01136 *s = avio_alloc_context(d->io_buffer, d->io_buffer_size, 1, d, NULL, 01137 max_packet_size ? dyn_packet_buf_write : dyn_buf_write, 01138 max_packet_size ? NULL : dyn_buf_seek); 01139 if(!*s) { 01140 av_free(d); 01141 return AVERROR(ENOMEM); 01142 } 01143 (*s)->max_packet_size = max_packet_size; 01144 return 0; 01145 } 01146 01147 int avio_open_dyn_buf(AVIOContext **s) 01148 { 01149 return url_open_dyn_buf_internal(s, 0); 01150 } 01151 01152 int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size) 01153 { 01154 if (max_packet_size <= 0) 01155 return -1; 01156 return url_open_dyn_buf_internal(s, max_packet_size); 01157 } 01158 01159 int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer) 01160 { 01161 DynBuffer *d = s->opaque; 01162 int size; 01163 static const char padbuf[FF_INPUT_BUFFER_PADDING_SIZE] = {0}; 01164 int padding = 0; 01165 01166 /* don't attempt to pad fixed-size packet buffers */ 01167 if (!s->max_packet_size) { 01168 avio_write(s, padbuf, sizeof(padbuf)); 01169 padding = FF_INPUT_BUFFER_PADDING_SIZE; 01170 } 01171 01172 avio_flush(s); 01173 01174 *pbuffer = d->buffer; 01175 size = d->size; 01176 av_free(d); 01177 av_free(s); 01178 return size - padding; 01179 }