[vlc-commits] picture_pool: wrap pooled pictures

Rémi Denis-Courmont git at videolan.org
Sat Nov 1 13:31:07 CET 2014


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sat Nov  1 12:00:14 2014 +0200| [2d314967c9824d088f22ac556be143b87b4cc5ee] | committer: Rémi Denis-Courmont

picture_pool: wrap pooled pictures

The pool can now have its own independent garbage collector, that no
longer clobbers the original garbage collector.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=2d314967c9824d088f22ac556be143b87b4cc5ee
---

 src/misc/picture_pool.c |   87 +++++++++++++++++++++++------------------------
 1 file changed, 43 insertions(+), 44 deletions(-)

diff --git a/src/misc/picture_pool.c b/src/misc/picture_pool.c
index 3c080b3..64ddf2e 100644
--- a/src/misc/picture_pool.c
+++ b/src/misc/picture_pool.c
@@ -39,10 +39,7 @@
  *****************************************************************************/
 struct picture_gc_sys_t {
     picture_pool_t *pool;
-    /* Saved release */
-    void (*destroy)(picture_t *);
-    void *destroy_sys;
-    /* */
+    picture_t *picture;
     atomic_bool zombie;
     int64_t tick;
 };
@@ -80,26 +77,57 @@ static void Release(picture_pool_t *pool)
     free(pool);
 }
 
-static void DestroyPicture(picture_t *picture)
+static void picture_pool_ReleasePicture(picture_t *picture)
 {
-    picture_gc_sys_t *gc_sys = picture->gc.p_sys;
-    picture_pool_t *pool = gc_sys->pool;
+    picture_gc_sys_t *sys = picture->gc.p_sys;
+    picture_pool_t *pool = sys->pool;
 
     if (pool->pic_unlock != NULL)
         pool->pic_unlock(picture);
 
-    if (!atomic_load(&gc_sys->zombie))
+    if (!atomic_load(&sys->zombie))
         return;
 
     /* Picture from an already destroyed pool */
-    picture->gc.pf_destroy = gc_sys->destroy;
-    picture->gc.p_sys      = gc_sys->destroy_sys;
-    free(gc_sys);
+    picture_Release(sys->picture);
+    free(sys);
+    free(picture);
 
-    picture->gc.pf_destroy(picture);
     Release(pool);
 }
 
+static picture_t *picture_pool_ClonePicture(picture_pool_t *pool,
+                                            picture_t *picture)
+{
+    picture_gc_sys_t *sys = malloc(sizeof(*sys));
+    if (unlikely(sys == NULL))
+        return NULL;
+
+    sys->pool = pool;
+    sys->picture = picture;
+    atomic_init(&sys->zombie, false);
+    sys->tick = 0;
+
+    picture_resource_t res = {
+        .p_sys = picture->p_sys,
+        .pf_destroy = picture_pool_ReleasePicture,
+    };
+
+    for (int i = 0; i < picture->i_planes; i++) {
+        res.p[i].p_pixels = picture->p[i].p_pixels;
+        res.p[i].i_lines = picture->p[i].i_lines;
+        res.p[i].i_pitch = picture->p[i].i_pitch;
+    }
+
+    picture_t *clone = picture_NewFromResource(&picture->format, &res);
+    if (likely(clone != NULL))
+        clone->gc.p_sys = sys;
+    else
+        free(sys);
+
+    return clone;
+}
+
 static picture_pool_t *Create(picture_pool_t *master, int picture_count)
 {
     picture_pool_t *pool = calloc(1, sizeof(*pool));
@@ -131,42 +159,13 @@ picture_pool_t *picture_pool_NewExtended(const picture_pool_configuration_t *cfg
     pool->pic_lock   = cfg->lock;
     pool->pic_unlock = cfg->unlock;
 
-    /*
-     * NOTE: When a pooled picture is released, it must be returned to the list
-     * of available pictures from its pool, rather than destroyed.
-     * This requires a dedicated release callback, a pointer to the pool and a
-     * reference count. For simplicity, rather than allocate a whole new
-     * picture_t structure, the pool overrides gc.pf_destroy and gc.p_sys when
-     * created, and restores them when destroyed.
-     * There are some implications to keep in mind:
-     *  - The original creator of the picture (e.g. video output display) must
-     *    not manipulate the gc parameters while the picture is pooled.
-     *  - The picture cannot be pooled more than once, in other words, pools
-     *    cannot be stacked/layered.
-     *  - The picture must be available and its reference count equal to one
-     *    when it gets pooled.
-     *  - Picture plane pointers and sizes must not be mangled in any case.
-     */
     for (unsigned i = 0; i < cfg->picture_count; i++) {
-        picture_t *picture = cfg->picture[i];
-
-        /* Save the original garbage collector */
-        picture_gc_sys_t *gc_sys = malloc(sizeof(*gc_sys));
-        if (unlikely(gc_sys == NULL))
+        picture_t *picture = picture_pool_ClonePicture(pool, cfg->picture[i]);
+        if (unlikely(picture == NULL))
             abort();
-        gc_sys->pool        = pool;
-        gc_sys->destroy     = picture->gc.pf_destroy;
-        gc_sys->destroy_sys = picture->gc.p_sys;
-        atomic_init(&gc_sys->zombie, false);
-        gc_sys->tick        = 0;
-
-        /* Override the garbage collector */
-        assert(atomic_load(&picture->gc.refcount) == 1);
+
         atomic_init(&picture->gc.refcount, 0);
-        picture->gc.pf_destroy = DestroyPicture;
-        picture->gc.p_sys      = gc_sys;
 
-        /* */
         pool->picture[i] = picture;
         pool->picture_reserved[i] = false;
         pool->refs++;



More information about the vlc-commits mailing list