X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavutil%2Fbuffer.c;h=b13eeadffb28e5e6763862e82f3f7749f46fefe5;hb=HEAD;hp=8d1aa5fa841eb934b9b1846672d9c43dbe23bca3;hpb=fbd607dd560afe44c3b90de1e6cbe5265cac8f1e;p=ffmpeg diff --git a/libavutil/buffer.c b/libavutil/buffer.c index 8d1aa5fa841..b13eeadffb2 100644 --- a/libavutil/buffer.c +++ b/libavutil/buffer.c @@ -20,12 +20,13 @@ #include #include +#include "avassert.h" #include "buffer_internal.h" #include "common.h" #include "mem.h" #include "thread.h" -AVBufferRef *av_buffer_create(uint8_t *data, int size, +AVBufferRef *av_buffer_create(uint8_t *data, size_t size, void (*free)(void *opaque, uint8_t *data), void *opaque, int flags) { @@ -43,8 +44,7 @@ AVBufferRef *av_buffer_create(uint8_t *data, int size, atomic_init(&buf->refcount, 1); - if (flags & AV_BUFFER_FLAG_READONLY) - buf->flags |= BUFFER_FLAG_READONLY; + buf->flags = flags; ref = av_mallocz(sizeof(*ref)); if (!ref) { @@ -64,7 +64,7 @@ void av_buffer_default_free(void *opaque, uint8_t *data) av_free(data); } -AVBufferRef *av_buffer_alloc(int size) +AVBufferRef *av_buffer_alloc(size_t size) { AVBufferRef *ret = NULL; uint8_t *data = NULL; @@ -80,7 +80,7 @@ AVBufferRef *av_buffer_alloc(int size) return ret; } -AVBufferRef *av_buffer_allocz(int size) +AVBufferRef *av_buffer_allocz(size_t size) { AVBufferRef *ret = av_buffer_alloc(size); if (!ret) @@ -116,7 +116,7 @@ static void buffer_replace(AVBufferRef **dst, AVBufferRef **src) } else av_freep(dst); - if (atomic_fetch_add_explicit(&b->refcount, -1, memory_order_acq_rel) == 1) { + if (atomic_fetch_sub_explicit(&b->refcount, 1, memory_order_acq_rel) == 1) { b->free(b->opaque, b->data); av_freep(&b); } @@ -166,10 +166,11 @@ int av_buffer_make_writable(AVBufferRef **pbuf) return 0; } -int av_buffer_realloc(AVBufferRef **pbuf, int size) +int av_buffer_realloc(AVBufferRef **pbuf, size_t size) { AVBufferRef *buf = *pbuf; uint8_t *tmp; + int ret; if (!buf) { /* allocate a new buffer with av_realloc(), so it will be reallocatable @@ -184,21 +185,21 @@ int av_buffer_realloc(AVBufferRef **pbuf, int size) return AVERROR(ENOMEM); } - buf->buffer->flags |= BUFFER_FLAG_REALLOCATABLE; + buf->buffer->flags_internal |= BUFFER_FLAG_REALLOCATABLE; *pbuf = buf; return 0; } else if (buf->size == size) return 0; - if (!(buf->buffer->flags & BUFFER_FLAG_REALLOCATABLE) || + if (!(buf->buffer->flags_internal & BUFFER_FLAG_REALLOCATABLE) || !av_buffer_is_writable(buf) || buf->data != buf->buffer->data) { /* cannot realloc, allocate a new reallocable buffer and copy data */ AVBufferRef *new = NULL; - av_buffer_realloc(&new, size); - if (!new) - return AVERROR(ENOMEM); + ret = av_buffer_realloc(&new, size); + if (ret < 0) + return ret; memcpy(new->data, buf->data, FFMIN(size, buf->size)); @@ -215,8 +216,34 @@ int av_buffer_realloc(AVBufferRef **pbuf, int size) return 0; } -AVBufferPool *av_buffer_pool_init2(int size, void *opaque, - AVBufferRef* (*alloc)(void *opaque, int size), +int av_buffer_replace(AVBufferRef **pdst, AVBufferRef *src) +{ + AVBufferRef *dst = *pdst; + AVBufferRef *tmp; + + if (!src) { + av_buffer_unref(pdst); + return 0; + } + + if (dst && dst->buffer == src->buffer) { + /* make sure the data pointers match */ + dst->data = src->data; + dst->size = src->size; + return 0; + } + + tmp = av_buffer_ref(src); + if (!tmp) + return AVERROR(ENOMEM); + + av_buffer_unref(pdst); + *pdst = tmp; + return 0; +} + +AVBufferPool *av_buffer_pool_init2(size_t size, void *opaque, + AVBufferRef* (*alloc)(void *opaque, size_t size), void (*pool_free)(void *opaque)) { AVBufferPool *pool = av_mallocz(sizeof(*pool)); @@ -228,6 +255,7 @@ AVBufferPool *av_buffer_pool_init2(int size, void *opaque, pool->size = size; pool->opaque = opaque; pool->alloc2 = alloc; + pool->alloc = av_buffer_alloc; // fallback pool->pool_free = pool_free; atomic_init(&pool->refcount, 1); @@ -235,7 +263,7 @@ AVBufferPool *av_buffer_pool_init2(int size, void *opaque, return pool; } -AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size)) +AVBufferPool *av_buffer_pool_init(size_t size, AVBufferRef* (*alloc)(size_t size)) { AVBufferPool *pool = av_mallocz(sizeof(*pool)); if (!pool) @@ -251,11 +279,7 @@ AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size)) return pool; } -/* - * This function gets called when the pool has been uninited and - * all the buffers returned to it. - */ -static void buffer_pool_free(AVBufferPool *pool) +static void buffer_pool_flush(AVBufferPool *pool) { while (pool->pool) { BufferPoolEntry *buf = pool->pool; @@ -264,6 +288,15 @@ static void buffer_pool_free(AVBufferPool *pool) buf->free(buf->opaque, buf->data); av_freep(&buf); } +} + +/* + * This function gets called when the pool has been uninited and + * all the buffers returned to it. + */ +static void buffer_pool_free(AVBufferPool *pool) +{ + buffer_pool_flush(pool); ff_mutex_destroy(&pool->mutex); if (pool->pool_free) @@ -281,7 +314,11 @@ void av_buffer_pool_uninit(AVBufferPool **ppool) pool = *ppool; *ppool = NULL; - if (atomic_fetch_add_explicit(&pool->refcount, -1, memory_order_acq_rel) == 1) + ff_mutex_lock(&pool->mutex); + buffer_pool_flush(pool); + ff_mutex_unlock(&pool->mutex); + + if (atomic_fetch_sub_explicit(&pool->refcount, 1, memory_order_acq_rel) == 1) buffer_pool_free(pool); } @@ -298,7 +335,7 @@ static void pool_release_buffer(void *opaque, uint8_t *data) pool->pool = buf; ff_mutex_unlock(&pool->mutex); - if (atomic_fetch_add_explicit(&pool->refcount, -1, memory_order_acq_rel) == 1) + if (atomic_fetch_sub_explicit(&pool->refcount, 1, memory_order_acq_rel) == 1) buffer_pool_free(pool); } @@ -309,6 +346,8 @@ static AVBufferRef *pool_alloc_buffer(AVBufferPool *pool) BufferPoolEntry *buf; AVBufferRef *ret; + av_assert0(pool->alloc || pool->alloc2); + ret = pool->alloc2 ? pool->alloc2(pool->opaque, pool->size) : pool->alloc(pool->size); if (!ret) @@ -355,3 +394,10 @@ AVBufferRef *av_buffer_pool_get(AVBufferPool *pool) return ret; } + +void *av_buffer_pool_buffer_get_opaque(AVBufferRef *ref) +{ + BufferPoolEntry *buf = ref->buffer->opaque; + av_assert0(buf); + return buf->opaque; +}