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