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