mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-24 13:56:33 +02:00
avutil/buffer: Avoid allocation of AVBuffer when using buffer pool
Do this by putting an AVBuffer structure into BufferPoolEntry and reuse it for all subsequent uses of said BufferPoolEntry. Reviewed-by: James Almer <jamrial@gmail.com> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
parent
6556146aa0
commit
4e0da7d311
@ -26,16 +26,11 @@
|
||||
#include "mem.h"
|
||||
#include "thread.h"
|
||||
|
||||
AVBufferRef *av_buffer_create(uint8_t *data, size_t size,
|
||||
void (*free)(void *opaque, uint8_t *data),
|
||||
void *opaque, int flags)
|
||||
static AVBufferRef *buffer_create(AVBuffer *buf, uint8_t *data, size_t size,
|
||||
void (*free)(void *opaque, uint8_t *data),
|
||||
void *opaque, int flags)
|
||||
{
|
||||
AVBufferRef *ref = NULL;
|
||||
AVBuffer *buf = NULL;
|
||||
|
||||
buf = av_mallocz(sizeof(*buf));
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
buf->data = data;
|
||||
buf->size = size;
|
||||
@ -47,10 +42,8 @@ AVBufferRef *av_buffer_create(uint8_t *data, size_t size,
|
||||
buf->flags = flags;
|
||||
|
||||
ref = av_mallocz(sizeof(*ref));
|
||||
if (!ref) {
|
||||
av_freep(&buf);
|
||||
if (!ref)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ref->buffer = buf;
|
||||
ref->data = data;
|
||||
@ -59,6 +52,23 @@ AVBufferRef *av_buffer_create(uint8_t *data, size_t size,
|
||||
return ref;
|
||||
}
|
||||
|
||||
AVBufferRef *av_buffer_create(uint8_t *data, size_t size,
|
||||
void (*free)(void *opaque, uint8_t *data),
|
||||
void *opaque, int flags)
|
||||
{
|
||||
AVBufferRef *ret;
|
||||
AVBuffer *buf = av_mallocz(sizeof(*buf));
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
ret = buffer_create(buf, data, size, free, opaque, flags);
|
||||
if (!ret) {
|
||||
av_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void av_buffer_default_free(void *opaque, uint8_t *data)
|
||||
{
|
||||
av_free(data);
|
||||
@ -117,8 +127,12 @@ static void buffer_replace(AVBufferRef **dst, AVBufferRef **src)
|
||||
av_freep(dst);
|
||||
|
||||
if (atomic_fetch_sub_explicit(&b->refcount, 1, memory_order_acq_rel) == 1) {
|
||||
/* b->free below might already free the structure containing *b,
|
||||
* so we have to read the flag now to avoid use-after-free. */
|
||||
int free_avbuffer = !(b->flags_internal & BUFFER_FLAG_NO_FREE);
|
||||
b->free(b->opaque, b->data);
|
||||
av_freep(&b);
|
||||
if (free_avbuffer)
|
||||
av_free(b);
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,11 +392,13 @@ AVBufferRef *av_buffer_pool_get(AVBufferPool *pool)
|
||||
ff_mutex_lock(&pool->mutex);
|
||||
buf = pool->pool;
|
||||
if (buf) {
|
||||
ret = av_buffer_create(buf->data, pool->size, pool_release_buffer,
|
||||
buf, 0);
|
||||
memset(&buf->buffer, 0, sizeof(buf->buffer));
|
||||
ret = buffer_create(&buf->buffer, buf->data, pool->size,
|
||||
pool_release_buffer, buf, 0);
|
||||
if (ret) {
|
||||
pool->pool = buf->next;
|
||||
buf->next = NULL;
|
||||
buf->buffer.flags_internal |= BUFFER_FLAG_NO_FREE;
|
||||
}
|
||||
} else {
|
||||
ret = pool_alloc_buffer(pool);
|
||||
|
@ -30,6 +30,11 @@
|
||||
* The buffer was av_realloc()ed, so it is reallocatable.
|
||||
*/
|
||||
#define BUFFER_FLAG_REALLOCATABLE (1 << 0)
|
||||
/**
|
||||
* The AVBuffer structure is part of a larger structure
|
||||
* and should not be freed.
|
||||
*/
|
||||
#define BUFFER_FLAG_NO_FREE (1 << 1)
|
||||
|
||||
struct AVBuffer {
|
||||
uint8_t *data; /**< data described by this buffer */
|
||||
@ -73,6 +78,12 @@ typedef struct BufferPoolEntry {
|
||||
|
||||
AVBufferPool *pool;
|
||||
struct BufferPoolEntry *next;
|
||||
|
||||
/*
|
||||
* An AVBuffer structure to (re)use as AVBuffer for subsequent uses
|
||||
* of this BufferPoolEntry.
|
||||
*/
|
||||
AVBuffer buffer;
|
||||
} BufferPoolEntry;
|
||||
|
||||
struct AVBufferPool {
|
||||
|
Loading…
x
Reference in New Issue
Block a user