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

Generated on Fri Feb 22 2013 07:24:31 for FFmpeg by  doxygen 1.7.1