]> git.sesse.net Git - ffmpeg/blob - libavformat/aviobuf.c
Merge remote-tracking branch 'newdev/master'
[ffmpeg] / libavformat / aviobuf.c
1 /*
2  * Buffered I/O for ffmpeg system
3  * Copyright (c) 2000,2001 Fabrice Bellard
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include "libavutil/crc.h"
23 #include "libavutil/intreadwrite.h"
24 #include "avformat.h"
25 #include "avio.h"
26 #include "avio_internal.h"
27 #include "internal.h"
28 #include <stdarg.h>
29
30 #define IO_BUFFER_SIZE 32768
31
32 /**
33  * Do seeks within this distance ahead of the current buffer by skipping
34  * data instead of calling the protocol seek function, for seekable
35  * protocols.
36  */
37 #define SHORT_SEEK_THRESHOLD 4096
38
39 static void fill_buffer(AVIOContext *s);
40 #if !FF_API_URL_RESETBUF
41 static int url_resetbuf(AVIOContext *s, int flags);
42 #endif
43
44 int ffio_init_context(AVIOContext *s,
45                   unsigned char *buffer,
46                   int buffer_size,
47                   int write_flag,
48                   void *opaque,
49                   int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
50                   int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
51                   int64_t (*seek)(void *opaque, int64_t offset, int whence))
52 {
53     s->buffer = buffer;
54     s->buffer_size = buffer_size;
55     s->buf_ptr = buffer;
56     s->opaque = opaque;
57     url_resetbuf(s, write_flag ? URL_WRONLY : URL_RDONLY);
58     s->write_packet = write_packet;
59     s->read_packet = read_packet;
60     s->seek = seek;
61     s->pos = 0;
62     s->must_flush = 0;
63     s->eof_reached = 0;
64     s->error = 0;
65     s->is_streamed = 0;
66     s->max_packet_size = 0;
67     s->update_checksum= NULL;
68     if(!read_packet && !write_flag){
69         s->pos = buffer_size;
70         s->buf_end = s->buffer + buffer_size;
71     }
72     s->read_pause = NULL;
73     s->read_seek  = NULL;
74     return 0;
75 }
76
77 #if FF_API_OLD_AVIO
78 int init_put_byte(AVIOContext *s,
79                   unsigned char *buffer,
80                   int buffer_size,
81                   int write_flag,
82                   void *opaque,
83                   int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
84                   int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
85                   int64_t (*seek)(void *opaque, int64_t offset, int whence))
86 {
87     return ffio_init_context(s, buffer, buffer_size, write_flag, opaque,
88                                 read_packet, write_packet, seek);
89 }
90 AVIOContext *av_alloc_put_byte(
91                   unsigned char *buffer,
92                   int buffer_size,
93                   int write_flag,
94                   void *opaque,
95                   int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
96                   int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
97                   int64_t (*seek)(void *opaque, int64_t offset, int whence))
98 {
99     return avio_alloc_context(buffer, buffer_size, write_flag, opaque,
100                               read_packet, write_packet, seek);
101 }
102 #endif
103
104 AVIOContext *avio_alloc_context(
105                   unsigned char *buffer,
106                   int buffer_size,
107                   int write_flag,
108                   void *opaque,
109                   int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
110                   int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
111                   int64_t (*seek)(void *opaque, int64_t offset, int whence))
112 {
113     AVIOContext *s = av_mallocz(sizeof(AVIOContext));
114     ffio_init_context(s, buffer, buffer_size, write_flag, opaque,
115                   read_packet, write_packet, seek);
116     return s;
117 }
118
119 static void flush_buffer(AVIOContext *s)
120 {
121     if (s->buf_ptr > s->buffer) {
122         if (s->write_packet && !s->error){
123             int ret= s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer);
124             if(ret < 0){
125                 s->error = ret;
126             }
127         }
128         if(s->update_checksum){
129             s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
130             s->checksum_ptr= s->buffer;
131         }
132         s->pos += s->buf_ptr - s->buffer;
133     }
134     s->buf_ptr = s->buffer;
135 }
136
137 void avio_w8(AVIOContext *s, int b)
138 {
139     *(s->buf_ptr)++ = b;
140     if (s->buf_ptr >= s->buf_end)
141         flush_buffer(s);
142 }
143
144 void ffio_fill(AVIOContext *s, int b, int count)
145 {
146     while (count > 0) {
147         int len = FFMIN(s->buf_end - s->buf_ptr, count);
148         memset(s->buf_ptr, b, len);
149         s->buf_ptr += len;
150
151         if (s->buf_ptr >= s->buf_end)
152             flush_buffer(s);
153
154         count -= len;
155     }
156 }
157
158 void avio_write(AVIOContext *s, const unsigned char *buf, int size)
159 {
160     while (size > 0) {
161         int len = FFMIN(s->buf_end - s->buf_ptr, size);
162         memcpy(s->buf_ptr, buf, len);
163         s->buf_ptr += len;
164
165         if (s->buf_ptr >= s->buf_end)
166             flush_buffer(s);
167
168         buf += len;
169         size -= len;
170     }
171 }
172
173 void avio_flush(AVIOContext *s)
174 {
175     flush_buffer(s);
176     s->must_flush = 0;
177 }
178
179 int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
180 {
181     int64_t offset1;
182     int64_t pos;
183     int force = whence & AVSEEK_FORCE;
184     whence &= ~AVSEEK_FORCE;
185
186     if(!s)
187         return AVERROR(EINVAL);
188
189     pos = s->pos - (s->write_flag ? 0 : (s->buf_end - s->buffer));
190
191     if (whence != SEEK_CUR && whence != SEEK_SET)
192         return AVERROR(EINVAL);
193
194     if (whence == SEEK_CUR) {
195         offset1 = pos + (s->buf_ptr - s->buffer);
196         if (offset == 0)
197             return offset1;
198         offset += offset1;
199     }
200     offset1 = offset - pos;
201     if (!s->must_flush &&
202         offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) {
203         /* can do the seek inside the buffer */
204         s->buf_ptr = s->buffer + offset1;
205     } else if ((s->is_streamed ||
206                offset1 <= s->buf_end + SHORT_SEEK_THRESHOLD - s->buffer) &&
207                !s->write_flag && offset1 >= 0 &&
208               (whence != SEEK_END || force)) {
209         while(s->pos < offset && !s->eof_reached)
210             fill_buffer(s);
211         if (s->eof_reached)
212             return AVERROR_EOF;
213         s->buf_ptr = s->buf_end + offset - s->pos;
214     } else {
215         int64_t res;
216
217 #if CONFIG_MUXERS || CONFIG_NETWORK
218         if (s->write_flag) {
219             flush_buffer(s);
220             s->must_flush = 1;
221         }
222 #endif /* CONFIG_MUXERS || CONFIG_NETWORK */
223         if (!s->seek)
224             return AVERROR(EPIPE);
225         if ((res = s->seek(s->opaque, offset, SEEK_SET)) < 0)
226             return res;
227         if (!s->write_flag)
228             s->buf_end = s->buffer;
229         s->buf_ptr = s->buffer;
230         s->pos = offset;
231     }
232     s->eof_reached = 0;
233     return offset;
234 }
235
236 int64_t avio_skip(AVIOContext *s, int64_t offset)
237 {
238     return avio_seek(s, offset, SEEK_CUR);
239 }
240
241 #if FF_API_OLD_AVIO
242 int url_fskip(AVIOContext *s, int64_t offset)
243 {
244     int64_t ret = avio_seek(s, offset, SEEK_CUR);
245     return ret < 0 ? ret : 0;
246 }
247
248 int64_t url_ftell(AVIOContext *s)
249 {
250     return avio_seek(s, 0, SEEK_CUR);
251 }
252 #endif
253
254 int64_t avio_size(AVIOContext *s)
255 {
256     int64_t size;
257
258     if(!s)
259         return AVERROR(EINVAL);
260
261     if (!s->seek)
262         return AVERROR(ENOSYS);
263     size = s->seek(s->opaque, 0, AVSEEK_SIZE);
264     if(size<0){
265         if ((size = s->seek(s->opaque, -1, SEEK_END)) < 0)
266             return size;
267         size++;
268         s->seek(s->opaque, s->pos, SEEK_SET);
269     }
270     return size;
271 }
272
273 int url_feof(AVIOContext *s)
274 {
275     if(!s)
276         return 0;
277     if(s->eof_reached){
278         s->eof_reached=0;
279         fill_buffer(s);
280     }
281     return s->eof_reached;
282 }
283
284 #if FF_API_OLD_AVIO
285 int url_ferror(AVIOContext *s)
286 {
287     if(!s)
288         return 0;
289     return s->error;
290 }
291 #endif
292
293 void avio_wl32(AVIOContext *s, unsigned int val)
294 {
295     avio_w8(s, val);
296     avio_w8(s, val >> 8);
297     avio_w8(s, val >> 16);
298     avio_w8(s, val >> 24);
299 }
300
301 void avio_wb32(AVIOContext *s, unsigned int val)
302 {
303     avio_w8(s, val >> 24);
304     avio_w8(s, val >> 16);
305     avio_w8(s, val >> 8);
306     avio_w8(s, val);
307 }
308
309 #if FF_API_OLD_AVIO
310 void put_strz(AVIOContext *s, const char *str)
311 {
312     avio_put_str(s, str);
313 }
314
315 #define GET(name, type) \
316     type get_be ##name(AVIOContext *s) \
317 {\
318     return avio_rb ##name(s);\
319 }\
320     type get_le ##name(AVIOContext *s) \
321 {\
322     return avio_rl ##name(s);\
323 }
324
325 GET(16, unsigned int)
326 GET(24, unsigned int)
327 GET(32, unsigned int)
328 GET(64, uint64_t)
329
330 #undef GET
331
332 #define PUT(name, type ) \
333     void put_le ##name(AVIOContext *s, type val)\
334 {\
335         avio_wl ##name(s, val);\
336 }\
337     void put_be ##name(AVIOContext *s, type val)\
338 {\
339         avio_wb ##name(s, val);\
340 }
341
342 PUT(16, unsigned int)
343 PUT(24, unsigned int)
344 PUT(32, unsigned int)
345 PUT(64, uint64_t)
346 #undef PUT
347
348 int get_byte(AVIOContext *s)
349 {
350    return avio_r8(s);
351 }
352 int get_buffer(AVIOContext *s, unsigned char *buf, int size)
353 {
354     return avio_read(s, buf, size);
355 }
356 int get_partial_buffer(AVIOContext *s, unsigned char *buf, int size)
357 {
358     return ffio_read_partial(s, buf, size);
359 }
360 void put_byte(AVIOContext *s, int val)
361 {
362     avio_w8(s, val);
363 }
364 void put_buffer(AVIOContext *s, const unsigned char *buf, int size)
365 {
366     avio_write(s, buf, size);
367 }
368 void put_nbyte(AVIOContext *s, int b, int count)
369 {
370     ffio_fill(s, b, count);
371 }
372
373 int url_fopen(AVIOContext **s, const char *filename, int flags)
374 {
375     return avio_open(s, filename, flags);
376 }
377 int url_fclose(AVIOContext *s)
378 {
379     return avio_close(s);
380 }
381 int64_t url_fseek(AVIOContext *s, int64_t offset, int whence)
382 {
383     return avio_seek(s, offset, whence);
384 }
385 int64_t url_fsize(AVIOContext *s)
386 {
387     return avio_size(s);
388 }
389 int url_setbufsize(AVIOContext *s, int buf_size)
390 {
391     return ffio_set_buf_size(s, buf_size);
392 }
393 int url_fprintf(AVIOContext *s, const char *fmt, ...)
394 {
395     va_list ap;
396     char buf[4096];
397     int ret;
398
399     va_start(ap, fmt);
400     ret = vsnprintf(buf, sizeof(buf), fmt, ap);
401     va_end(ap);
402     avio_write(s, buf, strlen(buf));
403     return ret;
404 }
405 void put_flush_packet(AVIOContext *s)
406 {
407     avio_flush(s);
408 }
409 int av_url_read_fpause(AVIOContext *s, int pause)
410 {
411     return ffio_read_pause(s, pause);
412 }
413 int64_t av_url_read_fseek(AVIOContext *s, int stream_index,
414                          int64_t timestamp, int flags)
415 {
416     return ffio_read_seek(s, stream_index, timestamp, flags);
417 }
418 void init_checksum(AVIOContext *s,
419                    unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len),
420                    unsigned long checksum)
421 {
422     ffio_init_checksum(s, update_checksum, checksum);
423 }
424 unsigned long get_checksum(AVIOContext *s)
425 {
426     return ffio_get_checksum(s);
427 }
428 #endif
429
430 int avio_put_str(AVIOContext *s, const char *str)
431 {
432     int len = 1;
433     if (str) {
434         len += strlen(str);
435         avio_write(s, (const unsigned char *) str, len);
436     } else
437         avio_w8(s, 0);
438     return len;
439 }
440
441 int avio_put_str16le(AVIOContext *s, const char *str)
442 {
443     const uint8_t *q = str;
444     int ret = 0;
445
446     while (*q) {
447         uint32_t ch;
448         uint16_t tmp;
449
450         GET_UTF8(ch, *q++, break;)
451         PUT_UTF16(ch, tmp, avio_wl16(s, tmp);ret += 2;)
452     }
453     avio_wl16(s, 0);
454     ret += 2;
455     return ret;
456 }
457
458 int ff_get_v_length(uint64_t val){
459     int i=1;
460
461     while(val>>=7)
462         i++;
463
464     return i;
465 }
466
467 void ff_put_v(AVIOContext *bc, uint64_t val){
468     int i= ff_get_v_length(val);
469
470     while(--i>0)
471         avio_w8(bc, 128 | (val>>(7*i)));
472
473     avio_w8(bc, val&127);
474 }
475
476 void avio_wl64(AVIOContext *s, uint64_t val)
477 {
478     avio_wl32(s, (uint32_t)(val & 0xffffffff));
479     avio_wl32(s, (uint32_t)(val >> 32));
480 }
481
482 void avio_wb64(AVIOContext *s, uint64_t val)
483 {
484     avio_wb32(s, (uint32_t)(val >> 32));
485     avio_wb32(s, (uint32_t)(val & 0xffffffff));
486 }
487
488 void avio_wl16(AVIOContext *s, unsigned int val)
489 {
490     avio_w8(s, val);
491     avio_w8(s, val >> 8);
492 }
493
494 void avio_wb16(AVIOContext *s, unsigned int val)
495 {
496     avio_w8(s, val >> 8);
497     avio_w8(s, val);
498 }
499
500 void avio_wl24(AVIOContext *s, unsigned int val)
501 {
502     avio_wl16(s, val & 0xffff);
503     avio_w8(s, val >> 16);
504 }
505
506 void avio_wb24(AVIOContext *s, unsigned int val)
507 {
508     avio_wb16(s, val >> 8);
509     avio_w8(s, val);
510 }
511
512 #if FF_API_OLD_AVIO
513 void put_tag(AVIOContext *s, const char *tag)
514 {
515     while (*tag) {
516         avio_w8(s, *tag++);
517     }
518 }
519 #endif
520
521 /* Input stream */
522
523 static void fill_buffer(AVIOContext *s)
524 {
525     uint8_t *dst= !s->max_packet_size && s->buf_end - s->buffer < s->buffer_size ? s->buf_end : s->buffer;
526     int len= s->buffer_size - (dst - s->buffer);
527     int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE;
528
529     /* no need to do anything if EOF already reached */
530     if (s->eof_reached)
531         return;
532
533     if(s->update_checksum && dst == s->buffer){
534         if(s->buf_end > s->checksum_ptr)
535             s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr);
536         s->checksum_ptr= s->buffer;
537     }
538
539     /* make buffer smaller in case it ended up large after probing */
540     if (s->buffer_size > max_buffer_size) {
541         ffio_set_buf_size(s, max_buffer_size);
542
543         s->checksum_ptr = dst = s->buffer;
544         len = s->buffer_size;
545     }
546
547     if(s->read_packet)
548         len = s->read_packet(s->opaque, dst, len);
549     else
550         len = 0;
551     if (len <= 0) {
552         /* do not modify buffer if EOF reached so that a seek back can
553            be done without rereading data */
554         s->eof_reached = 1;
555         if(len<0)
556             s->error= len;
557     } else {
558         s->pos += len;
559         s->buf_ptr = dst;
560         s->buf_end = dst + len;
561     }
562 }
563
564 unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf,
565                                     unsigned int len)
566 {
567     return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len);
568 }
569
570 unsigned long ffio_get_checksum(AVIOContext *s)
571 {
572     s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
573     s->update_checksum= NULL;
574     return s->checksum;
575 }
576
577 void ffio_init_checksum(AVIOContext *s,
578                    unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len),
579                    unsigned long checksum)
580 {
581     s->update_checksum= update_checksum;
582     if(s->update_checksum){
583         s->checksum= checksum;
584         s->checksum_ptr= s->buf_ptr;
585     }
586 }
587
588 /* XXX: put an inline version */
589 int avio_r8(AVIOContext *s)
590 {
591     if (s->buf_ptr >= s->buf_end)
592         fill_buffer(s);
593     if (s->buf_ptr < s->buf_end)
594         return *s->buf_ptr++;
595     return 0;
596 }
597
598 #if FF_API_OLD_AVIO
599 int url_fgetc(AVIOContext *s)
600 {
601     if (s->buf_ptr >= s->buf_end)
602         fill_buffer(s);
603     if (s->buf_ptr < s->buf_end)
604         return *s->buf_ptr++;
605     return URL_EOF;
606 }
607 #endif
608
609 int avio_read(AVIOContext *s, unsigned char *buf, int size)
610 {
611     int len, size1;
612
613     size1 = size;
614     while (size > 0) {
615         len = s->buf_end - s->buf_ptr;
616         if (len > size)
617             len = size;
618         if (len == 0) {
619             if(size > s->buffer_size && !s->update_checksum){
620                 if(s->read_packet)
621                     len = s->read_packet(s->opaque, buf, size);
622                 if (len <= 0) {
623                     /* do not modify buffer if EOF reached so that a seek back can
624                     be done without rereading data */
625                     s->eof_reached = 1;
626                     if(len<0)
627                         s->error= len;
628                     break;
629                 } else {
630                     s->pos += len;
631                     size -= len;
632                     buf += len;
633                     s->buf_ptr = s->buffer;
634                     s->buf_end = s->buffer/* + len*/;
635                 }
636             }else{
637                 fill_buffer(s);
638                 len = s->buf_end - s->buf_ptr;
639                 if (len == 0)
640                     break;
641             }
642         } else {
643             memcpy(buf, s->buf_ptr, len);
644             buf += len;
645             s->buf_ptr += len;
646             size -= len;
647         }
648     }
649     if (size1 == size) {
650         if (s->error)      return s->error;
651         if (url_feof(s))   return AVERROR_EOF;
652     }
653     return size1 - size;
654 }
655
656 int ffio_read_partial(AVIOContext *s, unsigned char *buf, int size)
657 {
658     int len;
659
660     if(size<0)
661         return -1;
662
663     len = s->buf_end - s->buf_ptr;
664     if (len == 0) {
665         fill_buffer(s);
666         len = s->buf_end - s->buf_ptr;
667     }
668     if (len > size)
669         len = size;
670     memcpy(buf, s->buf_ptr, len);
671     s->buf_ptr += len;
672     if (!len) {
673         if (s->error)      return s->error;
674         if (url_feof(s))   return AVERROR_EOF;
675     }
676     return len;
677 }
678
679 unsigned int avio_rl16(AVIOContext *s)
680 {
681     unsigned int val;
682     val = avio_r8(s);
683     val |= avio_r8(s) << 8;
684     return val;
685 }
686
687 unsigned int avio_rl24(AVIOContext *s)
688 {
689     unsigned int val;
690     val = avio_rl16(s);
691     val |= avio_r8(s) << 16;
692     return val;
693 }
694
695 unsigned int avio_rl32(AVIOContext *s)
696 {
697     unsigned int val;
698     val = avio_rl16(s);
699     val |= avio_rl16(s) << 16;
700     return val;
701 }
702
703 uint64_t avio_rl64(AVIOContext *s)
704 {
705     uint64_t val;
706     val = (uint64_t)avio_rl32(s);
707     val |= (uint64_t)avio_rl32(s) << 32;
708     return val;
709 }
710
711 unsigned int avio_rb16(AVIOContext *s)
712 {
713     unsigned int val;
714     val = avio_r8(s) << 8;
715     val |= avio_r8(s);
716     return val;
717 }
718
719 unsigned int avio_rb24(AVIOContext *s)
720 {
721     unsigned int val;
722     val = avio_rb16(s) << 8;
723     val |= avio_r8(s);
724     return val;
725 }
726 unsigned int avio_rb32(AVIOContext *s)
727 {
728     unsigned int val;
729     val = avio_rb16(s) << 16;
730     val |= avio_rb16(s);
731     return val;
732 }
733
734 #if FF_API_OLD_AVIO
735 char *get_strz(AVIOContext *s, char *buf, int maxlen)
736 {
737     avio_get_str(s, INT_MAX, buf, maxlen);
738     return buf;
739 }
740 #endif
741
742 int ff_get_line(AVIOContext *s, char *buf, int maxlen)
743 {
744     int i = 0;
745     char c;
746
747     do {
748         c = avio_r8(s);
749         if (c && i < maxlen-1)
750             buf[i++] = c;
751     } while (c != '\n' && c);
752
753     buf[i] = 0;
754     return i;
755 }
756
757 int avio_get_str(AVIOContext *s, int maxlen, char *buf, int buflen)
758 {
759     int i;
760
761     // reserve 1 byte for terminating 0
762     buflen = FFMIN(buflen - 1, maxlen);
763     for (i = 0; i < buflen; i++)
764         if (!(buf[i] = avio_r8(s)))
765             return i + 1;
766     if (buflen)
767         buf[i] = 0;
768     for (; i < maxlen; i++)
769         if (!avio_r8(s))
770             return i + 1;
771     return maxlen;
772 }
773
774 #define GET_STR16(type, read) \
775     int avio_get_str16 ##type(AVIOContext *pb, int maxlen, char *buf, int buflen)\
776 {\
777     char* q = buf;\
778     int ret = 0;\
779     while (ret + 1 < maxlen) {\
780         uint8_t tmp;\
781         uint32_t ch;\
782         GET_UTF16(ch, (ret += 2) <= maxlen ? read(pb) : 0, break;)\
783         if (!ch)\
784             break;\
785         PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;)\
786     }\
787     *q = 0;\
788     return ret;\
789 }\
790
791 GET_STR16(le, avio_rl16)
792 GET_STR16(be, avio_rb16)
793
794 #undef GET_STR16
795
796 uint64_t avio_rb64(AVIOContext *s)
797 {
798     uint64_t val;
799     val = (uint64_t)avio_rb32(s) << 32;
800     val |= (uint64_t)avio_rb32(s);
801     return val;
802 }
803
804 uint64_t ffio_read_varlen(AVIOContext *bc){
805     uint64_t val = 0;
806     int tmp;
807
808     do{
809         tmp = avio_r8(bc);
810         val= (val<<7) + (tmp&127);
811     }while(tmp&128);
812     return val;
813 }
814
815 int url_fdopen(AVIOContext **s, URLContext *h)
816 {
817     uint8_t *buffer;
818     int buffer_size, max_packet_size;
819
820     max_packet_size = url_get_max_packet_size(h);
821     if (max_packet_size) {
822         buffer_size = max_packet_size; /* no need to bufferize more than one packet */
823     } else {
824         buffer_size = IO_BUFFER_SIZE;
825     }
826     buffer = av_malloc(buffer_size);
827     if (!buffer)
828         return AVERROR(ENOMEM);
829
830     *s = av_mallocz(sizeof(AVIOContext));
831     if(!*s) {
832         av_free(buffer);
833         return AVERROR(ENOMEM);
834     }
835
836     if (ffio_init_context(*s, buffer, buffer_size,
837                       (h->flags & URL_WRONLY || h->flags & URL_RDWR), h,
838                       url_read, url_write, url_seek) < 0) {
839         av_free(buffer);
840         av_freep(s);
841         return AVERROR(EIO);
842     }
843     (*s)->is_streamed = h->is_streamed;
844     (*s)->max_packet_size = max_packet_size;
845     if(h->prot) {
846         (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause;
847         (*s)->read_seek  = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek;
848     }
849     return 0;
850 }
851
852 int ffio_set_buf_size(AVIOContext *s, int buf_size)
853 {
854     uint8_t *buffer;
855     buffer = av_malloc(buf_size);
856     if (!buffer)
857         return AVERROR(ENOMEM);
858
859     av_free(s->buffer);
860     s->buffer = buffer;
861     s->buffer_size = buf_size;
862     s->buf_ptr = buffer;
863     url_resetbuf(s, s->write_flag ? URL_WRONLY : URL_RDONLY);
864     return 0;
865 }
866
867 #if FF_API_URL_RESETBUF
868 int url_resetbuf(AVIOContext *s, int flags)
869 #else
870 static int url_resetbuf(AVIOContext *s, int flags)
871 #endif
872 {
873 #if FF_API_URL_RESETBUF
874     if (flags & URL_RDWR)
875         return AVERROR(EINVAL);
876 #else
877     assert(flags == URL_WRONLY || flags == URL_RDONLY);
878 #endif
879
880     if (flags & URL_WRONLY) {
881         s->buf_end = s->buffer + s->buffer_size;
882         s->write_flag = 1;
883     } else {
884         s->buf_end = s->buffer;
885         s->write_flag = 0;
886     }
887     return 0;
888 }
889
890 int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char *buf, int buf_size)
891 {
892     int64_t buffer_start;
893     int buffer_size;
894     int overlap, new_size, alloc_size;
895
896     if (s->write_flag)
897         return AVERROR(EINVAL);
898
899     buffer_size = s->buf_end - s->buffer;
900
901     /* the buffers must touch or overlap */
902     if ((buffer_start = s->pos - buffer_size) > buf_size)
903         return AVERROR(EINVAL);
904
905     overlap = buf_size - buffer_start;
906     new_size = buf_size + buffer_size - overlap;
907
908     alloc_size = FFMAX(s->buffer_size, new_size);
909     if (alloc_size > buf_size)
910         if (!(buf = av_realloc(buf, alloc_size)))
911             return AVERROR(ENOMEM);
912
913     if (new_size > buf_size) {
914         memcpy(buf + buf_size, s->buffer + overlap, buffer_size - overlap);
915         buf_size = new_size;
916     }
917
918     av_free(s->buffer);
919     s->buf_ptr = s->buffer = buf;
920     s->buffer_size = alloc_size;
921     s->pos = buf_size;
922     s->buf_end = s->buf_ptr + buf_size;
923     s->eof_reached = 0;
924     s->must_flush = 0;
925
926     return 0;
927 }
928
929 int avio_open(AVIOContext **s, const char *filename, int flags)
930 {
931     URLContext *h;
932     int err;
933
934     err = url_open(&h, filename, flags);
935     if (err < 0)
936         return err;
937     err = url_fdopen(s, h);
938     if (err < 0) {
939         url_close(h);
940         return err;
941     }
942     return 0;
943 }
944
945 int avio_close(AVIOContext *s)
946 {
947     URLContext *h = s->opaque;
948
949     av_free(s->buffer);
950     av_free(s);
951     return url_close(h);
952 }
953
954 #if FF_API_OLD_AVIO
955 URLContext *url_fileno(AVIOContext *s)
956 {
957     return s->opaque;
958 }
959 #endif
960
961 int avio_printf(AVIOContext *s, const char *fmt, ...)
962 {
963     va_list ap;
964     char buf[4096];
965     int ret;
966
967     va_start(ap, fmt);
968     ret = vsnprintf(buf, sizeof(buf), fmt, ap);
969     va_end(ap);
970     avio_write(s, buf, strlen(buf));
971     return ret;
972 }
973
974 #if FF_API_OLD_AVIO
975 char *url_fgets(AVIOContext *s, char *buf, int buf_size)
976 {
977     int c;
978     char *q;
979
980     c = avio_r8(s);
981     if (url_feof(s))
982         return NULL;
983     q = buf;
984     for(;;) {
985         if (url_feof(s) || c == '\n')
986             break;
987         if ((q - buf) < buf_size - 1)
988             *q++ = c;
989         c = avio_r8(s);
990     }
991     if (buf_size > 0)
992         *q = '\0';
993     return buf;
994 }
995
996 int url_fget_max_packet_size(AVIOContext *s)
997 {
998     return s->max_packet_size;
999 }
1000 #endif
1001
1002 int ffio_read_pause(AVIOContext *s, int pause)
1003 {
1004     if (!s->read_pause)
1005         return AVERROR(ENOSYS);
1006     return s->read_pause(s->opaque, pause);
1007 }
1008
1009 int64_t ffio_read_seek(AVIOContext *s, int stream_index,
1010                        int64_t timestamp, int flags)
1011 {
1012     URLContext *h = s->opaque;
1013     int64_t ret;
1014     if (!s->read_seek)
1015         return AVERROR(ENOSYS);
1016     ret = s->read_seek(h, stream_index, timestamp, flags);
1017     if(ret >= 0) {
1018         int64_t pos;
1019         s->buf_ptr = s->buf_end; // Flush buffer
1020         pos = s->seek(h, 0, SEEK_CUR);
1021         if (pos >= 0)
1022             s->pos = pos;
1023         else if (pos != AVERROR(ENOSYS))
1024             ret = pos;
1025     }
1026     return ret;
1027 }
1028
1029 /* url_open_dyn_buf and url_close_dyn_buf are used in rtp.c to send a response
1030  * back to the server even if CONFIG_MUXERS is false. */
1031 #if CONFIG_MUXERS || CONFIG_NETWORK
1032 /* buffer handling */
1033 #if FF_API_OLD_AVIO
1034 int url_open_buf(AVIOContext **s, uint8_t *buf, int buf_size, int flags)
1035 {
1036     int ret;
1037     *s = av_mallocz(sizeof(AVIOContext));
1038     if(!*s)
1039         return AVERROR(ENOMEM);
1040     ret = ffio_init_context(*s, buf, buf_size,
1041                         (flags & URL_WRONLY || flags & URL_RDWR),
1042                         NULL, NULL, NULL, NULL);
1043     if(ret != 0)
1044         av_freep(s);
1045     return ret;
1046 }
1047
1048 int url_close_buf(AVIOContext *s)
1049 {
1050     avio_flush(s);
1051     return s->buf_ptr - s->buffer;
1052 }
1053 #endif
1054
1055 /* output in a dynamic buffer */
1056
1057 typedef struct DynBuffer {
1058     int pos, size, allocated_size;
1059     uint8_t *buffer;
1060     int io_buffer_size;
1061     uint8_t io_buffer[1];
1062 } DynBuffer;
1063
1064 static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size)
1065 {
1066     DynBuffer *d = opaque;
1067     unsigned new_size, new_allocated_size;
1068
1069     /* reallocate buffer if needed */
1070     new_size = d->pos + buf_size;
1071     new_allocated_size = d->allocated_size;
1072     if(new_size < d->pos || new_size > INT_MAX/2)
1073         return -1;
1074     while (new_size > new_allocated_size) {
1075         if (!new_allocated_size)
1076             new_allocated_size = new_size;
1077         else
1078             new_allocated_size += new_allocated_size / 2 + 1;
1079     }
1080
1081     if (new_allocated_size > d->allocated_size) {
1082         d->buffer = av_realloc(d->buffer, new_allocated_size);
1083         if(d->buffer == NULL)
1084              return AVERROR(ENOMEM);
1085         d->allocated_size = new_allocated_size;
1086     }
1087     memcpy(d->buffer + d->pos, buf, buf_size);
1088     d->pos = new_size;
1089     if (d->pos > d->size)
1090         d->size = d->pos;
1091     return buf_size;
1092 }
1093
1094 static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size)
1095 {
1096     unsigned char buf1[4];
1097     int ret;
1098
1099     /* packetized write: output the header */
1100     AV_WB32(buf1, buf_size);
1101     ret= dyn_buf_write(opaque, buf1, 4);
1102     if(ret < 0)
1103         return ret;
1104
1105     /* then the data */
1106     return dyn_buf_write(opaque, buf, buf_size);
1107 }
1108
1109 static int64_t dyn_buf_seek(void *opaque, int64_t offset, int whence)
1110 {
1111     DynBuffer *d = opaque;
1112
1113     if (whence == SEEK_CUR)
1114         offset += d->pos;
1115     else if (whence == SEEK_END)
1116         offset += d->size;
1117     if (offset < 0 || offset > 0x7fffffffLL)
1118         return -1;
1119     d->pos = offset;
1120     return 0;
1121 }
1122
1123 static int url_open_dyn_buf_internal(AVIOContext **s, int max_packet_size)
1124 {
1125     DynBuffer *d;
1126     int ret;
1127     unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024;
1128
1129     if(sizeof(DynBuffer) + io_buffer_size < io_buffer_size)
1130         return -1;
1131     d = av_mallocz(sizeof(DynBuffer) + io_buffer_size);
1132     if (!d)
1133         return AVERROR(ENOMEM);
1134     *s = av_mallocz(sizeof(AVIOContext));
1135     if(!*s) {
1136         av_free(d);
1137         return AVERROR(ENOMEM);
1138     }
1139     d->io_buffer_size = io_buffer_size;
1140     ret = ffio_init_context(*s, d->io_buffer, io_buffer_size,
1141                         1, d, NULL,
1142                         max_packet_size ? dyn_packet_buf_write : dyn_buf_write,
1143                         max_packet_size ? NULL : dyn_buf_seek);
1144     if (ret == 0) {
1145         (*s)->max_packet_size = max_packet_size;
1146     } else {
1147         av_free(d);
1148         av_freep(s);
1149     }
1150     return ret;
1151 }
1152
1153 int url_open_dyn_buf(AVIOContext **s)
1154 {
1155     return url_open_dyn_buf_internal(s, 0);
1156 }
1157
1158 int url_open_dyn_packet_buf(AVIOContext **s, int max_packet_size)
1159 {
1160     if (max_packet_size <= 0)
1161         return -1;
1162     return url_open_dyn_buf_internal(s, max_packet_size);
1163 }
1164
1165 int url_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
1166 {
1167     DynBuffer *d = s->opaque;
1168     int size;
1169     static const char padbuf[FF_INPUT_BUFFER_PADDING_SIZE] = {0};
1170     int padding = 0;
1171
1172     /* don't attempt to pad fixed-size packet buffers */
1173     if (!s->max_packet_size) {
1174         avio_write(s, padbuf, sizeof(padbuf));
1175         padding = FF_INPUT_BUFFER_PADDING_SIZE;
1176     }
1177
1178     avio_flush(s);
1179
1180     *pbuffer = d->buffer;
1181     size = d->size;
1182     av_free(d);
1183     av_free(s);
1184     return size - padding;
1185 }
1186 #endif /* CONFIG_MUXERS || CONFIG_NETWORK */