From 1df4724ce1cf3057d8eb02aa3344b5cd826ea549 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Sun, 22 Dec 2002 15:02:06 +0000 Subject: flush moved to decoder loop. that simplifies things a lot. new buffer methods to avoid deadlocks doing flush from video_out CVS patchset: 3629 CVS date: 2002/12/22 15:02:06 --- src/xine-engine/buffer.c | 69 +++++++++++++++++++++++++++++++++++++--- src/xine-engine/buffer.h | 15 ++++++++- src/xine-engine/video_decoder.c | 10 ++++-- src/xine-engine/video_out.c | 70 +++++++++-------------------------------- 4 files changed, 100 insertions(+), 64 deletions(-) diff --git a/src/xine-engine/buffer.c b/src/xine-engine/buffer.c index e4d1c7724..2e93009a1 100644 --- a/src/xine-engine/buffer.c +++ b/src/xine-engine/buffer.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: buffer.c,v 1.19 2002/12/21 12:56:52 miguelfreitas Exp $ + * $Id: buffer.c,v 1.20 2002/12/22 15:02:06 miguelfreitas Exp $ * * * contents: @@ -115,6 +115,42 @@ static buf_element_t *buffer_pool_alloc (fifo_buffer_t *this) { return buf; } +/* + * allocate a buffer from buffer pool - may fail if none is available + */ + +static buf_element_t *buffer_pool_try_alloc (fifo_buffer_t *this) { + + buf_element_t *buf; + + pthread_mutex_lock (&this->buffer_pool_mutex); + + if (this->buffer_pool_top) { + + buf = this->buffer_pool_top; + this->buffer_pool_top = this->buffer_pool_top->next; + this->buffer_pool_num_free--; + + } else { + + buf = NULL; + + } + + pthread_mutex_unlock (&this->buffer_pool_mutex); + + /* set sane values to the newly allocated buffer */ + if( buf ) { + buf->content = buf->mem; /* 99% of demuxers will want this */ + buf->pts = 0; + buf->size = 0; + buf->decoder_flags = 0; + extra_info_reset( buf->extra_info ); + } + return buf; +} + + /* * append buffer element to fifo buffer */ @@ -136,6 +172,27 @@ static void fifo_buffer_put (fifo_buffer_t *fifo, buf_element_t *element) { pthread_mutex_unlock (&fifo->mutex); } +/* + * insert buffer element to fifo buffer (demuxers MUST NOT call this one) + */ +static void fifo_buffer_insert (fifo_buffer_t *fifo, buf_element_t *element) { + + pthread_mutex_lock (&fifo->mutex); + + element->next = fifo->first; + fifo->first = element; + + if( !fifo->last ) + fifo->last = element; + + fifo->fifo_size++; + + pthread_cond_signal (&fifo->not_empty); + + pthread_mutex_unlock (&fifo->mutex); +} + + /* * get element from fifo buffer */ @@ -270,6 +327,7 @@ fifo_buffer_t *fifo_buffer_new (int num_buffers, uint32_t buf_size) { this->last = NULL; this->fifo_size = 0; this->put = fifo_buffer_put; + this->insert = fifo_buffer_insert; this->get = fifo_buffer_get; this->clear = fifo_buffer_clear; this->size = fifo_buffer_size; @@ -313,10 +371,11 @@ fifo_buffer_t *fifo_buffer_new (int num_buffers, uint32_t buf_size) { buffer_pool_free (buf); } - this->buffer_pool_num_free = num_buffers; - this->buffer_pool_capacity = num_buffers; - this->buffer_pool_buf_size = buf_size; - this->buffer_pool_alloc = buffer_pool_alloc; + this->buffer_pool_num_free = num_buffers; + this->buffer_pool_capacity = num_buffers; + this->buffer_pool_buf_size = buf_size; + this->buffer_pool_alloc = buffer_pool_alloc; + this->buffer_pool_try_alloc = buffer_pool_try_alloc; return this; } diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h index 3fb3bd397..dad8752ae 100644 --- a/src/xine-engine/buffer.h +++ b/src/xine-engine/buffer.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: buffer.h,v 1.86 2002/12/21 12:56:52 miguelfreitas Exp $ + * $Id: buffer.h,v 1.87 2002/12/22 15:02:06 miguelfreitas Exp $ * * * contents: @@ -77,6 +77,7 @@ extern "C" { #define BUF_CONTROL_NEWPTS 0x01070000 #define BUF_CONTROL_RESET_DECODER 0x01080000 #define BUF_CONTROL_HEADERS_DONE 0x01090000 +#define BUF_CONTROL_FLUSH_DECODER 0x010a0000 /* video buffer types: (please keep in sync with buffer_types.c) */ @@ -404,6 +405,18 @@ struct fifo_buffer_s */ buf_element_t *(*buffer_pool_alloc) (fifo_buffer_t *this); + + + /* + * special functions, not used by demuxers + */ + + /* the same as buffer_pool_alloc but may fail if none is available */ + buf_element_t *(*buffer_pool_try_alloc) (fifo_buffer_t *this); + + /* the samme as put but insert at the head of the fifo */ + void (*insert) (fifo_buffer_t *fifo, buf_element_t *buf); + /* * private variables for buffer pool management diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c index 7f43b3dd0..218578734 100644 --- a/src/xine-engine/video_decoder.c +++ b/src/xine-engine/video_decoder.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_decoder.c,v 1.115 2002/12/21 16:13:43 miguelfreitas Exp $ + * $Id: video_decoder.c,v 1.116 2002/12/22 15:02:06 miguelfreitas Exp $ * */ @@ -193,7 +193,13 @@ void *video_decoder_loop (void *stream_gen) { stream->spu_decoder_plugin->reset (stream->spu_decoder_plugin); } break; - + + case BUF_CONTROL_FLUSH_DECODER: + if (stream->video_decoder_plugin) { + stream->video_decoder_plugin->flush (stream->video_decoder_plugin); + } + break; + case BUF_CONTROL_DISCONTINUITY: #ifdef LOG printf ("video_decoder: discontinuity ahead\n"); diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index 027327183..16611629e 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out.c,v 1.122 2002/12/21 19:23:01 miguelfreitas Exp $ + * $Id: video_out.c,v 1.123 2002/12/22 15:02:07 miguelfreitas Exp $ * * frame allocation / queuing / scheduling / output functions */ @@ -609,7 +609,7 @@ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts) { */ pthread_mutex_lock( &this->free_img_buf_queue->mutex ); if (img && !img->next) { - + if (img->stream->stream_info[XINE_STREAM_INFO_VIDEO_HAS_STILL] || img->stream->video_fifo->size(img->stream->video_fifo) < 10) { @@ -737,12 +737,12 @@ static void *video_out_loop (void *this_gen) { vos_t *this = (vos_t *) this_gen; int64_t frame_duration, next_frame_vpts; int64_t usec_to_sleep; - + /* * here it is - the heart of xine (or rather: one of the hearts * of xine) : the video output loop */ - + frame_duration = 1500; /* default */ next_frame_vpts = this->clock->get_current_time (this->clock); @@ -788,66 +788,24 @@ static void *video_out_loop (void *this_gen) { if (diff > 30000 && !this->display_img_buf_queue->first) { xine_stream_t *stream; -#if XINE_DEADLOCK_ON_QUIT - /* - * this flush code often deadlocks when a BUF_CONTROL_QUIT is - * sent to the video_decoder thread (that is, on xine exit): - * - * - we're detecting a "stall" here, this code locks - * streams_lock, and then video decoder's lock in the - * ...->flush() call - * - * - video_decoder performs actions for BUF_CONTROL_QUIT: it - * locks and disposes the video_decoder, which calls vo_close() - * and vo_close() tries to lock the streams_lock. - */ pthread_mutex_lock(&this->streams_lock); for (stream = xine_list_first_content(this->streams); stream; stream = xine_list_next_content(this->streams)) { - if (stream->video_decoder_plugin) { - + if (stream->video_decoder_plugin && stream->video_fifo) { + buf_element_t *buf; + #ifdef LOG - printf ("video_out: flushing current video decoder plugin (%d %d)\n", - this->display_img_buf_queue->num_buffers, - this->free_img_buf_queue->num_buffers); + printf ("video_out: flushing current video decoder plugin\n"); #endif - - stream->video_decoder_plugin->flush(stream->video_decoder_plugin); + + buf = stream->video_fifo->buffer_pool_try_alloc (stream->video_fifo); + if( buf ) { + buf->type = BUF_CONTROL_FLUSH_DECODER; + stream->video_fifo->put(stream->video_fifo, buf); + } } } pthread_mutex_unlock(&this->streams_lock); -#else - /* - * Ugly hack to avoid the above mentioned deadlock: try to - * release the streams_lock as soon as possible, when we know - * that the current stream is the last one. - * - * This hack only works when the stream with video_decorder_plugin - * is the last one in the streams list! - */ - pthread_mutex_lock(&this->streams_lock); - if ((stream = xine_list_first_content(this->streams)) != NULL) { - xine_stream_t *stream_next; - - for (; stream; stream = stream_next) { - stream_next = xine_list_next_content(this->streams); - if (!stream_next) - pthread_mutex_unlock(&this->streams_lock); - - if (stream->video_decoder_plugin) { - -#ifdef LOG - printf ("video_out: flushing current video decoder plugin (%d %d)\n", - this->display_img_buf_queue->num_buffers, - this->free_img_buf_queue->num_buffers); -#endif - - stream->video_decoder_plugin->flush(stream->video_decoder_plugin); - } - } - } else - pthread_mutex_unlock(&this->streams_lock); -#endif this->last_delivery_pts = vpts; } -- cgit v1.2.3