]> git.sesse.net Git - vlc/blobdiff - src/misc/picture_pool.c
Use var_Inherit* instead of var_CreateGet*.
[vlc] / src / misc / picture_pool.c
index 8719a374118b2f7590ecacad4b1194cdab96f7d3..39ae0f8304b05b631c228b083b4490c10470ccbd 100644 (file)
@@ -52,27 +52,43 @@ struct picture_release_sys_t {
 
 struct picture_pool_t {
     /* */
-    int64_t   tick;
+    picture_pool_t *master;
+    int64_t        tick;
     /* */
-    int       picture_count;
-    picture_t **picture;
+    int            picture_count;
+    picture_t      **picture;
+    bool           *picture_reserved;
 };
 
-static void PicturePoolPictureRelease(picture_t *);
+static void Release(picture_t *);
+static int  Lock(picture_t *);
+static void Unlock(picture_t *);
 
-picture_pool_t *picture_pool_NewExtended(const picture_pool_configuration_t *cfg)
+static picture_pool_t *Create(picture_pool_t *master, int picture_count)
 {
     picture_pool_t *pool = calloc(1, sizeof(*pool));
     if (!pool)
         return NULL;
 
-    pool->tick = 1;
-    pool->picture_count = cfg->picture_count;
+    pool->master = master;
+    pool->tick = master ? master->tick : 1;
+    pool->picture_count = picture_count;
     pool->picture = calloc(pool->picture_count, sizeof(*pool->picture));
-    if (!pool->picture) {
+    pool->picture_reserved = calloc(pool->picture_count, sizeof(*pool->picture_reserved));
+    if (!pool->picture || !pool->picture_reserved) {
+        free(pool->picture);
+        free(pool->picture_reserved);
         free(pool);
         return NULL;
     }
+    return pool;
+}
+
+picture_pool_t *picture_pool_NewExtended(const picture_pool_configuration_t *cfg)
+{
+    picture_pool_t *pool = Create(NULL, cfg->picture_count);
+    if (!pool)
+        return NULL;
 
     for (int i = 0; i < cfg->picture_count; i++) {
         picture_t *picture = cfg->picture[i];
@@ -92,11 +108,12 @@ picture_pool_t *picture_pool_NewExtended(const picture_pool_configuration_t *cfg
 
         /* */
         picture->i_refcount    = 0;
-        picture->pf_release    = PicturePoolPictureRelease;
+        picture->pf_release    = Release;
         picture->p_release_sys = release_sys;
 
         /* */
         pool->picture[i] = picture;
+        pool->picture_reserved[i] = false;
     }
     return pool;
 
@@ -137,23 +154,57 @@ error:
     return NULL;
 }
 
+picture_pool_t *picture_pool_Reserve(picture_pool_t *master, int count)
+{
+    picture_pool_t *pool = Create(master, count);
+    if (!pool)
+        return NULL;
+
+    int found = 0;
+    for (int i = 0; i < master->picture_count && found < count; i++) {
+        if (master->picture_reserved[i])
+            continue;
+
+        assert(master->picture[i]->i_refcount == 0);
+        master->picture_reserved[i] = true;
+
+        pool->picture[found]          = master->picture[i];
+        pool->picture_reserved[found] = false;
+        found++;
+    }
+    if (found < count) {
+        picture_pool_Delete(pool);
+        return NULL;
+    }
+    return pool;
+}
+
 void picture_pool_Delete(picture_pool_t *pool)
 {
     for (int i = 0; i < pool->picture_count; i++) {
         picture_t *picture = pool->picture[i];
-        picture_release_sys_t *release_sys = picture->p_release_sys;
+        if (pool->master) {
+            for (int j = 0; j < pool->master->picture_count; j++) {
+                if (pool->master->picture[j] == picture)
+                    pool->master->picture_reserved[j] = false;
+            }
+        } else {
+            picture_release_sys_t *release_sys = picture->p_release_sys;
 
-        assert(picture->i_refcount == 0);
+            assert(picture->i_refcount == 0);
+            assert(!pool->picture_reserved[i]);
 
-        /* Restore old release callback */
-        picture->i_refcount    = 1;
-        picture->pf_release    = release_sys->release;
-        picture->p_release_sys = release_sys->release_sys;
+            /* Restore old release callback */
+            picture->i_refcount    = 1;
+            picture->pf_release    = release_sys->release;
+            picture->p_release_sys = release_sys->release_sys;
 
-        picture_Release(picture);
+            picture_Release(picture);
 
-        free(release_sys);
+            free(release_sys);
+        }
     }
+    free(pool->picture_reserved);
     free(pool->picture);
     free(pool);
 }
@@ -161,12 +212,14 @@ void picture_pool_Delete(picture_pool_t *pool)
 picture_t *picture_pool_Get(picture_pool_t *pool)
 {
     for (int i = 0; i < pool->picture_count; i++) {
+        if (pool->picture_reserved[i])
+            continue;
+
         picture_t *picture = pool->picture[i];
         if (picture->i_refcount > 0)
             continue;
 
-        picture_release_sys_t *release_sys = picture->p_release_sys;
-        if (release_sys->lock && release_sys->lock(picture))
+        if (Lock(picture))
             continue;
 
         /* */
@@ -182,10 +235,13 @@ void picture_pool_NonEmpty(picture_pool_t *pool, bool reset)
     picture_t *old = NULL;
 
     for (int i = 0; i < pool->picture_count; i++) {
-        picture_t *picture = pool->picture[i];
+        if (pool->picture_reserved[i])
+            continue;
 
+        picture_t *picture = pool->picture[i];
         if (reset) {
-            /* TODO pf_unlock */
+            if (picture->i_refcount > 0)
+                Unlock(picture);
             picture->i_refcount = 0;
         } else if (picture->i_refcount == 0) {
             return;
@@ -194,18 +250,34 @@ void picture_pool_NonEmpty(picture_pool_t *pool, bool reset)
         }
     }
     if (!reset && old) {
-        /* TODO pf_unlock */
+        if (old->i_refcount > 0)
+            Unlock(old);
         old->i_refcount = 0;
     }
 }
+int picture_pool_GetSize(picture_pool_t *pool)
+{
+    return pool->picture_count;
+}
 
-static void PicturePoolPictureRelease(picture_t *picture)
+static void Release(picture_t *picture)
 {
     assert(picture->i_refcount > 0);
 
     if (--picture->i_refcount > 0)
         return;
+    Unlock(picture);
+}
 
+static int Lock(picture_t *picture)
+{
+    picture_release_sys_t *release_sys = picture->p_release_sys;
+    if (release_sys->lock)
+        return release_sys->lock(picture);
+    return VLC_SUCCESS;
+}
+static void Unlock(picture_t *picture)
+{
     picture_release_sys_t *release_sys = picture->p_release_sys;
     if (release_sys->unlock)
         release_sys->unlock(picture);