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