[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