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
->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
;
153 void avio_w8(AVIOContext
*s
, int b
)
155 av_assert2(b
>=-128 && b
<=255);
157 if (s
->buf_ptr
>= s
->buf_end
)
161 void ffio_fill(AVIOContext
*s
, int b
, int count
)
164 int len
= FFMIN(s
->buf_end
- s
->buf_ptr
, count
);
165 memset(s
->buf_ptr
, b
, len
);
168 if (s
->buf_ptr
>= s
->buf_end
)
175 void avio_write(AVIOContext
*s
, const unsigned char *buf
, int size
)
177 if (s
->direct
&& !s
->update_checksum
) {
179 writeout(s
, buf
, size
);
183 int len
= FFMIN(s
->buf_end
- s
->buf_ptr
, size
);
184 memcpy(s
->buf_ptr
, buf
, len
);
187 if (s
->buf_ptr
>= s
->buf_end
)
195 void avio_flush(AVIOContext
*s
)
201 int64_t avio_seek(AVIOContext
*s
, int64_t offset
, int whence
)
205 int force
= whence
& AVSEEK_FORCE
;
207 whence
&= ~AVSEEK_FORCE
;
210 return AVERROR(EINVAL
);
212 buffer_size
= s
->buf_end
- s
->buffer
;
213 pos
= s
->pos
- (s
->write_flag
? 0 : buffer_size
);
215 if (whence
!= SEEK_CUR
&& whence
!= SEEK_SET
)
216 return AVERROR(EINVAL
);
218 if (whence
== SEEK_CUR
) {
219 offset1
= pos
+ (s
->buf_ptr
- s
->buffer
);
224 offset1
= offset
- pos
;
225 if (!s
->must_flush
&& (!s
->direct
|| !s
->seek
) &&
226 offset1
>= 0 && offset1
<= buffer_size
) {
227 /* can do the seek inside the buffer */
228 s
->buf_ptr
= s
->buffer
+ offset1
;
229 } else if ((!s
->seekable
||
230 offset1
<= s
->buf_end
+ SHORT_SEEK_THRESHOLD
- s
->buffer
) &&
231 !s
->write_flag
&& offset1
>= 0 &&
232 (!s
->direct
|| !s
->seek
) &&
233 (whence
!= SEEK_END
|| force
)) {
234 while(s
->pos
< offset
&& !s
->eof_reached
)
238 s
->buf_ptr
= s
->buf_end
+ offset
- s
->pos
;
239 } else if(!s
->write_flag
&& offset1
< 0 && -offset1
< buffer_size
>>1 && s
->seek
&& offset
> 0) {
242 pos
-= FFMIN(buffer_size
>>1, pos
);
243 if ((res
= s
->seek(s
->opaque
, pos
, SEEK_SET
)) < 0)
246 s
->buf_ptr
= s
->buffer
;
250 return avio_seek(s
, offset
, SEEK_SET
| force
);
258 return AVERROR(EPIPE
);
259 if ((res
= s
->seek(s
->opaque
, offset
, SEEK_SET
)) < 0)
263 s
->buf_end
= s
->buffer
;
264 s
->buf_ptr
= s
->buffer
;
271 int64_t avio_skip(AVIOContext
*s
, int64_t offset
)
273 return avio_seek(s
, offset
, SEEK_CUR
);
276 int64_t avio_size(AVIOContext
*s
)
281 return AVERROR(EINVAL
);
284 return AVERROR(ENOSYS
);
285 size
= s
->seek(s
->opaque
, 0, AVSEEK_SIZE
);
287 if ((size
= s
->seek(s
->opaque
, -1, SEEK_END
)) < 0)
290 s
->seek(s
->opaque
, s
->pos
, SEEK_SET
);
295 int avio_feof(AVIOContext
*s
)
303 return s
->eof_reached
;
307 int url_feof(AVIOContext
*s
)
313 void avio_wl32(AVIOContext
*s
, unsigned int val
)
315 avio_w8(s
, (uint8_t) val
);
316 avio_w8(s
, (uint8_t)(val
>> 8 ));
317 avio_w8(s
, (uint8_t)(val
>> 16));
318 avio_w8(s
, val
>> 24 );
321 void avio_wb32(AVIOContext
*s
, unsigned int val
)
323 avio_w8(s
, val
>> 24 );
324 avio_w8(s
, (uint8_t)(val
>> 16));
325 avio_w8(s
, (uint8_t)(val
>> 8 ));
326 avio_w8(s
, (uint8_t) val
);
329 int avio_put_str(AVIOContext
*s
, const char *str
)
334 avio_write(s
, (const unsigned char *) str
, len
);
340 int avio_put_str16le(AVIOContext
*s
, const char *str
)
342 const uint8_t *q
= str
;
350 GET_UTF8(ch
, *q
++, goto invalid
;)
351 PUT_UTF16(ch
, tmp
, avio_wl16(s
, tmp
); ret
+= 2;)
354 av_log(s
, AV_LOG_ERROR
, "Invaid UTF8 sequence in avio_put_str16le\n");
355 err
= AVERROR(EINVAL
);
364 int ff_get_v_length(uint64_t val
)
374 void ff_put_v(AVIOContext
*bc
, uint64_t val
)
376 int i
= ff_get_v_length(val
);
379 avio_w8(bc
, 128 | (uint8_t)(val
>> (7*i
)));
381 avio_w8(bc
, val
& 127);
384 void avio_wl64(AVIOContext
*s
, uint64_t val
)
386 avio_wl32(s
, (uint32_t)(val
& 0xffffffff));
387 avio_wl32(s
, (uint32_t)(val
>> 32));
390 void avio_wb64(AVIOContext
*s
, uint64_t val
)
392 avio_wb32(s
, (uint32_t)(val
>> 32));
393 avio_wb32(s
, (uint32_t)(val
& 0xffffffff));
396 void avio_wl16(AVIOContext
*s
, unsigned int val
)
398 avio_w8(s
, (uint8_t)val
);
399 avio_w8(s
, (int)val
>> 8);
402 void avio_wb16(AVIOContext
*s
, unsigned int val
)
404 avio_w8(s
, (int)val
>> 8);
405 avio_w8(s
, (uint8_t)val
);
408 void avio_wl24(AVIOContext
*s
, unsigned int val
)
410 avio_wl16(s
, val
& 0xffff);
411 avio_w8(s
, (int)val
>> 16);
414 void avio_wb24(AVIOContext
*s
, unsigned int val
)
416 avio_wb16(s
, (int)val
>> 8);
417 avio_w8(s
, (uint8_t)val
);
422 static void fill_buffer(AVIOContext
*s
)
424 int max_buffer_size
= s
->max_packet_size
?
425 s
->max_packet_size
: IO_BUFFER_SIZE
;
426 uint8_t *dst
= s
->buf_end
- s
->buffer
+ max_buffer_size
< s
->buffer_size
?
427 s
->buf_end
: s
->buffer
;
428 int len
= s
->buffer_size
- (dst
- s
->buffer
);
430 /* can't fill the buffer without read_packet, just set EOF if appropriate */
431 if (!s
->read_packet
&& s
->buf_ptr
>= s
->buf_end
)
434 /* no need to do anything if EOF already reached */
438 if (s
->update_checksum
&& dst
== s
->buffer
) {
439 if (s
->buf_end
> s
->checksum_ptr
)
440 s
->checksum
= s
->update_checksum(s
->checksum
, s
->checksum_ptr
,
441 s
->buf_end
- s
->checksum_ptr
);
442 s
->checksum_ptr
= s
->buffer
;
445 /* make buffer smaller in case it ended up large after probing */
446 if (s
->read_packet
&& s
->orig_buffer_size
&& s
->buffer_size
> s
->orig_buffer_size
) {
447 if (dst
== s
->buffer
) {
448 ffio_set_buf_size(s
, s
->orig_buffer_size
);
450 s
->checksum_ptr
= dst
= s
->buffer
;
452 av_assert0(len
>= s
->orig_buffer_size
);
453 len
= s
->orig_buffer_size
;
457 len
= s
->read_packet(s
->opaque
, dst
, len
);
461 /* do not modify buffer if EOF reached so that a seek back can
462 be done without rereading data */
469 s
->buf_end
= dst
+ len
;
470 s
->bytes_read
+= len
;
474 unsigned long ff_crc04C11DB7_update(unsigned long checksum
, const uint8_t *buf
,
477 return av_crc(av_crc_get_table(AV_CRC_32_IEEE
), checksum
, buf
, len
);
480 unsigned long ff_crcA001_update(unsigned long checksum
, const uint8_t *buf
,
483 return av_crc(av_crc_get_table(AV_CRC_16_ANSI_LE
), checksum
, buf
, len
);
486 unsigned long ffio_get_checksum(AVIOContext
*s
)
488 s
->checksum
= s
->update_checksum(s
->checksum
, s
->checksum_ptr
,
489 s
->buf_ptr
- s
->checksum_ptr
);
490 s
->update_checksum
= NULL
;
494 void ffio_init_checksum(AVIOContext
*s
,
495 unsigned long (*update_checksum
)(unsigned long c
, const uint8_t *p
, unsigned int len
),
496 unsigned long checksum
)
498 s
->update_checksum
= update_checksum
;
499 if (s
->update_checksum
) {
500 s
->checksum
= checksum
;
501 s
->checksum_ptr
= s
->buf_ptr
;
505 /* XXX: put an inline version */
506 int avio_r8(AVIOContext
*s
)
508 if (s
->buf_ptr
>= s
->buf_end
)
510 if (s
->buf_ptr
< s
->buf_end
)
511 return *s
->buf_ptr
++;
515 int avio_read(AVIOContext
*s
, unsigned char *buf
, int size
)
521 len
= s
->buf_end
- s
->buf_ptr
;
524 if (len
== 0 || s
->write_flag
) {
525 if((s
->direct
|| size
> s
->buffer_size
) && !s
->update_checksum
){
527 len
= s
->read_packet(s
->opaque
, buf
, size
);
529 /* do not modify buffer if EOF reached so that a seek back can
530 be done without rereading data */
537 s
->bytes_read
+= len
;
540 s
->buf_ptr
= s
->buffer
;
541 s
->buf_end
= s
->buffer
/* + len*/;
545 len
= s
->buf_end
- s
->buf_ptr
;
550 memcpy(buf
, s
->buf_ptr
, len
);
557 if (s
->error
) return s
->error
;
558 if (avio_feof(s
)) return AVERROR_EOF
;
563 int ffio_read_indirect(AVIOContext
*s
, unsigned char *buf
, int size
, const unsigned char **data
)
565 if (s
->buf_end
- s
->buf_ptr
>= size
&& !s
->write_flag
) {
571 return avio_read(s
, buf
, size
);
575 int ffio_read_partial(AVIOContext
*s
, unsigned char *buf
, int size
)
582 if (s
->read_packet
&& s
->write_flag
) {
583 len
= s
->read_packet(s
->opaque
, buf
, size
);
589 len
= s
->buf_end
- s
->buf_ptr
;
591 /* Reset the buf_end pointer to the start of the buffer, to make sure
592 * the fill_buffer call tries to read as much data as fits into the
593 * full buffer, instead of just what space is left after buf_end.
594 * This avoids returning partial packets at the end of the buffer,
595 * for packet based inputs.
597 s
->buf_end
= s
->buf_ptr
= s
->buffer
;
599 len
= s
->buf_end
- s
->buf_ptr
;
603 memcpy(buf
, s
->buf_ptr
, len
);
606 if (s
->error
) return s
->error
;
607 if (avio_feof(s
)) return AVERROR_EOF
;
612 unsigned int avio_rl16(AVIOContext
*s
)
616 val
|= avio_r8(s
) << 8;
620 unsigned int avio_rl24(AVIOContext
*s
)
624 val
|= avio_r8(s
) << 16;
628 unsigned int avio_rl32(AVIOContext
*s
)
632 val
|= avio_rl16(s
) << 16;
636 uint64_t avio_rl64(AVIOContext
*s
)
639 val
= (uint64_t)avio_rl32(s
);
640 val
|= (uint64_t)avio_rl32(s
) << 32;
644 unsigned int avio_rb16(AVIOContext
*s
)
647 val
= avio_r8(s
) << 8;
652 unsigned int avio_rb24(AVIOContext
*s
)
655 val
= avio_rb16(s
) << 8;
659 unsigned int avio_rb32(AVIOContext
*s
)
662 val
= avio_rb16(s
) << 16;
667 int ff_get_line(AVIOContext
*s
, char *buf
, int maxlen
)
674 if (c
&& i
< maxlen
-1)
676 } while (c
!= '\n' && c
!= '\r' && c
);
677 if (c
== '\r' && avio_r8(s
) != '\n')
684 int avio_get_str(AVIOContext
*s
, int maxlen
, char *buf
, int buflen
)
689 return AVERROR(EINVAL
);
690 // reserve 1 byte for terminating 0
691 buflen
= FFMIN(buflen
- 1, maxlen
);
692 for (i
= 0; i
< buflen
; i
++)
693 if (!(buf
[i
] = avio_r8(s
)))
696 for (; i
< maxlen
; i
++)
702 #define GET_STR16(type, read) \
703 int avio_get_str16 ##type(AVIOContext *pb, int maxlen, char *buf, int buflen)\
708 return AVERROR(EINVAL); \
709 while (ret + 1 < maxlen) {\
712 GET_UTF16(ch, (ret += 2) <= maxlen ? read(pb) : 0, break;)\
715 PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;)\
721 GET_STR16(le, avio_rl16)
722 GET_STR16(be
, avio_rb16
)
726 uint64_t avio_rb64(AVIOContext
*s
)
729 val
= (uint64_t)avio_rb32(s
) << 32;
730 val
|= (uint64_t)avio_rb32(s
);
734 uint64_t ffio_read_varlen(AVIOContext
*bc
){
740 val
= (val
<<7) + (tmp
&127);
745 int ffio_fdopen(AVIOContext
**s
, URLContext
*h
)
748 int buffer_size
, max_packet_size
;
750 max_packet_size
= h
->max_packet_size
;
751 if (max_packet_size
) {
752 buffer_size
= max_packet_size
; /* no need to bufferize more than one packet */
754 buffer_size
= IO_BUFFER_SIZE
;
756 buffer
= av_malloc(buffer_size
);
758 return AVERROR(ENOMEM
);
760 *s
= avio_alloc_context(buffer
, buffer_size
, h
->flags
& AVIO_FLAG_WRITE
, h
,
761 (void*)ffurl_read
, (void*)ffurl_write
, (void*)ffurl_seek
);
764 return AVERROR(ENOMEM
);
766 (*s
)->direct
= h
->flags
& AVIO_FLAG_DIRECT
;
767 (*s
)->seekable
= h
->is_streamed
? 0 : AVIO_SEEKABLE_NORMAL
;
768 (*s
)->max_packet_size
= max_packet_size
;
770 (*s
)->read_pause
= (int (*)(void *, int))h
->prot
->url_read_pause
;
771 (*s
)->read_seek
= (int64_t (*)(void *, int, int64_t, int))h
->prot
->url_read_seek
;
773 (*s
)->av_class
= &ffio_url_class
;
777 int ffio_ensure_seekback(AVIOContext
*s
, int64_t buf_size
)
780 int max_buffer_size
= s
->max_packet_size
?
781 s
->max_packet_size
: IO_BUFFER_SIZE
;
782 int filled
= s
->buf_end
- s
->buffer
;
784 buf_size
+= s
->buf_ptr
- s
->buffer
+ max_buffer_size
;
786 if (buf_size
< filled
|| s
->seekable
)
788 av_assert0(!s
->write_flag
);
790 buffer
= av_malloc(buf_size
);
792 return AVERROR(ENOMEM
);
794 memcpy(buffer
, s
->buffer
, filled
);
796 s
->buf_ptr
= buffer
+ (s
->buf_ptr
- s
->buffer
);
797 s
->buf_end
= buffer
+ (s
->buf_end
- s
->buffer
);
799 s
->buffer_size
= buf_size
;
803 int ffio_set_buf_size(AVIOContext
*s
, int buf_size
)
806 buffer
= av_malloc(buf_size
);
808 return AVERROR(ENOMEM
);
812 s
->orig_buffer_size
=
813 s
->buffer_size
= buf_size
;
815 url_resetbuf(s
, s
->write_flag
? AVIO_FLAG_WRITE
: AVIO_FLAG_READ
);
819 static int url_resetbuf(AVIOContext
*s
, int flags
)
821 av_assert1(flags
== AVIO_FLAG_WRITE
|| flags
== AVIO_FLAG_READ
);
823 if (flags
& AVIO_FLAG_WRITE
) {
824 s
->buf_end
= s
->buffer
+ s
->buffer_size
;
827 s
->buf_end
= s
->buffer
;
833 int ffio_rewind_with_probe_data(AVIOContext
*s
, unsigned char **bufp
, int buf_size
)
835 int64_t buffer_start
;
837 int overlap
, new_size
, alloc_size
;
838 uint8_t *buf
= *bufp
;
842 return AVERROR(EINVAL
);
845 buffer_size
= s
->buf_end
- s
->buffer
;
847 /* the buffers must touch or overlap */
848 if ((buffer_start
= s
->pos
- buffer_size
) > buf_size
) {
850 return AVERROR(EINVAL
);
853 overlap
= buf_size
- buffer_start
;
854 new_size
= buf_size
+ buffer_size
- overlap
;
856 alloc_size
= FFMAX(s
->buffer_size
, new_size
);
857 if (alloc_size
> buf_size
)
858 if (!(buf
= (*bufp
) = av_realloc_f(buf
, 1, alloc_size
)))
859 return AVERROR(ENOMEM
);
861 if (new_size
> buf_size
) {
862 memcpy(buf
+ buf_size
, s
->buffer
+ overlap
, buffer_size
- overlap
);
867 s
->buf_ptr
= s
->buffer
= buf
;
868 s
->buffer_size
= alloc_size
;
870 s
->buf_end
= s
->buf_ptr
+ buf_size
;
877 int avio_open(AVIOContext
**s
, const char *filename
, int flags
)
879 return avio_open2(s
, filename
, flags
, NULL
, NULL
);
882 int avio_open2(AVIOContext
**s
, const char *filename
, int flags
,
883 const AVIOInterruptCB
*int_cb
, AVDictionary
**options
)
888 err
= ffurl_open(&h
, filename
, flags
, int_cb
, options
);
891 err
= ffio_fdopen(s
, h
);
899 int avio_close(AVIOContext
*s
)
908 av_freep(&s
->buffer
);
910 av_log(s
, AV_LOG_DEBUG
, "Statistics: %d seeks, %d writeouts\n", s
->seek_count
, s
->writeout_count
);
912 av_log(s
, AV_LOG_DEBUG
, "Statistics: %"PRId64
" bytes read, %d seeks\n", s
->bytes_read
, s
->seek_count
);
914 return ffurl_close(h
);
917 int avio_closep(AVIOContext
**s
)
919 int ret
= avio_close(*s
);
924 int avio_printf(AVIOContext
*s
, const char *fmt
, ...)
931 ret
= vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
933 avio_write(s
, buf
, strlen(buf
));
937 int avio_pause(AVIOContext
*s
, int pause
)
940 return AVERROR(ENOSYS
);
941 return s
->read_pause(s
->opaque
, pause
);
944 int64_t avio_seek_time(AVIOContext
*s
, int stream_index
,
945 int64_t timestamp
, int flags
)
947 URLContext
*h
= s
->opaque
;
950 return AVERROR(ENOSYS
);
951 ret
= s
->read_seek(h
, stream_index
, timestamp
, flags
);
954 s
->buf_ptr
= s
->buf_end
; // Flush buffer
955 pos
= s
->seek(h
, 0, SEEK_CUR
);
958 else if (pos
!= AVERROR(ENOSYS
))
964 int avio_read_to_bprint(AVIOContext
*h
, AVBPrint
*pb
, size_t max_size
)
969 ret
= avio_read(h
, buf
, FFMIN(max_size
, sizeof(buf
)));
970 if (ret
== AVERROR_EOF
)
974 av_bprint_append_data(pb
, buf
, ret
);
975 if (!av_bprint_is_complete(pb
))
976 return AVERROR(ENOMEM
);
982 /* output in a dynamic buffer */
984 typedef struct DynBuffer
{
985 int pos
, size
, allocated_size
;
988 uint8_t io_buffer
[1];
991 static int dyn_buf_write(void *opaque
, uint8_t *buf
, int buf_size
)
993 DynBuffer
*d
= opaque
;
994 unsigned new_size
, new_allocated_size
;
996 /* reallocate buffer if needed */
997 new_size
= d
->pos
+ buf_size
;
998 new_allocated_size
= d
->allocated_size
;
999 if (new_size
< d
->pos
|| new_size
> INT_MAX
/2)
1001 while (new_size
> new_allocated_size
) {
1002 if (!new_allocated_size
)
1003 new_allocated_size
= new_size
;
1005 new_allocated_size
+= new_allocated_size
/ 2 + 1;
1008 if (new_allocated_size
> d
->allocated_size
) {
1010 if ((err
= av_reallocp(&d
->buffer
, new_allocated_size
)) < 0) {
1011 d
->allocated_size
= 0;
1015 d
->allocated_size
= new_allocated_size
;
1017 memcpy(d
->buffer
+ d
->pos
, buf
, buf_size
);
1019 if (d
->pos
> d
->size
)
1024 static int dyn_packet_buf_write(void *opaque
, uint8_t *buf
, int buf_size
)
1026 unsigned char buf1
[4];
1029 /* packetized write: output the header */
1030 AV_WB32(buf1
, buf_size
);
1031 ret
= dyn_buf_write(opaque
, buf1
, 4);
1036 return dyn_buf_write(opaque
, buf
, buf_size
);
1039 static int64_t dyn_buf_seek(void *opaque
, int64_t offset
, int whence
)
1041 DynBuffer
*d
= opaque
;
1043 if (whence
== SEEK_CUR
)
1045 else if (whence
== SEEK_END
)
1047 if (offset
< 0 || offset
> 0x7fffffffLL
)
1053 static int url_open_dyn_buf_internal(AVIOContext
**s
, int max_packet_size
)
1056 unsigned io_buffer_size
= max_packet_size
? max_packet_size
: 1024;
1058 if (sizeof(DynBuffer
) + io_buffer_size
< io_buffer_size
)
1060 d
= av_mallocz(sizeof(DynBuffer
) + io_buffer_size
);
1062 return AVERROR(ENOMEM
);
1063 d
->io_buffer_size
= io_buffer_size
;
1064 *s
= avio_alloc_context(d
->io_buffer
, d
->io_buffer_size
, 1, d
, NULL
,
1065 max_packet_size
? dyn_packet_buf_write
: dyn_buf_write
,
1066 max_packet_size
? NULL
: dyn_buf_seek
);
1069 return AVERROR(ENOMEM
);
1071 (*s
)->max_packet_size
= max_packet_size
;
1075 int avio_open_dyn_buf(AVIOContext
**s
)
1077 return url_open_dyn_buf_internal(s
, 0);
1080 int ffio_open_dyn_packet_buf(AVIOContext
**s
, int max_packet_size
)
1082 if (max_packet_size
<= 0)
1084 return url_open_dyn_buf_internal(s
, max_packet_size
);
1087 int avio_close_dyn_buf(AVIOContext
*s
, uint8_t **pbuffer
)
1091 static const char padbuf
[FF_INPUT_BUFFER_PADDING_SIZE
] = {0};
1100 /* don't attempt to pad fixed-size packet buffers */
1101 if (!s
->max_packet_size
) {
1102 avio_write(s
, padbuf
, sizeof(padbuf
));
1103 padding
= FF_INPUT_BUFFER_PADDING_SIZE
;
1108 *pbuffer
= d
->buffer
;
1112 return size
- padding
;
1115 static int null_buf_write(void *opaque
, uint8_t *buf
, int buf_size
)
1117 DynBuffer
*d
= opaque
;
1120 if (d
->pos
> d
->size
)
1125 int ffio_open_null_buf(AVIOContext
**s
)
1127 int ret
= url_open_dyn_buf_internal(s
, 0);
1129 AVIOContext
*pb
= *s
;
1130 pb
->write_packet
= null_buf_write
;
1135 int ffio_close_null_buf(AVIOContext
*s
)
1137 DynBuffer
*d
= s
->opaque
;