[vlc-devel] commit: Added picture_pool_t and functions helpers. (Laurent Aimar )

git version control git at videolan.org
Sun May 31 01:49:14 CEST 2009


vlc | branch: master | Laurent Aimar <fenrir at videolan.org> | Sat May 30 23:59:11 2009 +0200| [13d18251673ad5f7a0094bfd39c55e94d9df5062] | committer: Laurent Aimar 

Added picture_pool_t and functions helpers.

It is usefull to avoid reallocating pictures over and over.

 Becarefull, it is not yet thread safe as picture_t reference count
is not.
 I will change it when more work has been done on the vout.

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

 include/vlc_picture_pool.h       |   88 ++++++++++++++++++++++
 src/libvlccore.sym               |    5 +
 src/video_output/vout_pictures.c |  151 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 244 insertions(+), 0 deletions(-)

diff --git a/include/vlc_picture_pool.h b/include/vlc_picture_pool.h
new file mode 100644
index 0000000..72469c6
--- /dev/null
+++ b/include/vlc_picture_pool.h
@@ -0,0 +1,88 @@
+/*****************************************************************************
+ * vlc_picture_pool.h: picture pool definitions
+ *****************************************************************************
+ * Copyright (C) 2009 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLC_PICTURE_POOL_H
+#define VLC_PICTURE_POOL_H 1
+
+/**
+ * \file
+ * This file defines picture pool structures and functions in vlc
+ */
+
+#include <vlc_picture.h>
+
+/**
+ * Picture pool handle
+ *
+ * XXX it is not thread safe, all pool manipulations and picture_Release
+ * must be properly locked if needed.
+ */
+typedef struct picture_pool_t picture_pool_t;
+
+/**
+ * It creates a picture_pool_t wrapping the given arrays of picture.
+ *
+ * It is usefull to avoid useless picture creations/destructions.
+ * The given picture must not have a reference count greater than 1.
+ * The pool takes ownership of the picture and MUST not be used directly.
+ * When deleted, the pool will release the pictures using picture_Release.
+ */
+VLC_EXPORT( picture_pool_t *, picture_pool_New, ( int i_picture, picture_t *pp_picture[] ) );
+
+/**
+ * It creates a picture_pool_t creating images using the given format.
+ *
+ * Provided for convenience.
+ */
+VLC_EXPORT( picture_pool_t *, picture_pool_NewFromFormat, ( const video_format_t *, int i_picture ) );
+
+/**
+ * It destroys a pool created by picture_pool_New.
+ *
+ * All pictures must already be released to the pool. The pool will then
+ * released them.
+ */
+VLC_EXPORT( void, picture_pool_Delete, ( picture_pool_t * ) );
+
+/**
+ * It retreives a picture_t from a pool.
+ *
+ * The picture must be release by using picture_Release.
+ */
+VLC_EXPORT( picture_t *, picture_pool_Get, ( picture_pool_t * ) );
+
+/**
+ * It forces the next picture_pool_Get to return a picture even if no
+ * pictures are free.
+ *
+ * If b_reset is true, all pictures will be marked as free.
+ *
+ * It does it by releasing itself the oldest used picture if none is
+ * available.
+ * XXX it should be used with great care, the only reason you may need
+ * it is to workaround a bug.
+ */
+VLC_EXPORT( void, picture_pool_NonEmpty, ( picture_pool_t *, bool b_reset ) );
+
+#endif /* VLC_PICTURE_POOL_H */
+
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index d10ce07..43915bf 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -284,6 +284,11 @@ picture_fifo_Peek
 picture_fifo_Pop
 picture_fifo_Push
 picture_New
+picture_pool_Delete
+picture_pool_Get
+picture_pool_New
+picture_pool_NewFromFormat
+picture_pool_NonEmpty
 picture_Reset
 picture_Setup
 plane_CopyPixels
diff --git a/src/video_output/vout_pictures.c b/src/video_output/vout_pictures.c
index 2e7be9e..9e31ad5 100644
--- a/src/video_output/vout_pictures.c
+++ b/src/video_output/vout_pictures.c
@@ -39,6 +39,7 @@
 #include <vlc_image.h>
 #include <vlc_block.h>
 #include <vlc_picture_fifo.h>
+#include <vlc_picture_pool.h>
 
 #include "vout_pictures.h"
 #include "vout_internal.h"
@@ -1187,3 +1188,153 @@ void picture_fifo_Delete( picture_fifo_t *p_fifo )
     vlc_mutex_destroy( &p_fifo->lock );
 }
 
+/*****************************************************************************
+ *
+ *****************************************************************************/
+struct picture_release_sys_t
+{
+    /* Saved release */
+    void (*pf_release)( picture_t * );
+    picture_release_sys_t *p_release_sys;
+
+    /* */
+    int64_t i_tick;
+};
+
+struct picture_pool_t
+{
+    int64_t i_tick;
+
+    int i_picture;
+    picture_t **pp_picture;
+};
+
+static void PicturePoolPictureRelease( picture_t * );
+
+picture_pool_t *picture_pool_New( int i_picture, picture_t *pp_picture[] )
+{
+    picture_pool_t *p_pool = calloc( 1, sizeof(*p_pool) );
+    if( !p_pool )
+        return NULL;
+
+    p_pool->i_tick = 1;
+    p_pool->i_picture = i_picture;
+    p_pool->pp_picture = calloc( p_pool->i_picture, sizeof(*p_pool->pp_picture) );
+
+    for( int i = 0; i < i_picture; i++ )
+    {
+        picture_t *p_picture = pp_picture[i];
+
+        /* The pool must be the only owner of the picture */
+        assert( p_picture->i_refcount == 1 );
+
+        /* Install the new release callback */
+        picture_release_sys_t *p_release_sys = malloc( sizeof(*p_release_sys) );
+        p_release_sys->pf_release = p_picture->pf_release;
+        p_release_sys->p_release_sys = p_picture->p_release_sys;
+        p_release_sys->i_tick = 0;
+
+        p_picture->i_refcount = 0;
+        p_picture->pf_release = PicturePoolPictureRelease;
+        p_picture->p_release_sys = p_release_sys;
+
+        /* */
+        p_pool->pp_picture[i] = p_picture;
+    }
+    return p_pool;
+}
+
+picture_pool_t *picture_pool_NewFromFormat( const video_format_t *p_fmt, int i_picture )
+{
+    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] )
+            goto error;
+    }
+    picture_pool_t *p_pool = picture_pool_New( i_picture, pp_picture );
+    if( !p_pool )
+        goto error;
+
+    return p_pool;
+
+error:
+    for( int i = 0; i < i_picture; i++ )
+    {
+        if( !pp_picture[i] )
+            break;
+        picture_Release( pp_picture[i] );
+    }
+    return NULL;
+}
+
+void picture_pool_Delete( picture_pool_t *p_pool )
+{
+    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;
+
+        assert( p_picture->i_refcount == 0 );
+
+        /* 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;
+
+        picture_Release( p_picture );
+
+        free( p_release_sys );
+    }
+    free( p_pool );
+}
+
+picture_t *picture_pool_Get( picture_pool_t *p_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 )
+        {
+            p_picture->p_release_sys->i_tick = p_pool->i_tick++;
+            picture_Hold( p_picture );
+            return p_picture;
+        }
+    }
+    return NULL;
+}
+
+void picture_pool_NonEmpty( picture_pool_t *p_pool, bool b_reset )
+{
+    picture_t *p_old = NULL;
+
+    for( int i = 0; i < p_pool->i_picture; i++ )
+    {
+        picture_t *p_picture = p_pool->pp_picture[i];
+
+        if( b_reset )
+            p_picture->i_refcount = 0;
+        else if( p_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;
+    }
+    if( !b_reset && p_old )
+        p_old->i_refcount = 0;
+}
+
+static void PicturePoolPictureRelease( picture_t *p_picture )
+{
+    assert( p_picture->i_refcount > 0 );
+
+    if( --p_picture->i_refcount > 0 )
+        return;
+
+    /* Nothing to do for the moment */
+}
+




More information about the vlc-devel mailing list