2 * Buffered I/O for ffmpeg system
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/crc.h"
23 #include "libavutil/intreadwrite.h"
28 #define IO_BUFFER_SIZE 32768
30 static void fill_buffer(ByteIOContext
*s
);
31 #if LIBAVFORMAT_VERSION_MAJOR >= 53
32 static int url_resetbuf(ByteIOContext
*s
, int flags
);
35 int init_put_byte(ByteIOContext
*s
,
36 unsigned char *buffer
,
40 int (*read_packet
)(void *opaque
, uint8_t *buf
, int buf_size
),
41 int (*write_packet
)(void *opaque
, uint8_t *buf
, int buf_size
),
42 int64_t (*seek
)(void *opaque
, int64_t offset
, int whence
))
45 s
->buffer_size
= buffer_size
;
48 url_resetbuf(s
, write_flag ? URL_WRONLY
: URL_RDONLY
);
49 s
->write_packet
= write_packet
;
50 s
->read_packet
= read_packet
;
57 s
->max_packet_size
= 0;
58 s
->update_checksum
= NULL
;
59 if(!read_packet
&& !write_flag
){
61 s
->buf_end
= s
->buffer
+ buffer_size
;
68 ByteIOContext
*av_alloc_put_byte(
69 unsigned char *buffer
,
73 int (*read_packet
)(void *opaque
, uint8_t *buf
, int buf_size
),
74 int (*write_packet
)(void *opaque
, uint8_t *buf
, int buf_size
),
75 int64_t (*seek
)(void *opaque
, int64_t offset
, int whence
))
77 ByteIOContext
*s
= av_mallocz(sizeof(ByteIOContext
));
78 init_put_byte(s
, buffer
, buffer_size
, write_flag
, opaque
,
79 read_packet
, write_packet
, seek
);
83 static void flush_buffer(ByteIOContext
*s
)
85 if (s
->buf_ptr
> s
->buffer
) {
86 if (s
->write_packet
&& !s
->error
){
87 int ret
= s
->write_packet(s
->opaque
, s
->buffer
, s
->buf_ptr
- s
->buffer
);
92 if(s
->update_checksum
){
93 s
->checksum
= s
->update_checksum(s
->checksum
, s
->checksum_ptr
, s
->buf_ptr
- s
->checksum_ptr
);
94 s
->checksum_ptr
= s
->buffer
;
96 s
->pos
+= s
->buf_ptr
- s
->buffer
;
98 s
->buf_ptr
= s
->buffer
;
101 void put_byte(ByteIOContext
*s
, int b
)
104 if (s
->buf_ptr
>= s
->buf_end
)
108 void put_buffer(ByteIOContext
*s
, const unsigned char *buf
, int size
)
111 int len
= FFMIN(s
->buf_end
- s
->buf_ptr
, size
);
112 memcpy(s
->buf_ptr
, buf
, len
);
115 if (s
->buf_ptr
>= s
->buf_end
)
123 void put_flush_packet(ByteIOContext
*s
)
129 int64_t url_fseek(ByteIOContext
*s
, int64_t offset
, int whence
)
133 int force
= whence
& AVSEEK_FORCE
;
134 whence
&= ~AVSEEK_FORCE
;
137 return AVERROR(EINVAL
);
139 pos
= s
->pos
- (s
->write_flag ?
0 : (s
->buf_end
- s
->buffer
));
141 if (whence
!= SEEK_CUR
&& whence
!= SEEK_SET
)
142 return AVERROR(EINVAL
);
144 if (whence
== SEEK_CUR
) {
145 offset1
= pos
+ (s
->buf_ptr
- s
->buffer
);
150 offset1
= offset
- pos
;
151 if (!s
->must_flush
&&
152 offset1
>= 0 && offset1
<= (s
->buf_end
- s
->buffer
)) {
153 /* can do the seek inside the buffer */
154 s
->buf_ptr
= s
->buffer
+ offset1
;
155 } else if(s
->is_streamed
&& !s
->write_flag
&& offset1
>= 0 &&
156 (whence
!= SEEK_END
|| force
)) {
157 while(s
->pos
< offset
&& !s
->eof_reached
)
161 s
->buf_ptr
= s
->buf_end
+ offset
- s
->pos
;
163 int64_t res
= AVERROR(EPIPE
);
165 #if CONFIG_MUXERS || CONFIG_NETWORK
170 #endif /* CONFIG_MUXERS || CONFIG_NETWORK */
171 if (!s
->seek
|| (res
= s
->seek(s
->opaque
, offset
, SEEK_SET
)) < 0)
174 s
->buf_end
= s
->buffer
;
175 s
->buf_ptr
= s
->buffer
;
182 void url_fskip(ByteIOContext
*s
, int64_t offset
)
184 url_fseek(s
, offset
, SEEK_CUR
);
187 int64_t url_ftell(ByteIOContext
*s
)
189 return url_fseek(s
, 0, SEEK_CUR
);
192 int64_t url_fsize(ByteIOContext
*s
)
197 return AVERROR(EINVAL
);
200 return AVERROR(EPIPE
);
201 size
= s
->seek(s
->opaque
, 0, AVSEEK_SIZE
);
203 if ((size
= s
->seek(s
->opaque
, -1, SEEK_END
)) < 0)
206 s
->seek(s
->opaque
, s
->pos
, SEEK_SET
);
211 int url_feof(ByteIOContext
*s
)
215 return s
->eof_reached
;
218 int url_ferror(ByteIOContext
*s
)
225 void put_le32(ByteIOContext
*s
, unsigned int val
)
228 put_byte(s
, val
>> 8);
229 put_byte(s
, val
>> 16);
230 put_byte(s
, val
>> 24);
233 void put_be32(ByteIOContext
*s
, unsigned int val
)
235 put_byte(s
, val
>> 24);
236 put_byte(s
, val
>> 16);
237 put_byte(s
, val
>> 8);
241 void put_strz(ByteIOContext
*s
, const char *str
)
244 put_buffer(s
, (const unsigned char *) str
, strlen(str
) + 1);
249 void put_le64(ByteIOContext
*s
, uint64_t val
)
251 put_le32(s
, (uint32_t)(val
& 0xffffffff));
252 put_le32(s
, (uint32_t)(val
>> 32));
255 void put_be64(ByteIOContext
*s
, uint64_t val
)
257 put_be32(s
, (uint32_t)(val
>> 32));
258 put_be32(s
, (uint32_t)(val
& 0xffffffff));
261 void put_le16(ByteIOContext
*s
, unsigned int val
)
264 put_byte(s
, val
>> 8);
267 void put_be16(ByteIOContext
*s
, unsigned int val
)
269 put_byte(s
, val
>> 8);
273 void put_le24(ByteIOContext
*s
, unsigned int val
)
275 put_le16(s
, val
& 0xffff);
276 put_byte(s
, val
>> 16);
279 void put_be24(ByteIOContext
*s
, unsigned int val
)
281 put_be16(s
, val
>> 8);
285 void put_tag(ByteIOContext
*s
, const char *tag
)
294 static void fill_buffer(ByteIOContext
*s
)
296 uint8_t *dst
= !s
->max_packet_size
&& s
->buf_end
- s
->buffer
< s
->buffer_size ? s
->buf_ptr
: s
->buffer
;
297 int len
= s
->buffer_size
- (dst
- s
->buffer
);
298 int max_buffer_size
= s
->max_packet_size ? s
->max_packet_size
: IO_BUFFER_SIZE
;
300 assert(s
->buf_ptr
== s
->buf_end
);
302 /* no need to do anything if EOF already reached */
306 if(s
->update_checksum
&& dst
== s
->buffer
){
307 if(s
->buf_end
> s
->checksum_ptr
)
308 s
->checksum
= s
->update_checksum(s
->checksum
, s
->checksum_ptr
, s
->buf_end
- s
->checksum_ptr
);
309 s
->checksum_ptr
= s
->buffer
;
312 /* make buffer smaller in case it ended up large after probing */
313 if (s
->buffer_size
> max_buffer_size
) {
314 url_setbufsize(s
, max_buffer_size
);
316 s
->checksum_ptr
= dst
= s
->buffer
;
317 len
= s
->buffer_size
;
321 len
= s
->read_packet(s
->opaque
, dst
, len
);
325 /* do not modify buffer if EOF reached so that a seek back can
326 be done without rereading data */
333 s
->buf_end
= dst
+ len
;
337 unsigned long ff_crc04C11DB7_update(unsigned long checksum
, const uint8_t *buf
,
340 return av_crc(av_crc_get_table(AV_CRC_32_IEEE
), checksum
, buf
, len
);
343 unsigned long get_checksum(ByteIOContext
*s
)
345 s
->checksum
= s
->update_checksum(s
->checksum
, s
->checksum_ptr
, s
->buf_ptr
- s
->checksum_ptr
);
346 s
->update_checksum
= NULL
;
350 void init_checksum(ByteIOContext
*s
,
351 unsigned long (*update_checksum
)(unsigned long c
, const uint8_t *p
, unsigned int len
),
352 unsigned long checksum
)
354 s
->update_checksum
= update_checksum
;
355 if(s
->update_checksum
){
356 s
->checksum
= checksum
;
357 s
->checksum_ptr
= s
->buf_ptr
;
361 /* XXX: put an inline version */
362 int get_byte(ByteIOContext
*s
)
364 if (s
->buf_ptr
< s
->buf_end
) {
365 return *s
->buf_ptr
++;
368 if (s
->buf_ptr
< s
->buf_end
)
369 return *s
->buf_ptr
++;
375 int url_fgetc(ByteIOContext
*s
)
377 if (s
->buf_ptr
< s
->buf_end
) {
378 return *s
->buf_ptr
++;
381 if (s
->buf_ptr
< s
->buf_end
)
382 return *s
->buf_ptr
++;
388 int get_buffer(ByteIOContext
*s
, unsigned char *buf
, int size
)
394 len
= s
->buf_end
- s
->buf_ptr
;
398 if(size
> s
->buffer_size
&& !s
->update_checksum
){
400 len
= s
->read_packet(s
->opaque
, buf
, size
);
402 /* do not modify buffer if EOF reached so that a seek back can
403 be done without rereading data */
412 s
->buf_ptr
= s
->buffer
;
413 s
->buf_end
= s
->buffer
/* + len*/;
417 len
= s
->buf_end
- s
->buf_ptr
;
422 memcpy(buf
, s
->buf_ptr
, len
);
429 if (url_ferror(s
)) return url_ferror(s
);
430 if (url_feof(s
)) return AVERROR_EOF
;
435 int get_partial_buffer(ByteIOContext
*s
, unsigned char *buf
, int size
)
442 len
= s
->buf_end
- s
->buf_ptr
;
445 len
= s
->buf_end
- s
->buf_ptr
;
449 memcpy(buf
, s
->buf_ptr
, len
);
452 if (url_ferror(s
)) return url_ferror(s
);
453 if (url_feof(s
)) return AVERROR_EOF
;
458 unsigned int get_le16(ByteIOContext
*s
)
462 val
|= get_byte(s
) << 8;
466 unsigned int get_le24(ByteIOContext
*s
)
470 val
|= get_byte(s
) << 16;
474 unsigned int get_le32(ByteIOContext
*s
)
478 val
|= get_le16(s
) << 16;
482 uint64_t get_le64(ByteIOContext
*s
)
485 val
= (uint64_t)get_le32(s
);
486 val
|= (uint64_t)get_le32(s
) << 32;
490 unsigned int get_be16(ByteIOContext
*s
)
493 val
= get_byte(s
) << 8;
498 unsigned int get_be24(ByteIOContext
*s
)
501 val
= get_be16(s
) << 8;
505 unsigned int get_be32(ByteIOContext
*s
)
508 val
= get_be16(s
) << 16;
513 char *get_strz(ByteIOContext
*s
, char *buf
, int maxlen
)
518 while ((c
= get_byte(s
))) {
523 buf
[i
] = 0; /* Ensure null terminated, but may be truncated */
528 uint64_t get_be64(ByteIOContext
*s
)
531 val
= (uint64_t)get_be32(s
) << 32;
532 val
|= (uint64_t)get_be32(s
);
536 uint64_t ff_get_v(ByteIOContext
*bc
){
542 val
= (val
<<7) + (tmp
&127);
547 int url_fdopen(ByteIOContext
**s
, URLContext
*h
)
550 int buffer_size
, max_packet_size
;
552 max_packet_size
= url_get_max_packet_size(h
);
553 if (max_packet_size
) {
554 buffer_size
= max_packet_size
; /* no need to bufferize more than one packet */
556 buffer_size
= IO_BUFFER_SIZE
;
558 buffer
= av_malloc(buffer_size
);
560 return AVERROR(ENOMEM
);
562 *s
= av_mallocz(sizeof(ByteIOContext
));
565 return AVERROR(ENOMEM
);
568 if (init_put_byte(*s
, buffer
, buffer_size
,
569 (h
->flags
& URL_WRONLY
|| h
->flags
& URL_RDWR
), h
,
570 url_read
, url_write
, url_seek
) < 0) {
575 (*s
)->is_streamed
= h
->is_streamed
;
576 (*s
)->max_packet_size
= max_packet_size
;
578 (*s
)->read_pause
= (int (*)(void *, int))h
->prot
->url_read_pause
;
579 (*s
)->read_seek
= (int64_t (*)(void *, int, int64_t, int))h
->prot
->url_read_seek
;
584 int url_setbufsize(ByteIOContext
*s
, int buf_size
)
587 buffer
= av_malloc(buf_size
);
589 return AVERROR(ENOMEM
);
593 s
->buffer_size
= buf_size
;
595 url_resetbuf(s
, s
->write_flag ? URL_WRONLY
: URL_RDONLY
);
599 #if LIBAVFORMAT_VERSION_MAJOR < 53
600 int url_resetbuf(ByteIOContext
*s
, int flags
)
602 static int url_resetbuf(ByteIOContext
*s
, int flags
)
605 #if LIBAVFORMAT_VERSION_MAJOR < 53
606 URLContext
*h
= s
->opaque
;
607 if ((flags
& URL_RDWR
) || (h
&& h
->flags
!= flags
&& !h
->flags
& URL_RDWR
))
608 return AVERROR(EINVAL
);
610 assert(flags
== URL_WRONLY
|| flags
== URL_RDONLY
);
613 if (flags
& URL_WRONLY
) {
614 s
->buf_end
= s
->buffer
+ s
->buffer_size
;
617 s
->buf_end
= s
->buffer
;
623 int ff_rewind_with_probe_data(ByteIOContext
*s
, unsigned char *buf
, int buf_size
)
625 int64_t buffer_start
;
627 int overlap
, new_size
;
630 return AVERROR(EINVAL
);
632 buffer_size
= s
->buf_end
- s
->buffer
;
634 /* the buffers must touch or overlap */
635 if ((buffer_start
= s
->pos
- buffer_size
) > buf_size
)
636 return AVERROR(EINVAL
);
638 overlap
= buf_size
- buffer_start
;
639 new_size
= buf_size
+ buffer_size
- overlap
;
641 if (new_size
> buf_size
) {
642 if (!(buf
= av_realloc(buf
, new_size
)))
643 return AVERROR(ENOMEM
);
645 memcpy(buf
+ buf_size
, s
->buffer
+ overlap
, buffer_size
- overlap
);
650 s
->buf_ptr
= s
->buffer
= buf
;
651 s
->pos
= s
->buffer_size
= buf_size
;
652 s
->buf_end
= s
->buf_ptr
+ buf_size
;
659 int url_fopen(ByteIOContext
**s
, const char *filename
, int flags
)
664 err
= url_open(&h
, filename
, flags
);
667 err
= url_fdopen(s
, h
);
675 int url_fclose(ByteIOContext
*s
)
677 URLContext
*h
= s
->opaque
;
684 URLContext
*url_fileno(ByteIOContext
*s
)
690 int url_fprintf(ByteIOContext
*s
, const char *fmt
, ...)
697 ret
= vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
699 put_buffer(s
, buf
, strlen(buf
));
702 #endif //CONFIG_MUXERS
704 char *url_fgets(ByteIOContext
*s
, char *buf
, int buf_size
)
714 if (c
== EOF
|| c
== '\n')
716 if ((q
- buf
) < buf_size
- 1)
725 int url_fget_max_packet_size(ByteIOContext
*s
)
727 return s
->max_packet_size
;
730 int av_url_read_fpause(ByteIOContext
*s
, int pause
)
733 return AVERROR(ENOSYS
);
734 return s
->read_pause(s
->opaque
, pause
);
737 int64_t av_url_read_fseek(ByteIOContext
*s
, int stream_index
,
738 int64_t timestamp
, int flags
)
740 URLContext
*h
= s
->opaque
;
743 return AVERROR(ENOSYS
);
744 ret
= s
->read_seek(h
, stream_index
, timestamp
, flags
);
747 s
->buf_ptr
= s
->buf_end
; // Flush buffer
748 pos
= s
->seek(h
, 0, SEEK_CUR
);
751 else if (pos
!= AVERROR(ENOSYS
))
757 /* url_open_dyn_buf and url_close_dyn_buf are used in rtp.c to send a response
758 * back to the server even if CONFIG_MUXERS is false. */
759 #if CONFIG_MUXERS || CONFIG_NETWORK
760 /* buffer handling */
761 int url_open_buf(ByteIOContext
**s
, uint8_t *buf
, int buf_size
, int flags
)
764 *s
= av_mallocz(sizeof(ByteIOContext
));
766 return AVERROR(ENOMEM
);
767 ret
= init_put_byte(*s
, buf
, buf_size
,
768 (flags
& URL_WRONLY
|| flags
& URL_RDWR
),
769 NULL
, NULL
, NULL
, NULL
);
775 int url_close_buf(ByteIOContext
*s
)
778 return s
->buf_ptr
- s
->buffer
;
781 /* output in a dynamic buffer */
783 typedef struct DynBuffer
{
784 int pos
, size
, allocated_size
;
787 uint8_t io_buffer
[1];
790 static int dyn_buf_write(void *opaque
, uint8_t *buf
, int buf_size
)
792 DynBuffer
*d
= opaque
;
793 unsigned new_size
, new_allocated_size
;
795 /* reallocate buffer if needed */
796 new_size
= d
->pos
+ buf_size
;
797 new_allocated_size
= d
->allocated_size
;
798 if(new_size
< d
->pos
|| new_size
> INT_MAX
/2)
800 while (new_size
> new_allocated_size
) {
801 if (!new_allocated_size
)
802 new_allocated_size
= new_size
;
804 new_allocated_size
+= new_allocated_size
/ 2 + 1;
807 if (new_allocated_size
> d
->allocated_size
) {
808 d
->buffer
= av_realloc(d
->buffer
, new_allocated_size
);
809 if(d
->buffer
== NULL
)
810 return AVERROR(ENOMEM
);
811 d
->allocated_size
= new_allocated_size
;
813 memcpy(d
->buffer
+ d
->pos
, buf
, buf_size
);
815 if (d
->pos
> d
->size
)
820 static int dyn_packet_buf_write(void *opaque
, uint8_t *buf
, int buf_size
)
822 unsigned char buf1
[4];
825 /* packetized write: output the header */
826 AV_WB32(buf1
, buf_size
);
827 ret
= dyn_buf_write(opaque
, buf1
, 4);
832 return dyn_buf_write(opaque
, buf
, buf_size
);
835 static int64_t dyn_buf_seek(void *opaque
, int64_t offset
, int whence
)
837 DynBuffer
*d
= opaque
;
839 if (whence
== SEEK_CUR
)
841 else if (whence
== SEEK_END
)
843 if (offset
< 0 || offset
> 0x7fffffffLL
)
849 static int url_open_dyn_buf_internal(ByteIOContext
**s
, int max_packet_size
)
853 unsigned io_buffer_size
= max_packet_size ? max_packet_size
: 1024;
855 if(sizeof(DynBuffer
) + io_buffer_size
< io_buffer_size
)
857 d
= av_mallocz(sizeof(DynBuffer
) + io_buffer_size
);
859 return AVERROR(ENOMEM
);
860 *s
= av_mallocz(sizeof(ByteIOContext
));
863 return AVERROR(ENOMEM
);
865 d
->io_buffer_size
= io_buffer_size
;
866 ret
= init_put_byte(*s
, d
->io_buffer
, io_buffer_size
,
868 max_packet_size ? dyn_packet_buf_write
: dyn_buf_write
,
869 max_packet_size ? NULL
: dyn_buf_seek
);
871 (*s
)->max_packet_size
= max_packet_size
;
879 int url_open_dyn_buf(ByteIOContext
**s
)
881 return url_open_dyn_buf_internal(s
, 0);
884 int url_open_dyn_packet_buf(ByteIOContext
**s
, int max_packet_size
)
886 if (max_packet_size
<= 0)
888 return url_open_dyn_buf_internal(s
, max_packet_size
);
891 int url_close_dyn_buf(ByteIOContext
*s
, uint8_t **pbuffer
)
893 DynBuffer
*d
= s
->opaque
;
898 *pbuffer
= d
->buffer
;
904 #endif /* CONFIG_MUXERS || CONFIG_NETWORK */