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