[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