Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FFmpeg/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2021-12-30 17:06:15 +0300
committerAnton Khirnov <anton@khirnov.net>2022-01-10 18:05:57 +0300
commit549ccea54e61e2e35b01a288466476504df03fd8 (patch)
tree65290cc07000edbc642c77c62c802bf64377bc95 /libavutil/fifo.c
parent5010c481d1a4bbd52655c43f5d7627d4c0a90f72 (diff)
lavu/fifo: do not copy the whole fifo when reallocating
av_realloc() the buffer and only move the part of the ring buffer that needs it. Also avoids allocating a temporary fifo.
Diffstat (limited to 'libavutil/fifo.c')
-rw-r--r--libavutil/fifo.c34
1 files changed, 24 insertions, 10 deletions
diff --git a/libavutil/fifo.c b/libavutil/fifo.c
index 5eee18a8c8..171c1aa9cd 100644
--- a/libavutil/fifo.c
+++ b/libavutil/fifo.c
@@ -27,7 +27,7 @@
AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size)
{
AVFifoBuffer *f;
- void *buffer = av_malloc_array(nmemb, size);
+ void *buffer = av_realloc_array(NULL, nmemb, size);
if (!buffer)
return NULL;
f = av_mallocz(sizeof(AVFifoBuffer));
@@ -83,17 +83,31 @@ int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size)
unsigned int old_size = f->end - f->buffer;
if (old_size < new_size) {
- int len = av_fifo_size(f);
- AVFifoBuffer *f2 = av_fifo_alloc(new_size);
+ size_t offset_r = f->rptr - f->buffer;
+ size_t offset_w = f->wptr - f->buffer;
+ uint8_t *tmp;
- if (!f2)
+ tmp = av_realloc(f->buffer, new_size);
+ if (!tmp)
return AVERROR(ENOMEM);
- av_fifo_generic_read(f, f2->buffer, len, NULL);
- f2->wptr += len;
- f2->wndx += len;
- av_free(f->buffer);
- *f = *f2;
- av_free(f2);
+
+ // move the data from the beginning of the ring buffer
+ // to the newly allocated space
+ // the second condition distinguishes full vs empty fifo
+ if (offset_w <= offset_r && av_fifo_size(f)) {
+ const size_t copy = FFMIN(new_size - old_size, offset_w);
+ memcpy(tmp + old_size, tmp, copy);
+ if (copy < offset_w) {
+ memmove(tmp, tmp + copy , offset_w - copy);
+ offset_w -= copy;
+ } else
+ offset_w = old_size + copy;
+ }
+
+ f->buffer = tmp;
+ f->end = f->buffer + new_size;
+ f->rptr = f->buffer + offset_r;
+ f->wptr = f->buffer + offset_w;
}
return 0;
}