00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/crc.h"
00023 #include "libavutil/dict.h"
00024 #include "libavutil/intreadwrite.h"
00025 #include "libavutil/log.h"
00026 #include "libavutil/opt.h"
00027 #include "avformat.h"
00028 #include "avio.h"
00029 #include "avio_internal.h"
00030 #include "internal.h"
00031 #include "url.h"
00032 #include <stdarg.h>
00033
00034 #define IO_BUFFER_SIZE 32768
00035
00041 #define SHORT_SEEK_THRESHOLD 4096
00042
00043 static void *ffio_url_child_next(void *obj, void *prev)
00044 {
00045 AVIOContext *s = obj;
00046 return prev ? NULL : s->opaque;
00047 }
00048
00049 static const AVClass *ffio_url_child_class_next(const AVClass *prev)
00050 {
00051 return prev ? NULL : &ffurl_context_class;
00052 }
00053
00054 static const AVOption ffio_url_options[] = {
00055 { NULL },
00056 };
00057
00058 const AVClass ffio_url_class = {
00059 .class_name = "AVIOContext",
00060 .item_name = av_default_item_name,
00061 .version = LIBAVUTIL_VERSION_INT,
00062 .option = ffio_url_options,
00063 .child_next = ffio_url_child_next,
00064 .child_class_next = ffio_url_child_class_next,
00065 };
00066
00067 static void fill_buffer(AVIOContext *s);
00068 static int url_resetbuf(AVIOContext *s, int flags);
00069
00070 int ffio_init_context(AVIOContext *s,
00071 unsigned char *buffer,
00072 int buffer_size,
00073 int write_flag,
00074 void *opaque,
00075 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
00076 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
00077 int64_t (*seek)(void *opaque, int64_t offset, int whence))
00078 {
00079 s->buffer = buffer;
00080 s->buffer_size = buffer_size;
00081 s->buf_ptr = buffer;
00082 s->opaque = opaque;
00083 s->direct = 0;
00084 url_resetbuf(s, write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ);
00085 s->write_packet = write_packet;
00086 s->read_packet = read_packet;
00087 s->seek = seek;
00088 s->pos = 0;
00089 s->must_flush = 0;
00090 s->eof_reached = 0;
00091 s->error = 0;
00092 s->seekable = AVIO_SEEKABLE_NORMAL;
00093 s->max_packet_size = 0;
00094 s->update_checksum= NULL;
00095 if(!read_packet && !write_flag){
00096 s->pos = buffer_size;
00097 s->buf_end = s->buffer + buffer_size;
00098 }
00099 s->read_pause = NULL;
00100 s->read_seek = NULL;
00101 return 0;
00102 }
00103
00104 AVIOContext *avio_alloc_context(
00105 unsigned char *buffer,
00106 int buffer_size,
00107 int write_flag,
00108 void *opaque,
00109 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
00110 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
00111 int64_t (*seek)(void *opaque, int64_t offset, int whence))
00112 {
00113 AVIOContext *s = av_mallocz(sizeof(AVIOContext));
00114 if (!s)
00115 return NULL;
00116 ffio_init_context(s, buffer, buffer_size, write_flag, opaque,
00117 read_packet, write_packet, seek);
00118 return s;
00119 }
00120
00121 static void writeout(AVIOContext *s, const uint8_t *data, int len)
00122 {
00123 if (s->write_packet && !s->error){
00124 int ret= s->write_packet(s->opaque, data, len);
00125 if(ret < 0){
00126 s->error = ret;
00127 }
00128 }
00129 s->pos += len;
00130 }
00131
00132 static void flush_buffer(AVIOContext *s)
00133 {
00134 if (s->buf_ptr > s->buffer) {
00135 writeout(s, s->buffer, s->buf_ptr - s->buffer);
00136 if(s->update_checksum){
00137 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
00138 s->checksum_ptr= s->buffer;
00139 }
00140 }
00141 s->buf_ptr = s->buffer;
00142 }
00143
00144 void avio_w8(AVIOContext *s, int b)
00145 {
00146 *s->buf_ptr++ = b;
00147 if (s->buf_ptr >= s->buf_end)
00148 flush_buffer(s);
00149 }
00150
00151 void ffio_fill(AVIOContext *s, int b, int count)
00152 {
00153 while (count > 0) {
00154 int len = FFMIN(s->buf_end - s->buf_ptr, count);
00155 memset(s->buf_ptr, b, len);
00156 s->buf_ptr += len;
00157
00158 if (s->buf_ptr >= s->buf_end)
00159 flush_buffer(s);
00160
00161 count -= len;
00162 }
00163 }
00164
00165 void avio_write(AVIOContext *s, const unsigned char *buf, int size)
00166 {
00167 if (s->direct && !s->update_checksum) {
00168 avio_flush(s);
00169 writeout(s, buf, size);
00170 return;
00171 }
00172 while (size > 0) {
00173 int len = FFMIN(s->buf_end - s->buf_ptr, size);
00174 memcpy(s->buf_ptr, buf, len);
00175 s->buf_ptr += len;
00176
00177 if (s->buf_ptr >= s->buf_end)
00178 flush_buffer(s);
00179
00180 buf += len;
00181 size -= len;
00182 }
00183 }
00184
00185 void avio_flush(AVIOContext *s)
00186 {
00187 flush_buffer(s);
00188 s->must_flush = 0;
00189 }
00190
00191 int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
00192 {
00193 int64_t offset1;
00194 int64_t pos;
00195 int force = whence & AVSEEK_FORCE;
00196 whence &= ~AVSEEK_FORCE;
00197
00198 if(!s)
00199 return AVERROR(EINVAL);
00200
00201 pos = s->pos - (s->write_flag ? 0 : (s->buf_end - s->buffer));
00202
00203 if (whence != SEEK_CUR && whence != SEEK_SET)
00204 return AVERROR(EINVAL);
00205
00206 if (whence == SEEK_CUR) {
00207 offset1 = pos + (s->buf_ptr - s->buffer);
00208 if (offset == 0)
00209 return offset1;
00210 offset += offset1;
00211 }
00212 offset1 = offset - pos;
00213 if (!s->must_flush && (!s->direct || !s->seek) &&
00214 offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) {
00215
00216 s->buf_ptr = s->buffer + offset1;
00217 } else if ((!s->seekable ||
00218 offset1 <= s->buf_end + SHORT_SEEK_THRESHOLD - s->buffer) &&
00219 !s->write_flag && offset1 >= 0 &&
00220 (!s->direct || !s->seek) &&
00221 (whence != SEEK_END || force)) {
00222 while(s->pos < offset && !s->eof_reached)
00223 fill_buffer(s);
00224 if (s->eof_reached)
00225 return AVERROR_EOF;
00226 s->buf_ptr = s->buf_end + offset - s->pos;
00227 } else {
00228 int64_t res;
00229
00230 #if CONFIG_MUXERS || CONFIG_NETWORK
00231 if (s->write_flag) {
00232 flush_buffer(s);
00233 s->must_flush = 1;
00234 }
00235 #endif
00236 if (!s->seek)
00237 return AVERROR(EPIPE);
00238 if ((res = s->seek(s->opaque, offset, SEEK_SET)) < 0)
00239 return res;
00240 if (!s->write_flag)
00241 s->buf_end = s->buffer;
00242 s->buf_ptr = s->buffer;
00243 s->pos = offset;
00244 }
00245 s->eof_reached = 0;
00246 return offset;
00247 }
00248
00249 int64_t avio_skip(AVIOContext *s, int64_t offset)
00250 {
00251 return avio_seek(s, offset, SEEK_CUR);
00252 }
00253
00254 int64_t avio_size(AVIOContext *s)
00255 {
00256 int64_t size;
00257
00258 if(!s)
00259 return AVERROR(EINVAL);
00260
00261 if (!s->seek)
00262 return AVERROR(ENOSYS);
00263 size = s->seek(s->opaque, 0, AVSEEK_SIZE);
00264 if(size<0){
00265 if ((size = s->seek(s->opaque, -1, SEEK_END)) < 0)
00266 return size;
00267 size++;
00268 s->seek(s->opaque, s->pos, SEEK_SET);
00269 }
00270 return size;
00271 }
00272
00273 int url_feof(AVIOContext *s)
00274 {
00275 if(!s)
00276 return 0;
00277 if(s->eof_reached){
00278 s->eof_reached=0;
00279 fill_buffer(s);
00280 }
00281 return s->eof_reached;
00282 }
00283
00284 void avio_wl32(AVIOContext *s, unsigned int val)
00285 {
00286 avio_w8(s, val);
00287 avio_w8(s, val >> 8);
00288 avio_w8(s, val >> 16);
00289 avio_w8(s, val >> 24);
00290 }
00291
00292 void avio_wb32(AVIOContext *s, unsigned int val)
00293 {
00294 avio_w8(s, val >> 24);
00295 avio_w8(s, val >> 16);
00296 avio_w8(s, val >> 8);
00297 avio_w8(s, val);
00298 }
00299
00300 int avio_put_str(AVIOContext *s, const char *str)
00301 {
00302 int len = 1;
00303 if (str) {
00304 len += strlen(str);
00305 avio_write(s, (const unsigned char *) str, len);
00306 } else
00307 avio_w8(s, 0);
00308 return len;
00309 }
00310
00311 int avio_put_str16le(AVIOContext *s, const char *str)
00312 {
00313 const uint8_t *q = str;
00314 int ret = 0;
00315
00316 while (*q) {
00317 uint32_t ch;
00318 uint16_t tmp;
00319
00320 GET_UTF8(ch, *q++, break;)
00321 PUT_UTF16(ch, tmp, avio_wl16(s, tmp);ret += 2;)
00322 }
00323 avio_wl16(s, 0);
00324 ret += 2;
00325 return ret;
00326 }
00327
00328 int ff_get_v_length(uint64_t val){
00329 int i=1;
00330
00331 while(val>>=7)
00332 i++;
00333
00334 return i;
00335 }
00336
00337 void ff_put_v(AVIOContext *bc, uint64_t val){
00338 int i= ff_get_v_length(val);
00339
00340 while(--i>0)
00341 avio_w8(bc, 128 | (val>>(7*i)));
00342
00343 avio_w8(bc, val&127);
00344 }
00345
00346 void avio_wl64(AVIOContext *s, uint64_t val)
00347 {
00348 avio_wl32(s, (uint32_t)(val & 0xffffffff));
00349 avio_wl32(s, (uint32_t)(val >> 32));
00350 }
00351
00352 void avio_wb64(AVIOContext *s, uint64_t val)
00353 {
00354 avio_wb32(s, (uint32_t)(val >> 32));
00355 avio_wb32(s, (uint32_t)(val & 0xffffffff));
00356 }
00357
00358 void avio_wl16(AVIOContext *s, unsigned int val)
00359 {
00360 avio_w8(s, val);
00361 avio_w8(s, val >> 8);
00362 }
00363
00364 void avio_wb16(AVIOContext *s, unsigned int val)
00365 {
00366 avio_w8(s, val >> 8);
00367 avio_w8(s, val);
00368 }
00369
00370 void avio_wl24(AVIOContext *s, unsigned int val)
00371 {
00372 avio_wl16(s, val & 0xffff);
00373 avio_w8(s, val >> 16);
00374 }
00375
00376 void avio_wb24(AVIOContext *s, unsigned int val)
00377 {
00378 avio_wb16(s, val >> 8);
00379 avio_w8(s, val);
00380 }
00381
00382
00383
00384 static void fill_buffer(AVIOContext *s)
00385 {
00386 uint8_t *dst= !s->max_packet_size && s->buf_end - s->buffer < s->buffer_size ? s->buf_end : s->buffer;
00387 int len= s->buffer_size - (dst - s->buffer);
00388 int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE;
00389
00390
00391 if (!s->read_packet && s->buf_ptr >= s->buf_end)
00392 s->eof_reached = 1;
00393
00394
00395 if (s->eof_reached)
00396 return;
00397
00398 if(s->update_checksum && dst == s->buffer){
00399 if(s->buf_end > s->checksum_ptr)
00400 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr);
00401 s->checksum_ptr= s->buffer;
00402 }
00403
00404
00405 if (s->read_packet && s->buffer_size > max_buffer_size) {
00406 ffio_set_buf_size(s, max_buffer_size);
00407
00408 s->checksum_ptr = dst = s->buffer;
00409 len = s->buffer_size;
00410 }
00411
00412 if(s->read_packet)
00413 len = s->read_packet(s->opaque, dst, len);
00414 else
00415 len = 0;
00416 if (len <= 0) {
00417
00418
00419 s->eof_reached = 1;
00420 if(len<0)
00421 s->error= len;
00422 } else {
00423 s->pos += len;
00424 s->buf_ptr = dst;
00425 s->buf_end = dst + len;
00426 }
00427 }
00428
00429 unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf,
00430 unsigned int len)
00431 {
00432 return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len);
00433 }
00434
00435 unsigned long ffio_get_checksum(AVIOContext *s)
00436 {
00437 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
00438 s->update_checksum= NULL;
00439 return s->checksum;
00440 }
00441
00442 void ffio_init_checksum(AVIOContext *s,
00443 unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len),
00444 unsigned long checksum)
00445 {
00446 s->update_checksum= update_checksum;
00447 if(s->update_checksum){
00448 s->checksum= checksum;
00449 s->checksum_ptr= s->buf_ptr;
00450 }
00451 }
00452
00453
00454 int avio_r8(AVIOContext *s)
00455 {
00456 if (s->buf_ptr >= s->buf_end)
00457 fill_buffer(s);
00458 if (s->buf_ptr < s->buf_end)
00459 return *s->buf_ptr++;
00460 return 0;
00461 }
00462
00463 int avio_read(AVIOContext *s, unsigned char *buf, int size)
00464 {
00465 int len, size1;
00466
00467 size1 = size;
00468 while (size > 0) {
00469 len = s->buf_end - s->buf_ptr;
00470 if (len > size)
00471 len = size;
00472 if (len == 0) {
00473 if((s->direct || size > s->buffer_size) && !s->update_checksum){
00474 if(s->read_packet)
00475 len = s->read_packet(s->opaque, buf, size);
00476 if (len <= 0) {
00477
00478
00479 s->eof_reached = 1;
00480 if(len<0)
00481 s->error= len;
00482 break;
00483 } else {
00484 s->pos += len;
00485 size -= len;
00486 buf += len;
00487 s->buf_ptr = s->buffer;
00488 s->buf_end = s->buffer;
00489 }
00490 }else{
00491 fill_buffer(s);
00492 len = s->buf_end - s->buf_ptr;
00493 if (len == 0)
00494 break;
00495 }
00496 } else {
00497 memcpy(buf, s->buf_ptr, len);
00498 buf += len;
00499 s->buf_ptr += len;
00500 size -= len;
00501 }
00502 }
00503 if (size1 == size) {
00504 if (s->error) return s->error;
00505 if (url_feof(s)) return AVERROR_EOF;
00506 }
00507 return size1 - size;
00508 }
00509
00510 int ffio_read_partial(AVIOContext *s, unsigned char *buf, int size)
00511 {
00512 int len;
00513
00514 if(size<0)
00515 return -1;
00516
00517 len = s->buf_end - s->buf_ptr;
00518 if (len == 0) {
00519 fill_buffer(s);
00520 len = s->buf_end - s->buf_ptr;
00521 }
00522 if (len > size)
00523 len = size;
00524 memcpy(buf, s->buf_ptr, len);
00525 s->buf_ptr += len;
00526 if (!len) {
00527 if (s->error) return s->error;
00528 if (url_feof(s)) return AVERROR_EOF;
00529 }
00530 return len;
00531 }
00532
00533 unsigned int avio_rl16(AVIOContext *s)
00534 {
00535 unsigned int val;
00536 val = avio_r8(s);
00537 val |= avio_r8(s) << 8;
00538 return val;
00539 }
00540
00541 unsigned int avio_rl24(AVIOContext *s)
00542 {
00543 unsigned int val;
00544 val = avio_rl16(s);
00545 val |= avio_r8(s) << 16;
00546 return val;
00547 }
00548
00549 unsigned int avio_rl32(AVIOContext *s)
00550 {
00551 unsigned int val;
00552 val = avio_rl16(s);
00553 val |= avio_rl16(s) << 16;
00554 return val;
00555 }
00556
00557 uint64_t avio_rl64(AVIOContext *s)
00558 {
00559 uint64_t val;
00560 val = (uint64_t)avio_rl32(s);
00561 val |= (uint64_t)avio_rl32(s) << 32;
00562 return val;
00563 }
00564
00565 unsigned int avio_rb16(AVIOContext *s)
00566 {
00567 unsigned int val;
00568 val = avio_r8(s) << 8;
00569 val |= avio_r8(s);
00570 return val;
00571 }
00572
00573 unsigned int avio_rb24(AVIOContext *s)
00574 {
00575 unsigned int val;
00576 val = avio_rb16(s) << 8;
00577 val |= avio_r8(s);
00578 return val;
00579 }
00580 unsigned int avio_rb32(AVIOContext *s)
00581 {
00582 unsigned int val;
00583 val = avio_rb16(s) << 16;
00584 val |= avio_rb16(s);
00585 return val;
00586 }
00587
00588 int ff_get_line(AVIOContext *s, char *buf, int maxlen)
00589 {
00590 int i = 0;
00591 char c;
00592
00593 do {
00594 c = avio_r8(s);
00595 if (c && i < maxlen-1)
00596 buf[i++] = c;
00597 } while (c != '\n' && c);
00598
00599 buf[i] = 0;
00600 return i;
00601 }
00602
00603 int avio_get_str(AVIOContext *s, int maxlen, char *buf, int buflen)
00604 {
00605 int i;
00606
00607 if (buflen <= 0)
00608 return AVERROR(EINVAL);
00609
00610 buflen = FFMIN(buflen - 1, maxlen);
00611 for (i = 0; i < buflen; i++)
00612 if (!(buf[i] = avio_r8(s)))
00613 return i + 1;
00614 buf[i] = 0;
00615 for (; i < maxlen; i++)
00616 if (!avio_r8(s))
00617 return i + 1;
00618 return maxlen;
00619 }
00620
00621 #define GET_STR16(type, read) \
00622 int avio_get_str16 ##type(AVIOContext *pb, int maxlen, char *buf, int buflen)\
00623 {\
00624 char* q = buf;\
00625 int ret = 0;\
00626 if (buflen <= 0) \
00627 return AVERROR(EINVAL); \
00628 while (ret + 1 < maxlen) {\
00629 uint8_t tmp;\
00630 uint32_t ch;\
00631 GET_UTF16(ch, (ret += 2) <= maxlen ? read(pb) : 0, break;)\
00632 if (!ch)\
00633 break;\
00634 PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;)\
00635 }\
00636 *q = 0;\
00637 return ret;\
00638 }\
00639
00640 GET_STR16(le, avio_rl16)
00641 GET_STR16(be, avio_rb16)
00642
00643 #undef GET_STR16
00644
00645 uint64_t avio_rb64(AVIOContext *s)
00646 {
00647 uint64_t val;
00648 val = (uint64_t)avio_rb32(s) << 32;
00649 val |= (uint64_t)avio_rb32(s);
00650 return val;
00651 }
00652
00653 uint64_t ffio_read_varlen(AVIOContext *bc){
00654 uint64_t val = 0;
00655 int tmp;
00656
00657 do{
00658 tmp = avio_r8(bc);
00659 val= (val<<7) + (tmp&127);
00660 }while(tmp&128);
00661 return val;
00662 }
00663
00664 int ffio_fdopen(AVIOContext **s, URLContext *h)
00665 {
00666 uint8_t *buffer;
00667 int buffer_size, max_packet_size;
00668
00669 max_packet_size = h->max_packet_size;
00670 if (max_packet_size) {
00671 buffer_size = max_packet_size;
00672 } else {
00673 buffer_size = IO_BUFFER_SIZE;
00674 }
00675 buffer = av_malloc(buffer_size);
00676 if (!buffer)
00677 return AVERROR(ENOMEM);
00678
00679 *s = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE, h,
00680 (void*)ffurl_read, (void*)ffurl_write, (void*)ffurl_seek);
00681 if (!*s) {
00682 av_free(buffer);
00683 return AVERROR(ENOMEM);
00684 }
00685 (*s)->direct = h->flags & AVIO_FLAG_DIRECT;
00686 (*s)->seekable = h->is_streamed ? 0 : AVIO_SEEKABLE_NORMAL;
00687 (*s)->max_packet_size = max_packet_size;
00688 if(h->prot) {
00689 (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause;
00690 (*s)->read_seek = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek;
00691 }
00692 (*s)->av_class = &ffio_url_class;
00693 return 0;
00694 }
00695
00696 int ffio_set_buf_size(AVIOContext *s, int buf_size)
00697 {
00698 uint8_t *buffer;
00699 buffer = av_malloc(buf_size);
00700 if (!buffer)
00701 return AVERROR(ENOMEM);
00702
00703 av_free(s->buffer);
00704 s->buffer = buffer;
00705 s->buffer_size = buf_size;
00706 s->buf_ptr = buffer;
00707 url_resetbuf(s, s->write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ);
00708 return 0;
00709 }
00710
00711 static int url_resetbuf(AVIOContext *s, int flags)
00712 {
00713 assert(flags == AVIO_FLAG_WRITE || flags == AVIO_FLAG_READ);
00714
00715 if (flags & AVIO_FLAG_WRITE) {
00716 s->buf_end = s->buffer + s->buffer_size;
00717 s->write_flag = 1;
00718 } else {
00719 s->buf_end = s->buffer;
00720 s->write_flag = 0;
00721 }
00722 return 0;
00723 }
00724
00725 int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char *buf, int buf_size)
00726 {
00727 int64_t buffer_start;
00728 int buffer_size;
00729 int overlap, new_size, alloc_size;
00730
00731 if (s->write_flag)
00732 return AVERROR(EINVAL);
00733
00734 buffer_size = s->buf_end - s->buffer;
00735
00736
00737 if ((buffer_start = s->pos - buffer_size) > buf_size)
00738 return AVERROR(EINVAL);
00739
00740 overlap = buf_size - buffer_start;
00741 new_size = buf_size + buffer_size - overlap;
00742
00743 alloc_size = FFMAX(s->buffer_size, new_size);
00744 if (alloc_size > buf_size)
00745 if (!(buf = av_realloc_f(buf, 1, alloc_size)))
00746 return AVERROR(ENOMEM);
00747
00748 if (new_size > buf_size) {
00749 memcpy(buf + buf_size, s->buffer + overlap, buffer_size - overlap);
00750 buf_size = new_size;
00751 }
00752
00753 av_free(s->buffer);
00754 s->buf_ptr = s->buffer = buf;
00755 s->buffer_size = alloc_size;
00756 s->pos = buf_size;
00757 s->buf_end = s->buf_ptr + buf_size;
00758 s->eof_reached = 0;
00759 s->must_flush = 0;
00760
00761 return 0;
00762 }
00763
00764 int avio_open(AVIOContext **s, const char *filename, int flags)
00765 {
00766 return avio_open2(s, filename, flags, NULL, NULL);
00767 }
00768
00769 int avio_open2(AVIOContext **s, const char *filename, int flags,
00770 const AVIOInterruptCB *int_cb, AVDictionary **options)
00771 {
00772 URLContext *h;
00773 int err;
00774
00775 err = ffurl_open(&h, filename, flags, int_cb, options);
00776 if (err < 0)
00777 return err;
00778 err = ffio_fdopen(s, h);
00779 if (err < 0) {
00780 ffurl_close(h);
00781 return err;
00782 }
00783 return 0;
00784 }
00785
00786 int avio_close(AVIOContext *s)
00787 {
00788 URLContext *h;
00789
00790 if (!s)
00791 return 0;
00792
00793 h = s->opaque;
00794 av_free(s->buffer);
00795 av_free(s);
00796 return ffurl_close(h);
00797 }
00798
00799 int avio_printf(AVIOContext *s, const char *fmt, ...)
00800 {
00801 va_list ap;
00802 char buf[4096];
00803 int ret;
00804
00805 va_start(ap, fmt);
00806 ret = vsnprintf(buf, sizeof(buf), fmt, ap);
00807 va_end(ap);
00808 avio_write(s, buf, strlen(buf));
00809 return ret;
00810 }
00811
00812 int avio_pause(AVIOContext *s, int pause)
00813 {
00814 if (!s->read_pause)
00815 return AVERROR(ENOSYS);
00816 return s->read_pause(s->opaque, pause);
00817 }
00818
00819 int64_t avio_seek_time(AVIOContext *s, int stream_index,
00820 int64_t timestamp, int flags)
00821 {
00822 URLContext *h = s->opaque;
00823 int64_t ret;
00824 if (!s->read_seek)
00825 return AVERROR(ENOSYS);
00826 ret = s->read_seek(h, stream_index, timestamp, flags);
00827 if(ret >= 0) {
00828 int64_t pos;
00829 s->buf_ptr = s->buf_end;
00830 pos = s->seek(h, 0, SEEK_CUR);
00831 if (pos >= 0)
00832 s->pos = pos;
00833 else if (pos != AVERROR(ENOSYS))
00834 ret = pos;
00835 }
00836 return ret;
00837 }
00838
00839
00840
00841 typedef struct DynBuffer {
00842 int pos, size, allocated_size;
00843 uint8_t *buffer;
00844 int io_buffer_size;
00845 uint8_t io_buffer[1];
00846 } DynBuffer;
00847
00848 static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size)
00849 {
00850 DynBuffer *d = opaque;
00851 unsigned new_size, new_allocated_size;
00852
00853
00854 new_size = d->pos + buf_size;
00855 new_allocated_size = d->allocated_size;
00856 if(new_size < d->pos || new_size > INT_MAX/2)
00857 return -1;
00858 while (new_size > new_allocated_size) {
00859 if (!new_allocated_size)
00860 new_allocated_size = new_size;
00861 else
00862 new_allocated_size += new_allocated_size / 2 + 1;
00863 }
00864
00865 if (new_allocated_size > d->allocated_size) {
00866 d->buffer = av_realloc_f(d->buffer, 1, new_allocated_size);
00867 if(d->buffer == NULL)
00868 return AVERROR(ENOMEM);
00869 d->allocated_size = new_allocated_size;
00870 }
00871 memcpy(d->buffer + d->pos, buf, buf_size);
00872 d->pos = new_size;
00873 if (d->pos > d->size)
00874 d->size = d->pos;
00875 return buf_size;
00876 }
00877
00878 static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size)
00879 {
00880 unsigned char buf1[4];
00881 int ret;
00882
00883
00884 AV_WB32(buf1, buf_size);
00885 ret= dyn_buf_write(opaque, buf1, 4);
00886 if(ret < 0)
00887 return ret;
00888
00889
00890 return dyn_buf_write(opaque, buf, buf_size);
00891 }
00892
00893 static int64_t dyn_buf_seek(void *opaque, int64_t offset, int whence)
00894 {
00895 DynBuffer *d = opaque;
00896
00897 if (whence == SEEK_CUR)
00898 offset += d->pos;
00899 else if (whence == SEEK_END)
00900 offset += d->size;
00901 if (offset < 0 || offset > 0x7fffffffLL)
00902 return -1;
00903 d->pos = offset;
00904 return 0;
00905 }
00906
00907 static int url_open_dyn_buf_internal(AVIOContext **s, int max_packet_size)
00908 {
00909 DynBuffer *d;
00910 unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024;
00911
00912 if(sizeof(DynBuffer) + io_buffer_size < io_buffer_size)
00913 return -1;
00914 d = av_mallocz(sizeof(DynBuffer) + io_buffer_size);
00915 if (!d)
00916 return AVERROR(ENOMEM);
00917 d->io_buffer_size = io_buffer_size;
00918 *s = avio_alloc_context(d->io_buffer, d->io_buffer_size, 1, d, NULL,
00919 max_packet_size ? dyn_packet_buf_write : dyn_buf_write,
00920 max_packet_size ? NULL : dyn_buf_seek);
00921 if(!*s) {
00922 av_free(d);
00923 return AVERROR(ENOMEM);
00924 }
00925 (*s)->max_packet_size = max_packet_size;
00926 return 0;
00927 }
00928
00929 int avio_open_dyn_buf(AVIOContext **s)
00930 {
00931 return url_open_dyn_buf_internal(s, 0);
00932 }
00933
00934 int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size)
00935 {
00936 if (max_packet_size <= 0)
00937 return -1;
00938 return url_open_dyn_buf_internal(s, max_packet_size);
00939 }
00940
00941 int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
00942 {
00943 DynBuffer *d = s->opaque;
00944 int size;
00945 static const char padbuf[FF_INPUT_BUFFER_PADDING_SIZE] = {0};
00946 int padding = 0;
00947
00948
00949 if (!s->max_packet_size) {
00950 avio_write(s, padbuf, sizeof(padbuf));
00951 padding = FF_INPUT_BUFFER_PADDING_SIZE;
00952 }
00953
00954 avio_flush(s);
00955
00956 *pbuffer = d->buffer;
00957 size = d->size;
00958 av_free(d);
00959 av_free(s);
00960 return size - padding;
00961 }