diff options
Diffstat (limited to 'src/xine-engine')
-rw-r--r-- | src/xine-engine/alphablend.c | 8 | ||||
-rw-r--r-- | src/xine-engine/audio_decoder.c | 6 | ||||
-rw-r--r-- | src/xine-engine/audio_out.c | 37 | ||||
-rw-r--r-- | src/xine-engine/broadcaster.c | 4 | ||||
-rw-r--r-- | src/xine-engine/broadcaster.h | 4 | ||||
-rw-r--r-- | src/xine-engine/buffer.h | 15 | ||||
-rw-r--r-- | src/xine-engine/demux.c | 88 | ||||
-rw-r--r-- | src/xine-engine/info_helper.c | 10 | ||||
-rw-r--r-- | src/xine-engine/load_plugins.c | 29 | ||||
-rw-r--r-- | src/xine-engine/metronom.c | 33 | ||||
-rw-r--r-- | src/xine-engine/osd.c | 35 | ||||
-rw-r--r-- | src/xine-engine/refcounter.c | 5 | ||||
-rw-r--r-- | src/xine-engine/refcounter.h | 4 | ||||
-rw-r--r-- | src/xine-engine/scratch.c | 2 | ||||
-rw-r--r-- | src/xine-engine/scratch.h | 5 | ||||
-rw-r--r-- | src/xine-engine/video_decoder.c | 2 | ||||
-rw-r--r-- | src/xine-engine/video_out.h | 4 | ||||
-rw-r--r-- | src/xine-engine/video_overlay.c | 4 | ||||
-rw-r--r-- | src/xine-engine/vo_scale.c | 4 | ||||
-rw-r--r-- | src/xine-engine/vo_scale.h | 4 | ||||
-rw-r--r-- | src/xine-engine/xine.c | 21 | ||||
-rw-r--r-- | src/xine-engine/xine_interface.c | 3 | ||||
-rw-r--r-- | src/xine-engine/xine_internal.h | 1 |
23 files changed, 236 insertions, 92 deletions
diff --git a/src/xine-engine/alphablend.c b/src/xine-engine/alphablend.c index 6f3ac3ebe..1dcd47eb7 100644 --- a/src/xine-engine/alphablend.c +++ b/src/xine-engine/alphablend.c @@ -23,6 +23,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /* #define LOG_BLEND_YUV #define LOG_BLEND_RGB16 @@ -1104,7 +1108,7 @@ static void blend_yuv_exact(uint8_t *dst_cr, uint8_t *dst_cb, int src_width, static uint8_t *(*blend_yuv_grow_extra_data(alphablend_t *extra_data, int osd_width))[ 3 ][ 2 ] { - struct __attribute__((packed)) header_s { + struct XINE_PACKED header_s { int id; int max_width; uint8_t *data[ 3 ][ 2 ]; @@ -1546,7 +1550,7 @@ static void blend_yuy2_exact(uint8_t *dst_cr, uint8_t *dst_cb, int src_width, static uint8_t *(*blend_yuy2_grow_extra_data(alphablend_t *extra_data, int osd_width))[ 3 ] { - struct __attribute__((packed)) header_s { + struct XINE_PACKED header_s { int id; int max_width; uint8_t *data[ 3 ]; diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c index 5476262d9..855dee372 100644 --- a/src/xine-engine/audio_decoder.c +++ b/src/xine-engine/audio_decoder.c @@ -89,16 +89,18 @@ static void *audio_decoder_loop (void *stream_gen) { if (stream->audio_decoder_plugin) { lprintf ("close old decoder\n"); - + + stream->keep_ao_driver_open = !!(buf->decoder_flags & BUF_FLAG_GAPLESS_SW); _x_free_audio_decoder (stream, stream->audio_decoder_plugin); stream->audio_decoder_plugin = NULL; stream->audio_track_map_entries = 0; stream->audio_type = 0; + stream->keep_ao_driver_open = 0; } running_ticket->release(running_ticket, 0); - if( !stream->gapless_switch ) + if( !(buf->decoder_flags & BUF_FLAG_GAPLESS_SW) ) stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_STREAMSTART, 0); buftype_unknown = 0; diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index d28c45ea6..a6f83dc9d 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -215,6 +215,7 @@ typedef struct { int num_driver_actions; /* number of threads, that wish to call * functions needing driver_lock */ pthread_mutex_t driver_action_lock; /* protects num_driver_actions */ + pthread_cond_t driver_action_cond; /* informs about num_driver_actions-- */ metronom_clock_t *clock; xine_t *xine; @@ -243,6 +244,7 @@ typedef struct { audio_fifo_t *free_fifo; audio_fifo_t *out_fifo; int64_t last_audio_vpts; + pthread_mutex_t current_speed_lock; uint32_t current_speed; /* the current playback speed */ /* FIXME: replace all this->clock->speed with this->current_speed. we should make * sure nobody will change speed without going through xine.c:set_speed_internal */ @@ -1040,6 +1042,7 @@ static void *ao_loop (void *this_gen) { * we must process/free buffers otherwise the entire engine will stop. */ + pthread_mutex_lock(&this->current_speed_lock); if ( this->audio_loop_running && (this->clock->speed == XINE_SPEED_PAUSE || (this->clock->speed != XINE_FINE_SPEED_NORMAL && @@ -1055,6 +1058,7 @@ static void *ao_loop (void *this_gen) { _x_refcounter_dec(in_buf->stream->refcounter); fifo_append (this->free_fifo, in_buf); in_buf = NULL; + pthread_mutex_unlock(&this->current_speed_lock); continue; } @@ -1065,6 +1069,7 @@ static void *ao_loop (void *this_gen) { } lprintf ("loop:pause: I feel sleepy (%d buffers).\n", this->out_fifo->num_buffers); + pthread_mutex_unlock(&this->current_speed_lock); xine_usec_sleep (10000); lprintf ("loop:pause: I wake up.\n"); continue; @@ -1274,12 +1279,20 @@ static void *ao_loop (void *this_gen) { fifo_append (this->free_fifo, in_buf); in_buf = NULL; } + pthread_mutex_unlock(&this->current_speed_lock); /* Give other threads a chance to use functions which require this->driver_lock to * be available. This is needed when using NPTL on Linux (and probably PThreads * on Solaris as well). */ - if (this->num_driver_actions > 0) - sched_yield(); + if (this->num_driver_actions > 0) { + /* calling sched_yield() is not sufficient on multicore systems */ + /* sched_yield(); */ + /* instead wait for the other thread to acquire this->driver_lock */ + pthread_mutex_lock(&this->driver_action_lock); + if (this->num_driver_actions > 0) + pthread_cond_wait(&this->driver_action_cond, &this->driver_action_lock); + pthread_mutex_unlock(&this->driver_action_lock); + } } if (in_buf) { @@ -1470,6 +1483,8 @@ static inline void dec_num_driver_actions(aos_t *this) { pthread_mutex_lock(&this->driver_action_lock); this->num_driver_actions--; + /* indicate the change to ao_loop() */ + pthread_cond_broadcast(&this->driver_action_cond); pthread_mutex_unlock(&this->driver_action_lock); } @@ -1609,7 +1624,7 @@ static void ao_close(xine_audio_port_t *this_gen, xine_stream_t *stream) { pthread_mutex_unlock(&this->streams_lock); /* close driver if no streams left */ - if (!ite && !this->grab_only && !stream->gapless_switch) { + if (!ite && !this->grab_only && !stream->keep_ao_driver_open) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_out: no streams left, closing driver\n"); if (this->audio_loop_running) { @@ -1672,6 +1687,7 @@ static void ao_exit(xine_audio_port_t *this_gen) { } pthread_mutex_destroy(&this->driver_lock); + pthread_cond_destroy(&this->driver_action_cond); pthread_mutex_destroy(&this->driver_action_lock); pthread_mutex_destroy(&this->streams_lock); xine_list_delete(this->streams); @@ -1684,6 +1700,7 @@ static void ao_exit(xine_audio_port_t *this_gen) { free (this->frame_buf[1]); free (this->zero_space); + pthread_mutex_destroy(&this->current_speed_lock); pthread_mutex_destroy(&this->flush_audio_driver_lock); pthread_cond_destroy(&this->flush_audio_driver_reached); @@ -1910,8 +1927,15 @@ static int ao_set_property (xine_audio_port_t *this_gen, int property, int value if (value != XINE_FINE_SPEED_NORMAL && value != XINE_SPEED_PAUSE && !this->slow_fast_audio ) this->ao.control(&this->ao, AO_CTRL_FLUSH_BUFFERS, NULL); - this->ao.control(&this->ao, - (value == XINE_SPEED_PAUSE) ? AO_CTRL_PLAY_PAUSE : AO_CTRL_PLAY_RESUME, NULL); + if( value == XINE_SPEED_PAUSE ) { + /* current_speed_lock is here to make sure the ao_loop will pause in a safe place. + * that is, we cannot pause writing to device, filling gaps etc. */ + pthread_mutex_lock(&this->current_speed_lock); + this->ao.control(&this->ao, AO_CTRL_PLAY_PAUSE, NULL); + pthread_mutex_unlock(&this->current_speed_lock); + } else { + this->ao.control(&this->ao, AO_CTRL_PLAY_RESUME, NULL); + } this->current_speed = value; if( this->slow_fast_audio ) ao_update_resample_factor(this); @@ -2056,6 +2080,7 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, this->driver = driver; this->xine = xine; this->clock = xine->clock; + this->current_speed = xine->clock->speed; this->streams = xine_list_new(); /* warning: driver_lock is a recursive mutex. it must NOT be @@ -2067,6 +2092,7 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, pthread_mutex_init( &this->streams_lock, NULL ); pthread_mutex_init( &this->driver_lock, &attr ); pthread_mutex_init( &this->driver_action_lock, NULL ); + pthread_cond_init( &this->driver_action_cond, NULL ); this->ao.open = ao_open; this->ao.get_buffer = ao_get_buffer; @@ -2087,6 +2113,7 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, this->discard_buffers = 0; this->zero_space = calloc (1, ZERO_BUF_SIZE * 4 * 6); /* MAX as 32bit, 6 channels. */ + pthread_mutex_init( &this->current_speed_lock, NULL ); pthread_mutex_init( &this->flush_audio_driver_lock, NULL ); pthread_cond_init( &this->flush_audio_driver_reached, NULL ); diff --git a/src/xine-engine/broadcaster.c b/src/xine-engine/broadcaster.c index 5ce1619d1..81711de49 100644 --- a/src/xine-engine/broadcaster.c +++ b/src/xine-engine/broadcaster.c @@ -32,6 +32,10 @@ * 'xine -V none -A none' */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <unistd.h> diff --git a/src/xine-engine/broadcaster.h b/src/xine-engine/broadcaster.h index 0c6a291eb..b59d33349 100644 --- a/src/xine-engine/broadcaster.h +++ b/src/xine-engine/broadcaster.h @@ -27,10 +27,6 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - typedef struct broadcaster_s broadcaster_t; broadcaster_t *_x_init_broadcaster(xine_stream_t *stream, int port) XINE_MALLOC XINE_PROTECTED; diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h index 04fa030bf..e0866f549 100644 --- a/src/xine-engine/buffer.h +++ b/src/xine-engine/buffer.h @@ -35,10 +35,6 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <string.h> #include <stdio.h> #include <pthread.h> @@ -275,6 +271,7 @@ extern "C" { #define BUF_SPU_CVD 0x04050000 #define BUF_SPU_OGM 0x04060000 #define BUF_SPU_CMML 0x04070000 +#define BUF_SPU_HDMV 0x04080000 /* demuxer block types: */ @@ -378,6 +375,16 @@ struct buf_element_s { * decoder_info[2] carries denominator for display aspect ratio */ #define BUF_FLAG_ASPECT 0x0800 +/* represent the state of gapless_switch at the time buf was enqueued */ +#define BUF_FLAG_GAPLESS_SW 0x1000 + +/* Amount of audio padding added by encoder (mp3, aac). These empty + * audio frames are causing a gap when switching between mp3 files. + * decoder_info[1] carries amount of audio frames padded at the + * beginning of the buffer + * decoder_info[2] carries amount of audio frames padded at the end of + * the buffer */ +#define BUF_FLAG_AUDIO_PADDING 0x2000 /* Special buffer types: * Sometimes there is a need to relay special information from a demuxer diff --git a/src/xine-engine/demux.c b/src/xine-engine/demux.c index 257a72383..98b2e3fd3 100644 --- a/src/xine-engine/demux.c +++ b/src/xine-engine/demux.c @@ -21,6 +21,9 @@ * hide some xine engine details from demuxers and reduce code duplication */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include <stdio.h> #include <string.h> @@ -117,6 +120,34 @@ void _x_demux_flush_engine (xine_stream_t *stream) { } +static struct timespec _x_compute_interval(unsigned int millisecs) { + struct timespec ts; +#ifdef WIN32 + FILETIME ft; + ULARGE_INTEGER ui; + + GetSystemTimeAsFileTime(&ft); + ui.u.LowPart = ft.dwLowDateTime; + ui.u.HighPart = ft.dwHighDateTime; + ui.QuadPart += millisecs * 10000; + ts.tv_sec = ui.QuadPart / 10000000; + ts.tv_sec = (ui.QuadPart % 10000000)*100; +#elif _POSIX_TIMERS > 0 + 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; +#else + struct timeval tv; + gettimeofday(&tv, NULL); + uint64_t ttimer = (uint64_t)tv.tv_sec*1000 + tv.tv_usec/1000 + millisecs; + ts.tv_sec = ttimer/1000; + ts.tv_nsec = (ttimer%1000)*1000000; +#endif + return ts; +} + + void _x_demux_control_newpts( xine_stream_t *stream, int64_t pts, uint32_t flags ) { buf_element_t *buf; @@ -138,6 +169,29 @@ 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 && 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; +} + /* sync with decoder fifos, making sure everything gets processed */ void _x_demux_control_headers_done (xine_stream_t *stream) { @@ -175,21 +229,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 (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; @@ -203,15 +263,18 @@ void _x_demux_control_headers_done (xine_stream_t *stream) { void _x_demux_control_start( xine_stream_t *stream ) { buf_element_t *buf; + uint32_t flags = (stream->gapless_switch) ? BUF_FLAG_GAPLESS_SW : 0; pthread_mutex_lock(&stream->demux_mutex); buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); buf->type = BUF_CONTROL_START; + buf->decoder_flags = flags; stream->video_fifo->put (stream->video_fifo, buf); buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo); buf->type = BUF_CONTROL_START; + buf->decoder_flags = flags; stream->audio_fifo->put (stream->audio_fifo, buf); pthread_mutex_unlock(&stream->demux_mutex); @@ -343,10 +406,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 (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); diff --git a/src/xine-engine/info_helper.c b/src/xine-engine/info_helper.c index 34d1bbdba..6ce9bcd38 100644 --- a/src/xine-engine/info_helper.c +++ b/src/xine-engine/info_helper.c @@ -251,7 +251,15 @@ static void meta_info_set_unlocked_encoding(xine_stream_t *stream, int info, con size_t inbytesleft, outbytesleft; inbuf = (ICONV_CONST char *)value; - inbytesleft = strlen(value); + if (!strncmp (enc, "UTF-16", 6) || !strncmp (enc, "UCS-2", 5)) + { + /* strlen() won't work with UTF-16* or UCS-2* */ + inbytesleft = 0; + while (value[inbytesleft] || value[inbytesleft + 1]) + inbytesleft += 2; + } /* ... do we need to handle UCS-4? Probably not. */ + else + inbytesleft = strlen(value); outbytesleft = 4 * inbytesleft; /* estimative (max) */ outbuf = utf8_value = malloc(outbytesleft+1); diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c index f0e33ceed..04e0b4461 100644 --- a/src/xine-engine/load_plugins.c +++ b/src/xine-engine/load_plugins.c @@ -485,7 +485,7 @@ static void _register_plugins_internal(xine_t *this, plugin_file_t *file, plugin while ( info && info->type != PLUGIN_NONE ) { - if (file) + if (file && file->filename) xine_log (this, XINE_LOG_PLUGIN, _("load_plugins: plugin %s found\n"), file->filename); else @@ -1062,20 +1062,21 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { static void save_catalog (xine_t *this) { FILE *fp; - char *cachefile, *dirfile; + char *cachefile, *cachefile_new, *dirfile; const char *relname = CACHE_CATALOG_FILE; const char *dirname = CACHE_CATALOG_DIR; const char *const homedir = xine_get_homedir(); asprintf(&cachefile, "%s/%s", homedir, relname); + asprintf(&cachefile_new, "%s.new", cachefile); /* make sure homedir (~/.xine) exists */ asprintf(&dirfile, "%s/%s", homedir, dirname); mkdir (dirfile, 0755); free (dirfile); - if( (fp = fopen(cachefile,"w")) != NULL ) { + if( (fp = fopen(cachefile_new,"w")) != NULL ) { int i; fprintf(fp, "# this file is automatically created by xine, do not edit.\n\n"); @@ -1084,9 +1085,29 @@ static void save_catalog (xine_t *this) { for (i = 0; i < PLUGIN_TYPE_MAX; i++) { save_plugin_list (fp, this->plugin_catalog->plugin_lists[i]); } - fclose(fp); + if (fclose(fp)) + { + const char *err = strerror (errno); + xine_log (this, XINE_LOG_MSG, + _("failed to save catalogue cache: %s\n"), err); + goto do_unlink; + } + else if (rename (cachefile_new, cachefile)) + { + const char *err = strerror (errno); + xine_log (this, XINE_LOG_MSG, + _("failed to replace catalogue cache: %s\n"), err); + do_unlink: + if (unlink (cachefile_new) && errno != ENOENT) + { + err = strerror (errno); + xine_log (this, XINE_LOG_MSG, + _("failed to remove new catalogue cache: %s\n"), err); + } + } } free(cachefile); + free(cachefile_new); } /* diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index 84b936941..eb9abb84a 100644 --- a/src/xine-engine/metronom.c +++ b/src/xine-engine/metronom.c @@ -304,6 +304,8 @@ static void metronom_handle_discontinuity (metronom_t *this, int type, /* video_vpts and audio_vpts adjustements */ cur_time = this->xine->clock->get_current_time(this->xine->clock); + xprintf(this->xine, XINE_VERBOSITY_DEBUG, + "current time : %" PRId64 "\n", cur_time); switch (type) { case DISC_STREAMSTART: @@ -320,33 +322,12 @@ static void metronom_handle_discontinuity (metronom_t *this, int type, case DISC_ABSOLUTE: case DISC_RELATIVE: - if (this->video_vpts < cur_time) { - /* still frame */ - if (this->audio_vpts > cur_time) { - /* still frame with audio */ - this->video_vpts = this->audio_vpts; - xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video vpts adjusted to audio vpts %" PRId64 "\n", this->video_vpts); - } else { - /* still frame, no audio */ - this->video_vpts = this->prebuffer + cur_time; - this->audio_vpts = this->video_vpts; - this->audio_vpts_rmndr = 0; - this->force_video_jump = 1; - this->force_audio_jump = 1; - this->video_drift = 0; - xprintf(this->xine, XINE_VERBOSITY_DEBUG, "vpts adjusted with prebuffer to %" PRId64 "\n", - this->video_vpts); - } + if (this->video_vpts < this->audio_vpts) { + this->video_vpts = this->audio_vpts; + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video vpts adjusted to audio vpts %" PRId64 "\n", this->video_vpts); } else { - /* video */ - if (this->audio_vpts < cur_time) { - /* video, no sound */ - this->audio_vpts = this->video_vpts; - this->audio_vpts_rmndr = 0; - xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio vpts adjusted to video vpts %" PRId64 "\n", this->video_vpts); - } else { - /* video + audio */ - } + this->audio_vpts = this->video_vpts; + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio vpts adjusted to video vpts %" PRId64 "\n", this->video_vpts); } break; } diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c index 73470be1f..0a66efaab 100644 --- a/src/xine-engine/osd.c +++ b/src/xine-engine/osd.c @@ -121,6 +121,20 @@ struct osd_ft2context_s { FT_Face face; int size; }; + +static void osd_free_ft2 (osd_object_t *osd) +{ + if( osd->ft2 ) { + if ( osd->ft2->face ) + FT_Done_Face (osd->ft2->face); + if ( osd->ft2->library ) + FT_Done_FreeType(osd->ft2->library); + free( osd->ft2 ); + osd->ft2 = NULL; + } +} +#else +static inline void osd_free_ft2 (osd_object_t *osd __attr_unused) {} #endif /* @@ -873,6 +887,11 @@ static int osd_set_font_freetype2( osd_object_t *osd, const char *fontname, int return 0; } } + + if (osd->ft2->face) { + FT_Done_Face (osd->ft2->face); + osd->ft2->face = NULL; + } #ifdef HAVE_FONTCONFIG do { @@ -931,16 +950,14 @@ static int osd_set_font_freetype2( osd_object_t *osd, const char *fontname, int _("osd: error loading font %s with ft2\n"), fontname); } - free(osd->ft2); - osd->ft2 = NULL; + osd_free_ft2 (osd); return 0; end: if (FT_Set_Pixel_Sizes(osd->ft2->face, 0, size)) { xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, _("osd: error setting font size (no scalable font?)\n")); - free(osd->ft2); - osd->ft2 = NULL; + osd_free_ft2 (osd); return 0; } @@ -1516,15 +1533,7 @@ static void osd_free_object (osd_object_t *osd_to_close) { if ( osd == osd_to_close ) { free( osd->area ); -#ifdef HAVE_FT2 - if( osd->ft2 ) { - if ( osd->ft2->library ) - FT_Done_FreeType(osd->ft2->library); - - free( osd->ft2 ); - } -#endif - + osd_free_ft2 (osd); osd_free_encoding(osd); if( last ) diff --git a/src/xine-engine/refcounter.c b/src/xine-engine/refcounter.c index 8e952952b..384bdf5ed 100644 --- a/src/xine-engine/refcounter.c +++ b/src/xine-engine/refcounter.c @@ -17,6 +17,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define LOG_MODULE "refcounter" #define LOG_VERBOSE /* diff --git a/src/xine-engine/refcounter.h b/src/xine-engine/refcounter.h index d51973675..b3ddd71fc 100644 --- a/src/xine-engine/refcounter.h +++ b/src/xine-engine/refcounter.h @@ -20,10 +20,6 @@ #ifndef HAVE_REFCOUNTER_H #define HAVE_REFCOUNTER_H -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <pthread.h> typedef struct { diff --git a/src/xine-engine/scratch.c b/src/xine-engine/scratch.c index 696e99ffb..980af2f71 100644 --- a/src/xine-engine/scratch.c +++ b/src/xine-engine/scratch.c @@ -37,7 +37,7 @@ #include "xineutils.h" #include "scratch.h" -static void __attribute__((__format__(__printf__, 2, 0))) +static void XINE_FORMAT_PRINTF(2, 0) scratch_printf (scratch_buffer_t *this, const char *format, va_list argp) { time_t t; diff --git a/src/xine-engine/scratch.h b/src/xine-engine/scratch.h index 1029276e3..c45af198f 100644 --- a/src/xine-engine/scratch.h +++ b/src/xine-engine/scratch.h @@ -32,10 +32,7 @@ typedef struct scratch_buffer_s scratch_buffer_t; struct scratch_buffer_s { - void -#if __GNUC__ >= 3 - __attribute__((__format__(__printf__, 2, 0))) -#endif + void XINE_FORMAT_PRINTF(2, 0) (*scratch_printf) (scratch_buffer_t *this, const char *format, va_list ap); char **(*get_content) (scratch_buffer_t *this); diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c index c88e01714..d3c9e0d34 100644 --- a/src/xine-engine/video_decoder.c +++ b/src/xine-engine/video_decoder.c @@ -160,7 +160,7 @@ static void *video_decoder_loop (void *stream_gen) { running_ticket->release(running_ticket, 0); - if( !stream->gapless_switch ) + if( !(buf->decoder_flags & BUF_FLAG_GAPLESS_SW) ) stream->metronom->handle_video_discontinuity (stream->metronom, DISC_STREAMSTART, 0); diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 480c1c8f2..ae0f61407 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -36,10 +36,6 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <pthread.h> #ifdef XINE_COMPILE diff --git a/src/xine-engine/video_overlay.c b/src/xine-engine/video_overlay.c index 945df3cb9..b88f10c11 100644 --- a/src/xine-engine/video_overlay.c +++ b/src/xine-engine/video_overlay.c @@ -18,6 +18,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <unistd.h> #include <string.h> diff --git a/src/xine-engine/vo_scale.c b/src/xine-engine/vo_scale.c index ff30c47a6..8d84c32da 100644 --- a/src/xine-engine/vo_scale.c +++ b/src/xine-engine/vo_scale.c @@ -22,6 +22,10 @@ * Takes into account aspect ratio correction and zooming. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <string.h> #include <math.h> diff --git a/src/xine-engine/vo_scale.h b/src/xine-engine/vo_scale.h index 829405162..eb2607024 100644 --- a/src/xine-engine/vo_scale.h +++ b/src/xine-engine/vo_scale.h @@ -29,10 +29,6 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #ifdef XINE_COMPILE # include "configfile.h" #else diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index e0c98c018..1154a4602 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -330,17 +330,20 @@ static xine_ticket_t *XINE_MALLOC ticket_init(void) { static void set_speed_internal (xine_stream_t *stream, int speed) { xine_t *xine = stream->xine; + int old_speed = xine->clock->speed; - if (xine->clock->speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE) + if (old_speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE) /* get all decoder and post threads in a state where they agree to be blocked */ xine->port_ticket->revoke(xine->port_ticket, 0); - if (xine->clock->speed == XINE_SPEED_PAUSE && speed != XINE_SPEED_PAUSE) + if (old_speed == XINE_SPEED_PAUSE && speed != XINE_SPEED_PAUSE) /* all decoder and post threads may continue now */ xine->port_ticket->issue(xine->port_ticket, 0); - stream->xine->clock->set_fine_speed (stream->xine->clock, speed); - + if (old_speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE) + /* set master clock so audio_out loop can pause in a safe place */ + stream->xine->clock->set_fine_speed (stream->xine->clock, speed); + /* see coment on audio_out loop about audio_paused */ if( stream->audio_out ) { xine->port_ticket->acquire(xine->port_ticket, 1); @@ -350,6 +353,10 @@ static void set_speed_internal (xine_stream_t *stream, int speed) { xine->port_ticket->release(xine->port_ticket, 1); } + + if (old_speed == XINE_SPEED_PAUSE || speed != XINE_SPEED_PAUSE) + /* master clock is set after resuming the audio device (audio_out loop may continue) */ + stream->xine->clock->set_fine_speed (stream->xine->clock, speed); } @@ -419,6 +426,7 @@ void xine_stop (xine_stream_t *stream) { static void close_internal (xine_stream_t *stream) { int i ; + int gapless_switch = stream->gapless_switch; if( stream->slave ) { xine_close( stream->slave ); @@ -429,7 +437,7 @@ static void close_internal (xine_stream_t *stream) { } } - if( !stream->gapless_switch ) { + if( !gapless_switch ) { /* make sure that other threads cannot change the speed, especially pauseing the stream */ pthread_mutex_lock(&stream->speed_change_lock); stream->ignore_speed_change = 1; @@ -445,7 +453,7 @@ static void close_internal (xine_stream_t *stream) { stop_internal( stream ); - if( !stream->gapless_switch ) { + if( !gapless_switch ) { if (stream->video_out) stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 0); if (stream->audio_out) @@ -596,6 +604,7 @@ xine_stream_t *xine_stream_new (xine_t *this, stream->early_finish_event = 0; stream->delay_finish_event = 0; stream->gapless_switch = 0; + stream->keep_ao_driver_open = 0; stream->video_out = vo; if (vo) diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c index 8301414cd..c9481ab94 100644 --- a/src/xine-engine/xine_interface.c +++ b/src/xine-engine/xine_interface.c @@ -529,6 +529,9 @@ void xine_set_param (xine_stream_t *stream, int param, int value) { case XINE_PARAM_GAPLESS_SWITCH: stream->gapless_switch = !!value; + if( stream->gapless_switch && !stream->early_finish_event ) { + xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "frontend possibly buggy: gapless_switch without early_finish_event\n"); + } break; default: diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h index f97ca0b24..945157fc2 100644 --- a/src/xine-engine/xine_internal.h +++ b/src/xine-engine/xine_internal.h @@ -361,6 +361,7 @@ struct xine_stream_s { int early_finish_event; /* do not wait fifos get empty before sending event */ int gapless_switch; /* next stream switch will be gapless */ int delay_finish_event; /* delay event in 1/10 sec units. 0=>no delay, -1=>forever */ + int keep_ao_driver_open; #endif }; |