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
);
226 offset1
= offset
- pos
;
227 if (!s
->must_flush
&& (!s
->direct
|| !s
->seek
) &&
228 offset1
>= 0 && offset1
<= buffer_size
) {
229 /* can do the seek inside the buffer */
230 s
->buf_ptr
= s
->buffer
+ offset1
;
231 } else if ((!s
->seekable
||
232 offset1
<= s
->buf_end
+ SHORT_SEEK_THRESHOLD
- s
->buffer
) &&
233 !s
->write_flag
&& offset1
>= 0 &&
234 (!s
->direct
|| !s
->seek
) &&
235 (whence
!= SEEK_END
|| force
)) {
236 while(s
->pos
< offset
&& !s
->eof_reached
)
240 s
->buf_ptr
= s
->buf_end
+ offset
- s
->pos
;
241 } else if(!s
->write_flag
&& offset1
< 0 && -offset1
< buffer_size
>>1 && s
->seek
&& offset
> 0) {
244 pos
-= FFMIN(buffer_size
>>1, pos
);
245 if ((res
= s
->seek(s
->opaque
, pos
, SEEK_SET
)) < 0)
248 s
->buf_ptr
= s
->buffer
;
252 return avio_seek(s
, offset
, SEEK_SET
| force
);
260 return AVERROR(EPIPE
);
261 if ((res
= s
->seek(s
->opaque
, offset
, SEEK_SET
)) < 0)
265 s
->buf_end
= s
->buffer
;
266 s
->buf_ptr
= s
->buffer
;
273 int64_t avio_skip(AVIOContext
*s
, int64_t offset
)
275 return avio_seek(s
, offset
, SEEK_CUR
);
278 int64_t avio_size(AVIOContext
*s
)
283 return AVERROR(EINVAL
);
286 return AVERROR(ENOSYS
);
287 size
= s
->seek(s
->opaque
, 0, AVSEEK_SIZE
);
289 if ((size
= s
->seek(s
->opaque
, -1, SEEK_END
)) < 0)
292 s
->seek(s
->opaque
, s
->pos
, SEEK_SET
);
297 int avio_feof(AVIOContext
*s
)
305 return s
->eof_reached
;
309 int url_feof(AVIOContext
*s
)
315 void avio_wl32(AVIOContext
*s
, unsigned int val
)
317 avio_w8(s
, (uint8_t) val
);
318 avio_w8(s
, (uint8_t)(val
>> 8 ));
319 avio_w8(s
, (uint8_t)(val
>> 16));
320 avio_w8(s
, val
>> 24 );
323 void avio_wb32(AVIOContext
*s
, unsigned int val
)
325 avio_w8(s
, val
>> 24 );
326 avio_w8(s
, (uint8_t)(val
>> 16));
327 avio_w8(s
, (uint8_t)(val
>> 8 ));
328 avio_w8(s
, (uint8_t) val
);
331 int avio_put_str(AVIOContext
*s
, const char *str
)
336 avio_write(s
, (const unsigned char *) str
, len
);
342 int avio_put_str16le(AVIOContext
*s
, const char *str
)
344 const uint8_t *q
= str
;
352 GET_UTF8(ch
, *q
++, goto invalid
;)
353 PUT_UTF16(ch
, tmp
, avio_wl16(s
, tmp
); ret
+= 2;)
356 av_log(s
, AV_LOG_ERROR
, "Invaid UTF8 sequence in avio_put_str16le\n");
357 err
= AVERROR(EINVAL
);
366 int ff_get_v_length(uint64_t val
)
376 void ff_put_v(AVIOContext
*bc
, uint64_t val
)
378 int i
= ff_get_v_length(val
);
381 avio_w8(bc
, 128 | (uint8_t)(val
>> (7*i
)));
383 avio_w8(bc
, val
& 127);
386 void avio_wl64(AVIOContext
*s
, uint64_t val
)
388 avio_wl32(s
, (uint32_t)(val
& 0xffffffff));
389 avio_wl32(s
, (uint32_t)(val
>> 32));
392 void avio_wb64(AVIOContext
*s
, uint64_t val
)
394 avio_wb32(s
, (uint32_t)(val
>> 32));
395 avio_wb32(s
, (uint32_t)(val
& 0xffffffff));
398 void avio_wl16(AVIOContext
*s
, unsigned int val
)
400 avio_w8(s
, (uint8_t)val
);
401 avio_w8(s
, (int)val
>> 8);
404 void avio_wb16(AVIOContext
*s
, unsigned int val
)
406 avio_w8(s
, (int)val
>> 8);
407 avio_w8(s
, (uint8_t)val
);
410 void avio_wl24(AVIOContext
*s
, unsigned int val
)
412 avio_wl16(s
, val
& 0xffff);
413 avio_w8(s
, (int)val
>> 16);
416 void avio_wb24(AVIOContext
*s
, unsigned int val
)
418 avio_wb16(s
, (int)val
>> 8);
419 avio_w8(s
, (uint8_t)val
);
424 static void fill_buffer(AVIOContext
*s
)
426 int max_buffer_size
= s
->max_packet_size
?
427 s
->max_packet_size
: IO_BUFFER_SIZE
;
428 uint8_t *dst
= s
->buf_end
- s
->buffer
+ max_buffer_size
< s
->buffer_size
?
429 s
->buf_end
: s
->buffer
;
430 int len
= s
->buffer_size
- (dst
- s
->buffer
);
432 /* can't fill the buffer without read_packet, just set EOF if appropriate */
433 if (!s
->read_packet
&& s
->buf_ptr
>= s
->buf_end
)
436 /* no need to do anything if EOF already reached */
440 if (s
->update_checksum
&& dst
== s
->buffer
) {
441 if (s
->buf_end
> s
->checksum_ptr
)
442 s
->checksum
= s
->update_checksum(s
->checksum
, s
->checksum_ptr
,
443 s
->buf_end
- s
->checksum_ptr
);
444 s
->checksum_ptr
= s
->buffer
;
447 /* make buffer smaller in case it ended up large after probing */
448 if (s
->read_packet
&& s
->orig_buffer_size
&& s
->buffer_size
> s
->orig_buffer_size
) {
449 if (dst
== s
->buffer
) {
450 ffio_set_buf_size(s
, s
->orig_buffer_size
);
452 s
->checksum_ptr
= dst
= s
->buffer
;
454 av_assert0(len
>= s
->orig_buffer_size
);
455 len
= s
->orig_buffer_size
;
459 len
= s
->read_packet(s
->opaque
, dst
, len
);
463 /* do not modify buffer if EOF reached so that a seek back can
464 be done without rereading data */
471 s
->buf_end
= dst
+ len
;
472 s
->bytes_read
+= len
;
476 unsigned long ff_crc04C11DB7_update(unsigned long checksum
, const uint8_t *buf
,
479 return av_crc(av_crc_get_table(AV_CRC_32_IEEE
), checksum
, buf
, len
);
482 unsigned long ff_crcA001_update(unsigned long checksum
, const uint8_t *buf
,
485 return av_crc(av_crc_get_table(AV_CRC_16_ANSI_LE
), checksum
, buf
, len
);
488 unsigned long ffio_get_checksum(AVIOContext
*s
)
490 s
->checksum
= s
->update_checksum(s
->checksum
, s
->checksum_ptr
,
491 s
->buf_ptr
- s
->checksum_ptr
);
492 s
->update_checksum
= NULL
;
496 void ffio_init_checksum(AVIOContext
*s
,
497 unsigned long (*update_checksum
)(unsigned long c
, const uint8_t *p
, unsigned int len
),
498 unsigned long checksum
)
500 s
->update_checksum
= update_checksum
;
501 if (s
->update_checksum
) {
502 s
->checksum
= checksum
;
503 s
->checksum_ptr
= s
->buf_ptr
;
507 /* XXX: put an inline version */
508 int avio_r8(AVIOContext
*s
)
510 if (s
->buf_ptr
>= s
->buf_end
)
512 if (s
->buf_ptr
< s
->buf_end
)
513 return *s
->buf_ptr
++;
517 int avio_read(AVIOContext
*s
, unsigned char *buf
, int size
)
523 len
= s
->buf_end
- s
->buf_ptr
;
526 if (len
== 0 || s
->write_flag
) {
527 if((s
->direct
|| size
> s
->buffer_size
) && !s
->update_checksum
){
529 len
= s
->read_packet(s
->opaque
, buf
, size
);
531 /* do not modify buffer if EOF reached so that a seek back can
532 be done without rereading data */
539 s
->bytes_read
+= len
;
542 s
->buf_ptr
= s
->buffer
;
543 s
->buf_end
= s
->buffer
/* + len*/;
547 len
= s
->buf_end
- s
->buf_ptr
;
552 memcpy(buf
, s
->buf_ptr
, len
);
559 if (s
->error
) return s
->error
;
560 if (avio_feof(s
)) return AVERROR_EOF
;
565 int ffio_read_indirect(AVIOContext
*s
, unsigned char *buf
, int size
, const unsigned char **data
)
567 if (s
->buf_end
- s
->buf_ptr
>= size
&& !s
->write_flag
) {
573 return avio_read(s
, buf
, size
);
577 int ffio_read_partial(AVIOContext
*s
, unsigned char *buf
, int size
)
584 if (s
->read_packet
&& s
->write_flag
) {
585 len
= s
->read_packet(s
->opaque
, buf
, size
);
591 len
= s
->buf_end
- s
->buf_ptr
;
593 /* Reset the buf_end pointer to the start of the buffer, to make sure
594 * the fill_buffer call tries to read as much data as fits into the
595 * full buffer, instead of just what space is left after buf_end.
596 * This avoids returning partial packets at the end of the buffer,
597 * for packet based inputs.
599 s
->buf_end
= s
->buf_ptr
= s
->buffer
;
601 len
= s
->buf_end
- s
->buf_ptr
;
605 memcpy(buf
, s
->buf_ptr
, len
);
608 if (s
->error
) return s
->error
;
609 if (avio_feof(s
)) return AVERROR_EOF
;
614 unsigned int avio_rl16(AVIOContext
*s
)
618 val
|= avio_r8(s
) << 8;
622 unsigned int avio_rl24(AVIOContext
*s
)
626 val
|= avio_r8(s
) << 16;
630 unsigned int avio_rl32(AVIOContext
*s
)
634 val
|= avio_rl16(s
) << 16;
638 uint64_t avio_rl64(AVIOContext
*s
)
641 val
= (uint64_t)avio_rl32(s
);
642 val
|= (uint64_t)avio_rl32(s
) << 32;
646 unsigned int avio_rb16(AVIOContext
*s
)
649 val
= avio_r8(s
) << 8;
654 unsigned int avio_rb24(AVIOContext
*s
)
657 val
= avio_rb16(s
) << 8;
661 unsigned int avio_rb32(AVIOContext
*s
)
664 val
= avio_rb16(s
) << 16;
669 int ff_get_line(AVIOContext
*s
, char *buf
, int maxlen
)
676 if (c
&& i
< maxlen
-1)
678 } while (c
!= '\n' && c
!= '\r' && c
);
679 if (c
== '\r' && avio_r8(s
) != '\n' && !avio_feof(s
))
686 int avio_get_str(AVIOContext
*s
, int maxlen
, char *buf
, int buflen
)
691 return AVERROR(EINVAL
);
692 // reserve 1 byte for terminating 0
693 buflen
= FFMIN(buflen
- 1, maxlen
);
694 for (i
= 0; i
< buflen
; i
++)
695 if (!(buf
[i
] = avio_r8(s
)))
698 for (; i
< maxlen
; i
++)
704 #define GET_STR16(type, read) \
705 int avio_get_str16 ##type(AVIOContext *pb, int maxlen, char *buf, int buflen)\
710 return AVERROR(EINVAL); \
711 while (ret + 1 < maxlen) {\
714 GET_UTF16(ch, (ret += 2) <= maxlen ? read(pb) : 0, break;)\
717 PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;)\
723 GET_STR16(le, avio_rl16)
724 GET_STR16(be
, avio_rb16
)
728 uint64_t avio_rb64(AVIOContext
*s
)
731 val
= (uint64_t)avio_rb32(s
) << 32;
732 val
|= (uint64_t)avio_rb32(s
);
736 uint64_t ffio_read_varlen(AVIOContext
*bc
){
742 val
= (val
<<7) + (tmp
&127);
747 int ffio_fdopen(AVIOContext
**s
, URLContext
*h
)
750 int buffer_size
, max_packet_size
;
752 max_packet_size
= h
->max_packet_size
;
753 if (max_packet_size
) {
754 buffer_size
= max_packet_size
; /* no need to bufferize more than one packet */
756 buffer_size
= IO_BUFFER_SIZE
;
758 buffer
= av_malloc(buffer_size
);
760 return AVERROR(ENOMEM
);
762 *s
= avio_alloc_context(buffer
, buffer_size
, h
->flags
& AVIO_FLAG_WRITE
, h
,
763 (void*)ffurl_read
, (void*)ffurl_write
, (void*)ffurl_seek
);
766 return AVERROR(ENOMEM
);
768 (*s
)->direct
= h
->flags
& AVIO_FLAG_DIRECT
;
769 (*s
)->seekable
= h
->is_streamed
? 0 : AVIO_SEEKABLE_NORMAL
;
770 (*s
)->max_packet_size
= max_packet_size
;
772 (*s
)->read_pause
= (int (*)(void *, int))h
->prot
->url_read_pause
;
773 (*s
)->read_seek
= (int64_t (*)(void *, int, int64_t, int))h
->prot
->url_read_seek
;
775 (*s
)->av_class
= &ffio_url_class
;
779 int ffio_ensure_seekback(AVIOContext
*s
, int64_t buf_size
)
782 int max_buffer_size
= s
->max_packet_size
?
783 s
->max_packet_size
: IO_BUFFER_SIZE
;
784 int filled
= s
->buf_end
- s
->buffer
;
786 buf_size
+= s
->buf_ptr
- s
->buffer
+ max_buffer_size
;
788 if (buf_size
< filled
|| s
->seekable
)
790 av_assert0(!s
->write_flag
);
792 buffer
= av_malloc(buf_size
);
794 return AVERROR(ENOMEM
);
796 memcpy(buffer
, s
->buffer
, filled
);
798 s
->buf_ptr
= buffer
+ (s
->buf_ptr
- s
->buffer
);
799 s
->buf_end
= buffer
+ (s
->buf_end
- s
->buffer
);
801 s
->buffer_size
= buf_size
;
805 int ffio_set_buf_size(AVIOContext
*s
, int buf_size
)
808 buffer
= av_malloc(buf_size
);
810 return AVERROR(ENOMEM
);
814 s
->orig_buffer_size
=
815 s
->buffer_size
= buf_size
;
817 url_resetbuf(s
, s
->write_flag
? AVIO_FLAG_WRITE
: AVIO_FLAG_READ
);
821 static int url_resetbuf(AVIOContext
*s
, int flags
)
823 av_assert1(flags
== AVIO_FLAG_WRITE
|| flags
== AVIO_FLAG_READ
);
825 if (flags
& AVIO_FLAG_WRITE
) {
826 s
->buf_end
= s
->buffer
+ s
->buffer_size
;
829 s
->buf_end
= s
->buffer
;
835 int ffio_rewind_with_probe_data(AVIOContext
*s
, unsigned char **bufp
, int buf_size
)
837 int64_t buffer_start
;
839 int overlap
, new_size
, alloc_size
;
840 uint8_t *buf
= *bufp
;
844 return AVERROR(EINVAL
);
847 buffer_size
= s
->buf_end
- s
->buffer
;
849 /* the buffers must touch or overlap */
850 if ((buffer_start
= s
->pos
- buffer_size
) > buf_size
) {
852 return AVERROR(EINVAL
);
855 overlap
= buf_size
- buffer_start
;
856 new_size
= buf_size
+ buffer_size
- overlap
;
858 alloc_size
= FFMAX(s
->buffer_size
, new_size
);
859 if (alloc_size
> buf_size
)
860 if (!(buf
= (*bufp
) = av_realloc_f(buf
, 1, alloc_size
)))
861 return AVERROR(ENOMEM
);
863 if (new_size
> buf_size
) {
864 memcpy(buf
+ buf_size
, s
->buffer
+ overlap
, buffer_size
- overlap
);
869 s
->buf_ptr
= s
->buffer
= buf
;
870 s
->buffer_size
= alloc_size
;
872 s
->buf_end
= s
->buf_ptr
+ buf_size
;
879 int avio_open(AVIOContext
**s
, const char *filename
, int flags
)
881 return avio_open2(s
, filename
, flags
, NULL
, NULL
);
884 int avio_open2(AVIOContext
**s
, const char *filename
, int flags
,
885 const AVIOInterruptCB
*int_cb
, AVDictionary
**options
)
890 err
= ffurl_open(&h
, filename
, flags
, int_cb
, options
);
893 err
= ffio_fdopen(s
, h
);
901 int avio_close(AVIOContext
*s
)
910 av_freep(&s
->buffer
);
912 av_log(s
, AV_LOG_DEBUG
, "Statistics: %d seeks, %d writeouts\n", s
->seek_count
, s
->writeout_count
);
914 av_log(s
, AV_LOG_DEBUG
, "Statistics: %"PRId64
" bytes read, %d seeks\n", s
->bytes_read
, s
->seek_count
);
916 return ffurl_close(h
);
919 int avio_closep(AVIOContext
**s
)
921 int ret
= avio_close(*s
);
926 int avio_printf(AVIOContext
*s
, const char *fmt
, ...)
933 ret
= vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
935 avio_write(s
, buf
, strlen(buf
));
939 int avio_pause(AVIOContext
*s
, int pause
)
942 return AVERROR(ENOSYS
);
943 return s
->read_pause(s
->opaque
, pause
);
946 int64_t avio_seek_time(AVIOContext
*s
, int stream_index
,
947 int64_t timestamp
, int flags
)
949 URLContext
*h
= s
->opaque
;
952 return AVERROR(ENOSYS
);
953 ret
= s
->read_seek(h
, stream_index
, timestamp
, flags
);
956 s
->buf_ptr
= s
->buf_end
; // Flush buffer
957 pos
= s
->seek(h
, 0, SEEK_CUR
);
960 else if (pos
!= AVERROR(ENOSYS
))
966 int avio_read_to_bprint(AVIOContext
*h
, AVBPrint
*pb
, size_t max_size
)
971 ret
= avio_read(h
, buf
, FFMIN(max_size
, sizeof(buf
)));
972 if (ret
== AVERROR_EOF
)
976 av_bprint_append_data(pb
, buf
, ret
);
977 if (!av_bprint_is_complete(pb
))
978 return AVERROR(ENOMEM
);
984 /* output in a dynamic buffer */
986 typedef struct DynBuffer
{
987 int pos
, size
, allocated_size
;
990 uint8_t io_buffer
[1];
993 static int dyn_buf_write(void *opaque
, uint8_t *buf
, int buf_size
)
995 DynBuffer
*d
= opaque
;
996 unsigned new_size
, new_allocated_size
;
998 /* reallocate buffer if needed */
999 new_size
= d
->pos
+ buf_size
;
1000 new_allocated_size
= d
->allocated_size
;
1001 if (new_size
< d
->pos
|| new_size
> INT_MAX
/2)
1003 while (new_size
> new_allocated_size
) {
1004 if (!new_allocated_size
)
1005 new_allocated_size
= new_size
;
1007 new_allocated_size
+= new_allocated_size
/ 2 + 1;
1010 if (new_allocated_size
> d
->allocated_size
) {
1012 if ((err
= av_reallocp(&d
->buffer
, new_allocated_size
)) < 0) {
1013 d
->allocated_size
= 0;
1017 d
->allocated_size
= new_allocated_size
;
1019 memcpy(d
->buffer
+ d
->pos
, buf
, buf_size
);
1021 if (d
->pos
> d
->size
)
1026 static int dyn_packet_buf_write(void *opaque
, uint8_t *buf
, int buf_size
)
1028 unsigned char buf1
[4];
1031 /* packetized write: output the header */
1032 AV_WB32(buf1
, buf_size
);
1033 ret
= dyn_buf_write(opaque
, buf1
, 4);
1038 return dyn_buf_write(opaque
, buf
, buf_size
);
1041 static int64_t dyn_buf_seek(void *opaque
, int64_t offset
, int whence
)
1043 DynBuffer
*d
= opaque
;
1045 if (whence
== SEEK_CUR
)
1047 else if (whence
== SEEK_END
)
1049 if (offset
< 0 || offset
> 0x7fffffffLL
)
1055 static int url_open_dyn_buf_internal(AVIOContext
**s
, int max_packet_size
)
1058 unsigned io_buffer_size
= max_packet_size
? max_packet_size
: 1024;
1060 if (sizeof(DynBuffer
) + io_buffer_size
< io_buffer_size
)
1062 d
= av_mallocz(sizeof(DynBuffer
) + io_buffer_size
);
1064 return AVERROR(ENOMEM
);
1065 d
->io_buffer_size
= io_buffer_size
;
1066 *s
= avio_alloc_context(d
->io_buffer
, d
->io_buffer_size
, 1, d
, NULL
,
1067 max_packet_size
? dyn_packet_buf_write
: dyn_buf_write
,
1068 max_packet_size
? NULL
: dyn_buf_seek
);
1071 return AVERROR(ENOMEM
);
1073 (*s
)->max_packet_size
= max_packet_size
;
1077 int avio_open_dyn_buf(AVIOContext
**s
)
1079 return url_open_dyn_buf_internal(s
, 0);
1082 int ffio_open_dyn_packet_buf(AVIOContext
**s
, int max_packet_size
)
1084 if (max_packet_size
<= 0)
1086 return url_open_dyn_buf_internal(s
, max_packet_size
);
1089 int avio_close_dyn_buf(AVIOContext
*s
, uint8_t **pbuffer
)
1093 static const char padbuf
[FF_INPUT_BUFFER_PADDING_SIZE
] = {0};
1101 /* don't attempt to pad fixed-size packet buffers */
1102 if (!s
->max_packet_size
) {
1103 avio_write(s
, padbuf
, sizeof(padbuf
));
1104 padding
= FF_INPUT_BUFFER_PADDING_SIZE
;
1110 *pbuffer
= d
->buffer
;
1114 return size
- padding
;
1117 static int null_buf_write(void *opaque
, uint8_t *buf
, int buf_size
)
1119 DynBuffer
*d
= opaque
;
1122 if (d
->pos
> d
->size
)
1127 int ffio_open_null_buf(AVIOContext
**s
)
1129 int ret
= url_open_dyn_buf_internal(s
, 0);
1131 AVIOContext
*pb
= *s
;
1132 pb
->write_packet
= null_buf_write
;
1137 int ffio_close_null_buf(AVIOContext
*s
)
1139 DynBuffer
*d
= s
->opaque
;