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