-/*****************************************************************************
- *
- *****************************************************************************/
-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 );
-}
-