[vlc-devel] [PATCH 2/2] picture_pool: fix Reserve() not locking/unlocking pictures

Thomas Guillem thomas at gllm.fr
Fri Dec 30 17:58:21 CET 2016


Pictures cloned from a reserved pool were not locked/unlocked via the master
pool callbacks. This commit fixes this issue. See the new comment in
picture_pool_Reserve().
---
 src/misc/picture_pool.c | 43 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 11 deletions(-)

diff --git a/src/misc/picture_pool.c b/src/misc/picture_pool.c
index 875aff42ab..e97cdbd9ed 100644
--- a/src/misc/picture_pool.c
+++ b/src/misc/picture_pool.c
@@ -66,7 +66,7 @@ void picture_pool_Release(picture_pool_t *pool)
     picture_pool_Destroy(pool);
 }
 
-static void picture_pool_ReleasePicture(picture_t *clone)
+static void picture_pool_ReleasePicture(picture_t *clone, bool locked)
 {
     picture_priv_t *priv = (picture_priv_t *)clone;
     uintptr_t sys = (uintptr_t)priv->gc.opaque;
@@ -76,7 +76,7 @@ static void picture_pool_ReleasePicture(picture_t *clone)
 
     free(clone);
 
-    if (pool->pic_unlock != NULL)
+    if (locked && pool->pic_unlock != NULL)
         pool->pic_unlock(picture);
     picture_Release(picture);
 
@@ -89,14 +89,25 @@ static void picture_pool_ReleasePicture(picture_t *clone)
     picture_pool_Destroy(pool);
 }
 
+static void picture_pool_ReleasePictureLocked(picture_t *clone)
+{
+    picture_pool_ReleasePicture(clone, true);
+}
+
+static void picture_pool_ReleasePictureUnlocked(picture_t *clone)
+{
+    picture_pool_ReleasePicture(clone, false);
+}
+
 static picture_t *picture_pool_ClonePicture(picture_pool_t *pool,
-                                            unsigned offset)
+                                            unsigned offset, bool locked)
 {
     picture_t *picture = pool->picture[offset];
     uintptr_t sys = ((uintptr_t)pool) + offset;
     picture_resource_t res = {
         .p_sys = picture->p_sys,
-        .pf_destroy = picture_pool_ReleasePicture,
+        .pf_destroy = locked ? picture_pool_ReleasePictureLocked
+                             : picture_pool_ReleasePictureUnlocked,
     };
 
     for (int i = 0; i < picture->i_planes; i++) {
@@ -121,7 +132,7 @@ static int fnsll(unsigned long long x, unsigned i)
     return ffsll(x & ~((1ULL << i) - 1));
 }
 
-static picture_t *picture_pool_GetInternal(picture_pool_t *pool)
+static picture_t *picture_pool_GetInternal(picture_pool_t *pool, bool lock)
 {
     vlc_mutex_lock(&pool->lock);
     assert(pool->refs > 0);
@@ -139,7 +150,7 @@ static picture_t *picture_pool_GetInternal(picture_pool_t *pool)
 
         picture_t *picture = pool->picture[i - 1];
 
-        if (pool->pic_lock != NULL
+        if (lock && pool->pic_lock != NULL
          && pool->pic_lock(picture) != VLC_SUCCESS)
         {
             vlc_mutex_lock(&pool->lock);
@@ -147,7 +158,7 @@ static picture_t *picture_pool_GetInternal(picture_pool_t *pool)
             continue;
         }
 
-        picture_t *clone = picture_pool_ClonePicture(pool, i - 1);
+        picture_t *clone = picture_pool_ClonePicture(pool, i - 1, lock);
         if (clone != NULL) {
             assert(clone->p_next == NULL);
             atomic_fetch_add(&pool->refs, 1);
@@ -222,12 +233,22 @@ picture_pool_t *picture_pool_Reserve(picture_pool_t *master, unsigned count)
     unsigned i;
 
     for (i = 0; i < count; i++) {
-        picture[i] = picture_pool_GetInternal(master);
+        /* Pictures that are used to initialize the reserved pool should not be
+         * locked and unlocked (hence the false). Only pictures cloned from the
+         * reserved pool should be locked/unlocked with the same callbacks than
+         * the master ones. */
+        picture[i] = picture_pool_GetInternal(master, false);
         if (picture[i] == NULL)
             goto error;
     }
 
-    picture_pool_t *pool = picture_pool_New(count, picture);
+    picture_pool_configuration_t pool_cfg = {
+        .picture_count = count,
+        .picture       = picture,
+        .lock          = master->pic_lock,
+        .unlock        = master->pic_unlock,
+    };
+    picture_pool_t *pool = picture_pool_NewExtended(&pool_cfg);
     if (!pool)
         goto error;
 
@@ -241,7 +262,7 @@ error:
 
 picture_t *picture_pool_Get(picture_pool_t *pool)
 {
-    return picture_pool_GetInternal(pool);
+    return picture_pool_GetInternal(pool, true);
 }
 
 picture_t *picture_pool_Wait(picture_pool_t *pool)
@@ -276,7 +297,7 @@ picture_t *picture_pool_Wait(picture_pool_t *pool)
         return NULL;
     }
 
-    picture_t *clone = picture_pool_ClonePicture(pool, i - 1);
+    picture_t *clone = picture_pool_ClonePicture(pool, i - 1, true);
     if (clone != NULL) {
         assert(clone->p_next == NULL);
         atomic_fetch_add(&pool->refs, 1);
-- 
2.11.0



More information about the vlc-devel mailing list