[FFmpeg-cvslog] lavu/fifo: do not copy the whole fifo when reallocating

Anton Khirnov git at videolan.org
Mon Jan 10 17:15:16 EET 2022


ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Thu Dec 30 15:06:15 2021 +0100| [549ccea54e61e2e35b01a288466476504df03fd8] | committer: Anton Khirnov

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.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=549ccea54e61e2e35b01a288466476504df03fd8
---

 libavutil/fifo.c | 34 ++++++++++++++++++++++++----------
 1 file 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;
 }



More information about the ffmpeg-cvslog mailing list