3 * Copyright (c) 2000,2001 Fabrice Bellard
5 * This file is part of FFmpeg.
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.
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.
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
22 #include "libavutil/bprint.h"
23 #include "libavutil/crc.h"
24 #include "libavutil/dict.h"
25 #include "libavutil/intreadwrite.h"
26 #include "libavutil/log.h"
27 #include "libavutil/opt.h"
28 #include "libavutil/avassert.h"
31 #include "avio_internal.h"
36 #define IO_BUFFER_SIZE 32768
39 * Do seeks within this distance ahead of the current buffer by skipping
40 * data instead of calling the protocol seek function, for seekable
43 #define SHORT_SEEK_THRESHOLD 4096
45 static void *ffio_url_child_next(void *obj
, void *prev
)
48 return prev
? NULL
: s
->opaque
;
51 static const AVClass
*ffio_url_child_class_next(const AVClass
*prev
)
53 return prev
? NULL
: &ffurl_context_class
;
56 static const AVOption ffio_url_options
[] = {
60 const AVClass ffio_url_class
= {
61 .class_name
= "AVIOContext",
62 .item_name
= av_default_item_name
,
63 .version
= LIBAVUTIL_VERSION_INT
,
64 .option
= ffio_url_options
,
65 .child_next
= ffio_url_child_next
,
66 .child_class_next
= ffio_url_child_class_next
,
69 static void fill_buffer(AVIOContext
*s
);
70 static int url_resetbuf(AVIOContext
*s
, int flags
);
72 int ffio_init_context(AVIOContext
*s
,
73 unsigned char *buffer
,
77 int (*read_packet
)(void *opaque
, uint8_t *buf
, int buf_size
),
78 int (*write_packet
)(void *opaque
, uint8_t *buf
, int buf_size
),
79 int64_t (*seek
)(void *opaque
, int64_t offset
, int whence
))
83 s
->buffer_size
= buffer_size
;
88 url_resetbuf(s
, write_flag
? AVIO_FLAG_WRITE
: AVIO_FLAG_READ
);
90 s
->write_packet
= write_packet
;
91 s
->read_packet
= read_packet
;
97 s
->seekable
= seek
? AVIO_SEEKABLE_NORMAL
: 0;
98 s
->max_packet_size
= 0;
99 s
->update_checksum
= NULL
;
101 if (!read_packet
&& !write_flag
) {
102 s
->pos
= buffer_size
;
103 s
->buf_end
= s
->buffer
+ buffer_size
;
105 s
->read_pause
= NULL
;
111 AVIOContext
*avio_alloc_context(
112 unsigned char *buffer
,
116 int (*read_packet
)(void *opaque
, uint8_t *buf
, int buf_size
),
117 int (*write_packet
)(void *opaque
, uint8_t *buf
, int buf_size
),
118 int64_t (*seek
)(void *opaque
, int64_t offset
, int whence
))
120 AVIOContext
*s
= av_mallocz(sizeof(AVIOContext
));
123 ffio_init_context(s
, buffer
, buffer_size
, write_flag
, opaque
,
124 read_packet
, write_packet
, seek
);
128 static void writeout(AVIOContext
*s
, const uint8_t *data
, int len
)
130 if (s
->write_packet
&& !s
->error
) {
131 int ret
= s
->write_packet(s
->opaque
, (uint8_t *)data
, len
);
136 s
->writeout_count
++;
140 static void flush_buffer(AVIOContext
*s
)
142 if (s
->write_flag
&& s
->buf_ptr
> s
->buffer
) {
143 writeout(s
, s
->buffer
, s
->buf_ptr
- s
->buffer
);
144 if (s
->update_checksum
) {
145 s
->checksum
= s
->update_checksum(s
->checksum
, s
->checksum_ptr
,
146 s
->buf_ptr
- s
->checksum_ptr
);
147 s
->checksum_ptr
= s
->buffer
;
150 s
->buf_ptr
= s
->buffer
;
152 s
->buf_end
= s
->buffer
;
155 void avio_w8(AVIOContext
*s
, int b
)
157 av_assert2(b
>=-128 && b
<=255);
159 if (s
->buf_ptr
>= s
->buf_end
)
163 void ffio_fill(AVIOContext
*s
, int b
, int count
)
166 int len
= FFMIN(s
->buf_end
- s
->buf_ptr
, count
);
167 memset(s
->buf_ptr
, b
, len
);
170 if (s
->buf_ptr
>= s
->buf_end
)
177 void avio_write(AVIOContext
*s
, const unsigned char *buf
, int size
)
179 if (s
->direct
&& !s
->update_checksum
) {
181 writeout(s
, buf
, size
);
185 int len
= FFMIN(s
->buf_end
- s
->buf_ptr
, size
);
186 memcpy(s
->buf_ptr
, buf
, len
);
189 if (s
->buf_ptr
>= s
->buf_end
)
197 void avio_flush(AVIOContext
*s
)
203 int64_t avio_seek(AVIOContext
*s
, int64_t offset
, int whence
)
207 int force
= whence
& AVSEEK_FORCE
;
209 whence
&= ~AVSEEK_FORCE
;
212 return AVERROR(EINVAL
);
214 buffer_size
= s
->buf_end
- s
->buffer
;
215 pos
= s
->pos
- (s
->write_flag
? 0 : buffer_size
);
217 if (whence
!= SEEK_CUR
&& whence
!= SEEK_SET
)
218 return AVERROR(EINVAL
);
220 if (whence
== SEEK_CUR
) {
221 offset1
= pos
+ (s
->buf_ptr
- s
->buffer
);
227 return AVERROR(EINVAL
);
229 offset1
= offset
- pos
;
230 if (!s
->must_flush
&& (!s
->direct
|| !s
->seek
) &&
231 offset1
>= 0 && offset1
<= buffer_size
) {
232 /* can do the seek inside the buffer */
233 s
->buf_ptr
= s
->buffer
+ offset1
;
234 } else if ((!s
->seekable
||
235 offset1
<= s
->buf_end
+ SHORT_SEEK_THRESHOLD
- s
->buffer
) &&
236 !s
->write_flag
&& offset1
>= 0 &&
237 (!s
->direct
|| !s
->seek
) &&
238 (whence
!= SEEK_END
|| force
)) {
239 while(s
->pos
< offset
&& !s
->eof_reached
)
243 s
->buf_ptr
= s
->buf_end
+ offset
- s
->pos
;
244 } else if(!s
->write_flag
&& offset1
< 0 && -offset1
< buffer_size
>>1 && s
->seek
&& offset
> 0) {
247 pos
-= FFMIN(buffer_size
>>1, pos
);
248 if ((res
= s
->seek(s
->opaque
, pos
, SEEK_SET
)) < 0)
251 s
->buf_ptr
= s
->buffer
;
255 return avio_seek(s
, offset
, SEEK_SET
| force
);
263 return AVERROR(EPIPE
);
264 if ((res
= s
->seek(s
->opaque
, offset
, SEEK_SET
)) < 0)
268 s
->buf_end
= s
->buffer
;
269 s
->buf_ptr
= s
->buffer
;
276 int64_t avio_skip(AVIOContext
*s
, int64_t offset
)
278 return avio_seek(s
, offset
, SEEK_CUR
);
281 int64_t avio_size(AVIOContext
*s
)
286 return AVERROR(EINVAL
);
289 return AVERROR(ENOSYS
);
290 size
= s
->seek(s
->opaque
, 0, AVSEEK_SIZE
);
292 if ((size
= s
->seek(s
->opaque
, -1, SEEK_END
)) < 0)
295 s
->seek(s
->opaque
, s
->pos
, SEEK_SET
);
300 int avio_feof(AVIOContext
*s
)
308 return s
->eof_reached
;
312 int url_feof(AVIOContext
*s
)
318 void avio_wl32(AVIOContext
*s
, unsigned int val
)
320 avio_w8(s
, (uint8_t) val
);
321 avio_w8(s
, (uint8_t)(val
>> 8 ));
322 avio_w8(s
, (uint8_t)(val
>> 16));
323 avio_w8(s
, val
>> 24 );
326 void avio_wb32(AVIOContext
*s
, unsigned int val
)
328 avio_w8(s
, val
>> 24 );
329 avio_w8(s
, (uint8_t)(val
>> 16));
330 avio_w8(s
, (uint8_t)(val
>> 8 ));
331 avio_w8(s
, (uint8_t) val
);
334 int avio_put_str(AVIOContext
*s
, const char *str
)
339 avio_write(s
, (const unsigned char *) str
, len
);
345 int avio_put_str16le(AVIOContext
*s
, const char *str
)
347 const uint8_t *q
= str
;
355 GET_UTF8(ch
, *q
++, goto invalid
;)
356 PUT_UTF16(ch
, tmp
, avio_wl16(s
, tmp
); ret
+= 2;)
359 av_log(s
, AV_LOG_ERROR
, "Invaid UTF8 sequence in avio_put_str16le\n");
360 err
= AVERROR(EINVAL
);
369 int ff_get_v_length(uint64_t val
)
379 void ff_put_v(AVIOContext
*bc
, uint64_t val
)
381 int i
= ff_get_v_length(val
);
384 avio_w8(bc
, 128 | (uint8_t)(val
>> (7*i
)));
386 avio_w8(bc
, val
& 127);
389 void avio_wl64(AVIOContext
*s
, uint64_t val
)
391 avio_wl32(s
, (uint32_t)(val
& 0xffffffff));
392 avio_wl32(s
, (uint32_t)(val
>> 32));
395 void avio_wb64(AVIOContext
*s
, uint64_t val
)
397 avio_wb32(s
, (uint32_t)(val
>> 32));
398 avio_wb32(s
, (uint32_t)(val
& 0xffffffff));
401 void avio_wl16(AVIOContext
*s
, unsigned int val
)
403 avio_w8(s
, (uint8_t)val
);
404 avio_w8(s
, (int)val
>> 8);
407 void avio_wb16(AVIOContext
*s
, unsigned int val
)
409 avio_w8(s
, (int)val
>> 8);
410 avio_w8(s
, (uint8_t)val
);
413 void avio_wl24(AVIOContext
*s
, unsigned int val
)
415 avio_wl16(s
, val
& 0xffff);
416 avio_w8(s
, (int)val
>> 16);
419 void avio_wb24(AVIOContext
*s
, unsigned int val
)
421 avio_wb16(s
, (int)val
>> 8);
422 avio_w8(s
, (uint8_t)val
);
427 static void fill_buffer(AVIOContext
*s
)
429 int max_buffer_size
= s
->max_packet_size
?
430 s
->max_packet_size
: IO_BUFFER_SIZE
;
431 uint8_t *dst
= s
->buf_end
- s
->buffer
+ max_buffer_size
< s
->buffer_size
?
432 s
->buf_end
: s
->buffer
;
433 int len
= s
->buffer_size
- (dst
- s
->buffer
);
435 /* can't fill the buffer without read_packet, just set EOF if appropriate */
436 if (!s
->read_packet
&& s
->buf_ptr
>= s
->buf_end
)
439 /* no need to do anything if EOF already reached */
443 if (s
->update_checksum
&& dst
== s
->buffer
) {
444 if (s
->buf_end
> s
->checksum_ptr
)
445 s
->checksum
= s
->update_checksum(s
->checksum
, s
->checksum_ptr
,
446 s
->buf_end
- s
->checksum_ptr
);
447 s
->checksum_ptr
= s
->buffer
;
450 /* make buffer smaller in case it ended up large after probing */
451 if (s
->read_packet
&& s
->orig_buffer_size
&& s
->buffer_size
> s
->orig_buffer_size
) {
452 if (dst
== s
->buffer
) {
453 ffio_set_buf_size(s
, s
->orig_buffer_size
);
455 s
->checksum_ptr
= dst
= s
->buffer
;
457 av_assert0(len
>= s
->orig_buffer_size
);
458 len
= s
->orig_buffer_size
;
462 len
= s
->read_packet(s
->opaque
, dst
, len
);
466 /* do not modify buffer if EOF reached so that a seek back can
467 be done without rereading data */
474 s
->buf_end
= dst
+ len
;
475 s
->bytes_read
+= len
;
479 unsigned long ff_crc04C11DB7_update(unsigned long checksum
, const uint8_t *buf
,
482 return av_crc(av_crc_get_table(AV_CRC_32_IEEE
), checksum
, buf
, len
);
485 unsigned long ff_crcA001_update(unsigned long checksum
, const uint8_t *buf
,
488 return av_crc(av_crc_get_table(AV_CRC_16_ANSI_LE
), checksum
, buf
, len
);
491 unsigned long ffio_get_checksum(AVIOContext
*s
)
493 s
->checksum
= s
->update_checksum(s
->checksum
, s
->checksum_ptr
,
494 s
->buf_ptr
- s
->checksum_ptr
);
495 s
->update_checksum
= NULL
;
499 void ffio_init_checksum(AVIOContext
*s
,
500 unsigned long (*update_checksum
)(unsigned long c
, const uint8_t *p
, unsigned int len
),
501 unsigned long checksum
)
503 s
->update_checksum
= update_checksum
;
504 if (s
->update_checksum
) {
505 s
->checksum
= checksum
;
506 s
->checksum_ptr
= s
->buf_ptr
;
510 /* XXX: put an inline version */
511 int avio_r8(AVIOContext
*s
)
513 if (s
->buf_ptr
>= s
->buf_end
)
515 if (s
->buf_ptr
< s
->buf_end
)
516 return *s
->buf_ptr
++;
520 int avio_read(AVIOContext
*s
, unsigned char *buf
, int size
)
526 len
= s
->buf_end
- s
->buf_ptr
;
529 if (len
== 0 || s
->write_flag
) {
530 if((s
->direct
|| size
> s
->buffer_size
) && !s
->update_checksum
){
532 len
= s
->read_packet(s
->opaque
, buf
, size
);
534 /* do not modify buffer if EOF reached so that a seek back can
535 be done without rereading data */
542 s
->bytes_read
+= len
;
545 s
->buf_ptr
= s
->buffer
;
546 s
->buf_end
= s
->buffer
/* + len*/;
550 len
= s
->buf_end
- s
->buf_ptr
;
555 memcpy(buf
, s
->buf_ptr
, len
);
562 if (s
->error
) return s
->error
;
563 if (avio_feof(s
)) return AVERROR_EOF
;
568 int ffio_read_indirect(AVIOContext
*s
, unsigned char *buf
, int size
, const unsigned char **data
)
570 if (s
->buf_end
- s
->buf_ptr
>= size
&& !s
->write_flag
) {
576 return avio_read(s
, buf
, size
);
580 int ffio_read_partial(AVIOContext
*s
, unsigned char *buf
, int size
)
587 if (s
->read_packet
&& s
->write_flag
) {
588 len
= s
->read_packet(s
->opaque
, buf
, size
);
594 len
= s
->buf_end
- s
->buf_ptr
;
596 /* Reset the buf_end pointer to the start of the buffer, to make sure
597 * the fill_buffer call tries to read as much data as fits into the
598 * full buffer, instead of just what space is left after buf_end.
599 * This avoids returning partial packets at the end of the buffer,
600 * for packet based inputs.
602 s
->buf_end
= s
->buf_ptr
= s
->buffer
;
604 len
= s
->buf_end
- s
->buf_ptr
;
608 memcpy(buf
, s
->buf_ptr
, len
);
611 if (s
->error
) return s
->error
;
612 if (avio_feof(s
)) return AVERROR_EOF
;
617 unsigned int avio_rl16(AVIOContext
*s
)
621 val
|= avio_r8(s
) << 8;
625 unsigned int avio_rl24(AVIOContext
*s
)
629 val
|= avio_r8(s
) << 16;
633 unsigned int avio_rl32(AVIOContext
*s
)
637 val
|= avio_rl16(s
) << 16;
641 uint64_t avio_rl64(AVIOContext
*s
)
644 val
= (uint64_t)avio_rl32(s
);
645 val
|= (uint64_t)avio_rl32(s
) << 32;
649 unsigned int avio_rb16(AVIOContext
*s
)
652 val
= avio_r8(s
) << 8;
657 unsigned int avio_rb24(AVIOContext
*s
)
660 val
= avio_rb16(s
) << 8;
664 unsigned int avio_rb32(AVIOContext
*s
)
667 val
= avio_rb16(s
) << 16;
672 int ff_get_line(AVIOContext
*s
, char *buf
, int maxlen
)
679 if (c
&& i
< maxlen
-1)
681 } while (c
!= '\n' && c
!= '\r' && c
);
682 if (c
== '\r' && avio_r8(s
) != '\n' && !avio_feof(s
))
689 int avio_get_str(AVIOContext
*s
, int maxlen
, char *buf
, int buflen
)
694 return AVERROR(EINVAL
);
695 // reserve 1 byte for terminating 0
696 buflen
= FFMIN(buflen
- 1, maxlen
);
697 for (i
= 0; i
< buflen
; i
++)
698 if (!(buf
[i
] = avio_r8(s
)))
701 for (; i
< maxlen
; i
++)
707 #define GET_STR16(type, read) \
708 int avio_get_str16 ##type(AVIOContext *pb, int maxlen, char *buf, int buflen)\
713 return AVERROR(EINVAL); \
714 while (ret + 1 < maxlen) {\
717 GET_UTF16(ch, (ret += 2) <= maxlen ? read(pb) : 0, break;)\
720 PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;)\
726 GET_STR16(le, avio_rl16)
727 GET_STR16(be
, avio_rb16
)
731 uint64_t avio_rb64(AVIOContext
*s
)
734 val
= (uint64_t)avio_rb32(s
) << 32;
735 val
|= (uint64_t)avio_rb32(s
);
739 uint64_t ffio_read_varlen(AVIOContext
*bc
){
745 val
= (val
<<7) + (tmp
&127);
750 int ffio_fdopen(AVIOContext
**s
, URLContext
*h
)
753 int buffer_size
, max_packet_size
;
755 max_packet_size
= h
->max_packet_size
;
756 if (max_packet_size
) {
757 buffer_size
= max_packet_size
; /* no need to bufferize more than one packet */
759 buffer_size
= IO_BUFFER_SIZE
;
761 buffer
= av_malloc(buffer_size
);
763 return AVERROR(ENOMEM
);
765 *s
= avio_alloc_context(buffer
, buffer_size
, h
->flags
& AVIO_FLAG_WRITE
, h
,
766 (void*)ffurl_read
, (void*)ffurl_write
, (void*)ffurl_seek
);
769 return AVERROR(ENOMEM
);
771 (*s
)->direct
= h
->flags
& AVIO_FLAG_DIRECT
;
772 (*s
)->seekable
= h
->is_streamed
? 0 : AVIO_SEEKABLE_NORMAL
;
773 (*s
)->max_packet_size
= max_packet_size
;
775 (*s
)->read_pause
= (int (*)(void *, int))h
->prot
->url_read_pause
;
776 (*s
)->read_seek
= (int64_t (*)(void *, int, int64_t, int))h
->prot
->url_read_seek
;
778 (*s
)->av_class
= &ffio_url_class
;
782 int ffio_ensure_seekback(AVIOContext
*s
, int64_t buf_size
)
785 int max_buffer_size
= s
->max_packet_size
?
786 s
->max_packet_size
: IO_BUFFER_SIZE
;
787 int filled
= s
->buf_end
- s
->buffer
;
789 buf_size
+= s
->buf_ptr
- s
->buffer
+ max_buffer_size
;
791 if (buf_size
< filled
|| s
->seekable
)
793 av_assert0(!s
->write_flag
);
795 buffer
= av_malloc(buf_size
);
797 return AVERROR(ENOMEM
);
799 memcpy(buffer
, s
->buffer
, filled
);
801 s
->buf_ptr
= buffer
+ (s
->buf_ptr
- s
->buffer
);
802 s
->buf_end
= buffer
+ (s
->buf_end
- s
->buffer
);
804 s
->buffer_size
= buf_size
;
808 int ffio_set_buf_size(AVIOContext
*s
, int buf_size
)
811 buffer
= av_malloc(buf_size
);
813 return AVERROR(ENOMEM
);
817 s
->orig_buffer_size
=
818 s
->buffer_size
= buf_size
;
820 url_resetbuf(s
, s
->write_flag
? AVIO_FLAG_WRITE
: AVIO_FLAG_READ
);
824 static int url_resetbuf(AVIOContext
*s
, int flags
)
826 av_assert1(flags
== AVIO_FLAG_WRITE
|| flags
== AVIO_FLAG_READ
);
828 if (flags
& AVIO_FLAG_WRITE
) {
829 s
->buf_end
= s
->buffer
+ s
->buffer_size
;
832 s
->buf_end
= s
->buffer
;
838 int ffio_rewind_with_probe_data(AVIOContext
*s
, unsigned char **bufp
, int buf_size
)
840 int64_t buffer_start
;
842 int overlap
, new_size
, alloc_size
;
843 uint8_t *buf
= *bufp
;
847 return AVERROR(EINVAL
);
850 buffer_size
= s
->buf_end
- s
->buffer
;
852 /* the buffers must touch or overlap */
853 if ((buffer_start
= s
->pos
- buffer_size
) > buf_size
) {
855 return AVERROR(EINVAL
);
858 overlap
= buf_size
- buffer_start
;
859 new_size
= buf_size
+ buffer_size
- overlap
;
861 alloc_size
= FFMAX(s
->buffer_size
, new_size
);
862 if (alloc_size
> buf_size
)
863 if (!(buf
= (*bufp
) = av_realloc_f(buf
, 1, alloc_size
)))
864 return AVERROR(ENOMEM
);
866 if (new_size
> buf_size
) {
867 memcpy(buf
+ buf_size
, s
->buffer
+ overlap
, buffer_size
- overlap
);
872 s
->buf_ptr
= s
->buffer
= buf
;
873 s
->buffer_size
= alloc_size
;
875 s
->buf_end
= s
->buf_ptr
+ buf_size
;
882 int avio_open(AVIOContext
**s
, const char *filename
, int flags
)
884 return avio_open2(s
, filename
, flags
, NULL
, NULL
);
887 int avio_open2(AVIOContext
**s
, const char *filename
, int flags
,
888 const AVIOInterruptCB
*int_cb
, AVDictionary
**options
)
893 err
= ffurl_open(&h
, filename
, flags
, int_cb
, options
);
896 err
= ffio_fdopen(s
, h
);
904 int avio_close(AVIOContext
*s
)
913 av_freep(&s
->buffer
);
915 av_log(s
, AV_LOG_DEBUG
, "Statistics: %d seeks, %d writeouts\n", s
->seek_count
, s
->writeout_count
);
917 av_log(s
, AV_LOG_DEBUG
, "Statistics: %"PRId64
" bytes read, %d seeks\n", s
->bytes_read
, s
->seek_count
);
919 return ffurl_close(h
);
922 int avio_closep(AVIOContext
**s
)
924 int ret
= avio_close(*s
);
929 int avio_printf(AVIOContext
*s
, const char *fmt
, ...)
936 ret
= vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
938 avio_write(s
, buf
, strlen(buf
));
942 int avio_pause(AVIOContext
*s
, int pause
)
945 return AVERROR(ENOSYS
);
946 return s
->read_pause(s
->opaque
, pause
);
949 int64_t avio_seek_time(AVIOContext
*s
, int stream_index
,
950 int64_t timestamp
, int flags
)
952 URLContext
*h
= s
->opaque
;
955 return AVERROR(ENOSYS
);
956 ret
= s
->read_seek(h
, stream_index
, timestamp
, flags
);
959 s
->buf_ptr
= s
->buf_end
; // Flush buffer
960 pos
= s
->seek(h
, 0, SEEK_CUR
);
963 else if (pos
!= AVERROR(ENOSYS
))
969 int avio_read_to_bprint(AVIOContext
*h
, AVBPrint
*pb
, size_t max_size
)
974 ret
= avio_read(h
, buf
, FFMIN(max_size
, sizeof(buf
)));
975 if (ret
== AVERROR_EOF
)
979 av_bprint_append_data(pb
, buf
, ret
);
980 if (!av_bprint_is_complete(pb
))
981 return AVERROR(ENOMEM
);
987 /* output in a dynamic buffer */
989 typedef struct DynBuffer
{
990 int pos
, size
, allocated_size
;
993 uint8_t io_buffer
[1];
996 static int dyn_buf_write(void *opaque
, uint8_t *buf
, int buf_size
)
998 DynBuffer
*d
= opaque
;
999 unsigned new_size
, new_allocated_size
;
1001 /* reallocate buffer if needed */
1002 new_size
= d
->pos
+ buf_size
;
1003 new_allocated_size
= d
->allocated_size
;
1004 if (new_size
< d
->pos
|| new_size
> INT_MAX
/2)
1006 while (new_size
> new_allocated_size
) {
1007 if (!new_allocated_size
)
1008 new_allocated_size
= new_size
;
1010 new_allocated_size
+= new_allocated_size
/ 2 + 1;
1013 if (new_allocated_size
> d
->allocated_size
) {
1015 if ((err
= av_reallocp(&d
->buffer
, new_allocated_size
)) < 0) {
1016 d
->allocated_size
= 0;
1020 d
->allocated_size
= new_allocated_size
;
1022 memcpy(d
->buffer
+ d
->pos
, buf
, buf_size
);
1024 if (d
->pos
> d
->size
)
1029 static int dyn_packet_buf_write(void *opaque
, uint8_t *buf
, int buf_size
)
1031 unsigned char buf1
[4];
1034 /* packetized write: output the header */
1035 AV_WB32(buf1
, buf_size
);
1036 ret
= dyn_buf_write(opaque
, buf1
, 4);
1041 return dyn_buf_write(opaque
, buf
, buf_size
);
1044 static int64_t dyn_buf_seek(void *opaque
, int64_t offset
, int whence
)
1046 DynBuffer
*d
= opaque
;
1048 if (whence
== SEEK_CUR
)
1050 else if (whence
== SEEK_END
)
1052 if (offset
< 0 || offset
> 0x7fffffffLL
)
1058 static int url_open_dyn_buf_internal(AVIOContext
**s
, int max_packet_size
)
1061 unsigned io_buffer_size
= max_packet_size
? max_packet_size
: 1024;
1063 if (sizeof(DynBuffer
) + io_buffer_size
< io_buffer_size
)
1065 d
= av_mallocz(sizeof(DynBuffer
) + io_buffer_size
);
1067 return AVERROR(ENOMEM
);
1068 d
->io_buffer_size
= io_buffer_size
;
1069 *s
= avio_alloc_context(d
->io_buffer
, d
->io_buffer_size
, 1, d
, NULL
,
1070 max_packet_size
? dyn_packet_buf_write
: dyn_buf_write
,
1071 max_packet_size
? NULL
: dyn_buf_seek
);
1074 return AVERROR(ENOMEM
);
1076 (*s
)->max_packet_size
= max_packet_size
;
1080 int avio_open_dyn_buf(AVIOContext
**s
)
1082 return url_open_dyn_buf_internal(s
, 0);
1085 int ffio_open_dyn_packet_buf(AVIOContext
**s
, int max_packet_size
)
1087 if (max_packet_size
<= 0)
1089 return url_open_dyn_buf_internal(s
, max_packet_size
);
1092 int avio_close_dyn_buf(AVIOContext
*s
, uint8_t **pbuffer
)
1096 static const char padbuf
[FF_INPUT_BUFFER_PADDING_SIZE
] = {0};
1104 /* don't attempt to pad fixed-size packet buffers */
1105 if (!s
->max_packet_size
) {
1106 avio_write(s
, padbuf
, sizeof(padbuf
));
1107 padding
= FF_INPUT_BUFFER_PADDING_SIZE
;
1113 *pbuffer
= d
->buffer
;
1117 return size
- padding
;
1120 static int null_buf_write(void *opaque
, uint8_t *buf
, int buf_size
)
1122 DynBuffer
*d
= opaque
;
1125 if (d
->pos
> d
->size
)
1130 int ffio_open_null_buf(AVIOContext
**s
)
1132 int ret
= url_open_dyn_buf_internal(s
, 0);
1134 AVIOContext
*pb
= *s
;
1135 pb
->write_packet
= null_buf_write
;
1140 int ffio_close_null_buf(AVIOContext
*s
)
1142 DynBuffer
*d
= s
->opaque
;