summaryrefslogtreecommitdiff
path: root/src/xine-engine/xine.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xine-engine/xine.c')
-rw-r--r--src/xine-engine/xine.c255
1 files changed, 195 insertions, 60 deletions
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index aebbffb39..1299b0f01 100644
--- a/src/xine-engine/xine.c
+++ b/src/xine-engine/xine.c
@@ -47,36 +47,41 @@
#include <locale.h>
#endif
+#include <basedir.h>
+
#define LOG_MODULE "xine"
#define LOG_VERBOSE
/*
#define LOG
+#define DEBUG
*/
#define XINE_ENABLE_EXPERIMENTAL_FEATURES
#define XINE_ENGINE_INTERNAL
#define METRONOM_CLOCK_INTERNAL
-#include "xine_internal.h"
-#include "plugin_catalog.h"
-#include "audio_out.h"
-#include "video_out.h"
-#include "demuxers/demux.h"
-#include "buffer.h"
-#include "spu_decoder.h"
-#include "input/input_plugin.h"
-#include "metronom.h"
-#include "configfile.h"
-#include "osd.h"
-
-#include "xineutils.h"
-#include "compat.h"
+#include <xine/xine_internal.h>
+#include <xine/plugin_catalog.h>
+#include <xine/audio_out.h>
+#include <xine/video_out.h>
+#include <xine/demux.h>
+#include <xine/buffer.h>
+#include <xine/spu_decoder.h>
+#include <xine/input_plugin.h>
+#include <xine/metronom.h>
+#include <xine/configfile.h>
+#include <xine/osd.h>
+#include <xine/spu.h>
+
+#include <xine/xineutils.h>
+#include <xine/compat.h>
#ifdef WIN32
# include <fcntl.h>
# include <winsock.h>
#endif /* WIN32 */
+#include "xine_private.h"
static void mutex_cleanup (void *mutex) {
pthread_mutex_unlock ((pthread_mutex_t *) mutex);
@@ -294,8 +299,37 @@ static void ticket_revoke(xine_ticket_t *this, int atomic) {
pthread_mutex_unlock(&this->revoke_lock);
}
+static int ticket_lock_port_rewiring(xine_ticket_t *this, int ms_timeout) {
+
+ if (ms_timeout >= 0) {
+ struct timespec abstime;
+
+ struct timeval now;
+ gettimeofday(&now, 0);
+
+ abstime.tv_sec = now.tv_sec + ms_timeout / 1000;
+ abstime.tv_nsec = now.tv_usec * 1000 + (ms_timeout % 1000) * 1e6;
+
+ if (abstime.tv_nsec > 1e9) {
+ abstime.tv_nsec -= 1e9;
+ abstime.tv_sec++;
+ }
+
+ return (0 == pthread_mutex_timedlock(&this->port_rewiring_lock, &abstime));
+ }
+
+ pthread_mutex_lock(&this->port_rewiring_lock);
+ return 1;
+}
+
+static void ticket_unlock_port_rewiring(xine_ticket_t *this) {
+
+ pthread_mutex_unlock(&this->port_rewiring_lock);
+}
+
static void ticket_dispose(xine_ticket_t *this) {
+ pthread_mutex_destroy(&this->port_rewiring_lock);
pthread_mutex_destroy(&this->lock);
pthread_mutex_destroy(&this->revoke_lock);
pthread_cond_destroy(&this->issued);
@@ -316,12 +350,15 @@ static xine_ticket_t *XINE_MALLOC ticket_init(void) {
port_ticket->renew = ticket_renew;
port_ticket->issue = ticket_issue;
port_ticket->revoke = ticket_revoke;
+ port_ticket->lock_port_rewiring = ticket_lock_port_rewiring;
+ port_ticket->unlock_port_rewiring = ticket_unlock_port_rewiring;
port_ticket->dispose = ticket_dispose;
port_ticket->holder_thread_count = XINE_MAX_TICKET_HOLDER_THREADS;
port_ticket->holder_threads = calloc(XINE_MAX_TICKET_HOLDER_THREADS,sizeof(*port_ticket->holder_threads));
pthread_mutex_init(&port_ticket->lock, NULL);
pthread_mutex_init(&port_ticket->revoke_lock, NULL);
+ pthread_mutex_init(&port_ticket->port_rewiring_lock, NULL);
pthread_cond_init(&port_ticket->issued, NULL);
pthread_cond_init(&port_ticket->revoked, NULL);
@@ -523,6 +560,7 @@ static int stream_rewire_audio(xine_post_out_t *output, void *data)
if (!data)
return 0;
+ stream->xine->port_ticket->lock_port_rewiring(stream->xine->port_ticket, -1);
stream->xine->port_ticket->revoke(stream->xine->port_ticket, 1);
if (stream->audio_out->status(stream->audio_out, stream, &bits, &rate, &mode)) {
@@ -533,6 +571,7 @@ static int stream_rewire_audio(xine_post_out_t *output, void *data)
stream->audio_out = new_port;
stream->xine->port_ticket->issue(stream->xine->port_ticket, 1);
+ stream->xine->port_ticket->unlock_port_rewiring(stream->xine->port_ticket);
return 1;
}
@@ -547,6 +586,7 @@ static int stream_rewire_video(xine_post_out_t *output, void *data)
if (!data)
return 0;
+ stream->xine->port_ticket->lock_port_rewiring(stream->xine->port_ticket, -1);
stream->xine->port_ticket->revoke(stream->xine->port_ticket, 1);
if (stream->video_out->status(stream->video_out, stream, &width, &height, &img_duration)) {
@@ -557,6 +597,7 @@ static int stream_rewire_video(xine_post_out_t *output, void *data)
stream->video_out = new_port;
stream->xine->port_ticket->issue(stream->xine->port_ticket, 1);
+ stream->xine->port_ticket->unlock_port_rewiring(stream->xine->port_ticket);
return 1;
}
@@ -702,9 +743,10 @@ xine_stream_t *xine_stream_new (xine_t *this,
/*
* osd
*/
- if (vo)
+ if (vo) {
+ _x_spu_misc_init (this);
stream->osd_renderer = _x_osd_renderer_init(stream);
- else
+ } else
stream->osd_renderer = NULL;
/*
@@ -871,11 +913,12 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
int res;
xine_log (stream->xine, XINE_LOG_MSG, _("xine: found input plugin : %s\n"),
- stream->input_plugin->input_class->get_description(stream->input_plugin->input_class));
+ dgettext(stream->input_plugin->input_class->text_domain ? : XINE_TEXTDOMAIN,
+ stream->input_plugin->input_class->description));
if (stream->input_plugin->input_class->eject_media)
stream->eject_class = stream->input_plugin->input_class;
_x_meta_info_set_utf8(stream, XINE_META_INFO_INPUT_PLUGIN,
- (stream->input_plugin->input_class->get_identifier (stream->input_plugin->input_class)));
+ stream->input_plugin->input_class->identifier);
res = (stream->input_plugin->open) (stream->input_plugin);
switch(res) {
@@ -929,7 +972,7 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
}
_x_meta_info_set_utf8(stream, XINE_META_INFO_SYSTEMLAYER,
- (stream->demux_plugin->demux_class->get_identifier(stream->demux_plugin->demux_class)));
+ stream->demux_plugin->demux_class->identifier);
free(demux_name);
} else {
xprintf(stream->xine, XINE_VERBOSITY_LOG, _("xine: error while parsing mrl\n"));
@@ -1005,7 +1048,7 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
lprintf ("demux and input plugin found\n");
_x_meta_info_set_utf8(stream, XINE_META_INFO_SYSTEMLAYER,
- (stream->demux_plugin->demux_class->get_identifier(stream->demux_plugin->demux_class)));
+ stream->demux_plugin->demux_class->identifier);
free(demux_name);
} else {
xprintf(stream->xine, XINE_VERBOSITY_LOG, _("xine: error while parsing mrl\n"));
@@ -1192,7 +1235,7 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
if( !no_cache )
/* enable buffered input plugin (request optimizer) */
- stream->input_plugin = _x_cache_plugin_get_instance(stream, 0);
+ stream->input_plugin = _x_cache_plugin_get_instance(stream);
/* Let the plugin request a specific demuxer (if the user hasn't).
* This overrides find-by-content & find-by-extension.
@@ -1208,7 +1251,7 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
{
lprintf ("demux and input plugin found\n");
_x_meta_info_set_utf8 (stream, XINE_META_INFO_SYSTEMLAYER,
- stream->demux_plugin->demux_class->get_identifier (stream->demux_plugin->demux_class));
+ stream->demux_plugin->demux_class->identifier);
}
else
xine_log (stream->xine, XINE_LOG_MSG, _("xine: couldn't load plugin-specified demux %s for >%s<\n"), default_demux, mrl);
@@ -1234,11 +1277,12 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
lprintf ("demux and input plugin found\n");
_x_meta_info_set_utf8(stream, XINE_META_INFO_SYSTEMLAYER,
- (stream->demux_plugin->demux_class->get_identifier(stream->demux_plugin->demux_class)));
+ stream->demux_plugin->demux_class->identifier);
}
xine_log (stream->xine, XINE_LOG_MSG, _("xine: found demuxer plugin: %s\n"),
- stream->demux_plugin->demux_class->get_description(stream->demux_plugin->demux_class));
+ dgettext(stream->demux_plugin->demux_class->text_domain ? : XINE_TEXTDOMAIN,
+ stream->demux_plugin->demux_class->description));
_x_extra_info_reset( stream->current_extra_info );
_x_extra_info_reset( stream->video_decoder_extra_info );
@@ -1564,6 +1608,8 @@ void xine_exit (xine_t *this) {
WSACleanup();
#endif
+ xdgFreeHandle(this->basedir_handle);
+
free (this);
}
@@ -1662,9 +1708,9 @@ static void config_demux_strategy_cb (void *this_gen, xine_cfg_entry_t *entry) {
static void config_save_cb (void *this_gen, xine_cfg_entry_t *entry) {
xine_t *this = (xine_t *)this_gen;
- char *homedir_trail_slash;
+ char homedir_trail_slash[strlen(xine_get_homedir()) + 2];
- asprintf(&homedir_trail_slash, "%s/", xine_get_homedir());
+ sprintf(homedir_trail_slash, "%s/", xine_get_homedir());
if (entry->str_value[0] &&
(entry->str_value[0] != '/' || strstr(entry->str_value, "/.") ||
strcmp(entry->str_value, xine_get_homedir()) == 0 ||
@@ -1683,13 +1729,15 @@ static void config_save_cb (void *this_gen, xine_cfg_entry_t *entry) {
pthread_mutex_unlock(&this->streams_lock);
}
- free(homedir_trail_slash);
this->save_path = entry->str_value;
}
void xine_init (xine_t *this) {
- static const char *demux_strategies[] = {"default", "reverse", "content",
- "extension", NULL};
+ static const char *const demux_strategies[] = {"default", "reverse", "content",
+ "extension", NULL};
+
+ /* First of all, initialise libxdg-basedir as it's used by plugins. */
+ this->basedir_handle = xdgAllocHandle();
/*
* locks
@@ -1706,7 +1754,7 @@ void xine_init (xine_t *this) {
/*
* plugins
*/
- _x_scan_plugins(this);
+ XINE_PROFILE(_x_scan_plugins(this));
#ifdef HAVE_SETLOCALE
if (!setlocale(LC_CTYPE, ""))
@@ -1972,6 +2020,8 @@ static int _x_get_current_frame_data (xine_stream_t *stream,
stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
frame = stream->video_out->get_last_frame (stream->video_out);
+ if (frame)
+ frame->lock(frame);
stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
if (!frame) {
@@ -2003,6 +2053,30 @@ static int _x_get_current_frame_data (xine_stream_t *stream,
switch (frame->format) {
+ default:
+ if (frame->proc_provide_standard_frame_data) {
+ uint8_t *img = data->img;
+ size_t img_size = data->img_size;
+ data->img = 0;
+ data->img_size = 0;
+
+ /* ask frame implementation for required img buffer size */
+ frame->proc_provide_standard_frame_data(frame, data);
+ required_size = data->img_size;
+
+ data->img = img;
+ data->img_size = img_size;
+ break;
+ }
+
+ if (!data->img && !(flags & XINE_FRAME_DATA_ALLOCATE_IMG))
+ break; /* not interested in image data */
+
+ xprintf (stream->xine, XINE_VERBOSITY_DEBUG,
+ "xine: error, snapshot function not implemented for format 0x%x\n", frame->format);
+ /* fall though and provide "green" YV12 image */
+ data->format = XINE_IMGFMT_YV12;
+
case XINE_IMGFMT_YV12:
required_size = frame->width * frame->height
+ ((frame->width + 1) / 2) * ((frame->height + 1) / 2)
@@ -2015,26 +2089,21 @@ static int _x_get_current_frame_data (xine_stream_t *stream,
+ ((frame->width + 1) / 2) * frame->height;
break;
- default:
- if (data->img || (flags & XINE_FRAME_DATA_ALLOCATE_IMG)) {
- xprintf (stream->xine, XINE_VERBOSITY_DEBUG,
- "xine: error, snapshot function not implemented for format 0x%x\n", frame->format);
- _x_abort ();
- }
-
- required_size = 0;
}
if (flags & XINE_FRAME_DATA_ALLOCATE_IMG) {
/* return allocated buffer size */
data->img_size = required_size;
/* allocate img or fail */
- if (!(data->img = calloc(1, required_size)))
+ if (!(data->img = calloc(1, required_size))) {
+ frame->free(frame);
return 0;
+ }
} else {
/* fail if supplied buffer is to small */
if (data->img && !img_size_unknown && data->img_size < required_size) {
data->img_size = required_size;
+ frame->free(frame);
return 0;
}
/* return used buffer size */
@@ -2070,11 +2139,14 @@ static int _x_get_current_frame_data (xine_stream_t *stream,
break;
default:
- xprintf (stream->xine, XINE_VERBOSITY_DEBUG,
- "xine: error, snapshot function not implemented for format 0x%x\n", frame->format);
- _x_abort ();
+ if (frame->proc_provide_standard_frame_data)
+ frame->proc_provide_standard_frame_data(frame, data);
+ else if (!(flags & XINE_FRAME_DATA_ALLOCATE_IMG))
+ memset(data->img, 0, data->img_size);
}
}
+
+ frame->free(frame);
return 1;
}
@@ -2141,18 +2213,6 @@ int xine_get_current_frame (xine_stream_t *stream, int *width, int *height,
return result;
}
-int xine_get_video_frame (xine_stream_t *stream,
- int timestamp, /* msec */
- int *width, int *height,
- int *ratio_code,
- int *duration, /* msec */
- int *format,
- uint8_t *img) {
- xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "xine: xine_get_video_frame not implemented yet.\n");
- _x_abort ();
- return 0;
-}
-
int xine_get_spu_lang (xine_stream_t *stream, int channel, char *lang) {
/* Ask the demuxer first (e.g. TS extracts this information from
@@ -2259,7 +2319,7 @@ void xine_log (xine_t *this, int buf, const char *format, ...) {
vsnprintf(buffer, SCRATCH_LINE_LEN_MAX, format, argp);
printf("%s", buffer);
va_end (argp);
- }
+ }
if (this->log_cb)
this->log_cb (this->log_cb_user_data, buf);
@@ -2296,11 +2356,6 @@ int xine_get_error (xine_stream_t *stream) {
return stream->err;
}
-int xine_trick_mode (xine_stream_t *stream, int mode, int value) {
- printf ("xine: xine_trick_mode not implemented yet.\n");
- _x_abort ();
-}
-
int xine_stream_master_slave(xine_stream_t *master, xine_stream_t *slave,
int affection) {
master->slave = slave;
@@ -2339,3 +2394,83 @@ int _x_query_buffer_usage(xine_stream_t *stream, int *num_video_buffers, int *nu
return ticket_acquired != 0;
}
+
+int _x_lock_port_rewiring(xine_t *xine, int ms_timeout)
+{
+ return xine->port_ticket->lock_port_rewiring(xine->port_ticket, ms_timeout);
+}
+
+void _x_unlock_port_rewiring(xine_t *xine)
+{
+ xine->port_ticket->unlock_port_rewiring(xine->port_ticket);
+}
+
+int _x_lock_frontend(xine_stream_t *stream, int ms_to_time_out)
+{
+ if (ms_to_time_out >= 0) {
+ struct timespec abstime;
+
+ struct timeval now;
+ gettimeofday(&now, 0);
+
+ abstime.tv_sec = now.tv_sec + ms_to_time_out / 1000;
+ abstime.tv_nsec = now.tv_usec * 1000 + (ms_to_time_out % 1000) * 1e6;
+
+ if (abstime.tv_nsec > 1e9) {
+ abstime.tv_nsec -= 1e9;
+ abstime.tv_sec++;
+ }
+
+ return (0 == pthread_mutex_timedlock(&stream->frontend_lock, &abstime));
+ }
+
+ pthread_mutex_lock(&stream->frontend_lock);
+ return 1;
+}
+
+void _x_unlock_frontend(xine_stream_t *stream)
+{
+ pthread_mutex_unlock(&stream->frontend_lock);
+}
+
+int _x_query_unprocessed_osd_events(xine_stream_t *stream)
+{
+ video_overlay_manager_t *ovl;
+ int redraw_needed;
+
+ if (!stream->xine->port_ticket->acquire_nonblocking(stream->xine->port_ticket, 1))
+ return -1;
+
+ ovl = stream->video_out->get_overlay_manager(stream->video_out);
+ redraw_needed = ovl->redraw_needed(ovl, 0);
+
+ if (redraw_needed)
+ stream->video_out->trigger_drawing(stream->video_out);
+
+ stream->xine->port_ticket->release_nonblocking(stream->xine->port_ticket, 1);
+
+ return redraw_needed;
+}
+
+int _x_demux_seek(xine_stream_t *stream, off_t start_pos, int start_time, int playing)
+{
+ if (!stream->demux_plugin)
+ return -1;
+ return stream->demux_plugin->seek(stream->demux_plugin, start_pos, start_time, playing);
+}
+
+int _x_continue_stream_processing(xine_stream_t *stream)
+{
+ return stream->status != XINE_STATUS_STOP
+ && stream->status != XINE_STATUS_QUIT;
+}
+
+void _x_trigger_relaxed_frame_drop_mode(xine_stream_t *stream)
+{
+ stream->first_frame_flag = 2;
+}
+
+void _x_reset_relaxed_frame_drop_mode(xine_stream_t *stream)
+{
+ stream->first_frame_flag = 1;
+}