Skip to content
This repository was archived by the owner on Jun 4, 2023. It is now read-only.
4 changes: 3 additions & 1 deletion libavformat/avio_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ int ffio_realloc_buf(AVIOContext *s, int buf_size);
*
* Will ensure that when reading sequentially up to buf_size, seeking
* within the current pos and pos+buf_size is possible.
* Once the stream position moves outside this window this guarantee is lost.
* Once the stream position moves outside this window or another
* ffio_ensure_seekback call requests a buffer outside this window this
* guarantee is lost.
*/
int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size);

Expand Down
60 changes: 36 additions & 24 deletions libavformat/aviobuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ static void fill_buffer(AVIOContext *s)
{
int max_buffer_size = s->max_packet_size ?
s->max_packet_size : IO_BUFFER_SIZE;
uint8_t *dst = s->buf_end - s->buffer + max_buffer_size < s->buffer_size ?
uint8_t *dst = s->buf_end - s->buffer + max_buffer_size <= s->buffer_size ?
s->buf_end : s->buffer;
int len = s->buffer_size - (dst - s->buffer);

Expand Down Expand Up @@ -707,13 +707,6 @@ int avio_read_partial(AVIOContext *s, unsigned char *buf, int size)

len = s->buf_end - s->buf_ptr;
if (len == 0) {
/* Reset the buf_end pointer to the start of the buffer, to make sure
* the fill_buffer call tries to read as much data as fits into the
* full buffer, instead of just what space is left after buf_end.
* This avoids returning partial packets at the end of the buffer,
* for packet based inputs.
*/
s->buf_end = s->buf_ptr = s->buffer;
fill_buffer(s);
len = s->buf_end - s->buf_ptr;
}
Expand Down Expand Up @@ -926,6 +919,11 @@ int ffio_fdopen(AVIOContext **s, URLContext *h)
} else {
buffer_size = IO_BUFFER_SIZE;
}
if (!(h->flags & AVIO_FLAG_WRITE) && h->is_streamed) {
if (buffer_size > INT_MAX/2)
return AVERROR(EINVAL);
buffer_size *= 2;
}
buffer = av_malloc(buffer_size);
if (!buffer)
return AVERROR(ENOMEM);
Expand Down Expand Up @@ -979,32 +977,46 @@ URLContext* ffio_geturlcontext(AVIOContext *s)
return NULL;
}

static void update_checksum(AVIOContext *s)
{
if (s->update_checksum && s->buf_ptr > s->checksum_ptr) {
s->checksum = s->update_checksum(s->checksum, s->checksum_ptr,
s->buf_ptr - s->checksum_ptr);
}
}

int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
{
uint8_t *buffer;
int max_buffer_size = s->max_packet_size ?
s->max_packet_size : IO_BUFFER_SIZE;
int filled = s->buf_end - s->buffer;
ptrdiff_t checksum_ptr_offset = s->checksum_ptr ? s->checksum_ptr - s->buffer : -1;
ptrdiff_t filled = s->buf_end - s->buf_ptr;

if (buf_size <= s->buf_end - s->buf_ptr)
return 0;

buf_size += s->buf_ptr - s->buffer + max_buffer_size;
buf_size += max_buffer_size - 1;

if (buf_size < filled || s->seekable || !s->read_packet)
if (buf_size + s->buf_ptr - s->buffer <= s->buffer_size || s->seekable || !s->read_packet)
return 0;
av_assert0(!s->write_flag);

buffer = av_malloc(buf_size);
if (!buffer)
return AVERROR(ENOMEM);

memcpy(buffer, s->buffer, filled);
av_free(s->buffer);
s->buf_ptr = buffer + (s->buf_ptr - s->buffer);
s->buf_end = buffer + (s->buf_end - s->buffer);
s->buffer = buffer;
s->buffer_size = buf_size;
if (checksum_ptr_offset >= 0)
s->checksum_ptr = s->buffer + checksum_ptr_offset;
if (buf_size <= s->buffer_size) {
update_checksum(s);
memmove(s->buffer, s->buf_ptr, filled);
} else {
buffer = av_malloc(buf_size);
if (!buffer)
return AVERROR(ENOMEM);
update_checksum(s);
memcpy(buffer, s->buf_ptr, filled);
av_free(s->buffer);
s->buffer = buffer;
s->buffer_size = buf_size;
}
s->buf_ptr = s->buffer;
s->buf_end = s->buffer + filled;
s->checksum_ptr = s->buffer;
return 0;
}

Expand Down