From 0f9fee360382c4f06d739ccf9046838cf1fca9e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= <remi@remlab.net> Date: Sun, 27 Sep 2015 19:41:14 +0300 Subject: [PATCH] picture_pool: add picture_pool_Wait() This variant of picture_pool_Get() sleeps until a picture is available. --- 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 1ce92ce41278..ec4bf39ea996 100644 --- a/include/vlc_picture_pool.h +++ b/include/vlc_picture_pool.h @@ -120,6 +120,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. * diff --git a/src/libvlccore.sym b/src/libvlccore.sym index 147dcd9bf0a3..dd813bc18972 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 bb9c103e1346..f82cb160f84e 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 2ff3d51563ee..35229cf66bd7 100644 --- a/src/test/picture_pool.c +++ b/src/test/picture_pool.c @@ -69,6 +69,14 @@ static void test(bool zombie) assert(pics[i]->p[0].p_pixels == plane); } + 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]); diff --git a/src/video_output/display.c b/src/video_output/display.c index 76287cfd7cb6..e9f27fd84175 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> -- GitLab