diff options
-rw-r--r-- | include/xine/audio_out.h | 4 | ||||
-rw-r--r-- | include/xine/video_out.h | 4 | ||||
-rw-r--r-- | include/xine/xine_internal.h | 17 | ||||
-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 |
6 files changed, 111 insertions, 5 deletions
diff --git a/include/xine/audio_out.h b/include/xine/audio_out.h index daeeb75ea..dd7d16a0d 100644 --- a/include/xine/audio_out.h +++ b/include/xine/audio_out.h @@ -341,7 +341,9 @@ int _x_ao_channels2mode( int channels ) XINE_PROTECTED; #define AO_PROP_AMP_MUTE 18 /* amplifier mute */ #define AO_PROP_NUM_STREAMS 19 /* read-only */ #define AO_PROP_CLOCK_SPEED 20 /* inform audio_out that speed has changed */ -#define AO_NUM_PROPERTIES 21 +#define AO_PROP_BUFS_TOTAL 21 /* read-only */ +#define AO_PROP_BUFS_FREE 22 /* read-only */ +#define AO_NUM_PROPERTIES 23 /* audio device control ops */ #define AO_CTRL_PLAY_PAUSE 0 diff --git a/include/xine/video_out.h b/include/xine/video_out.h index 201d0149f..9d5380884 100644 --- a/include/xine/video_out.h +++ b/include/xine/video_out.h @@ -261,7 +261,9 @@ struct xine_video_port_s { #define VO_PROP_OUTPUT_YOFFSET 22 /* read-only */ #define VO_PROP_SHARPNESS 24 #define VO_PROP_NOISE_REDUCTION 25 -#define VO_NUM_PROPERTIES 26 +#define VO_PROP_BUFS_TOTAL 26 /* read-only */ +#define VO_PROP_BUFS_FREE 27 /* read-only */ +#define VO_NUM_PROPERTIES 28 /* number of colors in the overlay palette. Currently limited to 256 at most, because some alphablend functions use an 8-bit index into diff --git a/include/xine/xine_internal.h b/include/xine/xine_internal.h index ac8e6cabf..7064539ab 100644 --- a/include/xine/xine_internal.h +++ b/include/xine/xine_internal.h @@ -361,11 +361,28 @@ struct xine_stream_s { * which is a valid stream that does not want to be addressed. */ #define XINE_ANON_STREAM ((xine_stream_t *)-1) +typedef struct +{ + int total; + int ready; + int avail; +} +xine_query_buffers_data_t; + +typedef struct +{ + xine_query_buffers_data_t vi; + xine_query_buffers_data_t ai; + xine_query_buffers_data_t vo; + xine_query_buffers_data_t ao; +} +xine_query_buffers_t; /* * private function prototypes: */ +int _x_query_buffers(xine_stream_t *stream, xine_query_buffers_t *query) XINE_PROTECTED; int _x_query_buffer_usage(xine_stream_t *stream, int *num_video_buffers, int *num_audio_buffers, int *num_video_frames, int *num_audio_frames) XINE_PROTECTED; int _x_lock_port_rewiring(xine_t *xine, int ms_to_time_out) XINE_PROTECTED; void _x_unlock_port_rewiring(xine_t *xine) XINE_PROTECTED; 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); |