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 <stdarg.h>
00027
00028 #define IO_BUFFER_SIZE 32768
00029
00030 static void fill_buffer(ByteIOContext *s);
00031 #if LIBAVFORMAT_VERSION_MAJOR >= 53
00032 static int url_resetbuf(ByteIOContext *s, int flags);
00033 #endif
00034
00035 int init_put_byte(ByteIOContext *s,
00036 unsigned char *buffer,
00037 int buffer_size,
00038 int write_flag,
00039 void *opaque,
00040 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
00041 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
00042 int64_t (*seek)(void *opaque, int64_t offset, int whence))
00043 {
00044 s->buffer = buffer;
00045 s->buffer_size = buffer_size;
00046 s->buf_ptr = buffer;
00047 s->opaque = opaque;
00048 url_resetbuf(s, write_flag ? URL_WRONLY : URL_RDONLY);
00049 s->write_packet = write_packet;
00050 s->read_packet = read_packet;
00051 s->seek = seek;
00052 s->pos = 0;
00053 s->must_flush = 0;
00054 s->eof_reached = 0;
00055 s->error = 0;
00056 s->is_streamed = 0;
00057 s->max_packet_size = 0;
00058 s->update_checksum= NULL;
00059 if(!read_packet && !write_flag){
00060 s->pos = buffer_size;
00061 s->buf_end = s->buffer + buffer_size;
00062 }
00063 s->read_pause = NULL;
00064 s->read_seek = NULL;
00065 return 0;
00066 }
00067
00068 ByteIOContext *av_alloc_put_byte(
00069 unsigned char *buffer,
00070 int buffer_size,
00071 int write_flag,
00072 void *opaque,
00073 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
00074 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
00075 int64_t (*seek)(void *opaque, int64_t offset, int whence))
00076 {
00077 ByteIOContext *s = av_mallocz(sizeof(ByteIOContext));
00078 init_put_byte(s, buffer, buffer_size, write_flag, opaque,
00079 read_packet, write_packet, seek);
00080 return s;
00081 }
00082
00083 static void flush_buffer(ByteIOContext *s)
00084 {
00085 if (s->buf_ptr > s->buffer) {
00086 if (s->write_packet && !s->error){
00087 int ret= s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer);
00088 if(ret < 0){
00089 s->error = ret;
00090 }
00091 }
00092 if(s->update_checksum){
00093 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
00094 s->checksum_ptr= s->buffer;
00095 }
00096 s->pos += s->buf_ptr - s->buffer;
00097 }
00098 s->buf_ptr = s->buffer;
00099 }
00100
00101 void put_byte(ByteIOContext *s, int b)
00102 {
00103 *(s->buf_ptr)++ = b;
00104 if (s->buf_ptr >= s->buf_end)
00105 flush_buffer(s);
00106 }
00107
00108 void put_buffer(ByteIOContext *s, const unsigned char *buf, int size)
00109 {
00110 while (size > 0) {
00111 int len = FFMIN(s->buf_end - s->buf_ptr, size);
00112 memcpy(s->buf_ptr, buf, len);
00113 s->buf_ptr += len;
00114
00115 if (s->buf_ptr >= s->buf_end)
00116 flush_buffer(s);
00117
00118 buf += len;
00119 size -= len;
00120 }
00121 }
00122
00123 void put_flush_packet(ByteIOContext *s)
00124 {
00125 flush_buffer(s);
00126 s->must_flush = 0;
00127 }
00128
00129 int64_t url_fseek(ByteIOContext *s, int64_t offset, int whence)
00130 {
00131 int64_t offset1;
00132 int64_t pos;
00133 int force = whence & AVSEEK_FORCE;
00134 whence &= ~AVSEEK_FORCE;
00135
00136 if(!s)
00137 return AVERROR(EINVAL);
00138
00139 pos = s->pos - (s->write_flag ? 0 : (s->buf_end - s->buffer));
00140
00141 if (whence != SEEK_CUR && whence != SEEK_SET)
00142 return AVERROR(EINVAL);
00143
00144 if (whence == SEEK_CUR) {
00145 offset1 = pos + (s->buf_ptr - s->buffer);
00146 if (offset == 0)
00147 return offset1;
00148 offset += offset1;
00149 }
00150 offset1 = offset - pos;
00151 if (!s->must_flush &&
00152 offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) {
00153
00154 s->buf_ptr = s->buffer + offset1;
00155 } else if(s->is_streamed && !s->write_flag && offset1 >= 0 &&
00156 (whence != SEEK_END || force)) {
00157 while(s->pos < offset && !s->eof_reached)
00158 fill_buffer(s);
00159 if (s->eof_reached)
00160 return AVERROR_EOF;
00161 s->buf_ptr = s->buf_end + offset - s->pos;
00162 } else {
00163 int64_t res = AVERROR(EPIPE);
00164
00165 #if CONFIG_MUXERS || CONFIG_NETWORK
00166 if (s->write_flag) {
00167 flush_buffer(s);
00168 s->must_flush = 1;
00169 }
00170 #endif
00171 if (!s->seek || (res = s->seek(s->opaque, offset, SEEK_SET)) < 0)
00172 return res;
00173 if (!s->write_flag)
00174 s->buf_end = s->buffer;
00175 s->buf_ptr = s->buffer;
00176 s->pos = offset;
00177 }
00178 s->eof_reached = 0;
00179 return offset;
00180 }
00181
00182 void url_fskip(ByteIOContext *s, int64_t offset)
00183 {
00184 url_fseek(s, offset, SEEK_CUR);
00185 }
00186
00187 int64_t url_ftell(ByteIOContext *s)
00188 {
00189 return url_fseek(s, 0, SEEK_CUR);
00190 }
00191
00192 int64_t url_fsize(ByteIOContext *s)
00193 {
00194 int64_t size;
00195
00196 if(!s)
00197 return AVERROR(EINVAL);
00198
00199 if (!s->seek)
00200 return AVERROR(EPIPE);
00201 size = s->seek(s->opaque, 0, AVSEEK_SIZE);
00202 if(size<0){
00203 if ((size = s->seek(s->opaque, -1, SEEK_END)) < 0)
00204 return size;
00205 size++;
00206 s->seek(s->opaque, s->pos, SEEK_SET);
00207 }
00208 return size;
00209 }
00210
00211 int url_feof(ByteIOContext *s)
00212 {
00213 if(!s)
00214 return 0;
00215 return s->eof_reached;
00216 }
00217
00218 int url_ferror(ByteIOContext *s)
00219 {
00220 if(!s)
00221 return 0;
00222 return s->error;
00223 }
00224
00225 void put_le32(ByteIOContext *s, unsigned int val)
00226 {
00227 put_byte(s, val);
00228 put_byte(s, val >> 8);
00229 put_byte(s, val >> 16);
00230 put_byte(s, val >> 24);
00231 }
00232
00233 void put_be32(ByteIOContext *s, unsigned int val)
00234 {
00235 put_byte(s, val >> 24);
00236 put_byte(s, val >> 16);
00237 put_byte(s, val >> 8);
00238 put_byte(s, val);
00239 }
00240
00241 void put_strz(ByteIOContext *s, const char *str)
00242 {
00243 if (str)
00244 put_buffer(s, (const unsigned char *) str, strlen(str) + 1);
00245 else
00246 put_byte(s, 0);
00247 }
00248
00249 void put_le64(ByteIOContext *s, uint64_t val)
00250 {
00251 put_le32(s, (uint32_t)(val & 0xffffffff));
00252 put_le32(s, (uint32_t)(val >> 32));
00253 }
00254
00255 void put_be64(ByteIOContext *s, uint64_t val)
00256 {
00257 put_be32(s, (uint32_t)(val >> 32));
00258 put_be32(s, (uint32_t)(val & 0xffffffff));
00259 }
00260
00261 void put_le16(ByteIOContext *s, unsigned int val)
00262 {
00263 put_byte(s, val);
00264 put_byte(s, val >> 8);
00265 }
00266
00267 void put_be16(ByteIOContext *s, unsigned int val)
00268 {
00269 put_byte(s, val >> 8);
00270 put_byte(s, val);
00271 }
00272
00273 void put_le24(ByteIOContext *s, unsigned int val)
00274 {
00275 put_le16(s, val & 0xffff);
00276 put_byte(s, val >> 16);
00277 }
00278
00279 void put_be24(ByteIOContext *s, unsigned int val)
00280 {
00281 put_be16(s, val >> 8);
00282 put_byte(s, val);
00283 }
00284
00285 void put_tag(ByteIOContext *s, const char *tag)
00286 {
00287 while (*tag) {
00288 put_byte(s, *tag++);
00289 }
00290 }
00291
00292
00293
00294 static void fill_buffer(ByteIOContext *s)
00295 {
00296 uint8_t *dst= !s->max_packet_size && s->buf_end - s->buffer < s->buffer_size ? s->buf_ptr : s->buffer;
00297 int len= s->buffer_size - (dst - s->buffer);
00298 int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE;
00299
00300 assert(s->buf_ptr == s->buf_end);
00301
00302
00303 if (s->eof_reached)
00304 return;
00305
00306 if(s->update_checksum && dst == s->buffer){
00307 if(s->buf_end > s->checksum_ptr)
00308 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr);
00309 s->checksum_ptr= s->buffer;
00310 }
00311
00312
00313 if (s->buffer_size > max_buffer_size) {
00314 url_setbufsize(s, max_buffer_size);
00315
00316 s->checksum_ptr = dst = s->buffer;
00317 len = s->buffer_size;
00318 }
00319
00320 if(s->read_packet)
00321 len = s->read_packet(s->opaque, dst, len);
00322 else
00323 len = 0;
00324 if (len <= 0) {
00325
00326
00327 s->eof_reached = 1;
00328 if(len<0)
00329 s->error= len;
00330 } else {
00331 s->pos += len;
00332 s->buf_ptr = dst;
00333 s->buf_end = dst + len;
00334 }
00335 }
00336
00337 unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf,
00338 unsigned int len)
00339 {
00340 return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len);
00341 }
00342
00343 unsigned long get_checksum(ByteIOContext *s)
00344 {
00345 s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
00346 s->update_checksum= NULL;
00347 return s->checksum;
00348 }
00349
00350 void init_checksum(ByteIOContext *s,
00351 unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len),
00352 unsigned long checksum)
00353 {
00354 s->update_checksum= update_checksum;
00355 if(s->update_checksum){
00356 s->checksum= checksum;
00357 s->checksum_ptr= s->buf_ptr;
00358 }
00359 }
00360
00361
00362 int get_byte(ByteIOContext *s)
00363 {
00364 if (s->buf_ptr < s->buf_end) {
00365 return *s->buf_ptr++;
00366 } else {
00367 fill_buffer(s);
00368 if (s->buf_ptr < s->buf_end)
00369 return *s->buf_ptr++;
00370 else
00371 return 0;
00372 }
00373 }
00374
00375 int url_fgetc(ByteIOContext *s)
00376 {
00377 if (s->buf_ptr < s->buf_end) {
00378 return *s->buf_ptr++;
00379 } else {
00380 fill_buffer(s);
00381 if (s->buf_ptr < s->buf_end)
00382 return *s->buf_ptr++;
00383 else
00384 return URL_EOF;
00385 }
00386 }
00387
00388 int get_buffer(ByteIOContext *s, unsigned char *buf, int size)
00389 {
00390 int len, size1;
00391
00392 size1 = size;
00393 while (size > 0) {
00394 len = s->buf_end - s->buf_ptr;
00395 if (len > size)
00396 len = size;
00397 if (len == 0) {
00398 if(size > s->buffer_size && !s->update_checksum){
00399 if(s->read_packet)
00400 len = s->read_packet(s->opaque, buf, size);
00401 if (len <= 0) {
00402
00403
00404 s->eof_reached = 1;
00405 if(len<0)
00406 s->error= len;
00407 break;
00408 } else {
00409 s->pos += len;
00410 size -= len;
00411 buf += len;
00412 s->buf_ptr = s->buffer;
00413 s->buf_end = s->buffer;
00414 }
00415 }else{
00416 fill_buffer(s);
00417 len = s->buf_end - s->buf_ptr;
00418 if (len == 0)
00419 break;
00420 }
00421 } else {
00422 memcpy(buf, s->buf_ptr, len);
00423 buf += len;
00424 s->buf_ptr += len;
00425 size -= len;
00426 }
00427 }
00428 if (size1 == size) {
00429 if (url_ferror(s)) return url_ferror(s);
00430 if (url_feof(s)) return AVERROR_EOF;
00431 }
00432 return size1 - size;
00433 }
00434
00435 int get_partial_buffer(ByteIOContext *s, unsigned char *buf, int size)
00436 {
00437 int len;
00438
00439 if(size<0)
00440 return -1;
00441
00442 len = s->buf_end - s->buf_ptr;
00443 if (len == 0) {
00444 fill_buffer(s);
00445 len = s->buf_end - s->buf_ptr;
00446 }
00447 if (len > size)
00448 len = size;
00449 memcpy(buf, s->buf_ptr, len);
00450 s->buf_ptr += len;
00451 if (!len) {
00452 if (url_ferror(s)) return url_ferror(s);
00453 if (url_feof(s)) return AVERROR_EOF;
00454 }
00455 return len;
00456 }
00457
00458 unsigned int get_le16(ByteIOContext *s)
00459 {
00460 unsigned int val;
00461 val = get_byte(s);
00462 val |= get_byte(s) << 8;
00463 return val;
00464 }
00465
00466 unsigned int get_le24(ByteIOContext *s)
00467 {
00468 unsigned int val;
00469 val = get_le16(s);
00470 val |= get_byte(s) << 16;
00471 return val;
00472 }
00473
00474 unsigned int get_le32(ByteIOContext *s)
00475 {
00476 unsigned int val;
00477 val = get_le16(s);
00478 val |= get_le16(s) << 16;
00479 return val;
00480 }
00481
00482 uint64_t get_le64(ByteIOContext *s)
00483 {
00484 uint64_t val;
00485 val = (uint64_t)get_le32(s);
00486 val |= (uint64_t)get_le32(s) << 32;
00487 return val;
00488 }
00489
00490 unsigned int get_be16(ByteIOContext *s)
00491 {
00492 unsigned int val;
00493 val = get_byte(s) << 8;
00494 val |= get_byte(s);
00495 return val;
00496 }
00497
00498 unsigned int get_be24(ByteIOContext *s)
00499 {
00500 unsigned int val;
00501 val = get_be16(s) << 8;
00502 val |= get_byte(s);
00503 return val;
00504 }
00505 unsigned int get_be32(ByteIOContext *s)
00506 {
00507 unsigned int val;
00508 val = get_be16(s) << 16;
00509 val |= get_be16(s);
00510 return val;
00511 }
00512
00513 char *get_strz(ByteIOContext *s, char *buf, int maxlen)
00514 {
00515 int i = 0;
00516 char c;
00517
00518 while ((c = get_byte(s))) {
00519 if (i < maxlen-1)
00520 buf[i++] = c;
00521 }
00522
00523 buf[i] = 0;
00524
00525 return buf;
00526 }
00527
00528 uint64_t get_be64(ByteIOContext *s)
00529 {
00530 uint64_t val;
00531 val = (uint64_t)get_be32(s) << 32;
00532 val |= (uint64_t)get_be32(s);
00533 return val;
00534 }
00535
00536 uint64_t ff_get_v(ByteIOContext *bc){
00537 uint64_t val = 0;
00538 int tmp;
00539
00540 do{
00541 tmp = get_byte(bc);
00542 val= (val<<7) + (tmp&127);
00543 }while(tmp&128);
00544 return val;
00545 }
00546
00547 int url_fdopen(ByteIOContext **s, URLContext *h)
00548 {
00549 uint8_t *buffer;
00550 int buffer_size, max_packet_size;
00551
00552 max_packet_size = url_get_max_packet_size(h);
00553 if (max_packet_size) {
00554 buffer_size = max_packet_size;
00555 } else {
00556 buffer_size = IO_BUFFER_SIZE;
00557 }
00558 buffer = av_malloc(buffer_size);
00559 if (!buffer)
00560 return AVERROR(ENOMEM);
00561
00562 *s = av_mallocz(sizeof(ByteIOContext));
00563 if(!*s) {
00564 av_free(buffer);
00565 return AVERROR(ENOMEM);
00566 }
00567
00568 if (init_put_byte(*s, buffer, buffer_size,
00569 (h->flags & URL_WRONLY || h->flags & URL_RDWR), h,
00570 url_read, url_write, url_seek) < 0) {
00571 av_free(buffer);
00572 av_freep(s);
00573 return AVERROR(EIO);
00574 }
00575 (*s)->is_streamed = h->is_streamed;
00576 (*s)->max_packet_size = max_packet_size;
00577 if(h->prot) {
00578 (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause;
00579 (*s)->read_seek = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek;
00580 }
00581 return 0;
00582 }
00583
00584 int url_setbufsize(ByteIOContext *s, int buf_size)
00585 {
00586 uint8_t *buffer;
00587 buffer = av_malloc(buf_size);
00588 if (!buffer)
00589 return AVERROR(ENOMEM);
00590
00591 av_free(s->buffer);
00592 s->buffer = buffer;
00593 s->buffer_size = buf_size;
00594 s->buf_ptr = buffer;
00595 url_resetbuf(s, s->write_flag ? URL_WRONLY : URL_RDONLY);
00596 return 0;
00597 }
00598
00599 #if LIBAVFORMAT_VERSION_MAJOR < 53
00600 int url_resetbuf(ByteIOContext *s, int flags)
00601 #else
00602 static int url_resetbuf(ByteIOContext *s, int flags)
00603 #endif
00604 {
00605 #if LIBAVFORMAT_VERSION_MAJOR < 53
00606 URLContext *h = s->opaque;
00607 if ((flags & URL_RDWR) || (h && h->flags != flags && !h->flags & URL_RDWR))
00608 return AVERROR(EINVAL);
00609 #else
00610 assert(flags == URL_WRONLY || flags == URL_RDONLY);
00611 #endif
00612
00613 if (flags & URL_WRONLY) {
00614 s->buf_end = s->buffer + s->buffer_size;
00615 s->write_flag = 1;
00616 } else {
00617 s->buf_end = s->buffer;
00618 s->write_flag = 0;
00619 }
00620 return 0;
00621 }
00622
00623 int ff_rewind_with_probe_data(ByteIOContext *s, unsigned char *buf, int buf_size)
00624 {
00625 int64_t buffer_start;
00626 int buffer_size;
00627 int overlap, new_size;
00628
00629 if (s->write_flag)
00630 return AVERROR(EINVAL);
00631
00632 buffer_size = s->buf_end - s->buffer;
00633
00634
00635 if ((buffer_start = s->pos - buffer_size) > buf_size)
00636 return AVERROR(EINVAL);
00637
00638 overlap = buf_size - buffer_start;
00639 new_size = buf_size + buffer_size - overlap;
00640
00641 if (new_size > buf_size) {
00642 if (!(buf = av_realloc(buf, new_size)))
00643 return AVERROR(ENOMEM);
00644
00645 memcpy(buf + buf_size, s->buffer + overlap, buffer_size - overlap);
00646 buf_size = new_size;
00647 }
00648
00649 av_free(s->buffer);
00650 s->buf_ptr = s->buffer = buf;
00651 s->pos = s->buffer_size = buf_size;
00652 s->buf_end = s->buf_ptr + buf_size;
00653 s->eof_reached = 0;
00654 s->must_flush = 0;
00655
00656 return 0;
00657 }
00658
00659 int url_fopen(ByteIOContext **s, const char *filename, int flags)
00660 {
00661 URLContext *h;
00662 int err;
00663
00664 err = url_open(&h, filename, flags);
00665 if (err < 0)
00666 return err;
00667 err = url_fdopen(s, h);
00668 if (err < 0) {
00669 url_close(h);
00670 return err;
00671 }
00672 return 0;
00673 }
00674
00675 int url_fclose(ByteIOContext *s)
00676 {
00677 URLContext *h = s->opaque;
00678
00679 av_free(s->buffer);
00680 av_free(s);
00681 return url_close(h);
00682 }
00683
00684 URLContext *url_fileno(ByteIOContext *s)
00685 {
00686 return s->opaque;
00687 }
00688
00689 #if CONFIG_MUXERS
00690 int url_fprintf(ByteIOContext *s, const char *fmt, ...)
00691 {
00692 va_list ap;
00693 char buf[4096];
00694 int ret;
00695
00696 va_start(ap, fmt);
00697 ret = vsnprintf(buf, sizeof(buf), fmt, ap);
00698 va_end(ap);
00699 put_buffer(s, buf, strlen(buf));
00700 return ret;
00701 }
00702 #endif //CONFIG_MUXERS
00703
00704 char *url_fgets(ByteIOContext *s, char *buf, int buf_size)
00705 {
00706 int c;
00707 char *q;
00708
00709 c = url_fgetc(s);
00710 if (c == EOF)
00711 return NULL;
00712 q = buf;
00713 for(;;) {
00714 if (c == EOF || c == '\n')
00715 break;
00716 if ((q - buf) < buf_size - 1)
00717 *q++ = c;
00718 c = url_fgetc(s);
00719 }
00720 if (buf_size > 0)
00721 *q = '\0';
00722 return buf;
00723 }
00724
00725 int url_fget_max_packet_size(ByteIOContext *s)
00726 {
00727 return s->max_packet_size;
00728 }
00729
00730 int av_url_read_fpause(ByteIOContext *s, int pause)
00731 {
00732 if (!s->read_pause)
00733 return AVERROR(ENOSYS);
00734 return s->read_pause(s->opaque, pause);
00735 }
00736
00737 int64_t av_url_read_fseek(ByteIOContext *s, int stream_index,
00738 int64_t timestamp, int flags)
00739 {
00740 URLContext *h = s->opaque;
00741 int64_t ret;
00742 if (!s->read_seek)
00743 return AVERROR(ENOSYS);
00744 ret = s->read_seek(h, stream_index, timestamp, flags);
00745 if(ret >= 0) {
00746 int64_t pos;
00747 s->buf_ptr = s->buf_end;
00748 pos = s->seek(h, 0, SEEK_CUR);
00749 if (pos >= 0)
00750 s->pos = pos;
00751 else if (pos != AVERROR(ENOSYS))
00752 ret = pos;
00753 }
00754 return ret;
00755 }
00756
00757
00758
00759 #if CONFIG_MUXERS || CONFIG_NETWORK
00760
00761 int url_open_buf(ByteIOContext **s, uint8_t *buf, int buf_size, int flags)
00762 {
00763 int ret;
00764 *s = av_mallocz(sizeof(ByteIOContext));
00765 if(!*s)
00766 return AVERROR(ENOMEM);
00767 ret = init_put_byte(*s, buf, buf_size,
00768 (flags & URL_WRONLY || flags & URL_RDWR),
00769 NULL, NULL, NULL, NULL);
00770 if(ret != 0)
00771 av_freep(s);
00772 return ret;
00773 }
00774
00775 int url_close_buf(ByteIOContext *s)
00776 {
00777 put_flush_packet(s);
00778 return s->buf_ptr - s->buffer;
00779 }
00780
00781
00782
00783 typedef struct DynBuffer {
00784 int pos, size, allocated_size;
00785 uint8_t *buffer;
00786 int io_buffer_size;
00787 uint8_t io_buffer[1];
00788 } DynBuffer;
00789
00790 static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size)
00791 {
00792 DynBuffer *d = opaque;
00793 unsigned new_size, new_allocated_size;
00794
00795
00796 new_size = d->pos + buf_size;
00797 new_allocated_size = d->allocated_size;
00798 if(new_size < d->pos || new_size > INT_MAX/2)
00799 return -1;
00800 while (new_size > new_allocated_size) {
00801 if (!new_allocated_size)
00802 new_allocated_size = new_size;
00803 else
00804 new_allocated_size += new_allocated_size / 2 + 1;
00805 }
00806
00807 if (new_allocated_size > d->allocated_size) {
00808 d->buffer = av_realloc(d->buffer, new_allocated_size);
00809 if(d->buffer == NULL)
00810 return AVERROR(ENOMEM);
00811 d->allocated_size = new_allocated_size;
00812 }
00813 memcpy(d->buffer + d->pos, buf, buf_size);
00814 d->pos = new_size;
00815 if (d->pos > d->size)
00816 d->size = d->pos;
00817 return buf_size;
00818 }
00819
00820 static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size)
00821 {
00822 unsigned char buf1[4];
00823 int ret;
00824
00825
00826 AV_WB32(buf1, buf_size);
00827 ret= dyn_buf_write(opaque, buf1, 4);
00828 if(ret < 0)
00829 return ret;
00830
00831
00832 return dyn_buf_write(opaque, buf, buf_size);
00833 }
00834
00835 static int64_t dyn_buf_seek(void *opaque, int64_t offset, int whence)
00836 {
00837 DynBuffer *d = opaque;
00838
00839 if (whence == SEEK_CUR)
00840 offset += d->pos;
00841 else if (whence == SEEK_END)
00842 offset += d->size;
00843 if (offset < 0 || offset > 0x7fffffffLL)
00844 return -1;
00845 d->pos = offset;
00846 return 0;
00847 }
00848
00849 static int url_open_dyn_buf_internal(ByteIOContext **s, int max_packet_size)
00850 {
00851 DynBuffer *d;
00852 int ret;
00853 unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024;
00854
00855 if(sizeof(DynBuffer) + io_buffer_size < io_buffer_size)
00856 return -1;
00857 d = av_mallocz(sizeof(DynBuffer) + io_buffer_size);
00858 if (!d)
00859 return AVERROR(ENOMEM);
00860 *s = av_mallocz(sizeof(ByteIOContext));
00861 if(!*s) {
00862 av_free(d);
00863 return AVERROR(ENOMEM);
00864 }
00865 d->io_buffer_size = io_buffer_size;
00866 ret = init_put_byte(*s, d->io_buffer, io_buffer_size,
00867 1, d, NULL,
00868 max_packet_size ? dyn_packet_buf_write : dyn_buf_write,
00869 max_packet_size ? NULL : dyn_buf_seek);
00870 if (ret == 0) {
00871 (*s)->max_packet_size = max_packet_size;
00872 } else {
00873 av_free(d);
00874 av_freep(s);
00875 }
00876 return ret;
00877 }
00878
00879 int url_open_dyn_buf(ByteIOContext **s)
00880 {
00881 return url_open_dyn_buf_internal(s, 0);
00882 }
00883
00884 int url_open_dyn_packet_buf(ByteIOContext **s, int max_packet_size)
00885 {
00886 if (max_packet_size <= 0)
00887 return -1;
00888 return url_open_dyn_buf_internal(s, max_packet_size);
00889 }
00890
00891 int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer)
00892 {
00893 DynBuffer *d = s->opaque;
00894 int size;
00895
00896 put_flush_packet(s);
00897
00898 *pbuffer = d->buffer;
00899 size = d->size;
00900 av_free(d);
00901 av_free(s);
00902 return size;
00903 }
00904 #endif