[vlc-commits] picture_pool: add picture_pool_Wait()

Rémi Denis-Courmont git at videolan.org
Sun Sep 27 22:05:13 CEST 2015


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sun Sep 27 19:41:14 2015 +0300| [0f9fee360382c4f06d739ccf9046838cf1fca9e3] | committer: Rémi Denis-Courmont

picture_pool: add picture_pool_Wait()

This variant of picture_pool_Get() sleeps until a picture is available.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=0f9fee360382c4f06d739ccf9046838cf1fca9e3
---

 include/vlc_picture_pool.h |   11 +++++++++++
 src/libvlccore.sym         |    1 +
 src/misc/picture_pool.c    |   37 +++++++++++++++++++++++++++++++++++++
 src/test/picture_pool.c    |    8 ++++++++
 src/video_output/display.c |    1 +
 5 files changed, 58 insertions(+)

diff --git a/include/vlc_picture_pool.h b/include/vlc_picture_pool.h
index 1ce92ce..ec4bf39 100644
--- a/include/vlc_picture_pool.h
+++ b/include/vlc_picture_pool.h
@@ -121,6 +121,17 @@ VLC_API void picture_pool_Release( picture_pool_t * );
 VLC_API picture_t * picture_pool_Get( picture_pool_t * ) VLC_USED;
 
 /**
+ * Obtains a picture from a pool.
+ *
+ * The picture must be released with picture_Release().
+ *
+ * @return a picture or NULL on memory error
+ *
+ * @note This function is thread-safe.
+ */
+VLC_API picture_t *picture_pool_Wait(picture_pool_t *) VLC_USED;
+
+/**
  * Enumerates all pictures in a pool, both free and allocated.
  *
  * @param cb callback to invoke once for each picture
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 147dcd9..dd813bc 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -311,6 +311,7 @@ picture_pool_New
 picture_pool_NewExtended
 picture_pool_NewFromFormat
 picture_pool_Reserve
+picture_pool_Wait
 picture_Reset
 picture_Setup
 plane_CopyPixels
diff --git a/src/misc/picture_pool.c b/src/misc/picture_pool.c
index bb9c103..f82cb16 100644
--- a/src/misc/picture_pool.c
+++ b/src/misc/picture_pool.c
@@ -40,6 +40,7 @@ struct picture_pool_t {
     int       (*pic_lock)(picture_t *);
     void      (*pic_unlock)(picture_t *);
     vlc_mutex_t lock;
+    vlc_cond_t  wait;
 
     unsigned long long available;
     atomic_ushort      refs;
@@ -52,6 +53,7 @@ static void picture_pool_Destroy(picture_pool_t *pool)
     if (atomic_fetch_sub(&pool->refs, 1) != 1)
         return;
 
+    vlc_cond_destroy(&pool->wait);
     vlc_mutex_destroy(&pool->lock);
     vlc_free(pool);
 }
@@ -80,6 +82,7 @@ static void picture_pool_ReleasePicture(picture_t *clone)
     vlc_mutex_lock(&pool->lock);
     assert(!(pool->available & (1ULL << offset)));
     pool->available |= 1ULL << offset;
+    vlc_cond_signal(&pool->wait);
     vlc_mutex_unlock(&pool->lock);
 
     picture_pool_Destroy(pool);
@@ -122,6 +125,7 @@ picture_pool_t *picture_pool_NewExtended(const picture_pool_configuration_t *cfg
     pool->pic_lock   = cfg->lock;
     pool->pic_unlock = cfg->unlock;
     vlc_mutex_init(&pool->lock);
+    vlc_cond_init(&pool->wait);
     pool->available = (1ULL << cfg->picture_count) - 1;
     atomic_init(&pool->refs,  1);
     pool->picture_count = cfg->picture_count;
@@ -225,6 +229,39 @@ picture_t *picture_pool_Get(picture_pool_t *pool)
     return NULL;
 }
 
+picture_t *picture_pool_Wait(picture_pool_t *pool)
+{
+    unsigned i;
+
+    vlc_mutex_lock(&pool->lock);
+    assert(pool->refs > 0);
+
+    while (pool->available == 0)
+        vlc_cond_wait(&pool->wait, &pool->lock);
+
+    i = ffsll(pool->available);
+    assert(i > 0);
+    pool->available &= ~(1ULL << (i - 1));
+    vlc_mutex_unlock(&pool->lock);
+
+    picture_t *picture = pool->picture[i - 1];
+
+    if (pool->pic_lock != NULL && pool->pic_lock(picture) != 0) {
+        vlc_mutex_lock(&pool->lock);
+        pool->available |= 1ULL << (i - 1);
+        vlc_cond_signal(&pool->wait);
+        vlc_mutex_unlock(&pool->lock);
+        return NULL;
+    }
+
+    picture_t *clone = picture_pool_ClonePicture(pool, i - 1);
+    if (clone != NULL) {
+        assert(clone->p_next == NULL);
+        atomic_fetch_add(&pool->refs, 1);
+    }
+    return clone;
+}
+
 unsigned picture_pool_Reset(picture_pool_t *pool)
 {
     unsigned ret;
diff --git a/src/test/picture_pool.c b/src/test/picture_pool.c
index 2ff3d51..35229cf 100644
--- a/src/test/picture_pool.c
+++ b/src/test/picture_pool.c
@@ -72,6 +72,14 @@ static void test(bool zombie)
     for (unsigned i = 0; i < PICTURES; i++)
         picture_Release(pics[i]);
 
+    for (unsigned i = 0; i < PICTURES; i++) {
+        pics[i] = picture_pool_Wait(pool);
+        assert(pics[i] != NULL);
+    }
+
+    for (unsigned i = 0; i < PICTURES; i++)
+        picture_Release(pics[i]);
+
     reserve = picture_pool_Reserve(pool, PICTURES / 2);
     assert(reserve != NULL);
 
diff --git a/src/video_output/display.c b/src/video_output/display.c
index 76287cf..e9f27fd 100644
--- a/src/video_output/display.c
+++ b/src/video_output/display.c
@@ -36,6 +36,7 @@
 #include <vlc_block.h>
 #include <vlc_modules.h>
 #include <vlc_filter.h>
+#include <vlc_picture_pool.h>
 
 #include <libvlc.h>
 



More information about the vlc-commits mailing list