[vlc-devel] [PATCH 1/5] [RFC] picture_pool: add a way to configure pools to expand dynamically

Steve Lhomme robux4 at ycbcr.xyz
Wed Dec 5 09:59:02 CET 2018


Can expand up to POOL_MAX pictures.

It can be initialized with some pictures or even 0 pictures.

With the push system each decoder/filter will have its own output pool. Rather
than dimension all of them to the max with can start with the minimum pictures
needed and expand if needed.
---
 include/vlc_picture_pool.h |  4 +++
 src/misc/picture_pool.c    | 58 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/include/vlc_picture_pool.h b/include/vlc_picture_pool.h
index 8b04370bfb..e1ebb7191b 100644
--- a/include/vlc_picture_pool.h
+++ b/include/vlc_picture_pool.h
@@ -43,6 +43,10 @@ typedef struct {
     unsigned  picture_count;
     picture_t *const *picture;
 
+    void                 *expand_ctx;
+    picture_t*           (*expand_cb)(void *, const video_format_t*); /* create a new picture for dynamic pools */
+    const video_format_t *expand_fmt;
+
     int       (*lock)(picture_t *);
     void      (*unlock)(picture_t *);
 } picture_pool_configuration_t;
diff --git a/src/misc/picture_pool.c b/src/misc/picture_pool.c
index 874a04e4d8..b52e1837e6 100644
--- a/src/misc/picture_pool.c
+++ b/src/misc/picture_pool.c
@@ -44,6 +44,10 @@ struct picture_pool_t {
     vlc_mutex_t lock;
     vlc_cond_t  wait;
 
+    void           *expand_ctx;
+    video_format_t expand_fmt;
+    picture_t*     (*expand_cb)(void *, const video_format_t*);
+
     bool               canceled;
     unsigned long long available;
     atomic_ushort      refs;
@@ -57,6 +61,7 @@ static void picture_pool_Destroy(picture_pool_t *pool)
         return;
 
     atomic_thread_fence(memory_order_acquire);
+    video_format_Clean(&pool->expand_fmt);
     vlc_cond_destroy(&pool->wait);
     vlc_mutex_destroy(&pool->lock);
     aligned_free(pool);
@@ -84,6 +89,7 @@ static void picture_pool_ReleasePicture(picture_t *clone)
     picture_Release(picture);
 
     vlc_mutex_lock(&pool->lock);
+    if (pool->available & (1ULL << offset))
     assert(!(pool->available & (1ULL << offset)));
     pool->available |= 1ULL << offset;
     vlc_cond_signal(&pool->wait);
@@ -122,13 +128,20 @@ picture_pool_t *picture_pool_NewExtended(const picture_pool_configuration_t *cfg
         return NULL;
 
     picture_pool_t *pool;
-    size_t size = sizeof (*pool) + cfg->picture_count * sizeof (picture_t *);
+    size_t size = sizeof (*pool) + (cfg->expand_cb ? POOL_MAX : cfg->picture_count) * sizeof (picture_t *);
 
     size += (-size) & (POOL_MAX - 1);
     pool = aligned_alloc(POOL_MAX, size);
     if (unlikely(pool == NULL))
         return NULL;
 
+    pool->expand_cb  = cfg->expand_cb;
+    pool->expand_ctx = cfg->expand_ctx;
+    if (pool->expand_cb != NULL)
+        video_format_Copy(&pool->expand_fmt, cfg->expand_fmt);
+    else
+        video_format_Init(&pool->expand_fmt, 0);
+
     pool->pic_lock   = cfg->lock;
     pool->pic_unlock = cfg->unlock;
     vlc_mutex_init(&pool->lock);
@@ -202,6 +215,34 @@ error:
     return NULL;
 }
 
+static picture_t *NewExpanded_Locked(picture_pool_t *pool)
+{
+    picture_t *picture = pool->expand_cb(pool->expand_ctx, &pool->expand_fmt);
+    if (picture != NULL)
+    {
+        if (pool->pic_lock != NULL && pool->pic_lock(picture) != VLC_SUCCESS)
+        {
+            picture_Release(picture);
+        }
+        else
+        {
+            int i = ctz(pool->available) % POOL_MAX;
+            pool->picture[i] = picture;
+            pool->picture_count++;
+            vlc_mutex_unlock(&pool->lock);
+
+            picture_t *clone = picture_pool_ClonePicture(pool, i);
+            if (clone != NULL) {
+                assert(clone->p_next == NULL);
+                atomic_fetch_add_explicit(&pool->refs, 1, memory_order_relaxed);
+            }
+            return clone;
+        }
+    }
+    vlc_mutex_unlock(&pool->lock);
+    return NULL;
+}
+
 picture_t *picture_pool_Get(picture_pool_t *pool)
 {
     unsigned long long available;
@@ -237,6 +278,11 @@ picture_t *picture_pool_Get(picture_pool_t *pool)
         return clone;
     }
 
+    if (pool->expand_cb && likely(pool->picture_count < POOL_MAX) && unlikely(!pool->canceled))
+    {
+        return NewExpanded_Locked(pool);
+    }
+
     vlc_mutex_unlock(&pool->lock);
     return NULL;
 }
@@ -246,6 +292,16 @@ picture_t *picture_pool_Wait(picture_pool_t *pool)
     vlc_mutex_lock(&pool->lock);
     assert(pool->refs > 0);
 
+    if ( pool->available == 0 && pool->expand_cb != NULL &&
+         likely(pool->picture_count < POOL_MAX) && unlikely(!pool->canceled) )
+    {
+        /* try to get a fresh expanded picture */
+        picture_t *pic = NewExpanded_Locked(pool);
+        if (pic != NULL)
+            return pic;
+        vlc_mutex_lock(&pool->lock); /* NewExpanded_Locked() returned unlocked */
+    }
+
     while (pool->available == 0)
     {
         if (pool->canceled)
-- 
2.17.1



More information about the vlc-devel mailing list