From patchwork Fri Mar 5 14:44:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martijn Otto X-Patchwork-Id: 26115 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 6260D44AEA1 for ; Fri, 5 Mar 2021 16:45:02 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 271356897E3; Fri, 5 Mar 2021 16:45:02 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from vps2.martijnotto.nl (vps.martijnotto.nl [136.144.132.217]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id C3C7C6897E3 for ; Fri, 5 Mar 2021 16:44:54 +0200 (EET) Received: from [2001:981:3fac:1:1949:ed1:35f3:824b] (helo=martijn-t480s.fritz.box) by vps2.martijnotto.nl with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1lIBhF-0004wv-SZ for ffmpeg-devel@ffmpeg.org; Fri, 05 Mar 2021 15:44:53 +0100 Message-ID: From: Martijn Otto To: ffmpeg-devel@ffmpeg.org Date: Fri, 05 Mar 2021 15:44:53 +0100 User-Agent: Evolution 3.30.5-1.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] Custom allocation functions X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" 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 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(). *