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