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