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