diff --git a/libavutil/buffer.c b/libavutil/buffer.c index e9bf54b96c..0f9f1a2992 100644 --- a/libavutil/buffer.c +++ b/libavutil/buffer.c @@ -23,6 +23,9 @@ #include "buffer_internal.h" #include "common.h" #include "mem.h" +#include "thread.h" + +#define USE_ATOMICS !(HAVE_PTHREADS || HAVE_W32THREADS) AVBufferRef *av_buffer_create(uint8_t *data, int size, void (*free)(void *opaque, uint8_t *data), @@ -209,6 +212,8 @@ AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size)) if (!pool) return NULL; + ff_mutex_init(&pool->mutex, NULL); + pool->size = size; pool->alloc = alloc ? alloc : av_buffer_alloc; @@ -230,6 +235,7 @@ static void buffer_pool_free(AVBufferPool *pool) buf->free(buf->opaque, buf->data); av_freep(&buf); } + ff_mutex_destroy(&pool->mutex); av_freep(&pool); } @@ -290,7 +296,15 @@ static void pool_release_buffer(void *opaque, uint8_t *data) if(CONFIG_MEMORY_POISONING) memset(buf->data, FF_MEMORY_POISON, pool->size); +#if USE_ATOMICS add_to_pool(buf); +#else + ff_mutex_lock(&pool->mutex); + buf->next = pool->pool; + pool->pool = buf; + ff_mutex_unlock(&pool->mutex); +#endif + if (!avpriv_atomic_int_add_and_fetch(&pool->refcount, -1)) buffer_pool_free(pool); } @@ -320,8 +334,10 @@ static AVBufferRef *pool_alloc_buffer(AVBufferPool *pool) ret->buffer->opaque = buf; ret->buffer->free = pool_release_buffer; +#if USE_ATOMICS avpriv_atomic_int_add_and_fetch(&pool->refcount, 1); avpriv_atomic_int_add_and_fetch(&pool->nb_allocated, 1); +#endif return ret; } @@ -331,6 +347,7 @@ AVBufferRef *av_buffer_pool_get(AVBufferPool *pool) AVBufferRef *ret; BufferPoolEntry *buf; +#if USE_ATOMICS /* check whether the pool is empty */ buf = get_pool(pool); if (!buf && pool->refcount <= pool->nb_allocated) { @@ -352,7 +369,24 @@ AVBufferRef *av_buffer_pool_get(AVBufferPool *pool) add_to_pool(buf); return NULL; } - avpriv_atomic_int_add_and_fetch(&pool->refcount, 1); +#else + ff_mutex_lock(&pool->mutex); + buf = pool->pool; + if (buf) { + ret = av_buffer_create(buf->data, pool->size, pool_release_buffer, + buf, 0); + if (ret) { + pool->pool = buf->next; + buf->next = NULL; + } + } else { + ret = pool_alloc_buffer(pool); + } + ff_mutex_unlock(&pool->mutex); +#endif + + if (ret) + avpriv_atomic_int_add_and_fetch(&pool->refcount, 1); return ret; } diff --git a/libavutil/buffer_internal.h b/libavutil/buffer_internal.h index c29190839e..e6530485d3 100644 --- a/libavutil/buffer_internal.h +++ b/libavutil/buffer_internal.h @@ -22,6 +22,7 @@ #include #include "buffer.h" +#include "thread.h" /** * The buffer is always treated as read-only. @@ -68,11 +69,12 @@ typedef struct BufferPoolEntry { void (*free)(void *opaque, uint8_t *data); AVBufferPool *pool; - struct BufferPoolEntry * volatile next; + struct BufferPoolEntry *next; } BufferPoolEntry; struct AVBufferPool { - BufferPoolEntry * volatile pool; + AVMutex mutex; + BufferPoolEntry *pool; /* * This is used to track when the pool is to be freed.