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->read_packet && s->buf_ptr >= s->buf_end)
00579 s->eof_reached = 1;
00580
00581
00582 if (s->eof_reached)
00583 return;
00584
00585 if(s->update_checksum && dst == s->buffer){
00586 if(s->buf_end > s->checksum_ptr)
00587 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr);
00588 s->checksum_ptr= s->buffer;
00589 }
00590
00591
00592 if (s->read_packet && s->buffer_size > max_buffer_size) {
00593 ffio_set_buf_size(s, max_buffer_size);
00594
00595 s->checksum_ptr = dst = s->buffer;
00596 len = s->buffer_size;
00597 }
00598
00599 if(s->read_packet)
00600 len = s->read_packet(s->opaque, dst, len);
00601 else
00602 len = 0;
00603 if (len <= 0) {
00604
00605
00606 s->eof_reached = 1;
00607 if(len<0)
00608 s->error= len;
00609 } else {
00610 s->pos += len;
00611 s->buf_ptr = dst;
00612 s->buf_end = dst + len;
00613 }
00614 }
00615
00616 unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf,
00617 unsigned int len)
00618 {
00619 return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len);
00620 }
00621
00622 unsigned long ffio_get_checksum(AVIOContext *s)
00623 {
00624 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
00625 s->update_checksum= NULL;
00626 return s->checksum;
00627 }
00628
00629 void ffio_init_checksum(AVIOContext *s,
00630 unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len),
00631 unsigned long checksum)
00632 {
00633 s->update_checksum= update_checksum;
00634 if(s->update_checksum){
00635 s->checksum= checksum;
00636 s->checksum_ptr= s->buf_ptr;
00637 }
00638 }
00639
00640
00641 int avio_r8(AVIOContext *s)
00642 {
00643 if (s->buf_ptr >= s->buf_end)
00644 fill_buffer(s);
00645 if (s->buf_ptr < s->buf_end)
00646 return *s->buf_ptr++;
00647 return 0;
00648 }
00649
00650 #if FF_API_OLD_AVIO
00651 int url_fgetc(AVIOContext *s)
00652 {
00653 if (s->buf_ptr >= s->buf_end)
00654 fill_buffer(s);
00655 if (s->buf_ptr < s->buf_end)
00656 return *s->buf_ptr++;
00657 return URL_EOF;
00658 }
00659 #endif
00660
00661 int avio_read(AVIOContext *s, unsigned char *buf, int size)
00662 {
00663 int len, size1;
00664
00665 size1 = size;
00666 while (size > 0) {
00667 len = s->buf_end - s->buf_ptr;
00668 if (len > size)
00669 len = size;
00670 if (len == 0) {
00671 if(size > s->buffer_size && !s->update_checksum){
00672 if(s->read_packet)
00673 len = s->read_packet(s->opaque, buf, size);
00674 if (len <= 0) {
00675
00676
00677 s->eof_reached = 1;
00678 if(len<0)
00679 s->error= len;
00680 break;
00681 } else {
00682 s->pos += len;
00683 size -= len;
00684 buf += len;
00685 s->buf_ptr = s->buffer;
00686 s->buf_end = s->buffer;
00687 }
00688 }else{
00689 fill_buffer(s);
00690 len = s->buf_end - s->buf_ptr;
00691 if (len == 0)
00692 break;
00693 }
00694 } else {
00695 memcpy(buf, s->buf_ptr, len);
00696 buf += len;
00697 s->buf_ptr += len;
00698 size -= len;
00699 }
00700 }
00701 if (size1 == size) {
00702 if (s->error) return s->error;
00703 if (url_feof(s)) return AVERROR_EOF;
00704 }
00705 return size1 - size;
00706 }
00707
00708 int ffio_read_partial(AVIOContext *s, unsigned char *buf, int size)
00709 {
00710 int len;
00711
00712 if(size<0)
00713 return -1;
00714
00715 len = s->buf_end - s->buf_ptr;
00716 if (len == 0) {
00717 fill_buffer(s);
00718 len = s->buf_end - s->buf_ptr;
00719 }
00720 if (len > size)
00721 len = size;
00722 memcpy(buf, s->buf_ptr, len);
00723 s->buf_ptr += len;
00724 if (!len) {
00725 if (s->error) return s->error;
00726 if (url_feof(s)) return AVERROR_EOF;
00727 }
00728 return len;
00729 }
00730
00731 unsigned int avio_rl16(AVIOContext *s)
00732 {
00733 unsigned int val;
00734 val = avio_r8(s);
00735 val |= avio_r8(s) << 8;
00736 return val;
00737 }
00738
00739 unsigned int avio_rl24(AVIOContext *s)
00740 {
00741 unsigned int val;
00742 val = avio_rl16(s);
00743 val |= avio_r8(s) << 16;
00744 return val;
00745 }
00746
00747 unsigned int avio_rl32(AVIOContext *s)
00748 {
00749 unsigned int val;
00750 val = avio_rl16(s);
00751 val |= avio_rl16(s) << 16;
00752 return val;
00753 }
00754
00755 uint64_t avio_rl64(AVIOContext *s)
00756 {
00757 uint64_t val;
00758 val = (uint64_t)avio_rl32(s);
00759 val |= (uint64_t)avio_rl32(s) << 32;
00760 return val;
00761 }
00762
00763 unsigned int avio_rb16(AVIOContext *s)
00764 {
00765 unsigned int val;
00766 val = avio_r8(s) << 8;
00767 val |= avio_r8(s);
00768 return val;
00769 }
00770
00771 unsigned int avio_rb24(AVIOContext *s)
00772 {
00773 unsigned int val;
00774 val = avio_rb16(s) << 8;
00775 val |= avio_r8(s);
00776 return val;
00777 }
00778 unsigned int avio_rb32(AVIOContext *s)
00779 {
00780 unsigned int val;
00781 val = avio_rb16(s) << 16;
00782 val |= avio_rb16(s);
00783 return val;
00784 }
00785
00786 #if FF_API_OLD_AVIO
00787 char *get_strz(AVIOContext *s, char *buf, int maxlen)
00788 {
00789 avio_get_str(s, INT_MAX, buf, maxlen);
00790 return buf;
00791 }
00792 #endif
00793
00794 int ff_get_line(AVIOContext *s, char *buf, int maxlen)
00795 {
00796 int i = 0;
00797 char c;
00798
00799 do {
00800 c = avio_r8(s);
00801 if (c && i < maxlen-1)
00802 buf[i++] = c;
00803 } while (c != '\n' && c);
00804
00805 buf[i] = 0;
00806 return i;
00807 }
00808
00809 int avio_get_str(AVIOContext *s, int maxlen, char *buf, int buflen)
00810 {
00811 int i;
00812
00813 if (buflen <= 0)
00814 return AVERROR(EINVAL);
00815
00816 buflen = FFMIN(buflen - 1, maxlen);
00817 for (i = 0; i < buflen; i++)
00818 if (!(buf[i] = avio_r8(s)))
00819 return i + 1;
00820 buf[i] = 0;
00821 for (; i < maxlen; i++)
00822 if (!avio_r8(s))
00823 return i + 1;
00824 return maxlen;
00825 }
00826
00827 #define GET_STR16(type, read) \
00828 int avio_get_str16 ##type(AVIOContext *pb, int maxlen, char *buf, int buflen)\
00829 {\
00830 char* q = buf;\
00831 int ret = 0;\
00832 if (buflen <= 0) \
00833 return AVERROR(EINVAL); \
00834 while (ret + 1 < maxlen) {\
00835 uint8_t tmp;\
00836 uint32_t ch;\
00837 GET_UTF16(ch, (ret += 2) <= maxlen ? read(pb) : 0, break;)\
00838 if (!ch)\
00839 break;\
00840 PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;)\
00841 }\
00842 *q = 0;\
00843 return ret;\
00844 }\
00845
00846 GET_STR16(le, avio_rl16)
00847 GET_STR16(be, avio_rb16)
00848
00849 #undef GET_STR16
00850
00851 uint64_t avio_rb64(AVIOContext *s)
00852 {
00853 uint64_t val;
00854 val = (uint64_t)avio_rb32(s) << 32;
00855 val |= (uint64_t)avio_rb32(s);
00856 return val;
00857 }
00858
00859 uint64_t ffio_read_varlen(AVIOContext *bc){
00860 uint64_t val = 0;
00861 int tmp;
00862
00863 do{
00864 tmp = avio_r8(bc);
00865 val= (val<<7) + (tmp&127);
00866 }while(tmp&128);
00867 return val;
00868 }
00869
00870 int ffio_fdopen(AVIOContext **s, URLContext *h)
00871 {
00872 uint8_t *buffer;
00873 int buffer_size, max_packet_size;
00874
00875 max_packet_size = h->max_packet_size;
00876 if (max_packet_size) {
00877 buffer_size = max_packet_size;
00878 } else {
00879 buffer_size = IO_BUFFER_SIZE;
00880 }
00881 buffer = av_malloc(buffer_size);
00882 if (!buffer)
00883 return AVERROR(ENOMEM);
00884
00885 *s = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE, h,
00886 ffurl_read, ffurl_write, ffurl_seek);
00887 if (!*s) {
00888 av_free(buffer);
00889 return AVERROR(ENOMEM);
00890 }
00891
00892 #if FF_API_OLD_AVIO
00893 (*s)->is_streamed = h->is_streamed;
00894 #endif
00895 (*s)->seekable = h->is_streamed ? 0 : AVIO_SEEKABLE_NORMAL;
00896 (*s)->max_packet_size = max_packet_size;
00897 if(h->prot) {
00898 (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause;
00899 (*s)->read_seek = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek;
00900 }
00901 #if !FF_API_OLD_AVIO
00902 (*s)->av_class = &ffio_url_class;
00903 #endif
00904 return 0;
00905 }
00906
00907 int ffio_set_buf_size(AVIOContext *s, int buf_size)
00908 {
00909 uint8_t *buffer;
00910 buffer = av_malloc(buf_size);
00911 if (!buffer)
00912 return AVERROR(ENOMEM);
00913
00914 av_free(s->buffer);
00915 s->buffer = buffer;
00916 s->buffer_size = buf_size;
00917 s->buf_ptr = buffer;
00918 url_resetbuf(s, s->write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ);
00919 return 0;
00920 }
00921
00922 static int url_resetbuf(AVIOContext *s, int flags)
00923 {
00924 assert(flags == AVIO_FLAG_WRITE || flags == AVIO_FLAG_READ);
00925
00926 if (flags & AVIO_FLAG_WRITE) {
00927 s->buf_end = s->buffer + s->buffer_size;
00928 s->write_flag = 1;
00929 } else {
00930 s->buf_end = s->buffer;
00931 s->write_flag = 0;
00932 }
00933 return 0;
00934 }
00935
00936 int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char *buf, int buf_size)
00937 {
00938 int64_t buffer_start;
00939 int buffer_size;
00940 int overlap, new_size, alloc_size;
00941
00942 if (s->write_flag)
00943 return AVERROR(EINVAL);
00944
00945 buffer_size = s->buf_end - s->buffer;
00946
00947
00948 if ((buffer_start = s->pos - buffer_size) > buf_size)
00949 return AVERROR(EINVAL);
00950
00951 overlap = buf_size - buffer_start;
00952 new_size = buf_size + buffer_size - overlap;
00953
00954 alloc_size = FFMAX(s->buffer_size, new_size);
00955 if (alloc_size > buf_size)
00956 if (!(buf = av_realloc_f(buf, 1, alloc_size)))
00957 return AVERROR(ENOMEM);
00958
00959 if (new_size > buf_size) {
00960 memcpy(buf + buf_size, s->buffer + overlap, buffer_size - overlap);
00961 buf_size = new_size;
00962 }
00963
00964 av_free(s->buffer);
00965 s->buf_ptr = s->buffer = buf;
00966 s->buffer_size = alloc_size;
00967 s->pos = buf_size;
00968 s->buf_end = s->buf_ptr + buf_size;
00969 s->eof_reached = 0;
00970 s->must_flush = 0;
00971
00972 return 0;
00973 }
00974
00975 int avio_open(AVIOContext **s, const char *filename, int flags)
00976 {
00977 return avio_open2(s, filename, flags, NULL, NULL);
00978 }
00979
00980 int avio_open2(AVIOContext **s, const char *filename, int flags,
00981 const AVIOInterruptCB *int_cb, AVDictionary **options)
00982 {
00983 URLContext *h;
00984 int err;
00985
00986 err = ffurl_open(&h, filename, flags, int_cb, options);
00987 if (err < 0)
00988 return err;
00989 err = ffio_fdopen(s, h);
00990 if (err < 0) {
00991 ffurl_close(h);
00992 return err;
00993 }
00994 return 0;
00995 }
00996
00997 int avio_close(AVIOContext *s)
00998 {
00999 URLContext *h = s->opaque;
01000
01001 av_free(s->buffer);
01002 av_free(s);
01003 return ffurl_close(h);
01004 }
01005
01006 #if FF_API_OLD_AVIO
01007 URLContext *url_fileno(AVIOContext *s)
01008 {
01009 return s->opaque;
01010 }
01011 #endif
01012
01013 int avio_printf(AVIOContext *s, const char *fmt, ...)
01014 {
01015 va_list ap;
01016 char buf[4096];
01017 int ret;
01018
01019 va_start(ap, fmt);
01020 ret = vsnprintf(buf, sizeof(buf), fmt, ap);
01021 va_end(ap);
01022 avio_write(s, buf, strlen(buf));
01023 return ret;
01024 }
01025
01026 #if FF_API_OLD_AVIO
01027 char *url_fgets(AVIOContext *s, char *buf, int buf_size)
01028 {
01029 int c;
01030 char *q;
01031
01032 c = avio_r8(s);
01033 if (url_feof(s))
01034 return NULL;
01035 q = buf;
01036 for(;;) {
01037 if (url_feof(s) || c == '\n')
01038 break;
01039 if ((q - buf) < buf_size - 1)
01040 *q++ = c;
01041 c = avio_r8(s);
01042 }
01043 if (buf_size > 0)
01044 *q = '\0';
01045 return buf;
01046 }
01047
01048 int url_fget_max_packet_size(AVIOContext *s)
01049 {
01050 return s->max_packet_size;
01051 }
01052 #endif
01053
01054 int avio_pause(AVIOContext *s, int pause)
01055 {
01056 if (!s->read_pause)
01057 return AVERROR(ENOSYS);
01058 return s->read_pause(s->opaque, pause);
01059 }
01060
01061 int64_t avio_seek_time(AVIOContext *s, int stream_index,
01062 int64_t timestamp, int flags)
01063 {
01064 URLContext *h = s->opaque;
01065 int64_t ret;
01066 if (!s->read_seek)
01067 return AVERROR(ENOSYS);
01068 ret = s->read_seek(h, stream_index, timestamp, flags);
01069 if(ret >= 0) {
01070 int64_t pos;
01071 s->buf_ptr = s->buf_end;
01072 pos = s->seek(h, 0, SEEK_CUR);
01073 if (pos >= 0)
01074 s->pos = pos;
01075 else if (pos != AVERROR(ENOSYS))
01076 ret = pos;
01077 }
01078 return ret;
01079 }
01080
01081
01082 #if FF_API_OLD_AVIO
01083 int url_open_buf(AVIOContext **s, uint8_t *buf, int buf_size, int flags)
01084 {
01085 int ret;
01086 *s = av_mallocz(sizeof(AVIOContext));
01087 if(!*s)
01088 return AVERROR(ENOMEM);
01089 ret = ffio_init_context(*s, buf, buf_size,
01090 flags & AVIO_FLAG_WRITE,
01091 NULL, NULL, NULL, NULL);
01092 if(ret != 0)
01093 av_freep(s);
01094 return ret;
01095 }
01096
01097 int url_close_buf(AVIOContext *s)
01098 {
01099 avio_flush(s);
01100 return s->buf_ptr - s->buffer;
01101 }
01102 #endif
01103
01104
01105
01106 typedef struct DynBuffer {
01107 int pos, size, allocated_size;
01108 uint8_t *buffer;
01109 int io_buffer_size;
01110 uint8_t io_buffer[1];
01111 } DynBuffer;
01112
01113 static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size)
01114 {
01115 DynBuffer *d = opaque;
01116 unsigned new_size, new_allocated_size;
01117
01118
01119 new_size = d->pos + buf_size;
01120 new_allocated_size = d->allocated_size;
01121 if(new_size < d->pos || new_size > INT_MAX/2)
01122 return -1;
01123 while (new_size > new_allocated_size) {
01124 if (!new_allocated_size)
01125 new_allocated_size = new_size;
01126 else
01127 new_allocated_size += new_allocated_size / 2 + 1;
01128 }
01129
01130 if (new_allocated_size > d->allocated_size) {
01131 d->buffer = av_realloc_f(d->buffer, 1, new_allocated_size);
01132 if(d->buffer == NULL)
01133 return AVERROR(ENOMEM);
01134 d->allocated_size = new_allocated_size;
01135 }
01136 memcpy(d->buffer + d->pos, buf, buf_size);
01137 d->pos = new_size;
01138 if (d->pos > d->size)
01139 d->size = d->pos;
01140 return buf_size;
01141 }
01142
01143 static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size)
01144 {
01145 unsigned char buf1[4];
01146 int ret;
01147
01148
01149 AV_WB32(buf1, buf_size);
01150 ret= dyn_buf_write(opaque, buf1, 4);
01151 if(ret < 0)
01152 return ret;
01153
01154
01155 return dyn_buf_write(opaque, buf, buf_size);
01156 }
01157
01158 static int64_t dyn_buf_seek(void *opaque, int64_t offset, int whence)
01159 {
01160 DynBuffer *d = opaque;
01161
01162 if (whence == SEEK_CUR)
01163 offset += d->pos;
01164 else if (whence == SEEK_END)
01165 offset += d->size;
01166 if (offset < 0 || offset > 0x7fffffffLL)
01167 return -1;
01168 d->pos = offset;
01169 return 0;
01170 }
01171
01172 static int url_open_dyn_buf_internal(AVIOContext **s, int max_packet_size)
01173 {
01174 DynBuffer *d;
01175 unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024;
01176
01177 if(sizeof(DynBuffer) + io_buffer_size < io_buffer_size)
01178 return -1;
01179 d = av_mallocz(sizeof(DynBuffer) + io_buffer_size);
01180 if (!d)
01181 return AVERROR(ENOMEM);
01182 d->io_buffer_size = io_buffer_size;
01183 *s = avio_alloc_context(d->io_buffer, d->io_buffer_size, 1, d, NULL,
01184 max_packet_size ? dyn_packet_buf_write : dyn_buf_write,
01185 max_packet_size ? NULL : dyn_buf_seek);
01186 if(!*s) {
01187 av_free(d);
01188 return AVERROR(ENOMEM);
01189 }
01190 (*s)->max_packet_size = max_packet_size;
01191 return 0;
01192 }
01193
01194 int avio_open_dyn_buf(AVIOContext **s)
01195 {
01196 return url_open_dyn_buf_internal(s, 0);
01197 }
01198
01199 int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size)
01200 {
01201 if (max_packet_size <= 0)
01202 return -1;
01203 return url_open_dyn_buf_internal(s, max_packet_size);
01204 }
01205
01206 int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
01207 {
01208 DynBuffer *d = s->opaque;
01209 int size;
01210 static const char padbuf[FF_INPUT_BUFFER_PADDING_SIZE] = {0};
01211 int padding = 0;
01212
01213
01214 if (!s->max_packet_size) {
01215 avio_write(s, padbuf, sizeof(padbuf));
01216 padding = FF_INPUT_BUFFER_PADDING_SIZE;
01217 }
01218
01219 avio_flush(s);
01220
01221 *pbuffer = d->buffer;
01222 size = d->size;
01223 av_free(d);
01224 av_free(s);
01225 return size - padding;
01226 }