• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavformat/aviobuf.c

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