summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Kretz <kretz@kde.org>2007-12-03 16:47:53 +0100
committerMatthias Kretz <kretz@kde.org>2007-12-03 16:47:53 +0100
commitb312cde90d985df949beac9708476af28bc82113 (patch)
tree674ed617f5da1db44b8db8b201320449302aadae
parent948b8dd9bfc33de61ff8c8bacf32eae53aa3b528 (diff)
downloadxine-lib-b312cde90d985df949beac9708476af28bc82113.tar.gz
xine-lib-b312cde90d985df949beac9708476af28bc82113.tar.bz2
Fixed a race condition between ao_loop and ao_close to not lose the last buffer.
In ao_loop only read the first buffer and remove it from the fifo only when the buffer has been written or is about to be discarded. This fixes the race between ao_loop and ao_close for good. Now fifo_remove_int may signal empty again right after removing the last buffer from the fifo.
-rw-r--r--ChangeLog2
-rw-r--r--src/xine-engine/audio_out.c27
2 files changed, 24 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index a4a680bbd..97dd87f94 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -20,6 +20,8 @@ xine-lib (1.1.9) (unreleased)
wakeups/s).
* Fixed ALSA close function to not discard all data that had been written
but not played yet.
+ * Fixed a race condition between ao_loop and ao_close to not lose the last
+ buffer.
xine-lib (1.1.8)
* Send a channel-changed event to the frontend when receiving the SYNC
diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c
index de74ac578..7519c3067 100644
--- a/src/xine-engine/audio_out.c
+++ b/src/xine-engine/audio_out.c
@@ -338,9 +338,7 @@ static void fifo_append (audio_fifo_t *fifo,
pthread_mutex_unlock (&fifo->mutex);
}
-static audio_buffer_t *fifo_remove_int (audio_fifo_t *fifo, int blocking) {
- audio_buffer_t *buf;
-
+static audio_buffer_t *fifo_peek_int (audio_fifo_t *fifo, int blocking) {
while (!fifo->first) {
pthread_cond_signal (&fifo->empty);
if (blocking)
@@ -355,8 +353,11 @@ static audio_buffer_t *fifo_remove_int (audio_fifo_t *fifo, int blocking) {
return NULL;
}
}
+ return fifo->first;
+}
- buf = fifo->first;
+static audio_buffer_t *fifo_remove_int (audio_fifo_t *fifo, int blocking) {
+ audio_buffer_t *buf = fifo_peek_int(fifo, blocking);
fifo->first = buf->next;
@@ -364,6 +365,7 @@ static audio_buffer_t *fifo_remove_int (audio_fifo_t *fifo, int blocking) {
fifo->last = NULL;
fifo->num_buffers = 0;
+ pthread_cond_signal (&fifo->empty);
} else
fifo->num_buffers--;
@@ -373,6 +375,17 @@ static audio_buffer_t *fifo_remove_int (audio_fifo_t *fifo, int blocking) {
return buf;
}
+static audio_buffer_t *fifo_peek (audio_fifo_t *fifo) {
+
+ audio_buffer_t *buf;
+
+ pthread_mutex_lock (&fifo->mutex);
+ buf = fifo_peek_int(fifo, 1);
+ pthread_mutex_unlock (&fifo->mutex);
+
+ return buf;
+}
+
static audio_buffer_t *fifo_remove (audio_fifo_t *fifo) {
audio_buffer_t *buf;
@@ -994,7 +1007,7 @@ static void *ao_loop (void *this_gen) {
if (!in_buf) {
lprintf ("loop: get buf from fifo\n");
- in_buf = fifo_remove (this->out_fifo);
+ in_buf = fifo_peek (this->out_fifo);
bufs_since_sync++;
lprintf ("got a buffer\n");
}
@@ -1007,6 +1020,7 @@ static void *ao_loop (void *this_gen) {
}
if (this->discard_buffers) {
+ fifo_remove (this->out_fifo);
if (in_buf->stream)
_x_refcounter_dec(in_buf->stream->refcounter);
fifo_append (this->free_fifo, in_buf);
@@ -1033,6 +1047,7 @@ static void *ao_loop (void *this_gen) {
cur_time = this->clock->get_current_time (this->clock);
if (in_buf->vpts < cur_time ) {
lprintf ("loop: next fifo\n");
+ fifo_remove (this->out_fifo);
if (in_buf->stream)
_x_refcounter_dec(in_buf->stream->refcounter);
fifo_append (this->free_fifo, in_buf);
@@ -1157,6 +1172,7 @@ static void *ao_loop (void *this_gen) {
/* drop package */
lprintf ("loop: drop package, next fifo\n");
+ fifo_remove (this->out_fifo);
if (in_buf->stream)
_x_refcounter_dec(in_buf->stream->refcounter);
fifo_append (this->free_fifo, in_buf);
@@ -1223,6 +1239,7 @@ static void *ao_loop (void *this_gen) {
} else {
result = 0;
}
+ fifo_remove (this->out_fifo);
if( result < 0 ) {
/* device unplugged. */