Merge commit 'fbd6c97f9ca858140df16dd07200ea0d4bdc1a83'
[ffmpeg.git] / libavutil / buffer.c
index e9bf54b..0f9f1a2 100644 (file)
@@ -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;
 }