diff options
author | Darren Salt <linux@youmustbejoking.demon.co.uk> | 2009-01-02 20:21:33 +0000 |
---|---|---|
committer | Darren Salt <linux@youmustbejoking.demon.co.uk> | 2009-01-02 20:21:33 +0000 |
commit | 398288888f6fde7697982a0c498ac724d2a6b698 (patch) | |
tree | 02e5625c656b7bed50e5361f759932428b9f6a58 | |
parent | 36591267df06370105922e368505ea5cc8512882 (diff) | |
download | xine-lib-398288888f6fde7697982a0c498ac724d2a6b698.tar.gz xine-lib-398288888f6fde7697982a0c498ac724d2a6b698.tar.bz2 |
Prevent another possible hang on stream stop (demuxer waiting for audio out).
The test stream sometimes causes the ASF demuxer to report "unknown GUID"
several times then act as if the headers have been received, with the audio
output thread waiting forever for data to be passed to it by the decoder, in
this case the ffmpeg audio decoder.
This particular hang occurs if playback is stopped before the demuxer has
decided that headers have been received (later, and we'd have the problem
which the parent cset of this cset fixes); having the demuxer control insert
empty audio buffers where it would otherwise wait forever for the audio
output thread to receive some data.
Test stream: mmsh://213.92.19.8:80/radiodeejay?MSWMExt=.asf
-rw-r--r-- | src/xine-engine/demux.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/src/xine-engine/demux.c b/src/xine-engine/demux.c index 257a72383..4f40c9848 100644 --- a/src/xine-engine/demux.c +++ b/src/xine-engine/demux.c @@ -138,6 +138,28 @@ void _x_demux_control_newpts( xine_stream_t *stream, int64_t pts, uint32_t flags pthread_mutex_unlock(&stream->demux_mutex); } +/* avoid ao_loop being stuck in a pthread_cond_wait, waiting for data; + * return 1 if the stream is stopped + * (better fix wanted!) + */ +static int demux_unstick_ao_loop (xine_stream_t *stream) +{ + if (!stream->audio_thread_created) + return 0; + + int status = xine_get_status (stream); + if (status != XINE_STATUS_QUIT && status != XINE_STATUS_STOP) + return 0; + + /* right, stream is stopped... */ + audio_buffer_t *buf = stream->audio_out->get_buffer (stream->audio_out); + buf->num_frames = 0; + buf->stream = NULL; + stream->audio_out->put_buffer (stream->audio_out, buf, stream); + + return 1; +} + /* sync with decoder fifos, making sure everything gets processed */ void _x_demux_control_headers_done (xine_stream_t *stream) { @@ -190,6 +212,9 @@ void _x_demux_control_headers_done (xine_stream_t *stream) { ts.tv_nsec = tv.tv_usec * 1000; /* use timedwait to workaround buggy pthread broadcast implementations */ pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts); + + if (demux_unstick_ao_loop (stream)) + break; } stream->demux_action_pending = 0; @@ -347,6 +372,9 @@ static void *demux_loop (void *stream_gen) { (stream->finished_count_video < finished_count_video)) { lprintf ("waiting for finisheds.\n"); pthread_cond_wait (&stream->counter_changed, &stream->counter_lock); + + if (demux_unstick_ao_loop (stream)) + break; } pthread_mutex_unlock (&stream->counter_lock); |