Commit 0f9fee36 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

picture_pool: add picture_pool_Wait()

This variant of picture_pool_Get() sleeps until a picture is available.
parent 8133a0aa
...@@ -120,6 +120,17 @@ VLC_API void picture_pool_Release( picture_pool_t * ); ...@@ -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; 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. * Enumerates all pictures in a pool, both free and allocated.
* *
......
...@@ -311,6 +311,7 @@ picture_pool_New ...@@ -311,6 +311,7 @@ picture_pool_New
picture_pool_NewExtended picture_pool_NewExtended
picture_pool_NewFromFormat picture_pool_NewFromFormat
picture_pool_Reserve picture_pool_Reserve
picture_pool_Wait
picture_Reset picture_Reset
picture_Setup picture_Setup
plane_CopyPixels plane_CopyPixels
......
...@@ -40,6 +40,7 @@ struct picture_pool_t { ...@@ -40,6 +40,7 @@ struct picture_pool_t {
int (*pic_lock)(picture_t *); int (*pic_lock)(picture_t *);
void (*pic_unlock)(picture_t *); void (*pic_unlock)(picture_t *);
vlc_mutex_t lock; vlc_mutex_t lock;
vlc_cond_t wait;
unsigned long long available; unsigned long long available;
atomic_ushort refs; atomic_ushort refs;
...@@ -52,6 +53,7 @@ static void picture_pool_Destroy(picture_pool_t *pool) ...@@ -52,6 +53,7 @@ static void picture_pool_Destroy(picture_pool_t *pool)
if (atomic_fetch_sub(&pool->refs, 1) != 1) if (atomic_fetch_sub(&pool->refs, 1) != 1)
return; return;
vlc_cond_destroy(&pool->wait);
vlc_mutex_destroy(&pool->lock); vlc_mutex_destroy(&pool->lock);
vlc_free(pool); vlc_free(pool);
} }
...@@ -80,6 +82,7 @@ static void picture_pool_ReleasePicture(picture_t *clone) ...@@ -80,6 +82,7 @@ static void picture_pool_ReleasePicture(picture_t *clone)
vlc_mutex_lock(&pool->lock); vlc_mutex_lock(&pool->lock);
assert(!(pool->available & (1ULL << offset))); assert(!(pool->available & (1ULL << offset)));
pool->available |= 1ULL << offset; pool->available |= 1ULL << offset;
vlc_cond_signal(&pool->wait);
vlc_mutex_unlock(&pool->lock); vlc_mutex_unlock(&pool->lock);
picture_pool_Destroy(pool); picture_pool_Destroy(pool);
...@@ -122,6 +125,7 @@ picture_pool_t *picture_pool_NewExtended(const picture_pool_configuration_t *cfg ...@@ -122,6 +125,7 @@ picture_pool_t *picture_pool_NewExtended(const picture_pool_configuration_t *cfg
pool->pic_lock = cfg->lock; pool->pic_lock = cfg->lock;
pool->pic_unlock = cfg->unlock; pool->pic_unlock = cfg->unlock;
vlc_mutex_init(&pool->lock); vlc_mutex_init(&pool->lock);
vlc_cond_init(&pool->wait);
pool->available = (1ULL << cfg->picture_count) - 1; pool->available = (1ULL << cfg->picture_count) - 1;
atomic_init(&pool->refs, 1); atomic_init(&pool->refs, 1);
pool->picture_count = cfg->picture_count; pool->picture_count = cfg->picture_count;
...@@ -225,6 +229,39 @@ picture_t *picture_pool_Get(picture_pool_t *pool) ...@@ -225,6 +229,39 @@ picture_t *picture_pool_Get(picture_pool_t *pool)
return NULL; 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 picture_pool_Reset(picture_pool_t *pool)
{ {
unsigned ret; unsigned ret;
......
...@@ -69,6 +69,14 @@ static void test(bool zombie) ...@@ -69,6 +69,14 @@ static void test(bool zombie)
assert(pics[i]->p[0].p_pixels == plane); 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++) for (unsigned i = 0; i < PICTURES; i++)
picture_Release(pics[i]); picture_Release(pics[i]);
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <vlc_block.h> #include <vlc_block.h>
#include <vlc_modules.h> #include <vlc_modules.h>
#include <vlc_filter.h> #include <vlc_filter.h>
#include <vlc_picture_pool.h>
#include <libvlc.h> #include <libvlc.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment