summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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. */