]> git.sesse.net Git - vlc/blobdiff - src/misc/picture_pool.c
Use standard putc_unlocked() instead of fputc_unlocked()
[vlc] / src / misc / picture_pool.c
index 23225c264e420b2cfdab3283963910832c582c65..05cfed139e90135c247f36233e489a3888c72038 100644 (file)
 /*****************************************************************************
  *
  *****************************************************************************/
-struct picture_release_sys_t
-{
+struct picture_release_sys_t {
     /* Saved release */
-    void (*pf_release)( picture_t * );
-    picture_release_sys_t *p_release_sys;
+    void (*release)(picture_t *);
+    picture_release_sys_t *release_sys;
 
     /* */
-    int  (*pf_lock)( picture_t * );
-    void (*pf_unlock)( picture_t * );
+    int  (*lock)(picture_t *);
+    void (*unlock)(picture_t *);
 
     /* */
-    int64_t i_tick;
+    int64_t tick;
 };
 
-struct picture_pool_t
-{
-    int64_t i_tick;
-
-    int i_picture;
-    picture_t **pp_picture;
+struct picture_pool_t {
+    /* */
+    picture_pool_t *master;
+    int64_t        tick;
+    /* */
+    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 *p_pool = calloc( 1, sizeof(*p_pool) );
-    if( !p_pool )
+    picture_pool_t *pool = calloc(1, sizeof(*pool));
+    if (!pool)
         return NULL;
 
-    p_pool->i_tick = 1;
-    p_pool->i_picture = cfg->picture_count;
-    p_pool->pp_picture = calloc( p_pool->i_picture, sizeof(*p_pool->pp_picture) );
-    if( !p_pool->pp_picture )
-    {
-        free( p_pool );
+    pool->master = master;
+    pool->tick = master ? master->tick : 1;
+    pool->picture_count = picture_count;
+    pool->picture = calloc(pool->picture_count, sizeof(*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 *p_picture = cfg->picture[i];
+    for (int i = 0; i < cfg->picture_count; i++) {
+        picture_t *picture = cfg->picture[i];
 
         /* The pool must be the only owner of the picture */
-        assert( p_picture->i_refcount == 1 );
+        assert(picture->i_refcount == 1);
 
         /* Install the new release callback */
-        picture_release_sys_t *p_release_sys = malloc( sizeof(*p_release_sys) );
-        if( !p_release_sys )
+        picture_release_sys_t *release_sys = malloc(sizeof(*release_sys));
+        if (!release_sys)
             abort();
-        p_release_sys->pf_release    = p_picture->pf_release;
-        p_release_sys->p_release_sys = p_picture->p_release_sys;
-        p_release_sys->pf_lock       = cfg->lock;
-        p_release_sys->pf_unlock     = cfg->unlock;
-        p_release_sys->i_tick        = 0;
+        release_sys->release     = picture->pf_release;
+        release_sys->release_sys = picture->p_release_sys;
+        release_sys->lock        = cfg->lock;
+        release_sys->unlock      = cfg->unlock;
+        release_sys->tick        = 0;
 
-        p_picture->i_refcount = 0;
-        p_picture->pf_release = PicturePoolPictureRelease;
-        p_picture->p_release_sys = p_release_sys;
+        /* */
+        picture->i_refcount    = 0;
+        picture->pf_release    = Release;
+        picture->p_release_sys = release_sys;
 
         /* */
-        p_pool->pp_picture[i] = p_picture;
+        pool->picture[i] = picture;
+        pool->picture_reserved[i] = false;
     }
-    return p_pool;
+    return pool;
 
 }
 
-picture_pool_t *picture_pool_New( int i_picture, picture_t *pp_picture[] )
+picture_pool_t *picture_pool_New(int picture_count, picture_t *picture[])
 {
     picture_pool_configuration_t cfg;
 
-    memset( &cfg, 0, sizeof(cfg) );
-    cfg.picture_count = i_picture;
-    cfg.picture       = pp_picture;
+    memset(&cfg, 0, sizeof(cfg));
+    cfg.picture_count = picture_count;
+    cfg.picture       = picture;
 
-    return picture_pool_NewExtended( &cfg );
+    return picture_pool_NewExtended(&cfg);
 }
 
-picture_pool_t *picture_pool_NewFromFormat( const video_format_t *p_fmt, int i_picture )
+picture_pool_t *picture_pool_NewFromFormat(const video_format_t *fmt, int picture_count)
 {
-    picture_t *pp_picture[i_picture];
-
-    for( int i = 0; i < i_picture; i++ )
-    {
-        pp_picture[i] = picture_New( p_fmt->i_chroma,
-                                     p_fmt->i_width, p_fmt->i_height,
-                                     p_fmt->i_aspect );
-        if( !pp_picture[i] )
+    picture_t *picture[picture_count];
+
+    for (int i = 0; i < picture_count; i++) {
+        picture[i] = picture_NewFromFormat(fmt);
+        if (!picture[i])
             goto error;
     }
-    picture_pool_t *p_pool = picture_pool_New( i_picture, pp_picture );
-    if( !p_pool )
+    picture_pool_t *pool = picture_pool_New(picture_count, picture);
+    if (!pool)
         goto error;
 
-    return p_pool;
+    return pool;
 
 error:
-    for( int i = 0; i < i_picture; i++ )
-    {
-        if( !pp_picture[i] )
+    for (int i = 0; i < picture_count; i++) {
+        if (!picture[i])
             break;
-        picture_Release( pp_picture[i] );
+        picture_Release(picture[i]);
     }
     return NULL;
 }
 
-void picture_pool_Delete( picture_pool_t *p_pool )
+picture_pool_t *picture_pool_Reserve(picture_pool_t *master, int count)
 {
-    for( int i = 0; i < p_pool->i_picture; i++ )
-    {
-        picture_t *p_picture = p_pool->pp_picture[i];
-        picture_release_sys_t *p_release_sys = p_picture->p_release_sys;
+    picture_pool_t *pool = Create(master, count);
+    if (!pool)
+        return NULL;
 
-        assert( p_picture->i_refcount == 0 );
+    int found = 0;
+    for (int i = 0; i < master->picture_count && found < count; i++) {
+        if (master->picture_reserved[i])
+            continue;
 
-        /* Restore old release callback */
-        p_picture->i_refcount = 1;
-        p_picture->pf_release = p_release_sys->pf_release;
-        p_picture->p_release_sys = p_release_sys->p_release_sys;
+        assert(master->picture[i]->i_refcount == 0);
+        master->picture_reserved[i] = true;
 
-        picture_Release( p_picture );
+        pool->picture[found]          = master->picture[i];
+        pool->picture_reserved[found] = false;
+        found++;
+    }
+    if (found < count) {
+        picture_pool_Delete(pool);
+        return NULL;
+    }
+    return pool;
+}
 
-        free( p_release_sys );
+void picture_pool_Delete(picture_pool_t *pool)
+{
+    for (int i = 0; i < pool->picture_count; i++) {
+        picture_t *picture = pool->picture[i];
+        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(!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;
+
+            picture_Release(picture);
+
+            free(release_sys);
+        }
     }
-    free( p_pool->pp_picture );
-    free( p_pool );
+    free(pool->picture_reserved);
+    free(pool->picture);
+    free(pool);
 }
 
-picture_t *picture_pool_Get( picture_pool_t *p_pool )
+picture_t *picture_pool_Get(picture_pool_t *pool)
 {
-    for( int i = 0; i < p_pool->i_picture; i++ )
-    {
-        picture_t *p_picture = p_pool->pp_picture[i];
-        if( p_picture->i_refcount > 0 )
+    for (int i = 0; i < pool->picture_count; i++) {
+        if (pool->picture_reserved[i])
             continue;
 
-        picture_release_sys_t *p_release_sys = p_picture->p_release_sys;
-        if( p_release_sys->pf_lock && p_release_sys->pf_lock(p_picture) )
+        picture_t *picture = pool->picture[i];
+        if (picture->i_refcount > 0)
+            continue;
+
+        if (Lock(picture))
             continue;
 
         /* */
-        p_picture->p_release_sys->i_tick = p_pool->i_tick++;
-        picture_Hold( p_picture );
-        return p_picture;
+        picture->p_next = NULL;
+        picture->p_release_sys->tick = pool->tick++;
+        picture_Hold(picture);
+        return picture;
     }
     return NULL;
 }
 
-void picture_pool_NonEmpty( picture_pool_t *p_pool, bool b_reset )
+void picture_pool_NonEmpty(picture_pool_t *pool, bool reset)
 {
-    picture_t *p_old = NULL;
+    picture_t *old = NULL;
 
-    for( int i = 0; i < p_pool->i_picture; i++ )
-    {
-        picture_t *p_picture = p_pool->pp_picture[i];
+    for (int i = 0; i < pool->picture_count; i++) {
+        if (pool->picture_reserved[i])
+            continue;
 
-        if( b_reset )
-            p_picture->i_refcount = 0;
-        else if( p_picture->i_refcount == 0 )
+        picture_t *picture = pool->picture[i];
+        if (reset) {
+            if (picture->i_refcount > 0)
+                Unlock(picture);
+            picture->i_refcount = 0;
+        } else if (picture->i_refcount == 0) {
             return;
-        else if( !p_old || p_picture->p_release_sys->i_tick < p_old->p_release_sys->i_tick )
-            p_old = p_picture;
+        } else if (!old || picture->p_release_sys->tick < old->p_release_sys->tick) {
+            old = picture;
+        }
     }
-    if( !b_reset && p_old )
-        p_old->i_refcount = 0;
+    if (!reset && old) {
+        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 *p_picture )
+static void Release(picture_t *picture)
 {
-    assert( p_picture->i_refcount > 0 );
+    assert(picture->i_refcount > 0);
 
-    if( --p_picture->i_refcount > 0 )
+    if (--picture->i_refcount > 0)
         return;
+    Unlock(picture);
+}
 
-    picture_release_sys_t *p_release_sys = p_picture->p_release_sys;
-    if( p_release_sys->pf_unlock )
-        p_release_sys->pf_unlock( p_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);
 }