From cad22619cdb867490ebfb59069f0aa472620edc5 Mon Sep 17 00:00:00 2001 From: Matthias Kretz Date: Sun, 2 Dec 2007 22:48:36 +0100 Subject: Fixed ALSA close function to not discard all data that had been written but not played yet. When closing the pcm device make sure that everything that was written to the device actually gets played. This was the race we were seeing with Ogg Vorbis and wav playback where a delayed driver->close would fix playback. Notice that blocking mode needs to be used for snd_pcm_drain, otherwise the call would be a noop. --- src/audio_out/audio_alsa_out.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/audio_out/audio_alsa_out.c b/src/audio_out/audio_alsa_out.c index e92bfbb3a..4ce2b1be3 100644 --- a/src/audio_out/audio_alsa_out.c +++ b/src/audio_out/audio_alsa_out.c @@ -856,7 +856,11 @@ static int ao_alsa_write(ao_driver_t *this_gen, int16_t *data, uint32_t count) { static void ao_alsa_close(ao_driver_t *this_gen) { alsa_driver_t *this = (alsa_driver_t *) this_gen; - if(this->audio_fd) snd_pcm_close(this->audio_fd); + if(this->audio_fd) { + snd_pcm_nonblock(this->audio_fd, 0); + snd_pcm_drain(this->audio_fd); + snd_pcm_close(this->audio_fd); + } this->audio_fd = NULL; this->has_pause_resume = 0; /* This is set at open time */ } -- cgit v1.2.3 From 5a7b7dcb302085db68a44f7f7acb6e4abbb73a75 Mon Sep 17 00:00:00 2001 From: Matthias Kretz Date: Sun, 2 Dec 2007 22:59:23 +0100 Subject: remove redundant check buf must be != NULL because of the while(!fifo->first) before and the buf->next after --- src/xine-engine/audio_out.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index 7e43fb5cf..0c37b8d1f 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -358,22 +358,19 @@ static audio_buffer_t *fifo_remove_int (audio_fifo_t *fifo, int blocking) { buf = fifo->first; - if (buf) { - fifo->first = buf->next; - - if (!fifo->first) { + fifo->first = buf->next; - fifo->last = NULL; - fifo->num_buffers = 0; - pthread_cond_signal (&fifo->empty); + if (!fifo->first) { - } else - fifo->num_buffers--; + fifo->last = NULL; + fifo->num_buffers = 0; + pthread_cond_signal (&fifo->empty); - } + } else + fifo->num_buffers--; buf->next = NULL; - + return buf; } -- cgit v1.2.3 From fc74afb82c232221a4205579e1eddb26a91d1c26 Mon Sep 17 00:00:00 2001 From: Matthias Kretz Date: Sun, 2 Dec 2007 23:03:46 +0100 Subject: Don't signal fifo->empty right after reading the last buffer but only when a read was requested and the fifo is empty. Rationale: ao_close uses fifo_wait_empty to make sure all buffers were written to the driver before it calls close on the driver. But if empty is already signaled when ao_loop just reads the next buffer then ao_close might close the driver before ao_loop has a chance to send the buffer to the driver. --- src/xine-engine/audio_out.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index 0c37b8d1f..de74ac578 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -364,7 +364,6 @@ 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--; -- cgit v1.2.3 From 948b8dd9bfc33de61ff8c8bacf32eae53aa3b528 Mon Sep 17 00:00:00 2001 From: Matthias Kretz Date: Sun, 2 Dec 2007 23:43:03 +0100 Subject: silence stdout of ogg demuxer --- src/demuxers/demux_ogg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c index 2c06f14ca..4eacf7070 100644 --- a/src/demuxers/demux_ogg.c +++ b/src/demuxers/demux_ogg.c @@ -239,7 +239,7 @@ static int read_ogg_packet (demux_ogg_t *this) { bytes = this->input->read(this->input, buffer, CHUNKSIZE); if (bytes == 0) { if (total == 0) { - printf("read_ogg_packet read nothing\n"); + lprintf("read_ogg_packet read nothing\n"); return 0; } break; -- cgit v1.2.3 From b312cde90d985df949beac9708476af28bc82113 Mon Sep 17 00:00:00 2001 From: Matthias Kretz Date: Mon, 3 Dec 2007 16:47:53 +0100 Subject: 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. --- src/xine-engine/audio_out.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'src') 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. */ -- cgit v1.2.3 From 0aa00fb217357cee4ef1008677e1247bb24eb42c Mon Sep 17 00:00:00 2001 From: Matthias Kretz Date: Tue, 4 Dec 2007 00:43:27 +0100 Subject: fifo_peek_int can return NULL (when non-blocking). make fifo_remove_int handle that case --- src/xine-engine/audio_out.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index 7519c3067..7fe92d9fe 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -358,6 +358,8 @@ static audio_buffer_t *fifo_peek_int (audio_fifo_t *fifo, int blocking) { static audio_buffer_t *fifo_remove_int (audio_fifo_t *fifo, int blocking) { audio_buffer_t *buf = fifo_peek_int(fifo, blocking); + if (!buf) + return NULL; fifo->first = buf->next; -- cgit v1.2.3