• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * buffered I/O
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/bprint.h"
23 #include "libavutil/crc.h"
24 #include "libavutil/dict.h"
25 #include "libavutil/internal.h"
26 #include "libavutil/intreadwrite.h"
27 #include "libavutil/log.h"
28 #include "libavutil/opt.h"
29 #include "libavutil/avassert.h"
30 #include "libavcodec/defs.h"
31 #include "avio.h"
32 #include "avio_internal.h"
33 #include "internal.h"
34 #include "url.h"
35 #include <stdarg.h>
36 
37 #define IO_BUFFER_SIZE 32768
38 
39 /**
40  * Do seeks within this distance ahead of the current buffer by skipping
41  * data instead of calling the protocol seek function, for seekable
42  * protocols.
43  */
44 #define SHORT_SEEK_THRESHOLD 32768
45 
ff_avio_child_next(void * obj,void * prev)46 static void *ff_avio_child_next(void *obj, void *prev)
47 {
48     AVIOContext *s = obj;
49     return prev ? NULL : s->opaque;
50 }
51 
child_class_iterate(void ** iter)52 static const AVClass *child_class_iterate(void **iter)
53 {
54     const AVClass *c = *iter ? NULL : &ffurl_context_class;
55     *iter = (void*)(uintptr_t)c;
56     return c;
57 }
58 
59 #define OFFSET(x) offsetof(AVIOContext,x)
60 #define E AV_OPT_FLAG_ENCODING_PARAM
61 #define D AV_OPT_FLAG_DECODING_PARAM
62 static const AVOption ff_avio_options[] = {
63     {"protocol_whitelist", "List of protocols that are allowed to be used", OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },  0, 0, D },
64     { NULL },
65 };
66 
67 const AVClass ff_avio_class = {
68     .class_name = "AVIOContext",
69     .item_name  = av_default_item_name,
70     .version    = LIBAVUTIL_VERSION_INT,
71     .option     = ff_avio_options,
72     .child_next = ff_avio_child_next,
73     .child_class_iterate = child_class_iterate,
74 };
75 
76 static void fill_buffer(AVIOContext *s);
77 static int url_resetbuf(AVIOContext *s, int flags);
78 /** @warning must be called before any I/O */
79 static int set_buf_size(AVIOContext *s, int buf_size);
80 
ffio_init_context(FFIOContext * ctx,unsigned char * buffer,int buffer_size,int write_flag,void * opaque,int (* read_packet)(void * opaque,uint8_t * buf,int buf_size),int (* write_packet)(void * opaque,uint8_t * buf,int buf_size),int64_t (* seek)(void * opaque,int64_t offset,int whence))81 void ffio_init_context(FFIOContext *ctx,
82                   unsigned char *buffer,
83                   int buffer_size,
84                   int write_flag,
85                   void *opaque,
86                   int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
87                   int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
88                   int64_t (*seek)(void *opaque, int64_t offset, int whence))
89 {
90     AVIOContext *const s = &ctx->pub;
91 
92     memset(ctx, 0, sizeof(*ctx));
93 
94     s->buffer      = buffer;
95     ctx->orig_buffer_size =
96     s->buffer_size = buffer_size;
97     s->buf_ptr     = buffer;
98     s->buf_ptr_max = buffer;
99     s->opaque      = opaque;
100     s->direct      = 0;
101 
102     url_resetbuf(s, write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ);
103 
104     s->write_packet    = write_packet;
105     s->read_packet     = read_packet;
106     s->seek            = seek;
107     s->pos             = 0;
108     s->eof_reached     = 0;
109     s->error           = 0;
110     s->seekable        = seek ? AVIO_SEEKABLE_NORMAL : 0;
111     s->min_packet_size = 0;
112     s->max_packet_size = 0;
113     s->update_checksum = NULL;
114     ctx->short_seek_threshold = SHORT_SEEK_THRESHOLD;
115 
116     if (!read_packet && !write_flag) {
117         s->pos     = buffer_size;
118         s->buf_end = s->buffer + buffer_size;
119     }
120     s->read_pause = NULL;
121     s->read_seek  = NULL;
122 
123     s->write_data_type       = NULL;
124     s->ignore_boundary_point = 0;
125     ctx->current_type        = AVIO_DATA_MARKER_UNKNOWN;
126     ctx->last_time           = AV_NOPTS_VALUE;
127     ctx->short_seek_get      = NULL;
128 #if FF_API_AVIOCONTEXT_WRITTEN
129 FF_DISABLE_DEPRECATION_WARNINGS
130     s->written               = 0;
131 FF_ENABLE_DEPRECATION_WARNINGS
132 #endif
133 }
134 
avio_alloc_context(unsigned char * buffer,int buffer_size,int write_flag,void * opaque,int (* read_packet)(void * opaque,uint8_t * buf,int buf_size),int (* write_packet)(void * opaque,uint8_t * buf,int buf_size),int64_t (* seek)(void * opaque,int64_t offset,int whence))135 AVIOContext *avio_alloc_context(
136                   unsigned char *buffer,
137                   int buffer_size,
138                   int write_flag,
139                   void *opaque,
140                   int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
141                   int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
142                   int64_t (*seek)(void *opaque, int64_t offset, int whence))
143 {
144     FFIOContext *s = av_malloc(sizeof(*s));
145     if (!s)
146         return NULL;
147     ffio_init_context(s, buffer, buffer_size, write_flag, opaque,
148                   read_packet, write_packet, seek);
149     return &s->pub;
150 }
151 
avio_context_free(AVIOContext ** ps)152 void avio_context_free(AVIOContext **ps)
153 {
154     av_freep(ps);
155 }
156 
writeout(AVIOContext * s,const uint8_t * data,int len)157 static void writeout(AVIOContext *s, const uint8_t *data, int len)
158 {
159     FFIOContext *const ctx = ffiocontext(s);
160     if (!s->error) {
161         int ret = 0;
162         if (s->write_data_type)
163             ret = s->write_data_type(s->opaque, (uint8_t *)data,
164                                      len,
165                                      ctx->current_type,
166                                      ctx->last_time);
167         else if (s->write_packet)
168             ret = s->write_packet(s->opaque, (uint8_t *)data, len);
169         if (ret < 0) {
170             s->error = ret;
171         } else {
172             ctx->bytes_written += len;
173             s->bytes_written = ctx->bytes_written;
174 
175             if (s->pos + len > ctx->written_output_size) {
176                 ctx->written_output_size = s->pos + len;
177 #if FF_API_AVIOCONTEXT_WRITTEN
178 FF_DISABLE_DEPRECATION_WARNINGS
179                 s->written = ctx->written_output_size;
180 FF_ENABLE_DEPRECATION_WARNINGS
181 #endif
182             }
183         }
184     }
185     if (ctx->current_type == AVIO_DATA_MARKER_SYNC_POINT ||
186         ctx->current_type == AVIO_DATA_MARKER_BOUNDARY_POINT) {
187         ctx->current_type = AVIO_DATA_MARKER_UNKNOWN;
188     }
189     ctx->last_time = AV_NOPTS_VALUE;
190     ctx->writeout_count++;
191     s->pos += len;
192 }
193 
flush_buffer(AVIOContext * s)194 static void flush_buffer(AVIOContext *s)
195 {
196     s->buf_ptr_max = FFMAX(s->buf_ptr, s->buf_ptr_max);
197     if (s->write_flag && s->buf_ptr_max > s->buffer) {
198         writeout(s, s->buffer, s->buf_ptr_max - s->buffer);
199         if (s->update_checksum) {
200             s->checksum     = s->update_checksum(s->checksum, s->checksum_ptr,
201                                                  s->buf_ptr_max - s->checksum_ptr);
202             s->checksum_ptr = s->buffer;
203         }
204     }
205     s->buf_ptr = s->buf_ptr_max = s->buffer;
206     if (!s->write_flag)
207         s->buf_end = s->buffer;
208 }
209 
avio_w8(AVIOContext * s,int b)210 void avio_w8(AVIOContext *s, int b)
211 {
212     av_assert2(b>=-128 && b<=255);
213     *s->buf_ptr++ = b;
214     if (s->buf_ptr >= s->buf_end)
215         flush_buffer(s);
216 }
217 
ffio_fill(AVIOContext * s,int b,int64_t count)218 void ffio_fill(AVIOContext *s, int b, int64_t count)
219 {
220     while (count > 0) {
221         int len = FFMIN(s->buf_end - s->buf_ptr, count);
222         memset(s->buf_ptr, b, len);
223         s->buf_ptr += len;
224 
225         if (s->buf_ptr >= s->buf_end)
226             flush_buffer(s);
227 
228         count -= len;
229     }
230 }
231 
avio_write(AVIOContext * s,const unsigned char * buf,int size)232 void avio_write(AVIOContext *s, const unsigned char *buf, int size)
233 {
234     if (s->direct && !s->update_checksum) {
235         avio_flush(s);
236         writeout(s, buf, size);
237         return;
238     }
239     while (size > 0) {
240         int len = FFMIN(s->buf_end - s->buf_ptr, size);
241         memcpy(s->buf_ptr, buf, len);
242         s->buf_ptr += len;
243 
244         if (s->buf_ptr >= s->buf_end)
245             flush_buffer(s);
246 
247         buf += len;
248         size -= len;
249     }
250 }
251 
avio_flush(AVIOContext * s)252 void avio_flush(AVIOContext *s)
253 {
254     int seekback = s->write_flag ? FFMIN(0, s->buf_ptr - s->buf_ptr_max) : 0;
255     flush_buffer(s);
256     if (seekback)
257         avio_seek(s, seekback, SEEK_CUR);
258 }
259 
avio_seek(AVIOContext * s,int64_t offset,int whence)260 int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
261 {
262     FFIOContext *const ctx = ffiocontext(s);
263     int64_t offset1;
264     int64_t pos;
265     int force = whence & AVSEEK_FORCE;
266     int buffer_size;
267     int short_seek;
268     whence &= ~AVSEEK_FORCE;
269 
270     if(!s)
271         return AVERROR(EINVAL);
272 
273     if ((whence & AVSEEK_SIZE))
274         return s->seek ? s->seek(s->opaque, offset, AVSEEK_SIZE) : AVERROR(ENOSYS);
275 
276     buffer_size = s->buf_end - s->buffer;
277     // pos is the absolute position that the beginning of s->buffer corresponds to in the file
278     pos = s->pos - (s->write_flag ? 0 : buffer_size);
279 
280     if (whence != SEEK_CUR && whence != SEEK_SET)
281         return AVERROR(EINVAL);
282 
283     if (whence == SEEK_CUR) {
284         offset1 = pos + (s->buf_ptr - s->buffer);
285         if (offset == 0)
286             return offset1;
287         if (offset > INT64_MAX - offset1)
288             return AVERROR(EINVAL);
289         offset += offset1;
290     }
291     if (offset < 0)
292         return AVERROR(EINVAL);
293 
294     short_seek = ctx->short_seek_threshold;
295     if (ctx->short_seek_get) {
296         int tmp = ctx->short_seek_get(s->opaque);
297         short_seek = FFMAX(tmp, short_seek);
298     }
299 
300     offset1 = offset - pos; // "offset1" is the relative offset from the beginning of s->buffer
301     s->buf_ptr_max = FFMAX(s->buf_ptr_max, s->buf_ptr);
302     if ((!s->direct || !s->seek) &&
303         offset1 >= 0 && offset1 <= (s->write_flag ? s->buf_ptr_max - s->buffer : buffer_size)) {
304         /* can do the seek inside the buffer */
305         s->buf_ptr = s->buffer + offset1;
306     } else if ((!(s->seekable & AVIO_SEEKABLE_NORMAL) ||
307                offset1 <= buffer_size + short_seek) &&
308                !s->write_flag && offset1 >= 0 &&
309                (!s->direct || !s->seek) &&
310               (whence != SEEK_END || force)) {
311         while(s->pos < offset && !s->eof_reached)
312             fill_buffer(s);
313         if (s->eof_reached)
314             return AVERROR_EOF;
315         s->buf_ptr = s->buf_end - (s->pos - offset);
316     } else if(!s->write_flag && offset1 < 0 && -offset1 < buffer_size>>1 && s->seek && offset > 0) {
317         int64_t res;
318 
319         pos -= FFMIN(buffer_size>>1, pos);
320         if ((res = s->seek(s->opaque, pos, SEEK_SET)) < 0)
321             return res;
322         s->buf_end =
323         s->buf_ptr = s->buffer;
324         s->pos = pos;
325         s->eof_reached = 0;
326         fill_buffer(s);
327         return avio_seek(s, offset, SEEK_SET | force);
328     } else {
329         int64_t res;
330         if (s->write_flag) {
331             flush_buffer(s);
332         }
333         if (!s->seek)
334             return AVERROR(EPIPE);
335         if ((res = s->seek(s->opaque, offset, SEEK_SET)) < 0)
336             return res;
337         ctx->seek_count++;
338         if (!s->write_flag)
339             s->buf_end = s->buffer;
340         s->buf_ptr = s->buf_ptr_max = s->buffer;
341         s->pos = offset;
342     }
343     s->eof_reached = 0;
344     return offset;
345 }
346 
avio_skip(AVIOContext * s,int64_t offset)347 int64_t avio_skip(AVIOContext *s, int64_t offset)
348 {
349     return avio_seek(s, offset, SEEK_CUR);
350 }
351 
avio_size(AVIOContext * s)352 int64_t avio_size(AVIOContext *s)
353 {
354     FFIOContext *const ctx = ffiocontext(s);
355     int64_t size;
356 
357     if (!s)
358         return AVERROR(EINVAL);
359 
360     if (ctx->written_output_size)
361         return ctx->written_output_size;
362 
363     if (!s->seek)
364         return AVERROR(ENOSYS);
365     size = s->seek(s->opaque, 0, AVSEEK_SIZE);
366     if (size < 0) {
367         if ((size = s->seek(s->opaque, -1, SEEK_END)) < 0)
368             return size;
369         size++;
370         s->seek(s->opaque, s->pos, SEEK_SET);
371     }
372     return size;
373 }
374 
avio_feof(AVIOContext * s)375 int avio_feof(AVIOContext *s)
376 {
377     if(!s)
378         return 0;
379     if(s->eof_reached){
380         s->eof_reached=0;
381         fill_buffer(s);
382     }
383     return s->eof_reached;
384 }
385 
avio_wl32(AVIOContext * s,unsigned int val)386 void avio_wl32(AVIOContext *s, unsigned int val)
387 {
388     avio_w8(s, (uint8_t) val       );
389     avio_w8(s, (uint8_t)(val >> 8 ));
390     avio_w8(s, (uint8_t)(val >> 16));
391     avio_w8(s,           val >> 24 );
392 }
393 
avio_wb32(AVIOContext * s,unsigned int val)394 void avio_wb32(AVIOContext *s, unsigned int val)
395 {
396     avio_w8(s,           val >> 24 );
397     avio_w8(s, (uint8_t)(val >> 16));
398     avio_w8(s, (uint8_t)(val >> 8 ));
399     avio_w8(s, (uint8_t) val       );
400 }
401 
avio_put_str(AVIOContext * s,const char * str)402 int avio_put_str(AVIOContext *s, const char *str)
403 {
404     int len = 1;
405     if (str) {
406         len += strlen(str);
407         avio_write(s, (const unsigned char *) str, len);
408     } else
409         avio_w8(s, 0);
410     return len;
411 }
412 
put_str16(AVIOContext * s,const char * str,const int be)413 static inline int put_str16(AVIOContext *s, const char *str, const int be)
414 {
415     const uint8_t *q = str;
416     int ret = 0;
417     int err = 0;
418 
419     while (*q) {
420         uint32_t ch;
421         uint16_t tmp;
422 
423         GET_UTF8(ch, *q++, goto invalid;)
424         PUT_UTF16(ch, tmp, be ? avio_wb16(s, tmp) : avio_wl16(s, tmp);
425                   ret += 2;)
426         continue;
427 invalid:
428         av_log(s, AV_LOG_ERROR, "Invalid UTF8 sequence in avio_put_str16%s\n", be ? "be" : "le");
429         err = AVERROR(EINVAL);
430         if (!*(q-1))
431             break;
432     }
433     if (be)
434         avio_wb16(s, 0);
435     else
436         avio_wl16(s, 0);
437     if (err)
438         return err;
439     ret += 2;
440     return ret;
441 }
442 
443 #define PUT_STR16(type, big_endian)                          \
444 int avio_put_str16 ## type(AVIOContext *s, const char *str)  \
445 {                                                            \
446 return put_str16(s, str, big_endian);                        \
447 }
448 
449 PUT_STR16(le, 0)
450 PUT_STR16(be, 1)
451 
452 #undef PUT_STR16
453 
avio_wl64(AVIOContext * s,uint64_t val)454 void avio_wl64(AVIOContext *s, uint64_t val)
455 {
456     avio_wl32(s, (uint32_t)(val & 0xffffffff));
457     avio_wl32(s, (uint32_t)(val >> 32));
458 }
459 
avio_wb64(AVIOContext * s,uint64_t val)460 void avio_wb64(AVIOContext *s, uint64_t val)
461 {
462     avio_wb32(s, (uint32_t)(val >> 32));
463     avio_wb32(s, (uint32_t)(val & 0xffffffff));
464 }
465 
avio_wl16(AVIOContext * s,unsigned int val)466 void avio_wl16(AVIOContext *s, unsigned int val)
467 {
468     avio_w8(s, (uint8_t)val);
469     avio_w8(s, (int)val >> 8);
470 }
471 
avio_wb16(AVIOContext * s,unsigned int val)472 void avio_wb16(AVIOContext *s, unsigned int val)
473 {
474     avio_w8(s, (int)val >> 8);
475     avio_w8(s, (uint8_t)val);
476 }
477 
avio_wl24(AVIOContext * s,unsigned int val)478 void avio_wl24(AVIOContext *s, unsigned int val)
479 {
480     avio_wl16(s, val & 0xffff);
481     avio_w8(s, (int)val >> 16);
482 }
483 
avio_wb24(AVIOContext * s,unsigned int val)484 void avio_wb24(AVIOContext *s, unsigned int val)
485 {
486     avio_wb16(s, (int)val >> 8);
487     avio_w8(s, (uint8_t)val);
488 }
489 
avio_write_marker(AVIOContext * s,int64_t time,enum AVIODataMarkerType type)490 void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type)
491 {
492     FFIOContext *const ctx = ffiocontext(s);
493     if (type == AVIO_DATA_MARKER_FLUSH_POINT) {
494         if (s->buf_ptr - s->buffer >= s->min_packet_size)
495             avio_flush(s);
496         return;
497     }
498     if (!s->write_data_type)
499         return;
500     // If ignoring boundary points, just treat it as unknown
501     if (type == AVIO_DATA_MARKER_BOUNDARY_POINT && s->ignore_boundary_point)
502         type = AVIO_DATA_MARKER_UNKNOWN;
503     // Avoid unnecessary flushes if we are already in non-header/trailer
504     // data and setting the type to unknown
505     if (type == AVIO_DATA_MARKER_UNKNOWN &&
506         (ctx->current_type != AVIO_DATA_MARKER_HEADER &&
507          ctx->current_type != AVIO_DATA_MARKER_TRAILER))
508         return;
509 
510     switch (type) {
511     case AVIO_DATA_MARKER_HEADER:
512     case AVIO_DATA_MARKER_TRAILER:
513         // For header/trailer, ignore a new marker of the same type;
514         // consecutive header/trailer markers can be merged.
515         if (type == ctx->current_type)
516             return;
517         break;
518     }
519 
520     // If we've reached here, we have a new, noteworthy marker.
521     // Flush the previous data and mark the start of the new data.
522     avio_flush(s);
523     ctx->current_type = type;
524     ctx->last_time = time;
525 }
526 
read_packet_wrapper(AVIOContext * s,uint8_t * buf,int size)527 static int read_packet_wrapper(AVIOContext *s, uint8_t *buf, int size)
528 {
529     int ret;
530 
531     if (!s->read_packet)
532         return AVERROR(EINVAL);
533     ret = s->read_packet(s->opaque, buf, size);
534     av_assert2(ret || s->max_packet_size);
535     return ret;
536 }
537 
538 /* Input stream */
539 
fill_buffer(AVIOContext * s)540 static void fill_buffer(AVIOContext *s)
541 {
542     FFIOContext *const ctx = (FFIOContext *)s;
543     int max_buffer_size = s->max_packet_size ?
544                           s->max_packet_size : IO_BUFFER_SIZE;
545     uint8_t *dst        = s->buf_end - s->buffer + max_buffer_size <= s->buffer_size ?
546                           s->buf_end : s->buffer;
547     int len             = s->buffer_size - (dst - s->buffer);
548 
549     /* can't fill the buffer without read_packet, just set EOF if appropriate */
550     if (!s->read_packet && s->buf_ptr >= s->buf_end)
551         s->eof_reached = 1;
552 
553     /* no need to do anything if EOF already reached */
554     if (s->eof_reached)
555         return;
556 
557     if (s->update_checksum && dst == s->buffer) {
558         if (s->buf_end > s->checksum_ptr)
559             s->checksum = s->update_checksum(s->checksum, s->checksum_ptr,
560                                              s->buf_end - s->checksum_ptr);
561         s->checksum_ptr = s->buffer;
562     }
563 
564     /* make buffer smaller in case it ended up large after probing */
565     if (s->read_packet && ctx->orig_buffer_size &&
566         s->buffer_size > ctx->orig_buffer_size  && len >= ctx->orig_buffer_size) {
567         if (dst == s->buffer && s->buf_ptr != dst) {
568             int ret = set_buf_size(s, ctx->orig_buffer_size);
569             if (ret < 0)
570                 av_log(s, AV_LOG_WARNING, "Failed to decrease buffer size\n");
571 
572             s->checksum_ptr = dst = s->buffer;
573         }
574         len = ctx->orig_buffer_size;
575     }
576 
577     len = read_packet_wrapper(s, dst, len);
578     if (len == AVERROR_EOF) {
579         /* do not modify buffer if EOF reached so that a seek back can
580            be done without rereading data */
581         s->eof_reached = 1;
582     } else if (len < 0) {
583         s->eof_reached = 1;
584         s->error= len;
585     } else {
586         s->pos += len;
587         s->buf_ptr = dst;
588         s->buf_end = dst + len;
589         ffiocontext(s)->bytes_read += len;
590         s->bytes_read = ffiocontext(s)->bytes_read;
591     }
592 }
593 
ff_crc04C11DB7_update(unsigned long checksum,const uint8_t * buf,unsigned int len)594 unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf,
595                                     unsigned int len)
596 {
597     return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len);
598 }
599 
ff_crcEDB88320_update(unsigned long checksum,const uint8_t * buf,unsigned int len)600 unsigned long ff_crcEDB88320_update(unsigned long checksum, const uint8_t *buf,
601                                     unsigned int len)
602 {
603     return av_crc(av_crc_get_table(AV_CRC_32_IEEE_LE), checksum, buf, len);
604 }
605 
ff_crcA001_update(unsigned long checksum,const uint8_t * buf,unsigned int len)606 unsigned long ff_crcA001_update(unsigned long checksum, const uint8_t *buf,
607                                 unsigned int len)
608 {
609     return av_crc(av_crc_get_table(AV_CRC_16_ANSI_LE), checksum, buf, len);
610 }
611 
ffio_get_checksum(AVIOContext * s)612 unsigned long ffio_get_checksum(AVIOContext *s)
613 {
614     s->checksum = s->update_checksum(s->checksum, s->checksum_ptr,
615                                      s->buf_ptr - s->checksum_ptr);
616     s->update_checksum = NULL;
617     return s->checksum;
618 }
619 
ffio_init_checksum(AVIOContext * s,unsigned long (* update_checksum)(unsigned long c,const uint8_t * p,unsigned int len),unsigned long checksum)620 void 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 */
avio_r8(AVIOContext * s)632 int 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 
avio_read(AVIOContext * s,unsigned char * buf,int size)641 int avio_read(AVIOContext *s, unsigned char *buf, int size)
642 {
643     int len, size1;
644 
645     size1 = size;
646     while (size > 0) {
647         len = FFMIN(s->buf_end - s->buf_ptr, size);
648         if (len == 0 || s->write_flag) {
649             if((s->direct || size > s->buffer_size) && !s->update_checksum && s->read_packet) {
650                 // bypass the buffer and read data directly into buf
651                 len = read_packet_wrapper(s, buf, size);
652                 if (len == AVERROR_EOF) {
653                     /* do not modify buffer if EOF reached so that a seek back can
654                     be done without rereading data */
655                     s->eof_reached = 1;
656                     break;
657                 } else if (len < 0) {
658                     s->eof_reached = 1;
659                     s->error= len;
660                     break;
661                 } else {
662                     s->pos += len;
663                     ffiocontext(s)->bytes_read += len;
664                     s->bytes_read = ffiocontext(s)->bytes_read;
665                     size -= len;
666                     buf += len;
667                     // reset the buffer
668                     s->buf_ptr = s->buffer;
669                     s->buf_end = s->buffer/* + len*/;
670                 }
671             } else {
672                 fill_buffer(s);
673                 len = s->buf_end - s->buf_ptr;
674                 if (len == 0)
675                     break;
676             }
677         } else {
678             memcpy(buf, s->buf_ptr, len);
679             buf += len;
680             s->buf_ptr += len;
681             size -= len;
682         }
683     }
684     if (size1 == size) {
685         if (s->error)      return s->error;
686         if (avio_feof(s))  return AVERROR_EOF;
687     }
688     return size1 - size;
689 }
690 
ffio_read_size(AVIOContext * s,unsigned char * buf,int size)691 int ffio_read_size(AVIOContext *s, unsigned char *buf, int size)
692 {
693     int ret = avio_read(s, buf, size);
694     if (ret == size)
695         return ret;
696     if (ret < 0 && ret != AVERROR_EOF)
697         return ret;
698     return AVERROR_INVALIDDATA;
699 }
700 
ffio_read_indirect(AVIOContext * s,unsigned char * buf,int size,const unsigned char ** data)701 int ffio_read_indirect(AVIOContext *s, unsigned char *buf, int size, const unsigned char **data)
702 {
703     if (s->buf_end - s->buf_ptr >= size && !s->write_flag) {
704         *data = s->buf_ptr;
705         s->buf_ptr += size;
706         return size;
707     } else {
708         *data = buf;
709         return avio_read(s, buf, size);
710     }
711 }
712 
avio_read_partial(AVIOContext * s,unsigned char * buf,int size)713 int avio_read_partial(AVIOContext *s, unsigned char *buf, int size)
714 {
715     int len;
716 
717     if (size < 0)
718         return AVERROR(EINVAL);
719 
720     if (s->read_packet && s->write_flag) {
721         len = read_packet_wrapper(s, buf, size);
722         if (len > 0)
723             s->pos += len;
724         return len;
725     }
726 
727     len = s->buf_end - s->buf_ptr;
728     if (len == 0) {
729         fill_buffer(s);
730         len = s->buf_end - s->buf_ptr;
731     }
732     if (len > size)
733         len = size;
734     memcpy(buf, s->buf_ptr, len);
735     s->buf_ptr += len;
736     if (!len) {
737         if (s->error)      return s->error;
738         if (avio_feof(s))  return AVERROR_EOF;
739     }
740     return len;
741 }
742 
avio_rl16(AVIOContext * s)743 unsigned int avio_rl16(AVIOContext *s)
744 {
745     unsigned int val;
746     val = avio_r8(s);
747     val |= avio_r8(s) << 8;
748     return val;
749 }
750 
avio_rl24(AVIOContext * s)751 unsigned int avio_rl24(AVIOContext *s)
752 {
753     unsigned int val;
754     val = avio_rl16(s);
755     val |= avio_r8(s) << 16;
756     return val;
757 }
758 
avio_rl32(AVIOContext * s)759 unsigned int avio_rl32(AVIOContext *s)
760 {
761     unsigned int val;
762     val = avio_rl16(s);
763     val |= avio_rl16(s) << 16;
764     return val;
765 }
766 
avio_rl64(AVIOContext * s)767 uint64_t avio_rl64(AVIOContext *s)
768 {
769     uint64_t val;
770     val = (uint64_t)avio_rl32(s);
771     val |= (uint64_t)avio_rl32(s) << 32;
772     return val;
773 }
774 
avio_rb16(AVIOContext * s)775 unsigned int avio_rb16(AVIOContext *s)
776 {
777     unsigned int val;
778     val = avio_r8(s) << 8;
779     val |= avio_r8(s);
780     return val;
781 }
782 
avio_rb24(AVIOContext * s)783 unsigned int avio_rb24(AVIOContext *s)
784 {
785     unsigned int val;
786     val = avio_rb16(s) << 8;
787     val |= avio_r8(s);
788     return val;
789 }
avio_rb32(AVIOContext * s)790 unsigned int avio_rb32(AVIOContext *s)
791 {
792     unsigned int val;
793     val = avio_rb16(s) << 16;
794     val |= avio_rb16(s);
795     return val;
796 }
797 
ff_get_line(AVIOContext * s,char * buf,int maxlen)798 int ff_get_line(AVIOContext *s, char *buf, int maxlen)
799 {
800     int i = 0;
801     char c;
802 
803     do {
804         c = avio_r8(s);
805         if (c && i < maxlen-1)
806             buf[i++] = c;
807     } while (c != '\n' && c != '\r' && c);
808     if (c == '\r' && avio_r8(s) != '\n' && !avio_feof(s))
809         avio_skip(s, -1);
810 
811     buf[i] = 0;
812     return i;
813 }
814 
ff_get_chomp_line(AVIOContext * s,char * buf,int maxlen)815 int ff_get_chomp_line(AVIOContext *s, char *buf, int maxlen)
816 {
817     int len = ff_get_line(s, buf, maxlen);
818     while (len > 0 && av_isspace(buf[len - 1]))
819         buf[--len] = '\0';
820     return len;
821 }
822 
823 typedef enum FFBPrintReadStringMode {
824     FFBPrintReadString = 0,
825     FFBPrintReadLine   = 1,
826 } FFBPrintReadStringMode;
827 
read_string_to_bprint(AVIOContext * s,AVBPrint * bp,FFBPrintReadStringMode mode,int64_t max_len)828 static int64_t read_string_to_bprint(AVIOContext *s, AVBPrint *bp,
829                                      FFBPrintReadStringMode mode,
830                                      int64_t max_len)
831 {
832     int len, end;
833     int64_t read = 0;
834     char tmp[1024];
835     char c;
836 
837     if (!max_len)
838         return 0;
839 
840     do {
841         len = 0;
842         do {
843             c = avio_r8(s);
844             end = ((mode == FFBPrintReadLine && (c == '\r' || c == '\n')) ||
845                    c == '\0');
846             if (!end)
847                 tmp[len++] = c;
848         } while (!end && len < sizeof(tmp) &&
849                  ((max_len < 0) || (read + len < max_len)));
850         av_bprint_append_data(bp, tmp, len);
851         read += len;
852     } while (!end && ((max_len < 0) || (read < max_len)));
853 
854     if (mode == FFBPrintReadLine &&
855         c == '\r' && avio_r8(s) != '\n' && !avio_feof(s))
856         avio_skip(s, -1);
857 
858     if (!c && s->error)
859         return s->error;
860 
861     if (!c && !read && avio_feof(s))
862         return AVERROR_EOF;
863 
864     return read;
865 }
866 
read_string_to_bprint_overwrite(AVIOContext * s,AVBPrint * bp,FFBPrintReadStringMode mode,int64_t max_len)867 static int64_t read_string_to_bprint_overwrite(AVIOContext *s, AVBPrint *bp,
868                                                FFBPrintReadStringMode mode,
869                                                int64_t max_len)
870 {
871     int64_t ret;
872 
873     av_bprint_clear(bp);
874     ret = read_string_to_bprint(s, bp, mode, max_len);
875     if (ret < 0)
876         return ret;
877 
878     if (!av_bprint_is_complete(bp))
879         return AVERROR(ENOMEM);
880 
881     return bp->len;
882 }
883 
ff_read_line_to_bprint_overwrite(AVIOContext * s,AVBPrint * bp)884 int64_t ff_read_line_to_bprint_overwrite(AVIOContext *s, AVBPrint *bp)
885 {
886     return read_string_to_bprint_overwrite(s, bp, FFBPrintReadLine, -1);
887 }
888 
ff_read_string_to_bprint_overwrite(AVIOContext * s,AVBPrint * bp,int64_t max_len)889 int64_t ff_read_string_to_bprint_overwrite(AVIOContext *s, AVBPrint *bp,
890                                            int64_t max_len)
891 {
892     return read_string_to_bprint_overwrite(s, bp, FFBPrintReadString, max_len);
893 }
894 
avio_get_str(AVIOContext * s,int maxlen,char * buf,int buflen)895 int avio_get_str(AVIOContext *s, int maxlen, char *buf, int buflen)
896 {
897     int i;
898 
899     if (buflen <= 0)
900         return AVERROR(EINVAL);
901     // reserve 1 byte for terminating 0
902     buflen = FFMIN(buflen - 1, maxlen);
903     for (i = 0; i < buflen; i++)
904         if (!(buf[i] = avio_r8(s)))
905             return i + 1;
906     buf[i] = 0;
907     for (; i < maxlen; i++)
908         if (!avio_r8(s))
909             return i + 1;
910     return maxlen;
911 }
912 
913 #define GET_STR16(type, read) \
914     int avio_get_str16 ##type(AVIOContext *pb, int maxlen, char *buf, int buflen)\
915 {\
916     char* q = buf;\
917     int ret = 0;\
918     if (buflen <= 0) \
919         return AVERROR(EINVAL); \
920     while (ret + 1 < maxlen) {\
921         uint8_t tmp;\
922         uint32_t ch;\
923         GET_UTF16(ch, (ret += 2) <= maxlen ? read(pb) : 0, break;)\
924         if (!ch)\
925             break;\
926         PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;)\
927     }\
928     *q = 0;\
929     return ret;\
930 }\
931 
GET_STR16(le,avio_rl16)932 GET_STR16(le, avio_rl16)
933 GET_STR16(be, avio_rb16)
934 
935 #undef GET_STR16
936 
937 uint64_t avio_rb64(AVIOContext *s)
938 {
939     uint64_t val;
940     val = (uint64_t)avio_rb32(s) << 32;
941     val |= (uint64_t)avio_rb32(s);
942     return val;
943 }
944 
ffio_read_varlen(AVIOContext * bc)945 uint64_t ffio_read_varlen(AVIOContext *bc){
946     uint64_t val = 0;
947     int tmp;
948 
949     do{
950         tmp = avio_r8(bc);
951         val= (val<<7) + (tmp&127);
952     }while(tmp&128);
953     return val;
954 }
955 
ffio_fdopen(AVIOContext ** s,URLContext * h)956 int ffio_fdopen(AVIOContext **s, URLContext *h)
957 {
958     uint8_t *buffer = NULL;
959     int buffer_size, max_packet_size;
960 
961     max_packet_size = h->max_packet_size;
962     if (max_packet_size) {
963         buffer_size = max_packet_size; /* no need to bufferize more than one packet */
964     } else {
965         buffer_size = IO_BUFFER_SIZE;
966     }
967     if (!(h->flags & AVIO_FLAG_WRITE) && h->is_streamed) {
968         if (buffer_size > INT_MAX/2)
969             return AVERROR(EINVAL);
970         buffer_size *= 2;
971     }
972     buffer = av_malloc(buffer_size);
973     if (!buffer)
974         return AVERROR(ENOMEM);
975 
976     *s = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE, h,
977                             (int (*)(void *, uint8_t *, int))  ffurl_read,
978                             (int (*)(void *, uint8_t *, int))  ffurl_write,
979                             (int64_t (*)(void *, int64_t, int))ffurl_seek);
980     if (!*s) {
981         av_freep(&buffer);
982         return AVERROR(ENOMEM);
983     }
984     (*s)->protocol_whitelist = av_strdup(h->protocol_whitelist);
985     if (!(*s)->protocol_whitelist && h->protocol_whitelist) {
986         avio_closep(s);
987         return AVERROR(ENOMEM);
988     }
989     (*s)->protocol_blacklist = av_strdup(h->protocol_blacklist);
990     if (!(*s)->protocol_blacklist && h->protocol_blacklist) {
991         avio_closep(s);
992         return AVERROR(ENOMEM);
993     }
994     (*s)->direct = h->flags & AVIO_FLAG_DIRECT;
995 
996     (*s)->seekable = h->is_streamed ? 0 : AVIO_SEEKABLE_NORMAL;
997     (*s)->max_packet_size = max_packet_size;
998     (*s)->min_packet_size = h->min_packet_size;
999     if(h->prot) {
1000         (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause;
1001         (*s)->read_seek  =
1002             (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek;
1003 
1004         if (h->prot->url_read_seek)
1005             (*s)->seekable |= AVIO_SEEKABLE_TIME;
1006     }
1007     ((FFIOContext*)(*s))->short_seek_get = (int (*)(void *))ffurl_get_short_seek;
1008     (*s)->av_class = &ff_avio_class;
1009     return 0;
1010 }
1011 
ffio_geturlcontext(AVIOContext * s)1012 URLContext* ffio_geturlcontext(AVIOContext *s)
1013 {
1014     if (!s)
1015         return NULL;
1016 
1017     if (s->opaque && s->read_packet == (int (*)(void *, uint8_t *, int))ffurl_read)
1018         return s->opaque;
1019     else
1020         return NULL;
1021 }
1022 
ffio_copy_url_options(AVIOContext * pb,AVDictionary ** avio_opts)1023 int ffio_copy_url_options(AVIOContext* pb, AVDictionary** avio_opts)
1024 {
1025     const char *opts[] = {
1026         "headers", "user_agent", "cookies", "http_proxy", "referer", "rw_timeout", "icy", NULL };
1027     const char **opt = opts;
1028     uint8_t *buf = NULL;
1029     int ret = 0;
1030 
1031     while (*opt) {
1032         if (av_opt_get(pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) {
1033             if (buf[0] != '\0') {
1034                 ret = av_dict_set(avio_opts, *opt, buf, AV_DICT_DONT_STRDUP_VAL);
1035                 if (ret < 0)
1036                     return ret;
1037             } else {
1038                 av_freep(&buf);
1039             }
1040         }
1041         opt++;
1042     }
1043 
1044     return ret;
1045 }
1046 
update_checksum(AVIOContext * s)1047 static void update_checksum(AVIOContext *s)
1048 {
1049     if (s->update_checksum && s->buf_ptr > s->checksum_ptr) {
1050         s->checksum = s->update_checksum(s->checksum, s->checksum_ptr,
1051                                          s->buf_ptr - s->checksum_ptr);
1052     }
1053 }
1054 
ffio_ensure_seekback(AVIOContext * s,int64_t buf_size)1055 int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
1056 {
1057     uint8_t *buffer;
1058     int max_buffer_size = s->max_packet_size ?
1059                           s->max_packet_size : IO_BUFFER_SIZE;
1060     ptrdiff_t filled = s->buf_end - s->buf_ptr;
1061 
1062     if (buf_size <= s->buf_end - s->buf_ptr)
1063         return 0;
1064 
1065     if (buf_size > INT_MAX - max_buffer_size)
1066         return AVERROR(EINVAL);
1067 
1068     buf_size += max_buffer_size - 1;
1069 
1070     if (buf_size + s->buf_ptr - s->buffer <= s->buffer_size || s->seekable || !s->read_packet)
1071         return 0;
1072     av_assert0(!s->write_flag);
1073 
1074     if (buf_size <= s->buffer_size) {
1075         update_checksum(s);
1076         memmove(s->buffer, s->buf_ptr, filled);
1077     } else {
1078         buffer = av_malloc(buf_size);
1079         if (!buffer)
1080             return AVERROR(ENOMEM);
1081         update_checksum(s);
1082         memcpy(buffer, s->buf_ptr, filled);
1083         av_free(s->buffer);
1084         s->buffer = buffer;
1085         s->buffer_size = buf_size;
1086     }
1087     s->buf_ptr = s->buffer;
1088     s->buf_end = s->buffer + filled;
1089     s->checksum_ptr = s->buffer;
1090     return 0;
1091 }
1092 
ffio_limit(AVIOContext * s,int size)1093 int ffio_limit(AVIOContext *s, int size)
1094 {
1095     FFIOContext *const ctx = ffiocontext(s);
1096     if (ctx->maxsize >= 0) {
1097         int64_t pos = avio_tell(s);
1098         int64_t remaining = ctx->maxsize - pos;
1099         if (remaining < size) {
1100             int64_t newsize = avio_size(s);
1101             if (!ctx->maxsize || ctx->maxsize < newsize)
1102                 ctx->maxsize = newsize - !newsize;
1103             if (pos > ctx->maxsize && ctx->maxsize >= 0)
1104                 ctx->maxsize = AVERROR(EIO);
1105             if (ctx->maxsize >= 0)
1106                 remaining = ctx->maxsize - pos;
1107         }
1108 
1109         if (ctx->maxsize >= 0 && remaining < size && size > 1) {
1110             av_log(NULL, remaining ? AV_LOG_ERROR : AV_LOG_DEBUG,
1111                    "Truncating packet of size %d to %"PRId64"\n",
1112                    size, remaining + !remaining);
1113             size = remaining + !remaining;
1114         }
1115     }
1116     return size;
1117 }
1118 
set_buf_size(AVIOContext * s,int buf_size)1119 static int set_buf_size(AVIOContext *s, int buf_size)
1120 {
1121     uint8_t *buffer;
1122     buffer = av_malloc(buf_size);
1123     if (!buffer)
1124         return AVERROR(ENOMEM);
1125 
1126     av_free(s->buffer);
1127     s->buffer = buffer;
1128     ffiocontext(s)->orig_buffer_size =
1129     s->buffer_size = buf_size;
1130     s->buf_ptr = s->buf_ptr_max = buffer;
1131     url_resetbuf(s, s->write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ);
1132     return 0;
1133 }
1134 
ffio_realloc_buf(AVIOContext * s,int buf_size)1135 int ffio_realloc_buf(AVIOContext *s, int buf_size)
1136 {
1137     uint8_t *buffer;
1138     int data_size;
1139 
1140     if (!s->buffer_size)
1141         return set_buf_size(s, buf_size);
1142 
1143     if (buf_size <= s->buffer_size)
1144         return 0;
1145 
1146     buffer = av_malloc(buf_size);
1147     if (!buffer)
1148         return AVERROR(ENOMEM);
1149 
1150     data_size = s->write_flag ? (s->buf_ptr - s->buffer) : (s->buf_end - s->buf_ptr);
1151     if (data_size > 0)
1152         memcpy(buffer, s->write_flag ? s->buffer : s->buf_ptr, data_size);
1153     av_free(s->buffer);
1154     s->buffer = buffer;
1155     ffiocontext(s)->orig_buffer_size = buf_size;
1156     s->buffer_size = buf_size;
1157     s->buf_ptr = s->write_flag ? (s->buffer + data_size) : s->buffer;
1158     if (s->write_flag)
1159         s->buf_ptr_max = s->buffer + data_size;
1160 
1161     s->buf_end = s->write_flag ? (s->buffer + s->buffer_size) : (s->buf_ptr + data_size);
1162 
1163     return 0;
1164 }
1165 
url_resetbuf(AVIOContext * s,int flags)1166 static int url_resetbuf(AVIOContext *s, int flags)
1167 {
1168     av_assert1(flags == AVIO_FLAG_WRITE || flags == AVIO_FLAG_READ);
1169 
1170     if (flags & AVIO_FLAG_WRITE) {
1171         s->buf_end = s->buffer + s->buffer_size;
1172         s->write_flag = 1;
1173     } else {
1174         s->buf_end = s->buffer;
1175         s->write_flag = 0;
1176     }
1177     return 0;
1178 }
1179 
ffio_rewind_with_probe_data(AVIOContext * s,unsigned char ** bufp,int buf_size)1180 int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char **bufp, int buf_size)
1181 {
1182     int64_t buffer_start;
1183     int buffer_size;
1184     int overlap, new_size, alloc_size;
1185     uint8_t *buf = *bufp;
1186 
1187     if (s->write_flag) {
1188         av_freep(bufp);
1189         return AVERROR(EINVAL);
1190     }
1191 
1192     buffer_size = s->buf_end - s->buffer;
1193 
1194     /* the buffers must touch or overlap */
1195     if ((buffer_start = s->pos - buffer_size) > buf_size) {
1196         av_freep(bufp);
1197         return AVERROR(EINVAL);
1198     }
1199 
1200     overlap = buf_size - buffer_start;
1201     new_size = buf_size + buffer_size - overlap;
1202 
1203     alloc_size = FFMAX(s->buffer_size, new_size);
1204     if (alloc_size > buf_size)
1205         if (!(buf = (*bufp) = av_realloc_f(buf, 1, alloc_size)))
1206             return AVERROR(ENOMEM);
1207 
1208     if (new_size > buf_size) {
1209         memcpy(buf + buf_size, s->buffer + overlap, buffer_size - overlap);
1210         buf_size = new_size;
1211     }
1212 
1213     av_free(s->buffer);
1214     s->buf_ptr = s->buffer = buf;
1215     s->buffer_size = alloc_size;
1216     s->pos = buf_size;
1217     s->buf_end = s->buf_ptr + buf_size;
1218     s->eof_reached = 0;
1219 
1220     return 0;
1221 }
1222 
avio_open(AVIOContext ** s,const char * filename,int flags)1223 int avio_open(AVIOContext **s, const char *filename, int flags)
1224 {
1225     return avio_open2(s, filename, flags, NULL, NULL);
1226 }
1227 
ffio_open_whitelist(AVIOContext ** s,const char * filename,int flags,const AVIOInterruptCB * int_cb,AVDictionary ** options,const char * whitelist,const char * blacklist)1228 int ffio_open_whitelist(AVIOContext **s, const char *filename, int flags,
1229                          const AVIOInterruptCB *int_cb, AVDictionary **options,
1230                          const char *whitelist, const char *blacklist
1231                         )
1232 {
1233     URLContext *h;
1234     int err;
1235 
1236     *s = NULL;
1237 
1238     err = ffurl_open_whitelist(&h, filename, flags, int_cb, options, whitelist, blacklist, NULL);
1239     if (err < 0)
1240         return err;
1241     err = ffio_fdopen(s, h);
1242     if (err < 0) {
1243         ffurl_close(h);
1244         return err;
1245     }
1246     return 0;
1247 }
1248 
avio_open2(AVIOContext ** s,const char * filename,int flags,const AVIOInterruptCB * int_cb,AVDictionary ** options)1249 int avio_open2(AVIOContext **s, const char *filename, int flags,
1250                const AVIOInterruptCB *int_cb, AVDictionary **options)
1251 {
1252     return ffio_open_whitelist(s, filename, flags, int_cb, options, NULL, NULL);
1253 }
1254 
avio_close(AVIOContext * s)1255 int avio_close(AVIOContext *s)
1256 {
1257     FFIOContext *const ctx = ffiocontext(s);
1258     URLContext *h;
1259     int ret, error;
1260 
1261     if (!s)
1262         return 0;
1263 
1264     avio_flush(s);
1265     h         = s->opaque;
1266     s->opaque = NULL;
1267 
1268     av_freep(&s->buffer);
1269     if (s->write_flag)
1270         av_log(s, AV_LOG_VERBOSE,
1271                "Statistics: %"PRId64" bytes written, %d seeks, %d writeouts\n",
1272                ctx->bytes_written, ctx->seek_count, ctx->writeout_count);
1273     else
1274         av_log(s, AV_LOG_VERBOSE, "Statistics: %"PRId64" bytes read, %d seeks\n",
1275                ctx->bytes_read, ctx->seek_count);
1276     av_opt_free(s);
1277 
1278     error = s->error;
1279     avio_context_free(&s);
1280 
1281     ret = ffurl_close(h);
1282     if (ret < 0)
1283         return ret;
1284 
1285     return error;
1286 }
1287 
avio_closep(AVIOContext ** s)1288 int avio_closep(AVIOContext **s)
1289 {
1290     int ret = avio_close(*s);
1291     *s = NULL;
1292     return ret;
1293 }
1294 
avio_vprintf(AVIOContext * s,const char * fmt,va_list ap)1295 int avio_vprintf(AVIOContext *s, const char *fmt, va_list ap)
1296 {
1297     AVBPrint bp;
1298 
1299     av_bprint_init(&bp, 0, INT_MAX);
1300     av_vbprintf(&bp, fmt, ap);
1301     if (!av_bprint_is_complete(&bp)) {
1302         av_bprint_finalize(&bp, NULL);
1303         s->error = AVERROR(ENOMEM);
1304         return AVERROR(ENOMEM);
1305     }
1306     avio_write(s, bp.str, bp.len);
1307     av_bprint_finalize(&bp, NULL);
1308     return bp.len;
1309 }
1310 
avio_printf(AVIOContext * s,const char * fmt,...)1311 int avio_printf(AVIOContext *s, const char *fmt, ...)
1312 {
1313     va_list ap;
1314     int ret;
1315 
1316     va_start(ap, fmt);
1317     ret = avio_vprintf(s, fmt, ap);
1318     va_end(ap);
1319 
1320     return ret;
1321 }
1322 
avio_print_string_array(AVIOContext * s,const char * strings[])1323 void avio_print_string_array(AVIOContext *s, const char *strings[])
1324 {
1325     for(; *strings; strings++)
1326         avio_write(s, (const unsigned char *)*strings, strlen(*strings));
1327 }
1328 
avio_pause(AVIOContext * s,int pause)1329 int avio_pause(AVIOContext *s, int pause)
1330 {
1331     if (!s->read_pause)
1332         return AVERROR(ENOSYS);
1333     return s->read_pause(s->opaque, pause);
1334 }
1335 
avio_seek_time(AVIOContext * s,int stream_index,int64_t timestamp,int flags)1336 int64_t avio_seek_time(AVIOContext *s, int stream_index,
1337                        int64_t timestamp, int flags)
1338 {
1339     int64_t ret;
1340     if (!s->read_seek)
1341         return AVERROR(ENOSYS);
1342     ret = s->read_seek(s->opaque, stream_index, timestamp, flags);
1343     if (ret >= 0) {
1344         int64_t pos;
1345         s->buf_ptr = s->buf_end; // Flush buffer
1346         pos = s->seek(s->opaque, 0, SEEK_CUR);
1347         if (pos >= 0)
1348             s->pos = pos;
1349         else if (pos != AVERROR(ENOSYS))
1350             ret = pos;
1351     }
1352     return ret;
1353 }
1354 
avio_read_to_bprint(AVIOContext * h,AVBPrint * pb,size_t max_size)1355 int avio_read_to_bprint(AVIOContext *h, AVBPrint *pb, size_t max_size)
1356 {
1357     int ret;
1358     char buf[1024];
1359     while (max_size) {
1360         ret = avio_read(h, buf, FFMIN(max_size, sizeof(buf)));
1361         if (ret == AVERROR_EOF)
1362             return 0;
1363         if (ret <= 0)
1364             return ret;
1365         av_bprint_append_data(pb, buf, ret);
1366         if (!av_bprint_is_complete(pb))
1367             return AVERROR(ENOMEM);
1368         max_size -= ret;
1369     }
1370     return 0;
1371 }
1372 
avio_accept(AVIOContext * s,AVIOContext ** c)1373 int avio_accept(AVIOContext *s, AVIOContext **c)
1374 {
1375     int ret;
1376     URLContext *sc = s->opaque;
1377     URLContext *cc = NULL;
1378     ret = ffurl_accept(sc, &cc);
1379     if (ret < 0)
1380         return ret;
1381     return ffio_fdopen(c, cc);
1382 }
1383 
avio_handshake(AVIOContext * c)1384 int avio_handshake(AVIOContext *c)
1385 {
1386     URLContext *cc = c->opaque;
1387     return ffurl_handshake(cc);
1388 }
1389 
1390 /* output in a dynamic buffer */
1391 
1392 typedef struct DynBuffer {
1393     int pos, size, allocated_size;
1394     uint8_t *buffer;
1395     int io_buffer_size;
1396     uint8_t io_buffer[1];
1397 } DynBuffer;
1398 
dyn_buf_write(void * opaque,uint8_t * buf,int buf_size)1399 static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size)
1400 {
1401     DynBuffer *d = opaque;
1402     unsigned new_size;
1403 
1404     /* reallocate buffer if needed */
1405     new_size = (unsigned)d->pos + buf_size;
1406     if (new_size < d->pos || new_size > INT_MAX)
1407         return AVERROR(ERANGE);
1408     if (new_size > d->allocated_size) {
1409         unsigned new_allocated_size = d->allocated_size ? d->allocated_size
1410                                                         : new_size;
1411         int err;
1412         while (new_size > new_allocated_size)
1413             new_allocated_size += new_allocated_size / 2 + 1;
1414 
1415         new_allocated_size = FFMIN(new_allocated_size, INT_MAX);
1416 
1417         if ((err = av_reallocp(&d->buffer, new_allocated_size)) < 0) {
1418             d->allocated_size = 0;
1419             d->size = 0;
1420             return err;
1421         }
1422         d->allocated_size = new_allocated_size;
1423     }
1424     memcpy(d->buffer + d->pos, buf, buf_size);
1425     d->pos = new_size;
1426     if (d->pos > d->size)
1427         d->size = d->pos;
1428     return buf_size;
1429 }
1430 
dyn_packet_buf_write(void * opaque,uint8_t * buf,int buf_size)1431 static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size)
1432 {
1433     unsigned char buf1[4];
1434     int ret;
1435 
1436     /* packetized write: output the header */
1437     AV_WB32(buf1, buf_size);
1438     ret = dyn_buf_write(opaque, buf1, 4);
1439     if (ret < 0)
1440         return ret;
1441 
1442     /* then the data */
1443     return dyn_buf_write(opaque, buf, buf_size);
1444 }
1445 
dyn_buf_seek(void * opaque,int64_t offset,int whence)1446 static int64_t dyn_buf_seek(void *opaque, int64_t offset, int whence)
1447 {
1448     DynBuffer *d = opaque;
1449 
1450     if (whence == SEEK_CUR)
1451         offset += d->pos;
1452     else if (whence == SEEK_END)
1453         offset += d->size;
1454     if (offset < 0)
1455         return AVERROR(EINVAL);
1456     if (offset > INT_MAX)
1457         return AVERROR(ERANGE);
1458     d->pos = offset;
1459     return 0;
1460 }
1461 
url_open_dyn_buf_internal(AVIOContext ** s,int max_packet_size)1462 static int url_open_dyn_buf_internal(AVIOContext **s, int max_packet_size)
1463 {
1464     struct { FFIOContext pb; DynBuffer d; } *ret;
1465     DynBuffer *d;
1466     unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024;
1467 
1468     if (sizeof(*ret) + io_buffer_size < io_buffer_size)
1469         return AVERROR(ERANGE);
1470     ret = av_mallocz(sizeof(*ret) + io_buffer_size);
1471     if (!ret)
1472         return AVERROR(ENOMEM);
1473     d = &ret->d;
1474     d->io_buffer_size = io_buffer_size;
1475     ffio_init_context(&ret->pb, d->io_buffer, d->io_buffer_size, 1, d, NULL,
1476                       max_packet_size ? dyn_packet_buf_write : dyn_buf_write,
1477                       max_packet_size ? NULL : dyn_buf_seek);
1478     *s = &ret->pb.pub;
1479     (*s)->max_packet_size = max_packet_size;
1480     return 0;
1481 }
1482 
avio_open_dyn_buf(AVIOContext ** s)1483 int avio_open_dyn_buf(AVIOContext **s)
1484 {
1485     return url_open_dyn_buf_internal(s, 0);
1486 }
1487 
ffio_open_dyn_packet_buf(AVIOContext ** s,int max_packet_size)1488 int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size)
1489 {
1490     if (max_packet_size <= 0)
1491         return AVERROR(EINVAL);
1492     return url_open_dyn_buf_internal(s, max_packet_size);
1493 }
1494 
avio_get_dyn_buf(AVIOContext * s,uint8_t ** pbuffer)1495 int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
1496 {
1497     DynBuffer *d;
1498 
1499     if (!s) {
1500         *pbuffer = NULL;
1501         return 0;
1502     }
1503     d = s->opaque;
1504 
1505     if (!s->error && !d->size) {
1506         *pbuffer = d->io_buffer;
1507         return FFMAX(s->buf_ptr, s->buf_ptr_max) - s->buffer;
1508     }
1509 
1510     avio_flush(s);
1511 
1512     *pbuffer = d->buffer;
1513 
1514     return d->size;
1515 }
1516 
ffio_reset_dyn_buf(AVIOContext * s)1517 void ffio_reset_dyn_buf(AVIOContext *s)
1518 {
1519     DynBuffer *d = s->opaque;
1520     int max_packet_size = s->max_packet_size;
1521 
1522     ffio_init_context(ffiocontext(s), d->io_buffer, d->io_buffer_size,
1523                       1, d, NULL, s->write_packet, s->seek);
1524     s->max_packet_size = max_packet_size;
1525     d->pos = d->size = 0;
1526 }
1527 
avio_close_dyn_buf(AVIOContext * s,uint8_t ** pbuffer)1528 int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
1529 {
1530     DynBuffer *d;
1531     int size;
1532     int padding = 0;
1533 
1534     if (!s) {
1535         *pbuffer = NULL;
1536         return 0;
1537     }
1538 
1539     /* don't attempt to pad fixed-size packet buffers */
1540     if (!s->max_packet_size) {
1541         ffio_fill(s, 0, AV_INPUT_BUFFER_PADDING_SIZE);
1542         padding = AV_INPUT_BUFFER_PADDING_SIZE;
1543     }
1544 
1545     avio_flush(s);
1546 
1547     d = s->opaque;
1548     *pbuffer = d->buffer;
1549     size = d->size;
1550 
1551     avio_context_free(&s);
1552 
1553     return size - padding;
1554 }
1555 
ffio_free_dyn_buf(AVIOContext ** s)1556 void ffio_free_dyn_buf(AVIOContext **s)
1557 {
1558     DynBuffer *d;
1559 
1560     if (!*s)
1561         return;
1562 
1563     d = (*s)->opaque;
1564     av_free(d->buffer);
1565     avio_context_free(s);
1566 }
1567 
null_buf_write(void * opaque,uint8_t * buf,int buf_size)1568 static int null_buf_write(void *opaque, uint8_t *buf, int buf_size)
1569 {
1570     DynBuffer *d = opaque;
1571 
1572     d->pos += buf_size;
1573     if (d->pos > d->size)
1574         d->size = d->pos;
1575     return buf_size;
1576 }
1577 
ffio_open_null_buf(AVIOContext ** s)1578 int ffio_open_null_buf(AVIOContext **s)
1579 {
1580     int ret = url_open_dyn_buf_internal(s, 0);
1581     if (ret >= 0) {
1582         AVIOContext *pb = *s;
1583         pb->write_packet = null_buf_write;
1584     }
1585     return ret;
1586 }
1587 
ffio_close_null_buf(AVIOContext * s)1588 int ffio_close_null_buf(AVIOContext *s)
1589 {
1590     DynBuffer *d = s->opaque;
1591     int size;
1592 
1593     avio_flush(s);
1594 
1595     size = d->size;
1596 
1597     avio_context_free(&s);
1598 
1599     return size;
1600 }
1601