summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinhard Nißl <rnissl@gmx.de>2011-01-22 14:54:31 +0100
committerReinhard Nißl <rnissl@gmx.de>2011-01-22 14:54:31 +0100
commit43fbcb6029f9a0f63ee8b61f63e54d74fc79de2a (patch)
treec4bf6e43457c3721b045bab870a481b63d92d5d1
parentc8e0257887a361a0b2b7a759309bcdb822d479b2 (diff)
downloadxine-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
-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);