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