summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/xine/audio_out.h4
-rw-r--r--include/xine/video_out.h4
-rw-r--r--include/xine/xine_internal.h17
-rw-r--r--src/xine-engine/audio_out.c20
-rw-r--r--src/xine-engine/video_out.c8
-rw-r--r--src/xine-engine/xine.c63
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);