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