# HG changeset patch # User Matthias Kretz # Date 1196632116 -3600 # Node ID 9040cfb7f4b21fcbd9384589c8599afcdcc7e88e # Parent 3d88fc984e4bb025816067890ae65ee2a7f61eb2 Fixed ogg demuxer to not discard data at the end of the stream. 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. diff -r 3d88fc984e4b -r 9040cfb7f4b2 src/audio_out/audio_alsa_out.c --- a/src/audio_out/audio_alsa_out.c Sun Nov 25 23:46:01 2007 +0100 +++ b/src/audio_out/audio_alsa_out.c Sun Dec 02 22:48:36 2007 +0100 @@ -856,7 +856,11 @@ static void ao_alsa_close(ao_driver_t *t 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 */ } # HG changeset patch # User Matthias Kretz # Date 1196632763 -3600 # Node ID da64a10b5e24eb29cb7409edd1b60efbdb5c847a # Parent 9040cfb7f4b21fcbd9384589c8599afcdcc7e88e remove redundant check buf must be != NULL because of the while(!fifo->first) before and the buf->next after diff -r 9040cfb7f4b2 -r da64a10b5e24 src/xine-engine/audio_out.c --- a/src/xine-engine/audio_out.c Sun Dec 02 22:48:36 2007 +0100 +++ b/src/xine-engine/audio_out.c Sun Dec 02 22:59:23 2007 +0100 @@ -358,22 +358,19 @@ static audio_buffer_t *fifo_remove_int ( buf = fifo->first; - if (buf) { - fifo->first = buf->next; - - if (!fifo->first) { - - fifo->last = NULL; - fifo->num_buffers = 0; - pthread_cond_signal (&fifo->empty); - - } else - fifo->num_buffers--; - - } + fifo->first = buf->next; + + if (!fifo->first) { + + fifo->last = NULL; + fifo->num_buffers = 0; + pthread_cond_signal (&fifo->empty); + + } else + fifo->num_buffers--; buf->next = NULL; - + return buf; } # HG changeset patch # User Matthias Kretz # Date 1196633026 -3600 # Node ID 05fb13609ba55a3917179e201fef34bfd3420dab # Parent da64a10b5e24eb29cb7409edd1b60efbdb5c847a 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. diff -r da64a10b5e24 -r 05fb13609ba5 src/xine-engine/audio_out.c --- a/src/xine-engine/audio_out.c Sun Dec 02 22:59:23 2007 +0100 +++ b/src/xine-engine/audio_out.c Sun Dec 02 23:03:46 2007 +0100 @@ -364,7 +364,6 @@ static audio_buffer_t *fifo_remove_int ( fifo->last = NULL; fifo->num_buffers = 0; - pthread_cond_signal (&fifo->empty); } else fifo->num_buffers--; # HG changeset patch # User Matthias Kretz # Date 1196696873 -3600 # Node ID dbf7e0bfc23ae1035210b4e7d7c1d98d7e29872c # Parent 05fb13609ba55a3917179e201fef34bfd3420dab 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. diff -r 05fb13609ba5 -r dbf7e0bfc23a src/xine-engine/audio_out.c --- a/src/xine-engine/audio_out.c Sun Dec 02 23:03:46 2007 +0100 +++ b/src/xine-engine/audio_out.c Mon Dec 03 16:47:53 2007 +0100 @@ -338,9 +338,7 @@ static void fifo_append (audio_fifo_t *f 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 ( return NULL; } } - - buf = fifo->first; + return 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,11 +365,23 @@ static audio_buffer_t *fifo_remove_int ( fifo->last = NULL; fifo->num_buffers = 0; + pthread_cond_signal (&fifo->empty); } else fifo->num_buffers--; buf->next = NULL; + + 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; } @@ -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. */ # HG changeset patch # User Matthias Kretz # Date 1196635383 -3600 # Node ID 0f73d62fc2df7072b573e97d6eca6f96fa175993 # Parent dbf7e0bfc23ae1035210b4e7d7c1d98d7e29872c silence stdout of ogg demuxer diff -r dbf7e0bfc23a -r 0f73d62fc2df src/demuxers/demux_ogg.c --- a/src/demuxers/demux_ogg.c Mon Dec 03 16:47:53 2007 +0100 +++ b/src/demuxers/demux_ogg.c Sun Dec 02 23:43:03 2007 +0100 @@ -239,7 +239,7 @@ static int read_ogg_packet (demux_ogg_t 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; # HG changeset patch # User Matthias Kretz # Date 1196697664 -3600 # Node ID 67d6b3fb8c9fbeef814a3c5b7992ad9c0f224b0a # Parent 0f73d62fc2df7072b573e97d6eca6f96fa175993 ChangeLog entries for my patches diff -r 0f73d62fc2df -r 67d6b3fb8c9f ChangeLog --- a/ChangeLog Sun Dec 02 23:43:03 2007 +0100 +++ b/ChangeLog Mon Dec 03 17:01:04 2007 +0100 @@ -14,6 +14,14 @@ xine-lib (1.1.9) (unreleased) This requires conversion to UTF-8 of entities with codes >= 128. * Fixed ATSC support. [Bug 1749508] * Fixed a possible DVB plugin crash when switching channels. + * Fixed ogg demuxer to not discard data at the end of the stream. + * Fixed deadlock on ao_close while paused. + * Nicer wakeup behaviour, using select instead of nanosleep (800 -> 100 + 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