From 2deed367f004bc8db10370bb2f91be477b1d0ad7 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Mon, 7 Sep 2009 19:31:51 +0200 Subject: [PATCH] Moved out picture_fifo/pool_t code from vout_pictures.c --- src/Makefile.am | 2 + src/misc/picture_fifo.c | 155 ++++++++++++++++ src/misc/picture_pool.c | 218 ++++++++++++++++++++++ src/video_output/vout_pictures.c | 301 ------------------------------- 4 files changed, 375 insertions(+), 301 deletions(-) create mode 100644 src/misc/picture_fifo.c create mode 100644 src/misc/picture_pool.c diff --git a/src/Makefile.am b/src/Makefile.am index 888751f976..64af99831b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -401,6 +401,8 @@ SOURCES_libvlc_common = \ misc/block.c \ misc/fourcc.c \ misc/es_format.c \ + misc/picture_fifo.c \ + misc/picture_pool.c \ modules/modules.h \ modules/modules.c \ modules/cache.c \ diff --git a/src/misc/picture_fifo.c b/src/misc/picture_fifo.c new file mode 100644 index 0000000000..1e6fd6c0b9 --- /dev/null +++ b/src/misc/picture_fifo.c @@ -0,0 +1,155 @@ +/***************************************************************************** + * picture_fifo.c : picture fifo functions + ***************************************************************************** + * Copyright (C) 2009 the VideoLAN team + * Copyright (C) 2009 Laurent Aimar + * $Id$ + * + * Authors: Laurent Aimar + * + * 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. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include + +#include +#include + +/***************************************************************************** + * + *****************************************************************************/ +struct picture_fifo_t +{ + vlc_mutex_t lock; + picture_t *p_first; + picture_t **pp_last; +}; + +static void PictureFifoReset( picture_fifo_t *p_fifo ) +{ + p_fifo->p_first = NULL; + p_fifo->pp_last = &p_fifo->p_first; +} +static void PictureFifoPush( picture_fifo_t *p_fifo, picture_t *p_picture ) +{ + assert( !p_picture->p_next ); + *p_fifo->pp_last = p_picture; + p_fifo->pp_last = &p_picture->p_next; +} +static picture_t *PictureFifoPop( picture_fifo_t *p_fifo ) +{ + picture_t *p_picture = p_fifo->p_first; + + if( p_picture ) + { + p_fifo->p_first = p_picture->p_next; + if( !p_fifo->p_first ) + p_fifo->pp_last = &p_fifo->p_first; + } + return p_picture; +} + +picture_fifo_t *picture_fifo_New(void) +{ + picture_fifo_t *p_fifo = malloc( sizeof(*p_fifo) ); + if( !p_fifo ) + return NULL; + + vlc_mutex_init( &p_fifo->lock ); + PictureFifoReset( p_fifo ); + return p_fifo; +} + +void picture_fifo_Push( picture_fifo_t *p_fifo, picture_t *p_picture ) +{ + vlc_mutex_lock( &p_fifo->lock ); + PictureFifoPush( p_fifo, p_picture ); + vlc_mutex_unlock( &p_fifo->lock ); +} +picture_t *picture_fifo_Pop( picture_fifo_t *p_fifo ) +{ + vlc_mutex_lock( &p_fifo->lock ); + picture_t *p_picture = PictureFifoPop( p_fifo ); + vlc_mutex_unlock( &p_fifo->lock ); + + return p_picture; +} +picture_t *picture_fifo_Peek( picture_fifo_t *p_fifo ) +{ + vlc_mutex_lock( &p_fifo->lock ); + picture_t *p_picture = p_fifo->p_first; + if( p_picture ) + picture_Hold( p_picture ); + vlc_mutex_unlock( &p_fifo->lock ); + + return p_picture; +} +void picture_fifo_Flush( picture_fifo_t *p_fifo, mtime_t i_date, bool b_below ) +{ + picture_t *p_picture; + + vlc_mutex_lock( &p_fifo->lock ); + + p_picture = p_fifo->p_first; + PictureFifoReset( p_fifo ); + + picture_fifo_t tmp; + PictureFifoReset( &tmp ); + + while( p_picture ) + { + picture_t *p_next = p_picture->p_next; + + p_picture->p_next = NULL; + if( ( b_below && p_picture->date <= i_date ) || + ( !b_below && p_picture->date >= i_date ) ) + PictureFifoPush( &tmp, p_picture ); + else + PictureFifoPush( p_fifo, p_picture ); + p_picture = p_next; + } + vlc_mutex_unlock( &p_fifo->lock ); + + for( ;; ) + { + picture_t *p_picture = PictureFifoPop( &tmp ); + if( !p_picture ) + break; + picture_Release( p_picture ); + } +} +void picture_fifo_OffsetDate( picture_fifo_t *p_fifo, mtime_t i_delta ) +{ + vlc_mutex_lock( &p_fifo->lock ); + for( picture_t *p_picture = p_fifo->p_first; p_picture != NULL; ) + { + p_picture->date += i_delta; + p_picture = p_picture->p_next; + } + vlc_mutex_unlock( &p_fifo->lock ); +} +void picture_fifo_Delete( picture_fifo_t *p_fifo ) +{ + picture_fifo_Flush( p_fifo, INT64_MAX, true ); + vlc_mutex_destroy( &p_fifo->lock ); +} + diff --git a/src/misc/picture_pool.c b/src/misc/picture_pool.c new file mode 100644 index 0000000000..23225c264e --- /dev/null +++ b/src/misc/picture_pool.c @@ -0,0 +1,218 @@ +/***************************************************************************** + * picture_pool.c : picture pool functions + ***************************************************************************** + * Copyright (C) 2009 the VideoLAN team + * Copyright (C) 2009 Laurent Aimar + * $Id$ + * + * Authors: Laurent Aimar + * + * 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. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include + +#include +#include + +/***************************************************************************** + * + *****************************************************************************/ +struct picture_release_sys_t +{ + /* Saved release */ + void (*pf_release)( picture_t * ); + picture_release_sys_t *p_release_sys; + + /* */ + int (*pf_lock)( picture_t * ); + void (*pf_unlock)( picture_t * ); + + /* */ + 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_NewExtended( const picture_pool_configuration_t *cfg ) +{ + picture_pool_t *p_pool = calloc( 1, sizeof(*p_pool) ); + if( !p_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 ); + return NULL; + } + + for( int i = 0; i < cfg->picture_count; i++ ) + { + picture_t *p_picture = cfg->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) ); + if( !p_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; + + 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_New( int i_picture, picture_t *pp_picture[] ) +{ + picture_pool_configuration_t cfg; + + memset( &cfg, 0, sizeof(cfg) ); + cfg.picture_count = i_picture; + cfg.picture = pp_picture; + + return picture_pool_NewExtended( &cfg ); +} + +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->pp_picture ); + 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 ) + 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) ) + continue; + + /* */ + 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; + + 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 ); +} + diff --git a/src/video_output/vout_pictures.c b/src/video_output/vout_pictures.c index d12e309633..9e57973f7e 100644 --- a/src/video_output/vout_pictures.c +++ b/src/video_output/vout_pictures.c @@ -1110,304 +1110,3 @@ int picture_Export( vlc_object_t *p_obj, return VLC_SUCCESS; } -/***************************************************************************** - * - *****************************************************************************/ -struct picture_fifo_t -{ - vlc_mutex_t lock; - picture_t *p_first; - picture_t **pp_last; -}; - -static void PictureFifoReset( picture_fifo_t *p_fifo ) -{ - p_fifo->p_first = NULL; - p_fifo->pp_last = &p_fifo->p_first; -} -static void PictureFifoPush( picture_fifo_t *p_fifo, picture_t *p_picture ) -{ - assert( !p_picture->p_next ); - *p_fifo->pp_last = p_picture; - p_fifo->pp_last = &p_picture->p_next; -} -static picture_t *PictureFifoPop( picture_fifo_t *p_fifo ) -{ - picture_t *p_picture = p_fifo->p_first; - - if( p_picture ) - { - p_fifo->p_first = p_picture->p_next; - if( !p_fifo->p_first ) - p_fifo->pp_last = &p_fifo->p_first; - } - return p_picture; -} - -picture_fifo_t *picture_fifo_New(void) -{ - picture_fifo_t *p_fifo = malloc( sizeof(*p_fifo) ); - if( !p_fifo ) - return NULL; - - vlc_mutex_init( &p_fifo->lock ); - PictureFifoReset( p_fifo ); - return p_fifo; -} - -void picture_fifo_Push( picture_fifo_t *p_fifo, picture_t *p_picture ) -{ - vlc_mutex_lock( &p_fifo->lock ); - PictureFifoPush( p_fifo, p_picture ); - vlc_mutex_unlock( &p_fifo->lock ); -} -picture_t *picture_fifo_Pop( picture_fifo_t *p_fifo ) -{ - vlc_mutex_lock( &p_fifo->lock ); - picture_t *p_picture = PictureFifoPop( p_fifo ); - vlc_mutex_unlock( &p_fifo->lock ); - - return p_picture; -} -picture_t *picture_fifo_Peek( picture_fifo_t *p_fifo ) -{ - vlc_mutex_lock( &p_fifo->lock ); - picture_t *p_picture = p_fifo->p_first; - if( p_picture ) - picture_Hold( p_picture ); - vlc_mutex_unlock( &p_fifo->lock ); - - return p_picture; -} -void picture_fifo_Flush( picture_fifo_t *p_fifo, mtime_t i_date, bool b_below ) -{ - picture_t *p_picture; - - vlc_mutex_lock( &p_fifo->lock ); - - p_picture = p_fifo->p_first; - PictureFifoReset( p_fifo ); - - picture_fifo_t tmp; - PictureFifoReset( &tmp ); - - while( p_picture ) - { - picture_t *p_next = p_picture->p_next; - - p_picture->p_next = NULL; - if( ( b_below && p_picture->date <= i_date ) || - ( !b_below && p_picture->date >= i_date ) ) - PictureFifoPush( &tmp, p_picture ); - else - PictureFifoPush( p_fifo, p_picture ); - p_picture = p_next; - } - vlc_mutex_unlock( &p_fifo->lock ); - - for( ;; ) - { - picture_t *p_picture = PictureFifoPop( &tmp ); - if( !p_picture ) - break; - picture_Release( p_picture ); - } -} -void picture_fifo_OffsetDate( picture_fifo_t *p_fifo, mtime_t i_delta ) -{ - vlc_mutex_lock( &p_fifo->lock ); - for( picture_t *p_picture = p_fifo->p_first; p_picture != NULL; ) - { - p_picture->date += i_delta; - p_picture = p_picture->p_next; - } - vlc_mutex_unlock( &p_fifo->lock ); -} -void picture_fifo_Delete( picture_fifo_t *p_fifo ) -{ - picture_fifo_Flush( p_fifo, INT64_MAX, true ); - 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; - - /* */ - int (*pf_lock)( picture_t * ); - void (*pf_unlock)( picture_t * ); - - /* */ - 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_NewExtended( const picture_pool_configuration_t *cfg ) -{ - picture_pool_t *p_pool = calloc( 1, sizeof(*p_pool) ); - if( !p_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 ); - return NULL; - } - - for( int i = 0; i < cfg->picture_count; i++ ) - { - picture_t *p_picture = cfg->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) ); - if( !p_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; - - 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_New( int i_picture, picture_t *pp_picture[] ) -{ - picture_pool_configuration_t cfg; - - memset( &cfg, 0, sizeof(cfg) ); - cfg.picture_count = i_picture; - cfg.picture = pp_picture; - - return picture_pool_NewExtended( &cfg ); -} - -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->pp_picture ); - 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 ) - 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) ) - continue; - - /* */ - 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; - - 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 ); -} - -- 2.39.2