Commit 2deed367 authored by Laurent Aimar's avatar Laurent Aimar

Moved out picture_fifo/pool_t code from vout_pictures.c

parent 9f1ddd82
......@@ -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 \
......
/*****************************************************************************
* picture_fifo.c : picture fifo functions
*****************************************************************************
* Copyright (C) 2009 the VideoLAN team
* Copyright (C) 2009 Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
* $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.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include <vlc_common.h>
#include <vlc_picture_fifo.h>
/*****************************************************************************
*
*****************************************************************************/
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 );
}
/*****************************************************************************
* picture_pool.c : picture pool functions
*****************************************************************************
* Copyright (C) 2009 the VideoLAN team
* Copyright (C) 2009 Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
* $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.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include <vlc_common.h>
#include <vlc_picture_pool.h>
/*****************************************************************************
*
*****************************************************************************/
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 );
}
......@@ -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;