diff options
author | Lorenzo Desole <lorenzodes@fastwebnet.it> | 2009-02-09 22:38:40 +0100 |
---|---|---|
committer | Lorenzo Desole <lorenzodes@fastwebnet.it> | 2009-02-09 22:38:40 +0100 |
commit | 2afab9c8441685d1ec8f6ef5c9f8c4a163533dfa (patch) | |
tree | 5c357d15823727e730790a4138fdee7266e2510c | |
parent | 8f9a6421c30167b2bf314d512ae70b27d0167bb1 (diff) | |
download | xine-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.c | 4 | ||||
-rw-r--r-- | src/xine-engine/demux.c | 52 |
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); |