summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Salt <linux@youmustbejoking.demon.co.uk>2009-01-02 20:21:33 +0000
committerDarren Salt <linux@youmustbejoking.demon.co.uk>2009-01-02 20:21:33 +0000
commit398288888f6fde7697982a0c498ac724d2a6b698 (patch)
tree02e5625c656b7bed50e5361f759932428b9f6a58
parent36591267df06370105922e368505ea5cc8512882 (diff)
downloadxine-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.c28
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);