Libav
|
00001 /* 00002 * Buffered I/O for ffmpeg system 00003 * Copyright (c) 2000,2001 Fabrice Bellard 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg 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 * FFmpeg 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 FFmpeg; 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 <stdarg.h> 00027 00028 #define IO_BUFFER_SIZE 32768 00029 00035 #define SHORT_SEEK_THRESHOLD 4096 00036 00037 static void fill_buffer(ByteIOContext *s); 00038 #if LIBAVFORMAT_VERSION_MAJOR >= 53 00039 static int url_resetbuf(ByteIOContext *s, int flags); 00040 #endif 00041 00042 int init_put_byte(ByteIOContext *s, 00043 unsigned char *buffer, 00044 int buffer_size, 00045 int write_flag, 00046 void *opaque, 00047 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), 00048 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), 00049 int64_t (*seek)(void *opaque, int64_t offset, int whence)) 00050 { 00051 s->buffer = buffer; 00052 s->buffer_size = buffer_size; 00053 s->buf_ptr = buffer; 00054 s->opaque = opaque; 00055 url_resetbuf(s, write_flag ? URL_WRONLY : URL_RDONLY); 00056 s->write_packet = write_packet; 00057 s->read_packet = read_packet; 00058 s->seek = seek; 00059 s->pos = 0; 00060 s->must_flush = 0; 00061 s->eof_reached = 0; 00062 s->error = 0; 00063 s->is_streamed = 0; 00064 s->max_packet_size = 0; 00065 s->update_checksum= NULL; 00066 if(!read_packet && !write_flag){ 00067 s->pos = buffer_size; 00068 s->buf_end = s->buffer + buffer_size; 00069 } 00070 s->read_pause = NULL; 00071 s->read_seek = NULL; 00072 return 0; 00073 } 00074 00075 ByteIOContext *av_alloc_put_byte( 00076 unsigned char *buffer, 00077 int buffer_size, 00078 int write_flag, 00079 void *opaque, 00080 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), 00081 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), 00082 int64_t (*seek)(void *opaque, int64_t offset, int whence)) 00083 { 00084 ByteIOContext *s = av_mallocz(sizeof(ByteIOContext)); 00085 init_put_byte(s, buffer, buffer_size, write_flag, opaque, 00086 read_packet, write_packet, seek); 00087 return s; 00088 } 00089 00090 static void flush_buffer(ByteIOContext *s) 00091 { 00092 if (s->buf_ptr > s->buffer) { 00093 if (s->write_packet && !s->error){ 00094 int ret= s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer); 00095 if(ret < 0){ 00096 s->error = ret; 00097 } 00098 } 00099 if(s->update_checksum){ 00100 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr); 00101 s->checksum_ptr= s->buffer; 00102 } 00103 s->pos += s->buf_ptr - s->buffer; 00104 } 00105 s->buf_ptr = s->buffer; 00106 } 00107 00108 void put_byte(ByteIOContext *s, int b) 00109 { 00110 *(s->buf_ptr)++ = b; 00111 if (s->buf_ptr >= s->buf_end) 00112 flush_buffer(s); 00113 } 00114 00115 void put_buffer(ByteIOContext *s, const unsigned char *buf, int size) 00116 { 00117 while (size > 0) { 00118 int len = FFMIN(s->buf_end - s->buf_ptr, size); 00119 memcpy(s->buf_ptr, buf, len); 00120 s->buf_ptr += len; 00121 00122 if (s->buf_ptr >= s->buf_end) 00123 flush_buffer(s); 00124 00125 buf += len; 00126 size -= len; 00127 } 00128 } 00129 00130 void put_flush_packet(ByteIOContext *s) 00131 { 00132 flush_buffer(s); 00133 s->must_flush = 0; 00134 } 00135 00136 int64_t url_fseek(ByteIOContext *s, int64_t offset, int whence) 00137 { 00138 int64_t offset1; 00139 int64_t pos; 00140 int force = whence & AVSEEK_FORCE; 00141 whence &= ~AVSEEK_FORCE; 00142 00143 if(!s) 00144 return AVERROR(EINVAL); 00145 00146 pos = s->pos - (s->write_flag ? 0 : (s->buf_end - s->buffer)); 00147 00148 if (whence != SEEK_CUR && whence != SEEK_SET) 00149 return AVERROR(EINVAL); 00150 00151 if (whence == SEEK_CUR) { 00152 offset1 = pos + (s->buf_ptr - s->buffer); 00153 if (offset == 0) 00154 return offset1; 00155 offset += offset1; 00156 } 00157 offset1 = offset - pos; 00158 if (!s->must_flush && 00159 offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) { 00160 /* can do the seek inside the buffer */ 00161 s->buf_ptr = s->buffer + offset1; 00162 } else if ((s->is_streamed || 00163 offset1 <= s->buf_end + SHORT_SEEK_THRESHOLD - s->buffer) && 00164 !s->write_flag && offset1 >= 0 && 00165 (whence != SEEK_END || force)) { 00166 while(s->pos < offset && !s->eof_reached) 00167 fill_buffer(s); 00168 if (s->eof_reached) 00169 return AVERROR_EOF; 00170 s->buf_ptr = s->buf_end + offset - s->pos; 00171 } else { 00172 int64_t res; 00173 00174 #if CONFIG_MUXERS || CONFIG_NETWORK 00175 if (s->write_flag) { 00176 flush_buffer(s); 00177 s->must_flush = 1; 00178 } 00179 #endif /* CONFIG_MUXERS || CONFIG_NETWORK */ 00180 if (!s->seek) 00181 return AVERROR(EPIPE); 00182 if ((res = s->seek(s->opaque, offset, SEEK_SET)) < 0) 00183 return res; 00184 if (!s->write_flag) 00185 s->buf_end = s->buffer; 00186 s->buf_ptr = s->buffer; 00187 s->pos = offset; 00188 } 00189 s->eof_reached = 0; 00190 return offset; 00191 } 00192 00193 void url_fskip(ByteIOContext *s, int64_t offset) 00194 { 00195 url_fseek(s, offset, SEEK_CUR); 00196 } 00197 00198 int64_t url_ftell(ByteIOContext *s) 00199 { 00200 return url_fseek(s, 0, SEEK_CUR); 00201 } 00202 00203 int64_t url_fsize(ByteIOContext *s) 00204 { 00205 int64_t size; 00206 00207 if(!s) 00208 return AVERROR(EINVAL); 00209 00210 if (!s->seek) 00211 return AVERROR(ENOSYS); 00212 size = s->seek(s->opaque, 0, AVSEEK_SIZE); 00213 if(size<0){ 00214 if ((size = s->seek(s->opaque, -1, SEEK_END)) < 0) 00215 return size; 00216 size++; 00217 s->seek(s->opaque, s->pos, SEEK_SET); 00218 } 00219 return size; 00220 } 00221 00222 int url_feof(ByteIOContext *s) 00223 { 00224 if(!s) 00225 return 0; 00226 return s->eof_reached; 00227 } 00228 00229 int url_ferror(ByteIOContext *s) 00230 { 00231 if(!s) 00232 return 0; 00233 return s->error; 00234 } 00235 00236 void put_le32(ByteIOContext *s, unsigned int val) 00237 { 00238 put_byte(s, val); 00239 put_byte(s, val >> 8); 00240 put_byte(s, val >> 16); 00241 put_byte(s, val >> 24); 00242 } 00243 00244 void put_be32(ByteIOContext *s, unsigned int val) 00245 { 00246 put_byte(s, val >> 24); 00247 put_byte(s, val >> 16); 00248 put_byte(s, val >> 8); 00249 put_byte(s, val); 00250 } 00251 00252 void put_strz(ByteIOContext *s, const char *str) 00253 { 00254 if (str) 00255 put_buffer(s, (const unsigned char *) str, strlen(str) + 1); 00256 else 00257 put_byte(s, 0); 00258 } 00259 00260 void put_le64(ByteIOContext *s, uint64_t val) 00261 { 00262 put_le32(s, (uint32_t)(val & 0xffffffff)); 00263 put_le32(s, (uint32_t)(val >> 32)); 00264 } 00265 00266 void put_be64(ByteIOContext *s, uint64_t val) 00267 { 00268 put_be32(s, (uint32_t)(val >> 32)); 00269 put_be32(s, (uint32_t)(val & 0xffffffff)); 00270 } 00271 00272 void put_le16(ByteIOContext *s, unsigned int val) 00273 { 00274 put_byte(s, val); 00275 put_byte(s, val >> 8); 00276 } 00277 00278 void put_be16(ByteIOContext *s, unsigned int val) 00279 { 00280 put_byte(s, val >> 8); 00281 put_byte(s, val); 00282 } 00283 00284 void put_le24(ByteIOContext *s, unsigned int val) 00285 { 00286 put_le16(s, val & 0xffff); 00287 put_byte(s, val >> 16); 00288 } 00289 00290 void put_be24(ByteIOContext *s, unsigned int val) 00291 { 00292 put_be16(s, val >> 8); 00293 put_byte(s, val); 00294 } 00295 00296 void put_tag(ByteIOContext *s, const char *tag) 00297 { 00298 while (*tag) { 00299 put_byte(s, *tag++); 00300 } 00301 } 00302 00303 /* Input stream */ 00304 00305 static void fill_buffer(ByteIOContext *s) 00306 { 00307 uint8_t *dst= !s->max_packet_size && s->buf_end - s->buffer < s->buffer_size ? s->buf_ptr : s->buffer; 00308 int len= s->buffer_size - (dst - s->buffer); 00309 int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE; 00310 00311 assert(s->buf_ptr == s->buf_end); 00312 00313 /* no need to do anything if EOF already reached */ 00314 if (s->eof_reached) 00315 return; 00316 00317 if(s->update_checksum && dst == s->buffer){ 00318 if(s->buf_end > s->checksum_ptr) 00319 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr); 00320 s->checksum_ptr= s->buffer; 00321 } 00322 00323 /* make buffer smaller in case it ended up large after probing */ 00324 if (s->buffer_size > max_buffer_size) { 00325 url_setbufsize(s, max_buffer_size); 00326 00327 s->checksum_ptr = dst = s->buffer; 00328 len = s->buffer_size; 00329 } 00330 00331 if(s->read_packet) 00332 len = s->read_packet(s->opaque, dst, len); 00333 else 00334 len = 0; 00335 if (len <= 0) { 00336 /* do not modify buffer if EOF reached so that a seek back can 00337 be done without rereading data */ 00338 s->eof_reached = 1; 00339 if(len<0) 00340 s->error= len; 00341 } else { 00342 s->pos += len; 00343 s->buf_ptr = dst; 00344 s->buf_end = dst + len; 00345 } 00346 } 00347 00348 unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, 00349 unsigned int len) 00350 { 00351 return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len); 00352 } 00353 00354 unsigned long get_checksum(ByteIOContext *s) 00355 { 00356 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr); 00357 s->update_checksum= NULL; 00358 return s->checksum; 00359 } 00360 00361 void init_checksum(ByteIOContext *s, 00362 unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), 00363 unsigned long checksum) 00364 { 00365 s->update_checksum= update_checksum; 00366 if(s->update_checksum){ 00367 s->checksum= checksum; 00368 s->checksum_ptr= s->buf_ptr; 00369 } 00370 } 00371 00372 /* XXX: put an inline version */ 00373 int get_byte(ByteIOContext *s) 00374 { 00375 if (s->buf_ptr < s->buf_end) { 00376 return *s->buf_ptr++; 00377 } else { 00378 fill_buffer(s); 00379 if (s->buf_ptr < s->buf_end) 00380 return *s->buf_ptr++; 00381 else 00382 return 0; 00383 } 00384 } 00385 00386 int url_fgetc(ByteIOContext *s) 00387 { 00388 if (s->buf_ptr < s->buf_end) { 00389 return *s->buf_ptr++; 00390 } else { 00391 fill_buffer(s); 00392 if (s->buf_ptr < s->buf_end) 00393 return *s->buf_ptr++; 00394 else 00395 return URL_EOF; 00396 } 00397 } 00398 00399 int get_buffer(ByteIOContext *s, unsigned char *buf, int size) 00400 { 00401 int len, size1; 00402 00403 size1 = size; 00404 while (size > 0) { 00405 len = s->buf_end - s->buf_ptr; 00406 if (len > size) 00407 len = size; 00408 if (len == 0) { 00409 if(size > s->buffer_size && !s->update_checksum){ 00410 if(s->read_packet) 00411 len = s->read_packet(s->opaque, buf, size); 00412 if (len <= 0) { 00413 /* do not modify buffer if EOF reached so that a seek back can 00414 be done without rereading data */ 00415 s->eof_reached = 1; 00416 if(len<0) 00417 s->error= len; 00418 break; 00419 } else { 00420 s->pos += len; 00421 size -= len; 00422 buf += len; 00423 s->buf_ptr = s->buffer; 00424 s->buf_end = s->buffer/* + len*/; 00425 } 00426 }else{ 00427 fill_buffer(s); 00428 len = s->buf_end - s->buf_ptr; 00429 if (len == 0) 00430 break; 00431 } 00432 } else { 00433 memcpy(buf, s->buf_ptr, len); 00434 buf += len; 00435 s->buf_ptr += len; 00436 size -= len; 00437 } 00438 } 00439 if (size1 == size) { 00440 if (url_ferror(s)) return url_ferror(s); 00441 if (url_feof(s)) return AVERROR_EOF; 00442 } 00443 return size1 - size; 00444 } 00445 00446 int get_partial_buffer(ByteIOContext *s, unsigned char *buf, int size) 00447 { 00448 int len; 00449 00450 if(size<0) 00451 return -1; 00452 00453 len = s->buf_end - s->buf_ptr; 00454 if (len == 0) { 00455 fill_buffer(s); 00456 len = s->buf_end - s->buf_ptr; 00457 } 00458 if (len > size) 00459 len = size; 00460 memcpy(buf, s->buf_ptr, len); 00461 s->buf_ptr += len; 00462 if (!len) { 00463 if (url_ferror(s)) return url_ferror(s); 00464 if (url_feof(s)) return AVERROR_EOF; 00465 } 00466 return len; 00467 } 00468 00469 unsigned int get_le16(ByteIOContext *s) 00470 { 00471 unsigned int val; 00472 val = get_byte(s); 00473 val |= get_byte(s) << 8; 00474 return val; 00475 } 00476 00477 unsigned int get_le24(ByteIOContext *s) 00478 { 00479 unsigned int val; 00480 val = get_le16(s); 00481 val |= get_byte(s) << 16; 00482 return val; 00483 } 00484 00485 unsigned int get_le32(ByteIOContext *s) 00486 { 00487 unsigned int val; 00488 val = get_le16(s); 00489 val |= get_le16(s) << 16; 00490 return val; 00491 } 00492 00493 uint64_t get_le64(ByteIOContext *s) 00494 { 00495 uint64_t val; 00496 val = (uint64_t)get_le32(s); 00497 val |= (uint64_t)get_le32(s) << 32; 00498 return val; 00499 } 00500 00501 unsigned int get_be16(ByteIOContext *s) 00502 { 00503 unsigned int val; 00504 val = get_byte(s) << 8; 00505 val |= get_byte(s); 00506 return val; 00507 } 00508 00509 unsigned int get_be24(ByteIOContext *s) 00510 { 00511 unsigned int val; 00512 val = get_be16(s) << 8; 00513 val |= get_byte(s); 00514 return val; 00515 } 00516 unsigned int get_be32(ByteIOContext *s) 00517 { 00518 unsigned int val; 00519 val = get_be16(s) << 16; 00520 val |= get_be16(s); 00521 return val; 00522 } 00523 00524 char *get_strz(ByteIOContext *s, char *buf, int maxlen) 00525 { 00526 int i = 0; 00527 char c; 00528 00529 while ((c = get_byte(s))) { 00530 if (i < maxlen-1) 00531 buf[i++] = c; 00532 } 00533 00534 buf[i] = 0; /* Ensure null terminated, but may be truncated */ 00535 00536 return buf; 00537 } 00538 00539 uint64_t get_be64(ByteIOContext *s) 00540 { 00541 uint64_t val; 00542 val = (uint64_t)get_be32(s) << 32; 00543 val |= (uint64_t)get_be32(s); 00544 return val; 00545 } 00546 00547 uint64_t ff_get_v(ByteIOContext *bc){ 00548 uint64_t val = 0; 00549 int tmp; 00550 00551 do{ 00552 tmp = get_byte(bc); 00553 val= (val<<7) + (tmp&127); 00554 }while(tmp&128); 00555 return val; 00556 } 00557 00558 int url_fdopen(ByteIOContext **s, URLContext *h) 00559 { 00560 uint8_t *buffer; 00561 int buffer_size, max_packet_size; 00562 00563 max_packet_size = url_get_max_packet_size(h); 00564 if (max_packet_size) { 00565 buffer_size = max_packet_size; /* no need to bufferize more than one packet */ 00566 } else { 00567 buffer_size = IO_BUFFER_SIZE; 00568 } 00569 buffer = av_malloc(buffer_size); 00570 if (!buffer) 00571 return AVERROR(ENOMEM); 00572 00573 *s = av_mallocz(sizeof(ByteIOContext)); 00574 if(!*s) { 00575 av_free(buffer); 00576 return AVERROR(ENOMEM); 00577 } 00578 00579 if (init_put_byte(*s, buffer, buffer_size, 00580 (h->flags & URL_WRONLY || h->flags & URL_RDWR), h, 00581 url_read, url_write, url_seek) < 0) { 00582 av_free(buffer); 00583 av_freep(s); 00584 return AVERROR(EIO); 00585 } 00586 (*s)->is_streamed = h->is_streamed; 00587 (*s)->max_packet_size = max_packet_size; 00588 if(h->prot) { 00589 (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause; 00590 (*s)->read_seek = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek; 00591 } 00592 return 0; 00593 } 00594 00595 int url_setbufsize(ByteIOContext *s, int buf_size) 00596 { 00597 uint8_t *buffer; 00598 buffer = av_malloc(buf_size); 00599 if (!buffer) 00600 return AVERROR(ENOMEM); 00601 00602 av_free(s->buffer); 00603 s->buffer = buffer; 00604 s->buffer_size = buf_size; 00605 s->buf_ptr = buffer; 00606 url_resetbuf(s, s->write_flag ? URL_WRONLY : URL_RDONLY); 00607 return 0; 00608 } 00609 00610 #if LIBAVFORMAT_VERSION_MAJOR < 53 00611 int url_resetbuf(ByteIOContext *s, int flags) 00612 #else 00613 static int url_resetbuf(ByteIOContext *s, int flags) 00614 #endif 00615 { 00616 #if LIBAVFORMAT_VERSION_MAJOR < 53 00617 URLContext *h = s->opaque; 00618 if ((flags & URL_RDWR) || (h && h->flags != flags && !h->flags & URL_RDWR)) 00619 return AVERROR(EINVAL); 00620 #else 00621 assert(flags == URL_WRONLY || flags == URL_RDONLY); 00622 #endif 00623 00624 if (flags & URL_WRONLY) { 00625 s->buf_end = s->buffer + s->buffer_size; 00626 s->write_flag = 1; 00627 } else { 00628 s->buf_end = s->buffer; 00629 s->write_flag = 0; 00630 } 00631 return 0; 00632 } 00633 00634 int ff_rewind_with_probe_data(ByteIOContext *s, unsigned char *buf, int buf_size) 00635 { 00636 int64_t buffer_start; 00637 int buffer_size; 00638 int overlap, new_size; 00639 00640 if (s->write_flag) 00641 return AVERROR(EINVAL); 00642 00643 buffer_size = s->buf_end - s->buffer; 00644 00645 /* the buffers must touch or overlap */ 00646 if ((buffer_start = s->pos - buffer_size) > buf_size) 00647 return AVERROR(EINVAL); 00648 00649 overlap = buf_size - buffer_start; 00650 new_size = buf_size + buffer_size - overlap; 00651 00652 if (new_size > buf_size) { 00653 if (!(buf = av_realloc(buf, new_size))) 00654 return AVERROR(ENOMEM); 00655 00656 memcpy(buf + buf_size, s->buffer + overlap, buffer_size - overlap); 00657 buf_size = new_size; 00658 } 00659 00660 av_free(s->buffer); 00661 s->buf_ptr = s->buffer = buf; 00662 s->pos = s->buffer_size = buf_size; 00663 s->buf_end = s->buf_ptr + buf_size; 00664 s->eof_reached = 0; 00665 s->must_flush = 0; 00666 00667 return 0; 00668 } 00669 00670 int url_fopen(ByteIOContext **s, const char *filename, int flags) 00671 { 00672 URLContext *h; 00673 int err; 00674 00675 err = url_open(&h, filename, flags); 00676 if (err < 0) 00677 return err; 00678 err = url_fdopen(s, h); 00679 if (err < 0) { 00680 url_close(h); 00681 return err; 00682 } 00683 return 0; 00684 } 00685 00686 int url_fclose(ByteIOContext *s) 00687 { 00688 URLContext *h = s->opaque; 00689 00690 av_free(s->buffer); 00691 av_free(s); 00692 return url_close(h); 00693 } 00694 00695 URLContext *url_fileno(ByteIOContext *s) 00696 { 00697 return s->opaque; 00698 } 00699 00700 #if CONFIG_MUXERS 00701 int url_fprintf(ByteIOContext *s, const char *fmt, ...) 00702 { 00703 va_list ap; 00704 char buf[4096]; 00705 int ret; 00706 00707 va_start(ap, fmt); 00708 ret = vsnprintf(buf, sizeof(buf), fmt, ap); 00709 va_end(ap); 00710 put_buffer(s, buf, strlen(buf)); 00711 return ret; 00712 } 00713 #endif //CONFIG_MUXERS 00714 00715 char *url_fgets(ByteIOContext *s, char *buf, int buf_size) 00716 { 00717 int c; 00718 char *q; 00719 00720 c = url_fgetc(s); 00721 if (c == EOF) 00722 return NULL; 00723 q = buf; 00724 for(;;) { 00725 if (c == EOF || c == '\n') 00726 break; 00727 if ((q - buf) < buf_size - 1) 00728 *q++ = c; 00729 c = url_fgetc(s); 00730 } 00731 if (buf_size > 0) 00732 *q = '\0'; 00733 return buf; 00734 } 00735 00736 int url_fget_max_packet_size(ByteIOContext *s) 00737 { 00738 return s->max_packet_size; 00739 } 00740 00741 int av_url_read_fpause(ByteIOContext *s, int pause) 00742 { 00743 if (!s->read_pause) 00744 return AVERROR(ENOSYS); 00745 return s->read_pause(s->opaque, pause); 00746 } 00747 00748 int64_t av_url_read_fseek(ByteIOContext *s, int stream_index, 00749 int64_t timestamp, int flags) 00750 { 00751 URLContext *h = s->opaque; 00752 int64_t ret; 00753 if (!s->read_seek) 00754 return AVERROR(ENOSYS); 00755 ret = s->read_seek(h, stream_index, timestamp, flags); 00756 if(ret >= 0) { 00757 int64_t pos; 00758 s->buf_ptr = s->buf_end; // Flush buffer 00759 pos = s->seek(h, 0, SEEK_CUR); 00760 if (pos >= 0) 00761 s->pos = pos; 00762 else if (pos != AVERROR(ENOSYS)) 00763 ret = pos; 00764 } 00765 return ret; 00766 } 00767 00768 /* url_open_dyn_buf and url_close_dyn_buf are used in rtp.c to send a response 00769 * back to the server even if CONFIG_MUXERS is false. */ 00770 #if CONFIG_MUXERS || CONFIG_NETWORK 00771 /* buffer handling */ 00772 int url_open_buf(ByteIOContext **s, uint8_t *buf, int buf_size, int flags) 00773 { 00774 int ret; 00775 *s = av_mallocz(sizeof(ByteIOContext)); 00776 if(!*s) 00777 return AVERROR(ENOMEM); 00778 ret = init_put_byte(*s, buf, buf_size, 00779 (flags & URL_WRONLY || flags & URL_RDWR), 00780 NULL, NULL, NULL, NULL); 00781 if(ret != 0) 00782 av_freep(s); 00783 return ret; 00784 } 00785 00786 int url_close_buf(ByteIOContext *s) 00787 { 00788 put_flush_packet(s); 00789 return s->buf_ptr - s->buffer; 00790 } 00791 00792 /* output in a dynamic buffer */ 00793 00794 typedef struct DynBuffer { 00795 int pos, size, allocated_size; 00796 uint8_t *buffer; 00797 int io_buffer_size; 00798 uint8_t io_buffer[1]; 00799 } DynBuffer; 00800 00801 static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size) 00802 { 00803 DynBuffer *d = opaque; 00804 unsigned new_size, new_allocated_size; 00805 00806 /* reallocate buffer if needed */ 00807 new_size = d->pos + buf_size; 00808 new_allocated_size = d->allocated_size; 00809 if(new_size < d->pos || new_size > INT_MAX/2) 00810 return -1; 00811 while (new_size > new_allocated_size) { 00812 if (!new_allocated_size) 00813 new_allocated_size = new_size; 00814 else 00815 new_allocated_size += new_allocated_size / 2 + 1; 00816 } 00817 00818 if (new_allocated_size > d->allocated_size) { 00819 d->buffer = av_realloc(d->buffer, new_allocated_size); 00820 if(d->buffer == NULL) 00821 return AVERROR(ENOMEM); 00822 d->allocated_size = new_allocated_size; 00823 } 00824 memcpy(d->buffer + d->pos, buf, buf_size); 00825 d->pos = new_size; 00826 if (d->pos > d->size) 00827 d->size = d->pos; 00828 return buf_size; 00829 } 00830 00831 static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size) 00832 { 00833 unsigned char buf1[4]; 00834 int ret; 00835 00836 /* packetized write: output the header */ 00837 AV_WB32(buf1, buf_size); 00838 ret= dyn_buf_write(opaque, buf1, 4); 00839 if(ret < 0) 00840 return ret; 00841 00842 /* then the data */ 00843 return dyn_buf_write(opaque, buf, buf_size); 00844 } 00845 00846 static int64_t dyn_buf_seek(void *opaque, int64_t offset, int whence) 00847 { 00848 DynBuffer *d = opaque; 00849 00850 if (whence == SEEK_CUR) 00851 offset += d->pos; 00852 else if (whence == SEEK_END) 00853 offset += d->size; 00854 if (offset < 0 || offset > 0x7fffffffLL) 00855 return -1; 00856 d->pos = offset; 00857 return 0; 00858 } 00859 00860 static int url_open_dyn_buf_internal(ByteIOContext **s, int max_packet_size) 00861 { 00862 DynBuffer *d; 00863 int ret; 00864 unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024; 00865 00866 if(sizeof(DynBuffer) + io_buffer_size < io_buffer_size) 00867 return -1; 00868 d = av_mallocz(sizeof(DynBuffer) + io_buffer_size); 00869 if (!d) 00870 return AVERROR(ENOMEM); 00871 *s = av_mallocz(sizeof(ByteIOContext)); 00872 if(!*s) { 00873 av_free(d); 00874 return AVERROR(ENOMEM); 00875 } 00876 d->io_buffer_size = io_buffer_size; 00877 ret = init_put_byte(*s, d->io_buffer, io_buffer_size, 00878 1, d, NULL, 00879 max_packet_size ? dyn_packet_buf_write : dyn_buf_write, 00880 max_packet_size ? NULL : dyn_buf_seek); 00881 if (ret == 0) { 00882 (*s)->max_packet_size = max_packet_size; 00883 } else { 00884 av_free(d); 00885 av_freep(s); 00886 } 00887 return ret; 00888 } 00889 00890 int url_open_dyn_buf(ByteIOContext **s) 00891 { 00892 return url_open_dyn_buf_internal(s, 0); 00893 } 00894 00895 int url_open_dyn_packet_buf(ByteIOContext **s, int max_packet_size) 00896 { 00897 if (max_packet_size <= 0) 00898 return -1; 00899 return url_open_dyn_buf_internal(s, max_packet_size); 00900 } 00901 00902 int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer) 00903 { 00904 DynBuffer *d = s->opaque; 00905 int size; 00906 00907 put_flush_packet(s); 00908 00909 *pbuffer = d->buffer; 00910 size = d->size; 00911 av_free(d); 00912 av_free(s); 00913 return size; 00914 } 00915 #endif /* CONFIG_MUXERS || CONFIG_NETWORK */