summaryrefslogtreecommitdiff
path: root/src/xine-engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/xine-engine')
-rw-r--r--src/xine-engine/alphablend.c8
-rw-r--r--src/xine-engine/audio_decoder.c6
-rw-r--r--src/xine-engine/audio_out.c37
-rw-r--r--src/xine-engine/broadcaster.c4
-rw-r--r--src/xine-engine/broadcaster.h4
-rw-r--r--src/xine-engine/buffer.h15
-rw-r--r--src/xine-engine/demux.c88
-rw-r--r--src/xine-engine/info_helper.c10
-rw-r--r--src/xine-engine/load_plugins.c29
-rw-r--r--src/xine-engine/metronom.c33
-rw-r--r--src/xine-engine/osd.c35
-rw-r--r--src/xine-engine/refcounter.c5
-rw-r--r--src/xine-engine/refcounter.h4
-rw-r--r--src/xine-engine/scratch.c2
-rw-r--r--src/xine-engine/scratch.h5
-rw-r--r--src/xine-engine/video_decoder.c2
-rw-r--r--src/xine-engine/video_out.h4
-rw-r--r--src/xine-engine/video_overlay.c4
-rw-r--r--src/xine-engine/vo_scale.c4
-rw-r--r--src/xine-engine/vo_scale.h4
-rw-r--r--src/xine-engine/xine.c21
-rw-r--r--src/xine-engine/xine_interface.c3
-rw-r--r--src/xine-engine/xine_internal.h1
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
};