Commit a606130b authored by Jean-Paul Saman's avatar Jean-Paul Saman

add picture-fifo_t

parent 0224dc73
...@@ -227,6 +227,7 @@ typedef video_format_t video_frame_format_t; ...@@ -227,6 +227,7 @@ typedef video_format_t video_frame_format_t;
typedef struct picture_t picture_t; typedef struct picture_t picture_t;
typedef struct picture_sys_t picture_sys_t; typedef struct picture_sys_t picture_sys_t;
typedef struct picture_heap_t picture_heap_t; typedef struct picture_heap_t picture_heap_t;
typedef struct picture_fifo_t picture_fifo_t;
/* Subpictures */ /* Subpictures */
typedef struct spu_t spu_t; typedef struct spu_t spu_t;
......
...@@ -222,6 +222,34 @@ static inline void picture_Copy( picture_t *p_dst, const picture_t *p_src ) ...@@ -222,6 +222,34 @@ static inline void picture_Copy( picture_t *p_dst, const picture_t *p_src )
*/ */
VLC_EXPORT( int, picture_Export, ( vlc_object_t *p_obj, block_t **pp_image, video_format_t *p_fmt, picture_t *p_picture, vlc_fourcc_t i_format, int i_override_width, int i_override_height ) ); VLC_EXPORT( int, picture_Export, ( vlc_object_t *p_obj, block_t **pp_image, video_format_t *p_fmt, picture_t *p_picture, vlc_fourcc_t i_format, int i_override_width, int i_override_height ) );
/****************************************************************************
* Fifos of pictures.
****************************************************************************
* - picture_FifoNew : create and init a new fifo
* - picture_FifoRelease : destroy a fifo and free all pictures in it.
* - picture_FifoEmpty : free all pictures in a fifo
* - picture_FifoPut : put a picture
* - picture_FifoGet : get a packet from the fifo (and wait if it is empty)
* - picture_FifoShow : show the first packet of the fifo (and wait if
* needed), be carefull, you can use it ONLY if you are sure to be the
* only one getting data from the fifo.
* - picture_FifoCount : how many packets are waiting in the fifo
* - picture_FifoWake : wake ups a thread with block_FifoGet() = NULL
* (this is used to wakeup a thread when there is no data to queue)
*
* picture_FifoGet and picture_FifoShow are cancellation points.
****************************************************************************/
VLC_EXPORT( picture_fifo_t *, picture_FifoNew, ( void ) LIBVLC_USED );
VLC_EXPORT( void, picture_FifoRelease, ( picture_fifo_t * ) );
/* TODO: do we need to export this? */
void picture_FifoPace (picture_fifo_t *fifo, size_t max_depth);
VLC_EXPORT( void, picture_FifoEmpty, ( picture_fifo_t * ) );
VLC_EXPORT( size_t, picture_FifoPut, ( picture_fifo_t *, picture_t * ) );
VLC_EXPORT( void, picture_FifoWake, ( picture_fifo_t * ) );
VLC_EXPORT( picture_t *, picture_FifoGet, ( picture_fifo_t * ) LIBVLC_USED );
VLC_EXPORT( picture_t *, picture_FifoShow, ( picture_fifo_t * ) );
VLC_EXPORT( size_t, picture_FifoCount, ( const picture_fifo_t *p_fifo ) LIBVLC_USED );
/** /**
* Video picture heap, either render (to store pictures used * Video picture heap, either render (to store pictures used
......
...@@ -278,6 +278,14 @@ path_sanitize ...@@ -278,6 +278,14 @@ path_sanitize
picture_CopyPixels picture_CopyPixels
picture_Delete picture_Delete
picture_Export picture_Export
picture_FifoCount
picture_FifoEmpty
picture_FifoGet
picture_FifoNew
picture_FifoPut
picture_FifoRelease
picture_FifoShow
picture_FifoWake
picture_New picture_New
plane_CopyPixels plane_CopyPixels
playlist_Add playlist_Add
......
...@@ -1170,3 +1170,201 @@ int picture_Export( vlc_object_t *p_obj, ...@@ -1170,3 +1170,201 @@ int picture_Export( vlc_object_t *p_obj,
* *
*****************************************************************************/ *****************************************************************************/
/**
* @section Thread-safe picture queue functions
*/
/**
* Internal state for picture queues
*/
struct picture_fifo_t
{
vlc_mutex_t lock; /* fifo data lock */
vlc_cond_t wait; /**< Wait for data */
vlc_cond_t wait_room; /**< Wait for queue depth to shrink */
picture_t *p_first;
picture_t **pp_last;
size_t i_depth;
bool b_force_wake;
};
picture_fifo_t *picture_FifoNew( void )
{
picture_fifo_t *p_fifo = malloc( sizeof( picture_fifo_t ) );
if( !p_fifo )
return NULL;
vlc_mutex_init( &p_fifo->lock );
vlc_cond_init( &p_fifo->wait );
vlc_cond_init( &p_fifo->wait_room );
p_fifo->p_first = NULL;
p_fifo->pp_last = &p_fifo->p_first;
p_fifo->i_depth = 0;
p_fifo->b_force_wake = false;
return p_fifo;
}
void picture_FifoRelease( picture_fifo_t *p_fifo )
{
picture_FifoEmpty( p_fifo );
vlc_cond_destroy( &p_fifo->wait_room );
vlc_cond_destroy( &p_fifo->wait );
vlc_mutex_destroy( &p_fifo->lock );
free( p_fifo );
}
void picture_FifoEmpty( picture_fifo_t *p_fifo )
{
picture_t *b;
vlc_mutex_lock( &p_fifo->lock );
for( b = p_fifo->p_first; b != NULL; )
{
picture_t *p_next;
p_next = b->p_next;
picture_Release( b );
b = p_next;
}
p_fifo->i_depth = 0;
p_fifo->p_first = NULL;
p_fifo->pp_last = &p_fifo->p_first;
vlc_cond_broadcast( &p_fifo->wait_room );
vlc_mutex_unlock( &p_fifo->lock );
}
/**
* Wait until the FIFO gets below a certain size (if needed).
*
* Note that if more than one thread writes to the FIFO, you cannot assume that
* the FIFO is actually below the requested size upon return (since another
* thread could have refilled it already). This is typically not an issue, as
* this function is meant for (relaxed) congestion control.
*
* This function may be a cancellation point and it is cancel-safe.
*
* @param fifo queue to wait on
* @param max_depth wait until the queue has no more than this many pictures
* (use SIZE_MAX to ignore this constraint)
* @return nothing.
*/
void picture_FifoPace (picture_fifo_t *fifo, size_t max_depth)
{
vlc_testcancel ();
vlc_mutex_lock (&fifo->lock);
while ((fifo->i_depth > max_depth))
{
mutex_cleanup_push (&fifo->lock);
vlc_cond_wait (&fifo->wait_room, &fifo->lock);
vlc_cleanup_pop ();
}
vlc_mutex_unlock (&fifo->lock);
}
/**
* Immediately queue one picture at the end of a FIFO.
* @param fifo queue
* @param picture head of a picture list to queue (may be NULL)
*/
size_t picture_FifoPut( picture_fifo_t *p_fifo, picture_t *p_picture )
{
size_t i_depth = 0;
vlc_mutex_lock( &p_fifo->lock );
while (p_picture != NULL)
{
*p_fifo->pp_last = p_picture;
p_fifo->pp_last = &p_picture->p_next;
p_fifo->i_depth++;
p_picture = p_picture->p_next;
}
i_depth = p_fifo->i_depth;
/* We queued one picture: wake up one read-waiting thread */
vlc_cond_signal( &p_fifo->wait );
vlc_mutex_unlock( &p_fifo->lock );
return i_depth;
}
void picture_FifoWake( picture_fifo_t *p_fifo )
{
vlc_mutex_lock( &p_fifo->lock );
if( p_fifo->p_first == NULL )
p_fifo->b_force_wake = true;
vlc_cond_broadcast( &p_fifo->wait );
vlc_mutex_unlock( &p_fifo->lock );
}
picture_t *picture_FifoGet( picture_fifo_t *p_fifo )
{
picture_t *b;
vlc_testcancel( );
vlc_mutex_lock( &p_fifo->lock );
mutex_cleanup_push( &p_fifo->lock );
/* Remember vlc_cond_wait() may cause spurious wakeups
* (on both Win32 and POSIX) */
while( ( p_fifo->p_first == NULL ) && !p_fifo->b_force_wake )
vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
vlc_cleanup_pop();
b = p_fifo->p_first;
p_fifo->b_force_wake = false;
if( b == NULL )
{
/* Forced wakeup */
vlc_mutex_unlock( &p_fifo->lock );
return NULL;
}
p_fifo->p_first = b->p_next;
p_fifo->i_depth--;
if( p_fifo->p_first == NULL )
{
p_fifo->pp_last = &p_fifo->p_first;
}
/* We don't know how many threads can queue new packets now. */
vlc_cond_broadcast( &p_fifo->wait_room );
vlc_mutex_unlock( &p_fifo->lock );
b->p_next = NULL;
return b;
}
picture_t *picture_FifoShow( picture_fifo_t *p_fifo )
{
picture_t *b;
vlc_testcancel( );
vlc_mutex_lock( &p_fifo->lock );
mutex_cleanup_push( &p_fifo->lock );
while( p_fifo->p_first == NULL )
vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
b = p_fifo->p_first;
vlc_cleanup_run ();
return b;
}
size_t picture_FifoCount( const picture_fifo_t *p_fifo )
{
size_t i_depth;
vlc_mutex_lock( &p_fifo->lock );
i_depth = p_fifo->i_depth;
vlc_mutex_unlock( &p_fifo->lock );
return i_depth;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment