summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLorenzo Desole <lorenzodes@fastwebnet.it>2009-02-09 22:38:40 +0100
committerLorenzo Desole <lorenzodes@fastwebnet.it>2009-02-09 22:38:40 +0100
commit2afab9c8441685d1ec8f6ef5c9f8c4a163533dfa (patch)
tree5c357d15823727e730790a4138fdee7266e2510c
parent8f9a6421c30167b2bf314d512ae70b27d0167bb1 (diff)
downloadxine-lib-2afab9c8441685d1ec8f6ef5c9f8c4a163533dfa.tar.gz
xine-lib-2afab9c8441685d1ec8f6ef5c9f8c4a163533dfa.tar.bz2
demux_unstick_ao_loop() reports that xine might be stuck != is stuck
Don't give up immediately if demux_unstick_ao_loop() reports that xine might be stuck, because it's not necessarily so. According to my tests, this fixes http://bugs.kde.org/show_bug.cgi?id=180339#c42 and http://bugs.debian.org/514114. This has been tested with Amarok and kde 4.1.x (with phonon) and kaffeine.
-rw-r--r--src/combined/ffmpeg/ff_audio_decoder.c4
-rw-r--r--src/xine-engine/demux.c52
2 files changed, 40 insertions, 16 deletions
diff --git a/src/combined/ffmpeg/ff_audio_decoder.c b/src/combined/ffmpeg/ff_audio_decoder.c
index 140a88f80..24c193b44 100644
--- a/src/combined/ffmpeg/ff_audio_decoder.c
+++ b/src/combined/ffmpeg/ff_audio_decoder.c
@@ -333,8 +333,10 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf)
while (out < decode_buffer_size) {
int stream_status = xine_get_status(this->stream);
- if (stream_status == XINE_STATUS_QUIT || stream_status == XINE_STATUS_STOP)
+ if (stream_status == XINE_STATUS_QUIT || stream_status == XINE_STATUS_STOP) {
+ this->size = 0;
return;
+ }
audio_buffer =
this->stream->audio_out->get_buffer (this->stream->audio_out);
diff --git a/src/xine-engine/demux.c b/src/xine-engine/demux.c
index 5e9cf5a83..2ff64dfd3 100644
--- a/src/xine-engine/demux.c
+++ b/src/xine-engine/demux.c
@@ -120,6 +120,16 @@ void _x_demux_flush_engine (xine_stream_t *stream) {
}
+struct timespec _x_compute_interval(unsigned int millisecs) {
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ uint64_t ttimer = (uint64_t)ts.tv_sec*1000 + ts.tv_nsec/1000000 + millisecs;
+ ts.tv_sec = ttimer/1000;
+ ts.tv_nsec = (ttimer%1000)*1000000;
+ return ts;
+}
+
+
void _x_demux_control_newpts( xine_stream_t *stream, int64_t pts, uint32_t flags ) {
buf_element_t *buf;
@@ -147,19 +157,20 @@ void _x_demux_control_newpts( xine_stream_t *stream, int64_t pts, uint32_t flags
*/
static int demux_unstick_ao_loop (xine_stream_t *stream)
{
- if (!stream->audio_thread_created)
+/* if (!stream->audio_thread_created)
return 0;
-
+*/
int status = xine_get_status (stream);
- if (status != XINE_STATUS_QUIT && status != XINE_STATUS_STOP)
+ if (status != XINE_STATUS_QUIT && status != XINE_STATUS_STOP && stream->demux_plugin->get_status(stream->demux_plugin) != DEMUX_FINISHED)
return 0;
-
+#if 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);
-
+#endif
+ lprintf("stuck\n");
return 1;
}
@@ -200,24 +211,27 @@ void _x_demux_control_headers_done (xine_stream_t *stream) {
stream->audio_fifo->put (stream->audio_fifo, buf_audio);
pthread_mutex_unlock(&stream->demux_mutex);
+ unsigned int max_iterations = 0;
while ((stream->header_count_audio < header_count_audio) ||
(stream->header_count_video < header_count_video)) {
- struct timeval tv;
- struct timespec ts;
lprintf ("waiting for headers. v:%d %d a:%d %d\n",
stream->header_count_video, header_count_video,
stream->header_count_audio, header_count_audio);
+
+ struct timespec ts = _x_compute_interval(1000);
+ int ret_wait;
- gettimeofday(&tv, NULL);
- ts.tv_sec = tv.tv_sec + 1;
- 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);
+ ret_wait = pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts);
- if (demux_unstick_ao_loop (stream))
+ if (ret_wait == ETIMEDOUT && demux_unstick_ao_loop (stream) && ++max_iterations > 4) {
+ xine_log(stream->xine,
+ XINE_LOG_MSG,_("Stuck in _x_demux_control_headers_done(). Taking the emergency exit\n"));
+ stream->emergency_brake = 1;
break;
+ }
}
stream->demux_action_pending = 0;
@@ -374,13 +388,21 @@ static void *demux_loop (void *stream_gen) {
pthread_mutex_unlock( &stream->demux_lock );
pthread_mutex_lock (&stream->counter_lock);
+ struct timespec ts;
+ unsigned int max_iterations = 0;
+ int ret_wait;
while ((stream->finished_count_audio < finished_count_audio) ||
(stream->finished_count_video < finished_count_video)) {
lprintf ("waiting for finisheds.\n");
- pthread_cond_wait (&stream->counter_changed, &stream->counter_lock);
+ ts = _x_compute_interval(1000);
+ ret_wait = pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts);
- if (demux_unstick_ao_loop (stream))
- /* break amarok */;
+ if (ret_wait == ETIMEDOUT && demux_unstick_ao_loop (stream) && ++max_iterations > 4) {
+ xine_log(stream->xine,
+ XINE_LOG_MSG,_("Stuck in demux_loop(). Taking the emergency exit\n"));
+ stream->emergency_brake = 1;
+ break;
+ }
}
pthread_mutex_unlock (&stream->counter_lock);