diff options
author | Reinhard Nißl <rnissl@gmx.de> | 2011-01-22 14:54:31 +0100 |
---|---|---|
committer | Reinhard Nißl <rnissl@gmx.de> | 2011-01-22 14:54:31 +0100 |
commit | 43fbcb6029f9a0f63ee8b61f63e54d74fc79de2a (patch) | |
tree | c4bf6e43457c3721b045bab870a481b63d92d5d1 /src | |
parent | c8e0257887a361a0b2b7a759309bcdb822d479b2 (diff) | |
download | xine-lib-43fbcb6029f9a0f63ee8b61f63e54d74fc79de2a.tar.gz xine-lib-43fbcb6029f9a0f63ee8b61f63e54d74fc79de2a.tar.bz2 |
Provide _x_query_buffers() to allow analyzing buffer usage by plugins
This function is similar to _x_query_buffer_usage() but retrieves also
the total and available (= free) number of buffers besides the number
of buffers ready for processing. For example if one wants to create a
buffering algorithm based on the number of frames ready, it's not that
easy to determine the maximum number of ready frames possible. In case
one configures engine.buffers.video_num_frames:50 it may happen, that
only 30 frames can actually be provided by the video out driver. Next
a video codec like H.264 may hold several frames in its display picture
buffer so that you may end up with only 13 ready frames at maximum. At
the same time, the number of available (= free) frames will be 0 (or
almost zero in case of vo). So it may be even easier to base the buffer
algorithm on the number of free buffers.
The reported numbers may also reveal that too few input buffers have
been provided to compensate a large a/v offset at input stage.
--HG--
extra : rebase_source : 255cb186891fbab5199a99031cf1b1e93ac19923
Diffstat (limited to 'src')
-rw-r--r-- | src/xine-engine/audio_out.c | 20 | ||||
-rw-r--r-- | src/xine-engine/video_out.c | 8 | ||||
-rw-r--r-- | src/xine-engine/xine.c | 63 |
3 files changed, 88 insertions, 3 deletions
diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index 5bb8242ae..4b2398bef 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -291,6 +291,7 @@ struct audio_fifo_s { pthread_cond_t empty; int num_buffers; + int num_buffers_max; }; static int ao_get_property (xine_audio_port_t *this_gen, int property); @@ -305,9 +306,10 @@ static audio_fifo_t *XINE_MALLOC fifo_new (xine_t *xine) { if (!fifo) return NULL; - fifo->first = NULL; - fifo->last = NULL; - fifo->num_buffers = 0; + fifo->first = NULL; + fifo->last = NULL; + fifo->num_buffers = 0; + fifo->num_buffers_max = 0; pthread_mutex_init (&fifo->mutex, NULL); pthread_cond_init (&fifo->not_empty, NULL); pthread_cond_init (&fifo->empty, NULL); @@ -334,6 +336,10 @@ static void fifo_append_int (audio_fifo_t *fifo, fifo->num_buffers++; } + + if (fifo->num_buffers_max < fifo->num_buffers) + fifo->num_buffers_max = fifo->num_buffers; + pthread_cond_signal (&fifo->not_empty); } @@ -1779,6 +1785,14 @@ static int ao_get_property (xine_audio_port_t *this_gen, int property) { ret = this->audio_loop_running ? this->out_fifo->num_buffers : -1; break; + case AO_PROP_BUFS_FREE: + ret = this->audio_loop_running ? this->free_fifo->num_buffers : -1; + break; + + case AO_PROP_BUFS_TOTAL: + ret = this->audio_loop_running ? this->free_fifo->num_buffers_max : -1; + break; + case AO_PROP_NUM_STREAMS: pthread_mutex_lock(&this->streams_lock); ret = xine_list_size(this->streams); diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index 2ffd5ae1d..fc227443c 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -1460,6 +1460,14 @@ static int vo_get_property (xine_video_port_t *this_gen, int property) { ret = this->video_loop_running ? this->display_img_buf_queue->num_buffers : -1; break; + case VO_PROP_BUFS_FREE: + ret = this->video_loop_running ? this->free_img_buf_queue->num_buffers : -1; + break; + + case VO_PROP_BUFS_TOTAL: + ret = this->video_loop_running ? this->free_img_buf_queue->num_buffers_max : -1; + break; + case VO_PROP_NUM_STREAMS: pthread_mutex_lock(&this->streams_lock); ret = xine_list_size(this->streams); diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index c3896c353..c2e6641ec 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -2399,6 +2399,69 @@ int _x_query_buffer_usage(xine_stream_t *stream, int *num_video_buffers, int *nu return ticket_acquired != 0; } +static void _x_query_buffers_fix_data(xine_query_buffers_data_t *data) +{ + if (data->total < 0) + data->total = 0; + + if (data->ready < 0) + data->ready = 0; + + if (data->avail < 0) + data->avail = 0; + + /* fix race condition of not filling data atomically */ + if (data->ready + data->avail > data->total) + data->avail = data->total - data->ready; +} + +int _x_query_buffers(xine_stream_t *stream, xine_query_buffers_t *query) +{ + int ticket_acquired = -1; + + memset(query, 0, sizeof (*query)); + + if (stream->video_fifo) + { + query->vi.total = stream->video_fifo->buffer_pool_capacity; + query->vi.ready = stream->video_fifo->size(stream->video_fifo); + query->vi.avail = stream->video_fifo->num_free(stream->video_fifo); + _x_query_buffers_fix_data(&query->vi); + } + + if (stream->audio_fifo) + { + query->ai.total = stream->audio_fifo->buffer_pool_capacity; + query->ai.ready = stream->audio_fifo->size(stream->audio_fifo); + query->ai.avail = stream->audio_fifo->num_free(stream->audio_fifo); + _x_query_buffers_fix_data(&query->ai); + } + + if (stream->video_out || stream->audio_out) + ticket_acquired = stream->xine->port_ticket->acquire_nonblocking(stream->xine->port_ticket, 1); + + if (ticket_acquired > 0) + { + if (stream->video_out) + { + query->vo.total = stream->video_out->get_property(stream->video_out, VO_PROP_BUFS_TOTAL); + query->vo.ready = stream->video_out->get_property(stream->video_out, VO_PROP_BUFS_IN_FIFO); + query->vo.avail = stream->video_out->get_property(stream->video_out, VO_PROP_BUFS_FREE); + } + + if (stream->audio_out) + { + query->ao.total = stream->audio_out->get_property(stream->audio_out, AO_PROP_BUFS_TOTAL); + query->ao.ready = stream->audio_out->get_property(stream->audio_out, AO_PROP_BUFS_IN_FIFO); + query->ao.avail = stream->audio_out->get_property(stream->audio_out, AO_PROP_BUFS_FREE); + } + + stream->xine->port_ticket->release_nonblocking(stream->xine->port_ticket, 1); + } + + return ticket_acquired != 0; +} + int _x_lock_port_rewiring(xine_t *xine, int ms_timeout) { return xine->port_ticket->lock_port_rewiring(xine->port_ticket, ms_timeout); |