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 "mem.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
|
|
||||||
AVBufferRef *av_buffer_create(uint8_t *data, size_t size,
|
static AVBufferRef *buffer_create(AVBuffer *buf, uint8_t *data, size_t size,
|
||||||
void (*free)(void *opaque, uint8_t *data),
|
void (*free)(void *opaque, uint8_t *data),
|
||||||
void *opaque, int flags)
|
void *opaque, int flags)
|
||||||
{
|
{
|
||||||
AVBufferRef *ref = NULL;
|
AVBufferRef *ref = NULL;
|
||||||
AVBuffer *buf = NULL;
|
|
||||||
|
|
||||||
buf = av_mallocz(sizeof(*buf));
|
|
||||||
if (!buf)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
buf->data = data;
|
buf->data = data;
|
||||||
buf->size = size;
|
buf->size = size;
|
||||||
|
@ -47,10 +42,8 @@ AVBufferRef *av_buffer_create(uint8_t *data, size_t size,
|
||||||
buf->flags = flags;
|
buf->flags = flags;
|
||||||
|
|
||||||
ref = av_mallocz(sizeof(*ref));
|
ref = av_mallocz(sizeof(*ref));
|
||||||
if (!ref) {
|
if (!ref)
|
||||||
av_freep(&buf);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
ref->buffer = buf;
|
ref->buffer = buf;
|
||||||
ref->data = data;
|
ref->data = data;
|
||||||
|
@ -59,6 +52,23 @@ AVBufferRef *av_buffer_create(uint8_t *data, size_t size,
|
||||||
return ref;
|
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)
|
void av_buffer_default_free(void *opaque, uint8_t *data)
|
||||||
{
|
{
|
||||||
av_free(data);
|
av_free(data);
|
||||||
|
@ -117,8 +127,12 @@ static void buffer_replace(AVBufferRef **dst, AVBufferRef **src)
|
||||||
av_freep(dst);
|
av_freep(dst);
|
||||||
|
|
||||||
if (atomic_fetch_sub_explicit(&b->refcount, 1, memory_order_acq_rel) == 1) {
|
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);
|
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);
|
ff_mutex_lock(&pool->mutex);
|
||||||
buf = pool->pool;
|
buf = pool->pool;
|
||||||
if (buf) {
|
if (buf) {
|
||||||
ret = av_buffer_create(buf->data, pool->size, pool_release_buffer,
|
memset(&buf->buffer, 0, sizeof(buf->buffer));
|
||||||
buf, 0);
|
ret = buffer_create(&buf->buffer, buf->data, pool->size,
|
||||||
|
pool_release_buffer, buf, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pool->pool = buf->next;
|
pool->pool = buf->next;
|
||||||
buf->next = NULL;
|
buf->next = NULL;
|
||||||
|
buf->buffer.flags_internal |= BUFFER_FLAG_NO_FREE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = pool_alloc_buffer(pool);
|
ret = pool_alloc_buffer(pool);
|
||||||
|
|
|
@ -30,6 +30,11 @@
|
||||||
* The buffer was av_realloc()ed, so it is reallocatable.
|
* The buffer was av_realloc()ed, so it is reallocatable.
|
||||||
*/
|
*/
|
||||||
#define BUFFER_FLAG_REALLOCATABLE (1 << 0)
|
#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 {
|
struct AVBuffer {
|
||||||
uint8_t *data; /**< data described by this buffer */
|
uint8_t *data; /**< data described by this buffer */
|
||||||
|
@ -73,6 +78,12 @@ typedef struct BufferPoolEntry {
|
||||||
|
|
||||||
AVBufferPool *pool;
|
AVBufferPool *pool;
|
||||||
struct BufferPoolEntry *next;
|
struct BufferPoolEntry *next;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An AVBuffer structure to (re)use as AVBuffer for subsequent uses
|
||||||
|
* of this BufferPoolEntry.
|
||||||
|
*/
|
||||||
|
AVBuffer buffer;
|
||||||
} BufferPoolEntry;
|
} BufferPoolEntry;
|
||||||
|
|
||||||
struct AVBufferPool {
|
struct AVBufferPool {
|
||||||
|
|
Loading…
Reference in New Issue