Hello all,

I have made some changes to get custom allocation functions in ffmpeg.
This is useful to me, as the software I work with easily runs into
congestion on memory allocations in certain cases.

I hope it is useful to others as well. It would be nice if this could
be part of ffmpeg proper. If you have specific issues with my
implementation, please let me know.

With regards,
Martijn
From 802b4aecb77c8a35eb6641aa8dd6d27bbcda1fe2 Mon Sep 17 00:00:00 2001
From: Martijn Otto <ffm...@martijnotto.nl>
Date: Thu, 4 Mar 2021 17:30:15 +0100
Subject: [PATCH] Add custom memory allocation routines.

This feature is a useful optimization strategy. It allows the
implementation of working with a memory pool for better performance.
---
 libavformat/hlsenc.c |  1 +
 libavutil/buffer.c   | 41 +++++++++++++++++++++++++++++++++++------
 libavutil/buffer.h   | 23 +++++++++++++++++++++++
 3 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 7d97ce1789..c8e4281e7b 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -927,6 +927,7 @@ static int hls_mux_init(AVFormatContext *s, VariantStream *vs)
         } else {
             ret = hlsenc_io_open(s, &vs->out, vs->base_output_dirname, &options);
         }
+        avio_flush(oc->pb);
         av_dict_free(&options);
     }
     if (ret < 0) {
diff --git a/libavutil/buffer.c b/libavutil/buffer.c
index 3204f11b68..bd86b38524 100644
--- a/libavutil/buffer.c
+++ b/libavutil/buffer.c
@@ -59,23 +59,52 @@ AVBufferRef *av_buffer_create(uint8_t *data, int size,
     return ref;
 }
 
+PFNBufferAlloc externalAllocFunc = NULL;
+PFNBufferDealloc externalDeallocFunc = NULL;
+
+void av_set_buffer_alloc_free_funcs( PFNBufferAlloc externalAlloc, PFNBufferDealloc externalDealloc )
+{
+    externalAllocFunc = externalAlloc;
+    externalDeallocFunc = externalDealloc;
+}
+
 void av_buffer_default_free(void *opaque, uint8_t *data)
 {
     av_free(data);
 }
+void av_buffer_external_free(void *opaque, uint8_t *data)
+{
+    if (externalDeallocFunc != NULL)
+        externalDeallocFunc(data);
+}
 
 AVBufferRef *av_buffer_alloc(int size)
 {
     AVBufferRef *ret = NULL;
     uint8_t    *data = NULL;
 
-    data = av_malloc(size);
-    if (!data)
-        return NULL;
+    //Give priority to the external allocation function to give the application a chance to manage it's own buffer allocations.
+    if (externalAllocFunc != NULL)
+        data = externalAllocFunc(size);
 
-    ret = av_buffer_create(data, size, av_buffer_default_free, NULL, 0);
-    if (!ret)
-        av_freep(&data);
+    if (data) {
+        //Create a buffer and tell it to free it's data using the external free function. We've used the external
+        //allocator for allocation, so we need to use external deallocator for deallocation.
+        ret = av_buffer_create(data, size, av_buffer_external_free, NULL, 0);
+        if (!ret)
+            av_buffer_external_free(NULL, data);
+    } else {
+        //The external allocation function may return NULL for other reasons than out of memory, so
+        //if it did we will fall back to our own allocation function.
+        data = av_malloc(size);
+        if (!data)
+            return NULL; //We're out of memory after all.
+
+        //We've created the buffer data ourselves so we can use our own free function.
+        ret = av_buffer_create(data, size, av_buffer_default_free, NULL, 0);
+        if (!ret)
+            av_freep(&data);
+    }
 
     return ret;
 }
diff --git a/libavutil/buffer.h b/libavutil/buffer.h
index fd4e381efa..3efe585d56 100644
--- a/libavutil/buffer.h
+++ b/libavutil/buffer.h
@@ -93,6 +93,29 @@ typedef struct AVBufferRef {
     int      size;
 } AVBufferRef;
 
+#if defined(_WIN32)
+    #define FFAPI __stdcall
+#else
+    #define FFAPI
+#endif
+
+typedef void* (FFAPI *PFNBufferAlloc)( int size );
+typedef void (FFAPI *PFNBufferDealloc)( void* buffer );
+/**
+ * Set allocation functions that can be used to externally manage buffer allocations.
+ * During regular playback buffers are continuously being allocated and deallocated. In high performance
+ * applications this becomes a problem. When multiple files are playing at the same time on different threads
+ * these allocations interlock with eachother causing performance loss due to reduced paralellism.
+ * To remedy this these applications may set these allocation/deallocation functions which it can use to prevent
+ * this behaviour. It could for example implement a pool allocator from which it will source the buffers.
+ *
+ * @param externalAlloc   The function that will be called when a new buffer is required. This function can return
+ *                        NULL if it does not take care of allocating buffers of the provided size. In this case FFMPeg will
+ *                        fall back to it's own allocation function.
+ * @param externalDealloc The function that will be called when a buffer is to be deallocated.
+ */
+void av_set_buffer_alloc_free_funcs( PFNBufferAlloc externalAlloc, PFNBufferDealloc externalDealloc );
+
 /**
  * Allocate an AVBuffer of the given size using av_malloc().
  *
-- 
2.20.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to