diff options
Diffstat (limited to 'src/xine-engine')
56 files changed, 2181 insertions, 5427 deletions
diff --git a/src/xine-engine/Makefile.am b/src/xine-engine/Makefile.am index 67ae63fae..616da19a5 100644 --- a/src/xine-engine/Makefile.am +++ b/src/xine-engine/Makefile.am @@ -1,55 +1,76 @@ +include $(top_srcdir)/misc/Makefile.quiet include $(top_srcdir)/misc/Makefile.common include $(top_srcdir)/lib/Makefile.common -AM_CFLAGS = $(X_CFLAGS) $(FT2_CFLAGS) $(FONTCONFIG_CFLAGS) $(VISIBILITY_FLAG) -AM_CPPFLAGS = $(ZLIB_CPPFLAGS) -DXINE_LIBRARY_COMPILE +AM_CFLAGS = -I$(top_srcdir)/src/video_out $(DEFAULT_OCFLAGS) $(X_CFLAGS) $(FT2_CFLAGS) $(FONTCONFIG_CFLAGS) \ + $(AVUTIL_CFLAGS) $(VISIBILITY_FLAG) +AM_CPPFLAGS = $(XDG_BASEDIR_CPPFLAGS) $(ZLIB_CPPFLAGS) -DXINE_LIBRARY_COMPILE -LIBTOOL = $(SHELL) $(top_builddir)/libtool -lib_LTLIBRARIES = libxine.la +XINEUTILS_LIB = $(top_builddir)/src/xine-utils/libxineutils.la + +YUV_LIB = $(top_builddir)/src/video_out/libyuv2rgb.la + +# FIXME: these are currently unused: +EXTRA_DIST = lrb.c lrb.h accel_vdpau.h accel_xvmc.h -XINEUTILS_LIB = $(top_builddir)/src/xine-utils/libxineutils.la -DEF_FILE = libxine-$(XINE_MAJOR).def if WIN32 +DEF_FILE = libxine-$(XINE_MAJOR).def def_ldflags=-Wl,--output-def,$(DEF_FILE) $(LDFLAGS_NOUNDEFINED) +else +DEF_FILE = endif +noinst_HEADERS = bswap.h ffmpeg_bswap.h xine_private.h + +lib_LTLIBRARIES = libxine.la + +# Technically, this is a lie; it just makes sure that we get a static lib. +noinst_LTLIBRARIES = libxine-interface.la + libxine_la_SOURCES = xine.c metronom.c configfile.c buffer.c \ load_plugins.c video_decoder.c buffer_types.c \ audio_decoder.c video_out.c audio_out.c resample.c events.c \ - video_overlay.c osd.c scratch.c demux.c vo_scale.c \ - xine_interface.c post.c tvmode.c broadcaster.c io_helper.c \ + video_overlay.c osd.c spu.c scratch.c demux.c vo_scale.c \ + xine_interface.c post.c broadcaster.c io_helper.c \ input_rip.c input_cache.c info_helper.c refcounter.c \ - alphablend.c - -# FIXME: these are currently unused: -EXTRA_DIST = lrb.c lrb.h accel_xvmc.h + alphablend.c \ + xine_private.h -libxine_la_DEPENDENCIES = $(XINEUTILS_LIB) \ - $(pthread_dep) $(LIBXINEPOSIX) +libxine_la_DEPENDENCIES = $(XINEUTILS_LIB) $(YUV_LIB) $(XDG_BASEDIR_DEPS) \ + $(pthread_dep) $(LIBXINEPOSIX) \ + libxine-interface.la +libxine_la_CFLAGS = $(AM_CFLAGS) -fno-strict-aliasing libxine_la_LIBADD = $(PTHREAD_LIBS) $(DYNAMIC_LD_LIBS) $(LTLIBINTL) $(ZLIB_LIBS) \ - -lm $(XINEUTILS_LIB) $(LTLIBICONV) $(FT2_LIBS) $(FONTCONFIG_LIBS) \ - $(LIBXINEPOSIX) $(RT_LIBS) $(NET_LIBS) + -lm $(XINEUTILS_LIB) $(YUV_LIB) $(LTLIBICONV) $(FT2_LIBS) $(FONTCONFIG_LIBS) \ + $(LIBXINEPOSIX) $(RT_LIBS) $(NET_LIBS) $(XDG_BASEDIR_LIBS) \ + $(AVUTIL_LIBS) -libxine_la_LDFLAGS = \ - -version-info $(XINE_LT_CURRENT):$(XINE_LT_REVISION):$(XINE_LT_AGE) \ - $(def_ldflags) +libxine_la_LDFLAGS = $(AM_LDFLAGS) $(def_ldflags) $(GCSECTIONS) \ + -weak libxine-interface.la \ + -version-info $(XINE_LT_CURRENT):$(XINE_LT_REVISION):$(XINE_LT_AGE) +libxine_interface_la_SOURCES = -xineinclude_HEADERS = buffer.h metronom.h configfile.h vo_scale.h \ - audio_out.h resample.h video_out.h xine_internal.h spu_decoder.h \ - video_overlay.h osd.h scratch.h xine_plugin.h xineintl.h \ - plugin_catalog.h audio_decoder.h video_decoder.h post.h \ - io_helper.h broadcaster.h info_helper.h refcounter.h alphablend.h +libxine_interface_la_LDFLAGS = $(AM_LDFLAGS) $(def_ldflags) \ + -version-info $(XINE_LT_CURRENT):$(XINE_LT_REVISION):$(XINE_LT_AGE) -noinst_HEADERS = bswap.h ffmpeg_bswap.h xine_private.h +# Yes, we need to install this. +install-exec-hook: libxine-interface.la + $(INSTALL_DATA) libxine-interface.la "$(DESTDIR)$(libdir)"/libxine-interface.la + +clean-local: + rm -f libxine-interface.la + +$(XINEUTILS_LIB): + $(MAKE) -C $(top_builddir)/src/xine-utils libxineutils.la + +$(YUV_LIB): + $(MAKE) -C $(top_builddir)/src/video_out libyuv2rgb.la if WIN32 install-exec-local: cp -p $(DEF_FILE) $(DESTDIR)$(libdir) - -uninstall-local: - rm -f $(DEF_FILE) endif -$(XINEUTILS_LIB): - $(MAKE) -C $(top_builddir)/src/xine-utils libxineutils.la +uninstall-local: + rm -f $(DEF_FILE) "$(DESTDIR)$(libdir)"/libxine-interface.la diff --git a/src/xine-engine/broadcaster.h b/src/xine-engine/accel_vdpau.h index 0cd416cac..6f9590114 100644 --- a/src/xine-engine/broadcaster.h +++ b/src/xine-engine/accel_vdpau.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2003 the xine project + * Copyright (C) 2008 the xine project * * This file is part of xine, a free video player. * @@ -17,22 +17,45 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * - * broadcaster.h + * + * Common acceleration definitions for vdpau + * + * */ -#ifndef HAVE_BROADCASTER_H -#define HAVE_BROADCASTER_H +#ifndef HAVE_XINE_ACCEL_VDPAU_H +#define HAVE_XINE_ACCEL_VDPAU_H #ifdef __cplusplus extern "C" { #endif -typedef struct broadcaster_s broadcaster_t; +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <vdpau/vdpau.h> + + +typedef struct { + vo_frame_t *vo_frame; + + VdpDevice vdp_device; + + VdpGetErrorString *vdp_get_error_string; + VdpDecoderCreate *vdp_decoder_create; + VdpDecoderDestroy *vdp_decoder_destroy; + VdpDecoderRender *vdp_decoder_render; + + VdpVideoSurface surface; + VdpChromaType chroma; + + VdpColorStandard color_standard; -broadcaster_t *_x_init_broadcaster(xine_stream_t *stream, int port) XINE_MALLOC XINE_PROTECTED; -void _x_close_broadcaster(broadcaster_t *this) XINE_PROTECTED; -int _x_get_broadcaster_port(broadcaster_t *this) XINE_PROTECTED; + int vdp_runtime_nr; /* this is used to keep in sync on preemptions */ + int *current_vdp_runtime_nr; +} vdpau_accel_t; #ifdef __cplusplus } diff --git a/src/xine-engine/accel_xvmc.h b/src/xine-engine/accel_xvmc.h index 197b76050..f7deeeb52 100644 --- a/src/xine-engine/accel_xvmc.h +++ b/src/xine-engine/accel_xvmc.h @@ -65,6 +65,7 @@ typedef struct xine_vld_frame_s { typedef struct xine_xvmc_s { + vo_frame_t *vo_frame; xine_macroblocks_t *macroblocks; void (*proc_macro_block)(int x,int y,int mb_type, int motion_type,int (*mv_field_sel)[2], @@ -74,6 +75,9 @@ typedef struct xine_xvmc_s { int second_field,int (*f_mot_pmv)[2],int (*b_mot_pmv)[2]); } xine_xvmc_t ; +#define XVMC_DATA(frame_gen) ((frame_gen) ? (xine_xvmc_t *)(frame_gen)->accel_data : (xine_xvmc_t *)0) +#define XVMC_FRAME(frame_gen) ((frame_gen) ? (xvmc_frame_t *)XVMC_DATA(frame_gen)->vo_frame : (xvmc_frame_t *)0) + typedef struct xine_xxmc_s { /* @@ -108,6 +112,9 @@ typedef struct xine_xxmc_s { void (*proc_xxmc_unlock) (vo_driver_t *this_gen); } xine_xxmc_t; +#define XXMC_DATA(frame_gen) ((frame_gen) ? (xine_xxmc_t *)(frame_gen)->accel_data : (xine_xxmc_t *)0) +#define XXMC_FRAME(frame_gen) ((frame_gen) ? (xxmc_frame_t *)XXMC_DATA(frame_gen)->xvmc.vo_frame : (xxmc_frame_t *)0) + /* * Register XvMC stream types here. */ diff --git a/src/xine-engine/alphablend.c b/src/xine-engine/alphablend.c index 4727740bd..15fc538ab 100644 --- a/src/xine-engine/alphablend.c +++ b/src/xine-engine/alphablend.c @@ -36,9 +36,9 @@ #include <stdlib.h> #include <stdio.h> -#include "xine_internal.h" -#include "video_out.h" -#include "alphablend.h" +#include <xine/xine_internal.h> +#include <xine/video_out.h> +#include <xine/alphablend.h> #include "bswap.h" diff --git a/src/xine-engine/alphablend.h b/src/xine-engine/alphablend.h deleted file mode 100644 index 86cc68302..000000000 --- a/src/xine-engine/alphablend.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * - * Copyright (C) 2000 Thomas Mirlacher - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA. - * - * The author may be reached as <dent@linuxvideo.org> - * - *------------------------------------------------------------ - * - */ - -#ifndef __ALPHABLEND_H__ -#define __ALPHABLEND_H__ - -#include "video_out.h" - -typedef struct { - void *buffer; - int buffer_size; - - int disable_exact_blending; - - int offset_x, offset_y; -} alphablend_t; - -void _x_alphablend_init(alphablend_t *extra_data, xine_t *xine) XINE_PROTECTED; -void _x_alphablend_free(alphablend_t *extra_data) XINE_PROTECTED; - -#if !SUPPORT_ATTRIBUTE_PACKED -#pragma pack(8) -#endif - -typedef struct { /* CLUT == Color LookUp Table */ - uint8_t cb; - uint8_t cr; - uint8_t y; - uint8_t foo; -} XINE_PACKED clut_t; - - -#if !SUPPORT_ATTRIBUTE_PACKED -#pragma pack() -#endif - -#define XX44_PALETTE_SIZE 32 - -typedef struct { - unsigned size; - unsigned max_used; - uint32_t cluts[XX44_PALETTE_SIZE]; - /* cache palette entries for both colors and hili_colors */ - int lookup_cache[OVL_PALETTE_SIZE*2]; -} xx44_palette_t; - - -void _x_blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, - int img_width, int img_height, - int dst_width, int dst_height, - alphablend_t *extra_data) XINE_PROTECTED; - -void _x_blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl, - int img_width, int img_height, - int dst_width, int dst_height, - alphablend_t *extra_data) XINE_PROTECTED; - -void _x_blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl, - int img_width, int img_height, - int dst_width, int dst_height, - alphablend_t *extra_data) XINE_PROTECTED; - -void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, - int dst_width, int dst_height, int dst_pitches[3], - alphablend_t *extra_data) XINE_PROTECTED; - -void _x_blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, - int dst_width, int dst_height, int dst_pitch, - alphablend_t *extra_data) XINE_PROTECTED; - -/* - * This function isn't too smart about blending. We want to avoid creating new - * colors in the palette as a result from two non-zero colors needed to be - * blended. Instead we choose the color with the highest alpha value to be - * visible. Some parts of the code taken from the "VeXP" project. - */ - -void _x_blend_xx44 (uint8_t *dst_img, vo_overlay_t *img_overl, - int dst_width, int dst_height, int dst_pitch, - alphablend_t *extra_data, - xx44_palette_t *palette,int ia44) XINE_PROTECTED; - -/* - * Functions to handle the xine-specific palette. - */ - -void _x_clear_xx44_palette(xx44_palette_t *p) XINE_PROTECTED; -void _x_init_xx44_palette(xx44_palette_t *p, unsigned num_entries) XINE_PROTECTED; -void _x_dispose_xx44_palette(xx44_palette_t *p) XINE_PROTECTED; - -/* - * Convert the xine-specific palette to something useful. - */ - -void _x_xx44_to_xvmc_palette(const xx44_palette_t *p,unsigned char *xvmc_palette, - unsigned first_xx44_entry, unsigned num_xx44_entries, - unsigned num_xvmc_components, char *xvmc_components) XINE_PROTECTED; - - -#endif diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c index 10c20f231..39604ee9b 100644 --- a/src/xine-engine/audio_decoder.c +++ b/src/xine-engine/audio_decoder.c @@ -39,8 +39,9 @@ #define LOG */ -#include "xine_internal.h" -#include "xineutils.h" +#include <xine/xine_internal.h> +#include <xine/xineutils.h> +#include "xine_private.h" static void *audio_decoder_loop (void *stream_gen) { diff --git a/src/xine-engine/audio_decoder.h b/src/xine-engine/audio_decoder.h deleted file mode 100644 index 9f695685f..000000000 --- a/src/xine-engine/audio_decoder.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2000-2004 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * xine audio decoder plugin interface - */ - -#ifndef HAVE_AUDIO_DECODER_H -#define HAVE_AUDIO_DECODER_H - -#ifdef XINE_COMPILE -# include <inttypes.h> -# include "buffer.h" -#else -# include <xine/os_types.h> -# include <xine/buffer.h> -#endif - -#define AUDIO_DECODER_IFACE_VERSION 15 - -/* - * generic xine audio decoder plugin interface - */ - -typedef struct audio_decoder_class_s audio_decoder_class_t; -typedef struct audio_decoder_s audio_decoder_t; - -struct audio_decoder_class_s { - - /* - * open a new instance of this plugin class - */ - audio_decoder_t* (*open_plugin) (audio_decoder_class_t *this, xine_stream_t *stream); - - /* - * return short, human readable identifier for this plugin class - */ - char* (*get_identifier) (audio_decoder_class_t *this); - - /* - * return human readable (verbose = 1 line) description for - * this plugin class - */ - char* (*get_description) (audio_decoder_class_t *this); - - /* - * free all class-related resources - */ - - void (*dispose) (audio_decoder_class_t *this); -}; - - -struct audio_decoder_s { - - /* - * decode data from buf and feed decoded samples to - * audio output - */ - void (*decode_data) (audio_decoder_t *this, buf_element_t *buf); - - /* - * reset decoder after engine flush (prepare for new - * audio data not related to recently decoded data) - */ - void (*reset) (audio_decoder_t *this); - - /* - * inform decoder that a time reference discontinuity has happened. - * that is, it must forget any currently held pts value - */ - void (*discontinuity) (audio_decoder_t *this); - - /* - * close down, free all resources - */ - void (*dispose) (audio_decoder_t *this); - - void *node; /* used by plugin loader */ - -}; - -#endif diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index b9738595b..4b2398bef 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -16,14 +16,18 @@ * You should have received a copy of the GNU General Public License * along with self program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * 22-8-2001 James imported some useful AC3 sections from the previous alsa driver. - * (c) 2001 Andy Lo A Foe <andy@alsaplayer.org> - * 20-8-2001 First implementation of Audio sync and Audio driver separation. - * (c) 2001 James Courtier-Dutton James@superbug.demon.co.uk */ -/* +/** + * @file + * @brief xine-lib audio output implementation + * + * @date 2001-08-20 First implementation of Audio sync and Audio driver separation. + * (c) 2001 James Courtier-Dutton <james@superbug.demon.co.uk> + * @date 2001-08-22 James imported some useful AC3 sections from the previous + * ALSA driver. (c) 2001 Andy Lo A Foe <andy@alsaplayer.org> + * + * * General Programming Guidelines: - * New concept of an "audio_frame". * An audio_frame consists of all the samples required to fill every @@ -85,11 +89,11 @@ #define LOG_RESAMPLE_SYNC 0 -#include "xine_internal.h" -#include "xineutils.h" -#include "audio_out.h" -#include "resample.h" -#include "metronom.h" +#include <xine/xine_internal.h> +#include <xine/xineutils.h> +#include <xine/audio_out.h> +#include <xine/resample.h> +#include <xine/metronom.h> #define NUM_AUDIO_BUFFERS 32 @@ -287,6 +291,7 @@ struct audio_fifo_s { pthread_cond_t empty; int num_buffers; + int num_buffers_max; }; static int ao_get_property (xine_audio_port_t *this_gen, int property); @@ -301,9 +306,10 @@ static audio_fifo_t *XINE_MALLOC fifo_new (xine_t *xine) { if (!fifo) return NULL; - fifo->first = NULL; - fifo->last = NULL; - fifo->num_buffers = 0; + fifo->first = NULL; + fifo->last = NULL; + fifo->num_buffers = 0; + fifo->num_buffers_max = 0; pthread_mutex_init (&fifo->mutex, NULL); pthread_cond_init (&fifo->not_empty, NULL); pthread_cond_init (&fifo->empty, NULL); @@ -330,6 +336,10 @@ static void fifo_append_int (audio_fifo_t *fifo, fifo->num_buffers++; } + + if (fifo->num_buffers_max < fifo->num_buffers) + fifo->num_buffers_max = fifo->num_buffers; + pthread_cond_signal (&fifo->not_empty); } @@ -589,18 +599,16 @@ static void audio_filter_compress (aos_t *this, int16_t *mem, int num_frames) { } static void audio_filter_amp (aos_t *this, void *buf, int num_frames) { - - int i; - int num_channels; double amp_factor; + int i; + const int total_frames = num_frames * _x_ao_mode2channels (this->input.mode); - num_channels = _x_ao_mode2channels (this->input.mode); - if (!num_channels) + if (!total_frames) return; amp_factor=this->amp_factor; if (this->amp_mute || amp_factor == 0) { - memset (buf, 0, num_frames * num_channels * (this->input.bits / 8)); + memset (buf, 0, total_frames * (this->input.bits / 8)); return; } @@ -608,7 +616,7 @@ static void audio_filter_amp (aos_t *this, void *buf, int num_frames) { int16_t test; int8_t *mem = (int8_t *) buf; - for (i=0; i<num_frames*num_channels; i++) { + for (i=0; i<total_frames; i++) { test = mem[i] * amp_factor; /* Force limit on amp_factor to prevent clipping */ if (test < INT8_MIN) { @@ -625,7 +633,7 @@ static void audio_filter_amp (aos_t *this, void *buf, int num_frames) { int32_t test; int16_t *mem = (int16_t *) buf; - for (i=0; i<num_frames*num_channels; i++) { + for (i=0; i<total_frames; i++) { test = mem[i] * amp_factor; /* Force limit on amp_factor to prevent clipping */ if (test < INT16_MIN) { @@ -1777,6 +1785,14 @@ static int ao_get_property (xine_audio_port_t *this_gen, int property) { ret = this->audio_loop_running ? this->out_fifo->num_buffers : -1; break; + case AO_PROP_BUFS_FREE: + ret = this->audio_loop_running ? this->free_fifo->num_buffers : -1; + break; + + case AO_PROP_BUFS_TOTAL: + ret = this->audio_loop_running ? this->free_fifo->num_buffers_max : -1; + break; + case AO_PROP_NUM_STREAMS: pthread_mutex_lock(&this->streams_lock); ret = xine_list_size(this->streams); @@ -2077,8 +2093,8 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, int i, err; pthread_attr_t pth_attrs; pthread_mutexattr_t attr; - static const char* resample_modes[] = {"auto", "off", "on", NULL}; - static const char* av_sync_methods[] = {"metronom feedback", "resample", NULL}; + static const char *const resample_modes[] = {"auto", "off", "on", NULL}; + static const char *const av_sync_methods[] = {"metronom feedback", "resample", NULL}; this = calloc(1, sizeof(aos_t)) ; diff --git a/src/xine-engine/audio_out.h b/src/xine-engine/audio_out.h deleted file mode 100644 index 832c65a9e..000000000 --- a/src/xine-engine/audio_out.h +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (C) 2000-2004 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - */ -#ifndef HAVE_AUDIO_OUT_H -#define HAVE_AUDIO_OUT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(XINE_COMPILE) -#include <inttypes.h> -#include "metronom.h" -#include "configfile.h" -#include "xineutils.h" -#else -#include <xine/os_types.h> -#include <xine/metronom.h> -#include <xine/configfile.h> -#include <xine/xineutils.h> -#endif - - -#define AUDIO_OUT_IFACE_VERSION 8 - -/* - * ao_driver_s contains the driver every audio output - * driver plugin has to implement. - */ - -typedef struct ao_driver_s ao_driver_t; - -struct ao_driver_s { - - /* - * - * find out what output modes + capatilities are supported by - * this plugin (constants for the bit vector to return see above) - * - * See AO_CAP_* bellow. - */ - uint32_t (*get_capabilities) (ao_driver_t *); - - /* - * open the driver and make it ready to receive audio data - * buffers may be flushed(!) - * - * return value: 0 : failure, >0 : output sample rate - */ - int (*open)(ao_driver_t *, uint32_t bits, uint32_t rate, int mode); - - /* return the number of audio channels - */ - int (*num_channels)(ao_driver_t *self_gen); - - /* return the number of bytes per frame. - * A frame is equivalent to one sample being output on every audio channel. - */ - int (*bytes_per_frame)(ao_driver_t *self_gen); - - /* return the delay is frames measured by - * looking at pending samples in the audio output device - */ - int (*delay)(ao_driver_t *self_gen); - - /* - * return gap tolerance (in pts) needed for this driver - */ - int (*get_gap_tolerance) (ao_driver_t *self_gen); - - /* - * write audio data to audio output device - * return value: - * >0 => audio samples were processed ok - * 0 => audio samples were not yet processed, - * call write_audio_data with the _same_ samples again - */ - int (*write)(ao_driver_t *, - int16_t* audio_data, uint32_t num_samples); - - /* - * this is called when the decoder no longer uses the audio - * output driver - the driver should get ready to get opened() again - */ - void (*close)(ao_driver_t *); - - /* - * shut down this audio output driver plugin and - * free all resources allocated - */ - void (*exit) (ao_driver_t *); - - /* - * Get, Set a property of audio driver. - * - * get_property() return 1 in success, 0 on failure. - * set_property() return value on success, ~value on failure. - * - * See AO_PROP_* below for available properties. - */ - int (*get_property) (ao_driver_t *, int property); - - int (*set_property) (ao_driver_t *, int property, int value); - - - /* - * misc control operations on the audio device. - * - * See AO_CTRL_* below. - */ - int (*control) (ao_driver_t *, int cmd, /* arg */ ...); - - void *node; -}; - -typedef struct ao_format_s ao_format_t; - -struct ao_format_s { - uint32_t bits; - uint32_t rate; - int mode; -}; - -typedef struct audio_fifo_s audio_fifo_t; - -typedef struct audio_buffer_s audio_buffer_t; - -struct audio_buffer_s { - - audio_buffer_t *next; - - int16_t *mem; - int mem_size; - int num_frames; - - int64_t vpts; - uint32_t frame_header_count; - uint32_t first_access_unit; - - /* extra info coming from input or demuxers */ - extra_info_t *extra_info; - - xine_stream_t *stream; /* stream that send that buffer */ - - ao_format_t format; /* let each buffer carry it's own format info */ -}; - -/* - * xine_audio_port_s contains the port every audio decoder talks to - * - * Remember that adding new functions to this structure requires - * adaption of the post plugin decoration layer. Be sure to look into - * src/xine-engine/post.[ch]. - */ - -struct xine_audio_port_s { - uint32_t (*get_capabilities) (xine_audio_port_t *); /* for constants see below */ - - /* * Get/Set audio property - * - * See AO_PROP_* bellow - */ - int (*get_property) (xine_audio_port_t *, int property); - int (*set_property) (xine_audio_port_t *, int property, int value); - - /* open audio driver for audio output - * return value: 0:failure, >0:output sample rate - */ - /* when you are not a full-blown stream, but still need to open the port - * (e.g. you are a post plugin) it is legal to pass an anonymous stream */ - int (*open) (xine_audio_port_t *, xine_stream_t *stream, - uint32_t bits, uint32_t rate, int mode); - - /* - * get a piece of memory for audio data - */ - audio_buffer_t * (*get_buffer) (xine_audio_port_t *); - - /* - * append a buffer filled with audio data to the audio fifo - * for output - */ - /* when the frame does not originate from a stream, it is legal to pass an anonymous stream */ - void (*put_buffer) (xine_audio_port_t *, audio_buffer_t *buf, xine_stream_t *stream); - - /* audio driver is no longer used by decoder => close */ - /* when you are not a full-blown stream, but still need to close the port - * (e.g. you are a post plugin) it is legal to pass an anonymous stream */ - void (*close) (xine_audio_port_t *self, xine_stream_t *stream); - - /* called on xine exit */ - void (*exit) (xine_audio_port_t *); - - /* - * misc control operations on the audio device. - * - * See AO_CTRL_* below. - */ - int (*control) (xine_audio_port_t *, int cmd, /* arg */ ...); - - /* - * Flush audio_out fifo. - */ - void (*flush) (xine_audio_port_t *); - - /* - * Check if port is opened for this stream and get parameters. - * The stream can be anonymous. - */ - int (*status) (xine_audio_port_t *, xine_stream_t *stream, - uint32_t *bits, uint32_t *rate, int *mode); - -}; - -typedef struct audio_driver_class_s audio_driver_class_t; - -struct audio_driver_class_s { - - /* - * open a new instance of this plugin class - */ - ao_driver_t* (*open_plugin) (audio_driver_class_t *, const void *data); - - /* - * return short, human readable identifier for this plugin class - */ - char* (*get_identifier) (audio_driver_class_t *); - - /* - * return human readable (verbose = 1 line) description for - * this plugin class - */ - char* (*get_description) (audio_driver_class_t *); - - /* - * free all class-related resources - */ - - void (*dispose) (audio_driver_class_t *); -}; - -/* - * this initiates the audio_out sync routines - * found in ./src/xine-engine/audio_out.c - */ -xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, int grab_only) XINE_MALLOC XINE_PROTECTED; - -/* - * audio output modes + capabilities - */ - -#define AO_CAP_NOCAP 0x00000000 /* driver has no capabilities */ -#define AO_CAP_MODE_A52 0x00000001 /* driver supports A/52 output */ -#define AO_CAP_MODE_AC5 0x00000002 /* driver supports AC5 output */ -/* 1 sample == 2 bytes (C) */ -#define AO_CAP_MODE_MONO 0x00000004 /* driver supports mono output */ -/* 1 sample == 4 bytes (L,R) */ -#define AO_CAP_MODE_STEREO 0x00000008 /* driver supports stereo output */ -/* 1 sample == 8 bytes (L,R,LR,RR) */ -#define AO_CAP_MODE_4CHANNEL 0x00000010 /* driver supports 4 channels */ -/* - * Sound cards generally support, 1,2,4,6 channels, but rarely 5. - * So xine will take 4.1, 5 and 6 channel a52 streams and - * down or upmix it correctly to fill the 6 output channels. - * Are there any requests for 2.1 out there? - */ -/* 1 sample == 12 bytes (L,R,LR,RR,Null,LFE) */ -#define AO_CAP_MODE_4_1CHANNEL 0x00000020 /* driver supports 4.1 channels */ -/* 1 sample == 12 bytes (L,R,LR,RR,C, Null) */ -#define AO_CAP_MODE_5CHANNEL 0x00000040 /* driver supports 5 channels */ -/* 1 sample == 12 bytes (L,R,LR,RR,C,LFE) */ -#define AO_CAP_MODE_5_1CHANNEL 0x00000080 /* driver supports 5.1 channels */ - -/* - * converts the audio output mode into the number of channels - */ -int _x_ao_mode2channels( int mode ) XINE_PROTECTED; -/* - * converts the number of channels into the audio output mode - */ -int _x_ao_channels2mode( int channels ) XINE_PROTECTED; - -#define AO_CAP_MIXER_VOL 0x00000100 /* driver supports mixer control */ -#define AO_CAP_PCM_VOL 0x00000200 /* driver supports pcm control */ -#define AO_CAP_MUTE_VOL 0x00000400 /* driver can mute volume */ -#define AO_CAP_8BITS 0x00000800 /* driver support 8-bit samples */ -#define AO_CAP_16BITS 0x00001000 /* driver support 16-bit samples */ -#define AO_CAP_24BITS 0x00002000 /* driver support 24-bit samples */ -#define AO_CAP_FLOAT32 0x00004000 /* driver support 32-bit samples. i.e. Floats */ - -/* properties supported by get/set_property() */ -#define AO_PROP_MIXER_VOL 0 -#define AO_PROP_PCM_VOL 1 -#define AO_PROP_MUTE_VOL 2 -#define AO_PROP_COMPRESSOR 3 -#define AO_PROP_DISCARD_BUFFERS 4 -#define AO_PROP_BUFS_IN_FIFO 5 /* read-only */ -#define AO_PROP_AMP 6 /* amplifier */ -#define AO_PROP_EQ_30HZ 7 /* equalizer */ -#define AO_PROP_EQ_60HZ 8 /* equalizer */ -#define AO_PROP_EQ_125HZ 9 /* equalizer */ -#define AO_PROP_EQ_250HZ 10 /* equalizer */ -#define AO_PROP_EQ_500HZ 11 /* equalizer */ -#define AO_PROP_EQ_1000HZ 12 /* equalizer */ -#define AO_PROP_EQ_2000HZ 13 /* equalizer */ -#define AO_PROP_EQ_4000HZ 14 /* equalizer */ -#define AO_PROP_EQ_8000HZ 15 /* equalizer */ -#define AO_PROP_EQ_16000HZ 16 /* equalizer */ -#define AO_PROP_CLOSE_DEVICE 17 /* force closing audio device */ -#define AO_PROP_AMP_MUTE 18 /* amplifier mute */ -#define AO_PROP_NUM_STREAMS 19 /* read-only */ -#define AO_PROP_CLOCK_SPEED 20 /* inform audio_out that speed has changed */ -#define AO_NUM_PROPERTIES 21 - -/* audio device control ops */ -#define AO_CTRL_PLAY_PAUSE 0 -#define AO_CTRL_PLAY_RESUME 1 -#define AO_CTRL_FLUSH_BUFFERS 2 - -/* above that value audio frames are discarded */ -#define AO_MAX_GAP 15000 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/xine-engine/broadcaster.c b/src/xine-engine/broadcaster.c index 435ec2df6..0c2f2d4b2 100644 --- a/src/xine-engine/broadcaster.c +++ b/src/xine-engine/broadcaster.c @@ -61,9 +61,9 @@ #include <dlfcn.h> #include <pthread.h> -#include "xine_internal.h" -#include "buffer.h" -#include "xineutils.h" +#include <xine/xine_internal.h> +#include <xine/buffer.h> +#include <xine/xineutils.h> #include "xine_private.h" #define QLEN 5 /* maximum connection queue length */ @@ -113,9 +113,10 @@ static int sock_check_opened(int socket) { /* * Write to socket. */ -static int sock_data_write(xine_t *xine, int socket, char *buf, int len) { +static int sock_data_write(xine_t *xine, int socket, void *buf_gen, int len) { ssize_t size; int wlen = 0; + uint8_t *buf = buf_gen; if((socket < 0) || (buf == NULL)) return -1; @@ -140,7 +141,7 @@ static int sock_data_write(xine_t *xine, int socket, char *buf, int len) { } static int XINE_FORMAT_PRINTF(3, 4) -sock_string_write(xine_t *xine, int socket, char *msg, ...) { +sock_string_write(xine_t *xine, int socket, const char *msg, ...) { char buf[_BUFSIZ]; va_list args; @@ -159,7 +160,7 @@ sock_string_write(xine_t *xine, int socket, char *msg, ...) { * this is the most important broadcaster function. * it sends data to every connected client (slaves). */ -static void broadcaster_data_write(broadcaster_t *this, char *buf, int len) { +static void broadcaster_data_write(broadcaster_t *this, void *buf, int len) { xine_list_iterator_t ite; ite = xine_list_front (this->connections); @@ -182,7 +183,7 @@ static void broadcaster_data_write(broadcaster_t *this, char *buf, int len) { } static void XINE_FORMAT_PRINTF(2, 3) -broadcaster_string_write(broadcaster_t *this, char *msg, ...) { +broadcaster_string_write(broadcaster_t *this, const char *msg, ...) { char buf[_BUFSIZ]; va_list args; @@ -254,7 +255,7 @@ static void *manager_loop (void *this_gen) { /* * receive xine buffers and send them through the broadcaster */ -static void send_buf (broadcaster_t *this, char *from, buf_element_t *buf) { +static void send_buf (broadcaster_t *this, const char *from, buf_element_t *buf) { int i; /* ignore END buffers since they would stop the slavery */ diff --git a/src/xine-engine/buffer.c b/src/xine-engine/buffer.c index 77c0abc9d..50ffb57cd 100644 --- a/src/xine-engine/buffer.c +++ b/src/xine-engine/buffer.c @@ -36,6 +36,12 @@ #include <stdlib.h> #include <assert.h> +#ifdef HAVE_FFMPEG_AVUTIL_H +# include <mem.h> +#else +# include <libavutil/mem.h> +#endif + /********** logging **********/ #define LOG_MODULE "buffer" #define LOG_VERBOSE @@ -43,9 +49,9 @@ #define LOG */ -#include "buffer.h" -#include "xineutils.h" -#include "xine_internal.h" +#include <xine/buffer.h> +#include <xine/xineutils.h> +#include <xine/xine_internal.h> /* * put a previously allocated buffer element back into the buffer pool @@ -358,7 +364,7 @@ static void fifo_buffer_dispose (fifo_buffer_t *this) { received++; } - free (this->buffer_pool_base); + av_free (this->buffer_pool_base); pthread_mutex_destroy(&this->mutex); pthread_cond_destroy(&this->not_empty); pthread_mutex_destroy(&this->buffer_pool_mutex); @@ -497,7 +503,6 @@ fifo_buffer_t *_x_fifo_buffer_new (int num_buffers, uint32_t buf_size) { fifo_buffer_t *this; int i; - int alignment = 2048; unsigned char *multi_buffer = NULL; this = calloc(1, sizeof(fifo_buffer_t)); @@ -527,15 +532,11 @@ fifo_buffer_t *_x_fifo_buffer_new (int num_buffers, uint32_t buf_size) { */ - if (buf_size % alignment != 0) - buf_size += alignment - (buf_size % alignment); - /* - printf ("Allocating %d buffers of %ld bytes in one chunk (alignment = %d)\n", - num_buffers, (long int) buf_size, alignment); + printf ("Allocating %d buffers of %ld bytes in one chunk\n", + num_buffers, (long int) buf_size); */ - multi_buffer = xine_xmalloc_aligned (alignment, num_buffers * buf_size, - &this->buffer_pool_base); + multi_buffer = this->buffer_pool_base = av_mallocz (num_buffers * buf_size); this->buffer_pool_top = NULL; diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h deleted file mode 100644 index 2c13919b8..000000000 --- a/src/xine-engine/buffer.h +++ /dev/null @@ -1,698 +0,0 @@ -/* - * Copyright (C) 2000-2008 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - * contents: - * - * buffer_entry structure - serves as a transport encapsulation - * of the mpeg audio/video data through xine - * - * free buffer pool management routines - * - * FIFO buffer structures/routines - */ - -#ifndef HAVE_BUFFER_H -#define HAVE_BUFFER_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <string.h> -#include <stdio.h> -#include <pthread.h> -#include <sys/types.h> - -#ifdef XINE_COMPILE -# include <inttypes.h> -# include "attributes.h" -#else -# include <xine/os_types.h> -# include <xine/attributes.h> -#endif - -#define BUF_MAX_CALLBACKS 5 - -/* - * buffer types - * - * a buffer type ID describes the contents of a buffer - * it consists of three fields: - * - * buf_type = 0xMMDDCCCC - * - * MM : major buffer type (CONTROL, VIDEO, AUDIO, SPU) - * DD : decoder selection (e.g. MPEG, OPENDIVX ... for VIDEO) - * CCCC : channel number or other subtype information for the decoder - */ - -#define BUF_MAJOR_MASK 0xFF000000 -#define BUF_DECODER_MASK 0x00FF0000 - -/* control buffer types */ - -#define BUF_CONTROL_BASE 0x01000000 -#define BUF_CONTROL_START 0x01000000 -#define BUF_CONTROL_END 0x01010000 -#define BUF_CONTROL_QUIT 0x01020000 -#define BUF_CONTROL_DISCONTINUITY 0x01030000 /* former AVSYNC_RESET */ -#define BUF_CONTROL_NOP 0x01040000 -#define BUF_CONTROL_AUDIO_CHANNEL 0x01050000 -#define BUF_CONTROL_SPU_CHANNEL 0x01060000 -#define BUF_CONTROL_NEWPTS 0x01070000 -#define BUF_CONTROL_RESET_DECODER 0x01080000 -#define BUF_CONTROL_HEADERS_DONE 0x01090000 -#define BUF_CONTROL_FLUSH_DECODER 0x010a0000 -#define BUF_CONTROL_RESET_TRACK_MAP 0x010b0000 - -/* video buffer types: (please keep in sync with buffer_types.c) */ - -#define BUF_VIDEO_BASE 0x02000000 -#define BUF_VIDEO_UNKNOWN 0x02ff0000 /* no decoder should handle this one */ -#define BUF_VIDEO_MPEG 0x02000000 -#define BUF_VIDEO_MPEG4 0x02010000 -#define BUF_VIDEO_CINEPAK 0x02020000 -#define BUF_VIDEO_SORENSON_V1 0x02030000 -#define BUF_VIDEO_MSMPEG4_V2 0x02040000 -#define BUF_VIDEO_MSMPEG4_V3 0x02050000 -#define BUF_VIDEO_MJPEG 0x02060000 -#define BUF_VIDEO_IV50 0x02070000 -#define BUF_VIDEO_IV41 0x02080000 -#define BUF_VIDEO_IV32 0x02090000 -#define BUF_VIDEO_IV31 0x020a0000 -#define BUF_VIDEO_ATIVCR1 0x020b0000 -#define BUF_VIDEO_ATIVCR2 0x020c0000 -#define BUF_VIDEO_I263 0x020d0000 -#define BUF_VIDEO_RV10 0x020e0000 -#define BUF_VIDEO_RGB 0x02100000 -#define BUF_VIDEO_YUY2 0x02110000 -#define BUF_VIDEO_JPEG 0x02120000 -#define BUF_VIDEO_WMV7 0x02130000 -#define BUF_VIDEO_WMV8 0x02140000 -#define BUF_VIDEO_MSVC 0x02150000 -#define BUF_VIDEO_DV 0x02160000 -#define BUF_VIDEO_REAL 0x02170000 -#define BUF_VIDEO_VP31 0x02180000 -#define BUF_VIDEO_H263 0x02190000 -#define BUF_VIDEO_3IVX 0x021A0000 -#define BUF_VIDEO_CYUV 0x021B0000 -#define BUF_VIDEO_DIVX5 0x021C0000 -#define BUF_VIDEO_XVID 0x021D0000 -#define BUF_VIDEO_SMC 0x021E0000 -#define BUF_VIDEO_RPZA 0x021F0000 -#define BUF_VIDEO_QTRLE 0x02200000 -#define BUF_VIDEO_MSRLE 0x02210000 -#define BUF_VIDEO_DUCKTM1 0x02220000 -#define BUF_VIDEO_FLI 0x02230000 -#define BUF_VIDEO_ROQ 0x02240000 -#define BUF_VIDEO_SORENSON_V3 0x02250000 -#define BUF_VIDEO_MSMPEG4_V1 0x02260000 -#define BUF_VIDEO_MSS1 0x02270000 -#define BUF_VIDEO_IDCIN 0x02280000 -#define BUF_VIDEO_PGVV 0x02290000 -#define BUF_VIDEO_ZYGO 0x022A0000 -#define BUF_VIDEO_TSCC 0x022B0000 -#define BUF_VIDEO_YVU9 0x022C0000 -#define BUF_VIDEO_VQA 0x022D0000 -#define BUF_VIDEO_GREY 0x022E0000 -#define BUF_VIDEO_XXAN 0x022F0000 -#define BUF_VIDEO_WC3 0x02300000 -#define BUF_VIDEO_YV12 0x02310000 -#define BUF_VIDEO_SEGA 0x02320000 -#define BUF_VIDEO_RV20 0x02330000 -#define BUF_VIDEO_RV30 0x02340000 -#define BUF_VIDEO_MVI2 0x02350000 -#define BUF_VIDEO_UCOD 0x02360000 -#define BUF_VIDEO_WMV9 0x02370000 -#define BUF_VIDEO_INTERPLAY 0x02380000 -#define BUF_VIDEO_RV40 0x02390000 -#define BUF_VIDEO_PSX_MDEC 0x023A0000 -#define BUF_VIDEO_YUV_FRAMES 0x023B0000 /* uncompressed YUV, delivered by v4l input plugin */ -#define BUF_VIDEO_HUFFYUV 0x023C0000 -#define BUF_VIDEO_IMAGE 0x023D0000 -#define BUF_VIDEO_THEORA 0x023E0000 -#define BUF_VIDEO_4XM 0x023F0000 -#define BUF_VIDEO_I420 0x02400000 -#define BUF_VIDEO_VP4 0x02410000 -#define BUF_VIDEO_VP5 0x02420000 -#define BUF_VIDEO_VP6 0x02430000 -#define BUF_VIDEO_VMD 0x02440000 -#define BUF_VIDEO_MSZH 0x02450000 -#define BUF_VIDEO_ZLIB 0x02460000 -#define BUF_VIDEO_8BPS 0x02470000 -#define BUF_VIDEO_ASV1 0x02480000 -#define BUF_VIDEO_ASV2 0x02490000 -#define BUF_VIDEO_BITPLANE 0x024A0000 /* Amiga typical picture and animation format */ -#define BUF_VIDEO_BITPLANE_BR1 0x024B0000 /* the same with Bytrun compression 1 */ -#define BUF_VIDEO_FLV1 0x024C0000 -#define BUF_VIDEO_H264 0x024D0000 -#define BUF_VIDEO_MJPEG_B 0x024E0000 -#define BUF_VIDEO_H261 0x024F0000 -#define BUF_VIDEO_AASC 0x02500000 -#define BUF_VIDEO_LOCO 0x02510000 -#define BUF_VIDEO_QDRW 0x02520000 -#define BUF_VIDEO_QPEG 0x02530000 -#define BUF_VIDEO_ULTI 0x02540000 -#define BUF_VIDEO_WNV1 0x02550000 -#define BUF_VIDEO_XL 0x02560000 -#define BUF_VIDEO_RT21 0x02570000 -#define BUF_VIDEO_FPS1 0x02580000 -#define BUF_VIDEO_DUCKTM2 0x02590000 -#define BUF_VIDEO_CSCD 0x025A0000 -#define BUF_VIDEO_ALGMM 0x025B0000 -#define BUF_VIDEO_ZMBV 0x025C0000 -#define BUF_VIDEO_AVS 0x025D0000 -#define BUF_VIDEO_SMACKER 0x025E0000 -#define BUF_VIDEO_NUV 0x025F0000 -#define BUF_VIDEO_KMVC 0x02600000 -#define BUF_VIDEO_FLASHSV 0x02610000 -#define BUF_VIDEO_CAVS 0x02620000 -#define BUF_VIDEO_VP6F 0x02630000 -#define BUF_VIDEO_THEORA_RAW 0x02640000 -#define BUF_VIDEO_VC1 0x02650000 -#define BUF_VIDEO_VMNC 0x02660000 -#define BUF_VIDEO_SNOW 0x02670000 -#define BUF_VIDEO_VP8 0x02680000 - -/* audio buffer types: (please keep in sync with buffer_types.c) */ - -#define BUF_AUDIO_BASE 0x03000000 -#define BUF_AUDIO_UNKNOWN 0x03ff0000 /* no decoder should handle this one */ -#define BUF_AUDIO_A52 0x03000000 -#define BUF_AUDIO_MPEG 0x03010000 -#define BUF_AUDIO_LPCM_BE 0x03020000 -#define BUF_AUDIO_LPCM_LE 0x03030000 -#define BUF_AUDIO_WMAV1 0x03040000 -#define BUF_AUDIO_DTS 0x03050000 -#define BUF_AUDIO_MSADPCM 0x03060000 -#define BUF_AUDIO_MSIMAADPCM 0x03070000 -#define BUF_AUDIO_MSGSM 0x03080000 -#define BUF_AUDIO_VORBIS 0x03090000 -#define BUF_AUDIO_IMC 0x030a0000 -#define BUF_AUDIO_LH 0x030b0000 -#define BUF_AUDIO_VOXWARE 0x030c0000 -#define BUF_AUDIO_ACELPNET 0x030d0000 -#define BUF_AUDIO_AAC 0x030e0000 -#define BUF_AUDIO_DNET 0x030f0000 -#define BUF_AUDIO_VIVOG723 0x03100000 -#define BUF_AUDIO_DK3ADPCM 0x03110000 -#define BUF_AUDIO_DK4ADPCM 0x03120000 -#define BUF_AUDIO_ROQ 0x03130000 -#define BUF_AUDIO_QTIMAADPCM 0x03140000 -#define BUF_AUDIO_MAC3 0x03150000 -#define BUF_AUDIO_MAC6 0x03160000 -#define BUF_AUDIO_QDESIGN1 0x03170000 -#define BUF_AUDIO_QDESIGN2 0x03180000 -#define BUF_AUDIO_QCLP 0x03190000 -#define BUF_AUDIO_SMJPEG_IMA 0x031A0000 -#define BUF_AUDIO_VQA_IMA 0x031B0000 -#define BUF_AUDIO_MULAW 0x031C0000 -#define BUF_AUDIO_ALAW 0x031D0000 -#define BUF_AUDIO_GSM610 0x031E0000 -#define BUF_AUDIO_EA_ADPCM 0x031F0000 -#define BUF_AUDIO_WMAV2 0x03200000 -#define BUF_AUDIO_COOK 0x03210000 -#define BUF_AUDIO_ATRK 0x03220000 -#define BUF_AUDIO_14_4 0x03230000 -#define BUF_AUDIO_28_8 0x03240000 -#define BUF_AUDIO_SIPRO 0x03250000 -#define BUF_AUDIO_WMAPRO 0x03260000 -#define BUF_AUDIO_WMAV3 BUF_AUDIO_WMAPRO -#define BUF_AUDIO_INTERPLAY 0x03270000 -#define BUF_AUDIO_XA_ADPCM 0x03280000 -#define BUF_AUDIO_WESTWOOD 0x03290000 -#define BUF_AUDIO_DIALOGIC_IMA 0x032A0000 -#define BUF_AUDIO_NSF 0x032B0000 -#define BUF_AUDIO_FLAC 0x032C0000 -#define BUF_AUDIO_DV 0x032D0000 -#define BUF_AUDIO_WMAV 0x032E0000 -#define BUF_AUDIO_SPEEX 0x032F0000 -#define BUF_AUDIO_RAWPCM 0x03300000 -#define BUF_AUDIO_4X_ADPCM 0x03310000 -#define BUF_AUDIO_VMD 0x03320000 -#define BUF_AUDIO_XAN_DPCM 0x03330000 -#define BUF_AUDIO_ALAC 0x03340000 -#define BUF_AUDIO_MPC 0x03350000 -#define BUF_AUDIO_SHORTEN 0x03360000 -#define BUF_AUDIO_WESTWOOD_SND1 0x03370000 -#define BUF_AUDIO_WMALL 0x03380000 -#define BUF_AUDIO_TRUESPEECH 0x03390000 -#define BUF_AUDIO_TTA 0x033A0000 -#define BUF_AUDIO_SMACKER 0x033B0000 -#define BUF_AUDIO_FLVADPCM 0x033C0000 -#define BUF_AUDIO_WAVPACK 0x033D0000 -#define BUF_AUDIO_MP3ADU 0x033E0000 -#define BUF_AUDIO_AMR_NB 0x033F0000 -#define BUF_AUDIO_AMR_WB 0x03400000 -#define BUF_AUDIO_EAC3 0x03410000 -#define BUF_AUDIO_AAC_LATM 0x03420000 - -/* spu buffer types: */ - -#define BUF_SPU_BASE 0x04000000 -#define BUF_SPU_DVD 0x04000000 -#define BUF_SPU_TEXT 0x04010000 -#define BUF_SPU_CC 0x04020000 -#define BUF_SPU_DVB 0x04030000 -#define BUF_SPU_SVCD 0x04040000 -#define BUF_SPU_CVD 0x04050000 -#define BUF_SPU_OGM 0x04060000 -#define BUF_SPU_CMML 0x04070000 -#define BUF_SPU_HDMV 0x04080000 - -/* demuxer block types: */ - -#define BUF_DEMUX_BLOCK 0x05000000 - -typedef struct extra_info_s extra_info_t; - -/* - * extra_info_t is used to pass information from input or demuxer plugins - * to output frames (past decoder). new data must be added after the existing - * fields for backward compatibility. - */ - -struct extra_info_s { - - int input_normpos; /* remember where this buf came from in - * the input source (0..65535). can be - * either time or offset based. */ - int input_time; /* time offset in miliseconds from - * beginning of stream */ - uint32_t frame_number; /* number of current frame if known */ - - int seek_count; /* internal engine use */ - int64_t vpts; /* set on output layers only */ - - int invalid; /* do not use this extra info to update anything */ - int total_time; /* duration in miliseconds of the stream */ -}; - - -#define BUF_NUM_DEC_INFO 5 - -typedef struct buf_element_s buf_element_t; -struct buf_element_s { - buf_element_t *next; - - unsigned char *mem; - unsigned char *content; /* start of raw content in mem (without header etc) */ - - int32_t size ; /* size of _content_ */ - int32_t max_size; /* size of pre-allocated memory pointed to by "mem" */ - uint32_t type; - int64_t pts; /* presentation time stamp, used for a/v sync */ - int64_t disc_off; /* discontinuity offset */ - - extra_info_t *extra_info; /* extra info will be passed to frames */ - - uint32_t decoder_flags; /* stuff like keyframe, is_header ... see below */ - - /* additional decoder flags and other dec-spec. stuff */ - uint32_t decoder_info[BUF_NUM_DEC_INFO]; - /* pointers to dec-spec. stuff */ - void *decoder_info_ptr[BUF_NUM_DEC_INFO]; - - void (*free_buffer) (buf_element_t *buf); - - void *source; /* pointer to source of this buffer for */ - /* free_buffer */ - -} ; - -/* keyframe should be set whenever possible (that is, when demuxer - * knows about frames and keyframes). */ -#define BUF_FLAG_KEYFRAME 0x0001 - -/* frame start/end. BUF_FLAG_FRAME_END is sent on last buf of a frame */ -#define BUF_FLAG_FRAME_START 0x0002 -#define BUF_FLAG_FRAME_END 0x0004 - -/* any out-of-band data needed to initialize decoder must have - * this flag set. */ -#define BUF_FLAG_HEADER 0x0008 - -/* preview buffers are normal data buffers that must not produce any - * output in decoders (may be used to sneak details about the stream - * to come). */ -#define BUF_FLAG_PREVIEW 0x0010 - -/* set when user stop the playback */ -#define BUF_FLAG_END_USER 0x0020 - -/* set when stream finished naturaly */ -#define BUF_FLAG_END_STREAM 0x0040 - -/* decoder_info[0] carries the frame step (1/90000). */ -#define BUF_FLAG_FRAMERATE 0x0080 - -/* hint to metronom that seeking has occurred */ -#define BUF_FLAG_SEEK 0x0100 - -/* special information inside, see below. */ -#define BUF_FLAG_SPECIAL 0x0200 - -/* header use standard xine_bmiheader or xine_waveformatex structs. - * xine_waveformatex is actually optional since the most important - * information for audio init is available from decoder_info[]. - * note: BUF_FLAG_HEADER must also be set. */ -#define BUF_FLAG_STDHEADER 0x0400 - -/* decoder_info[1] carries numerator for display aspect ratio - * 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 - * to a video decoder. For example, some file types store palette data in - * the file header independant of the video data. The special buffer type - * offers a way to communicate this or any other custom, format-specific - * data to the decoder. - * - * The interface was designed in a way that did not require an API - * version bump. To send a special buffer type, set a buffer's flags field - * to BUF_FLAG_SPECIAL. Set the buffer's decoder_info[1] field to a - * number according to one of the special buffer subtypes defined below. - * The second and third decoder_info[] fields are defined according to - * your buffer type's requirements. - * - * Finally, remember to set the buffer's size to 0. This way, if a special - * buffer is sent to a decode that does not know how to handle it, the - * buffer will fall through to the case where the buffer's data content - * is accumulated and no harm will be done. - */ - -/* these are the types of special buffers */ - -/* - * In a BUF_SPECIAL_PALETTE buffer: - * decoder_info[1] = BUF_SPECIAL_PALETTE - * decoder_info[2] = number of entries in palette table - * decoder_info_ptr[2] = pointer to palette table - * This buffer type is used to provide a file- and decoder-independent - * facility to transport RGB color palettes from demuxers to decoders. - * A palette table is an array of palette_entry_t structures. A decoder - * should not count on this array to exist for the duration of the - * program's execution and should copy, manipulate, and store the palette - * data privately if it needs the palette information. - */ -#define BUF_SPECIAL_PALETTE 1 - - -/* special buffer type 2 used to be defined but is now available for use */ - - -/* - * In a BUF_SPECIAL_ASPECT buffer: - * decoder_info[1] = BUF_SPECIAL_ASPECT - * decoder_info[2] = MPEG2 aspect ratio code - * decoder_info[3] = stream scale prohibitions - * This buffer is used to force mpeg decoders to use a certain aspect. - * Currently xine-dvdnav uses this, because it has more accurate information - * about the aspect from the dvd ifo-data. - * The stream scale prohibitions are also delivered, with bit 0 meaning - * "deny letterboxing" and bit 1 meaning "deny pan&scan" - */ -#define BUF_SPECIAL_ASPECT 3 - -/* - * In a BUF_SPECIAL_DECODER_CONFIG buffer: - * decoder_info[1] = BUF_SPECIAL_DECODER_CONFIG - * decoder_info[2] = data size - * decoder_info_ptr[2] = pointer to data - * This buffer is used to pass config information from .mp4 files - * (atom esds) to decoders. both mpeg4 and aac streams use that. - */ -#define BUF_SPECIAL_DECODER_CONFIG 4 - -/* - * In a BUF_SPECIAL_STSD_ATOM buffer: - * decoder_info[1] = BUF_SPECIAL_STSD_ATOM - * decoder_info[2] = size of the ImageDescription atom, minus the - * four length bytes at the beginning - * decoder_info_ptr[2] = pointer to ImageDescription atom, starting with - * the codec fourcc - * Some Quicktime decoders need information contained within the - * ImageDescription atom inside a Quicktime file's stsd atom. This - * special buffer carries the ImageDescription atom from the QT demuxer - * to an A/V decoder. - */ -#define BUF_SPECIAL_STSD_ATOM 5 - -/* - * In a BUF_SPECIAL_LPCM_CONFIG buffer: - * decoder_info[1] = BUF_SPECIAL_LPCM_CONFIG - * decoder_info[2] = config data - * lpcm data encoded into mpeg2 streams have a format configuration - * byte in every frame. this is used to detect the sample rate, - * number of bits and channels. - */ -#define BUF_SPECIAL_LPCM_CONFIG 6 - -/* - * In a BUF_SPECIAL_CHARSET_ENCODING buffer: - * decoder_info[1] = BUF_SPECIAL_CHARSET_ENCODING - * decoder_info[2] = size of charset encoding string - * decoder_info_ptr[2] = pointer to charset encoding string - * This is used mostly with subtitle buffers when encoding is - * known at demuxer level (take precedence over xine config - * settings such as subtitles.separate.src_encoding) - */ -#define BUF_SPECIAL_CHARSET_ENCODING 7 - - -/* - * In a BUF_SPECIAL_SPU_DVD_SUBTYPE: - * decoder_info[1] = BUF_SPECIAL_SPU_DVD_SUBTYPE - * decoder_info[2] = subtype - * decoder_info[3] = - * This buffer is pass SPU subtypes from DVDs - */ -#define BUF_SPECIAL_SPU_DVD_SUBTYPE 8 - - -#define SPU_DVD_SUBTYPE_CLUT 1 -#define SPU_DVD_SUBTYPE_PACKAGE 2 -#define SPU_DVD_SUBTYPE_VOBSUB_PACKAGE 3 -#define SPU_DVD_SUBTYPE_NAV 4 - -/* In a BUF_SPECIAL_SPU_DVB_DESCRIPTOR - * decoder_info[1] = BUF_SPECIAL_SPU_DVB_DESCRIPTOR - * decoder_info[2] = size of spu_dvb_descriptor_t - * decoder_info_ptr[2] = pointer to spu_dvb_descriptor_t, or NULL - * decoder_info[3] = - * - * This buffer is used to tell a DVBSUB decoder when the stream - * changes. For more information on how to write a DVBSUB decoder, - * see the comment at the top of src/demuxers/demux_ts.c - **/ -#define BUF_SPECIAL_SPU_DVB_DESCRIPTOR 9 - -/* - * In a BUF_SPECIAL_RV_CHUNK_TABLE: - * decoder_info[1] = BUF_SPECIAL_RV_CHUNK_TABLE - * decoder_info[2] = number of entries in chunk table - * decoder_info_ptr[2] = pointer to the chunk table - * - * This buffer transports the chunk table associated to each RealVideo frame. - */ -#define BUF_SPECIAL_RV_CHUNK_TABLE 10 - -typedef struct spu_dvb_descriptor_s spu_dvb_descriptor_t; -struct spu_dvb_descriptor_s -{ - char lang[4]; - long comp_page_id; - long aux_page_id; -} ; - -typedef struct palette_entry_s palette_entry_t; -struct palette_entry_s -{ - unsigned char r, g, b; -} ; - -typedef struct fifo_buffer_s fifo_buffer_t; -struct fifo_buffer_s -{ - buf_element_t *first, *last; - - int fifo_size; - uint32_t fifo_data_size; - void *fifo_empty_cb_data; - - pthread_mutex_t mutex; - pthread_cond_t not_empty; - - /* - * functions to access this fifo: - */ - - void (*put) (fifo_buffer_t *fifo, buf_element_t *buf); - - buf_element_t *(*get) (fifo_buffer_t *fifo); - - void (*clear) (fifo_buffer_t *fifo) ; - - int (*size) (fifo_buffer_t *fifo); - - int (*num_free) (fifo_buffer_t *fifo); - - uint32_t (*data_size) (fifo_buffer_t *fifo); - - void (*dispose) (fifo_buffer_t *fifo); - - /* - * alloc buffer for this fifo from global buf pool - * you don't have to use this function to allocate a buffer, - * an input plugin can decide to implement it's own - * buffer allocation functions - */ - - buf_element_t *(*buffer_pool_alloc) (fifo_buffer_t *self); - - - /* - * special functions, not used by demuxers - */ - - /* the same as buffer_pool_alloc but may fail if none is available */ - buf_element_t *(*buffer_pool_try_alloc) (fifo_buffer_t *self); - - /* the same as put but insert at the head of the fifo */ - void (*insert) (fifo_buffer_t *fifo, buf_element_t *buf); - - /* callbacks */ - void (*register_alloc_cb) (fifo_buffer_t *fifo, void (*cb)(fifo_buffer_t *fifo, void *), void *cb_data); - void (*register_put_cb) (fifo_buffer_t *fifo, void (*cb)(fifo_buffer_t *fifo, buf_element_t *buf, void *), void *cb_data); - void (*register_get_cb) (fifo_buffer_t *fifo, void (*cb)(fifo_buffer_t *fifo, buf_element_t *buf, void *), void *cb_data); - void (*unregister_alloc_cb) (fifo_buffer_t *fifo, void (*cb)(fifo_buffer_t *fifo, void *)); - void (*unregister_put_cb) (fifo_buffer_t *fifo, void (*cb)(fifo_buffer_t *fifo, buf_element_t *buf, void *)); - void (*unregister_get_cb) (fifo_buffer_t *fifo, void (*cb)(fifo_buffer_t *fifo, buf_element_t *buf, void *)); - - /* - * private variables for buffer pool management - */ - buf_element_t *buffer_pool_top; /* a stack actually */ - pthread_mutex_t buffer_pool_mutex; - pthread_cond_t buffer_pool_cond_not_empty; - int buffer_pool_num_free; - int buffer_pool_capacity; - int buffer_pool_buf_size; - void *buffer_pool_base; /*used to free mem chunk */ - void (*alloc_cb[BUF_MAX_CALLBACKS])(fifo_buffer_t *fifo, void *data_cb); - void (*put_cb[BUF_MAX_CALLBACKS])(fifo_buffer_t *fifo, buf_element_t *buf, void *data_cb); - void (*get_cb[BUF_MAX_CALLBACKS])(fifo_buffer_t *fifo, buf_element_t *buf, void *data_cb); - void *alloc_cb_data[BUF_MAX_CALLBACKS]; - void *put_cb_data[BUF_MAX_CALLBACKS]; - void *get_cb_data[BUF_MAX_CALLBACKS]; -} ; - -/* - * allocate and initialize new (empty) fifo buffer, - * init buffer pool for it: - * allocate num_buffers of buf_size bytes each - */ - -fifo_buffer_t *_x_fifo_buffer_new (int num_buffers, uint32_t buf_size) XINE_MALLOC XINE_PROTECTED; -fifo_buffer_t *_x_dummy_fifo_buffer_new (int num_buffers, uint32_t buf_size) XINE_MALLOC XINE_PROTECTED; - - -/* return BUF_VIDEO_xxx given the fourcc - * fourcc_int must be read in machine endianness - * example: fourcc_int = *(uint32_t *)fourcc_char; - */ -uint32_t _x_fourcc_to_buf_video( uint32_t fourcc_int ) XINE_PROTECTED; - -/* return codec name given BUF_VIDEO_xxx */ -const char * _x_buf_video_name( uint32_t buf_type ) XINE_PROTECTED; - -/* return BUF_AUDIO_xxx given the formattag */ -uint32_t _x_formattag_to_buf_audio( uint32_t formattag ) XINE_PROTECTED; - -/* return codec name given BUF_AUDIO_xxx */ -const char * _x_buf_audio_name( uint32_t buf_type ) XINE_PROTECTED; - - -#ifndef SUPPORT_ATTRIBUTE_PACKED -/* no attribute packed? let's try with pragma pack as a last resort */ -#pragma pack(2) -#endif -/* this is xine version of BITMAPINFOHEADER - * - should be safe to compile on 64bits machines - * - will always use machine endian format, so demuxers reading - * stuff from win32 formats must use the function below. - */ -typedef struct XINE_PACKED { - int32_t biSize; - int32_t biWidth; - int32_t biHeight; - int16_t biPlanes; - int16_t biBitCount; - uint32_t biCompression; - int32_t biSizeImage; - int32_t biXPelsPerMeter; - int32_t biYPelsPerMeter; - int32_t biClrUsed; - int32_t biClrImportant; -} xine_bmiheader; - -/* this is xine version of WAVEFORMATEX - * (the same comments from xine_bmiheader) - */ -typedef struct XINE_PACKED { - int16_t wFormatTag; - int16_t nChannels; - int32_t nSamplesPerSec; - int32_t nAvgBytesPerSec; - int16_t nBlockAlign; - int16_t wBitsPerSample; - int16_t cbSize; -} xine_waveformatex; -#ifndef SUPPORT_ATTRIBUTE_PACKED -#pragma pack() -#endif - -/* convert xine_bmiheader struct from little endian */ -void _x_bmiheader_le2me( xine_bmiheader *bih ) XINE_PROTECTED; - -/* convert xine_waveformatex struct from little endian */ -void _x_waveformatex_le2me( xine_waveformatex *wavex ) XINE_PROTECTED; - -static __inline int _x_is_fourcc(const void *ptr, const void *tag) { - return memcmp(ptr, tag, 4) == 0; -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/xine-engine/buffer_types.c b/src/xine-engine/buffer_types.c index 20b2d0754..31ee4443a 100644 --- a/src/xine-engine/buffer_types.c +++ b/src/xine-engine/buffer_types.c @@ -32,7 +32,9 @@ #include <string.h> #include <stdlib.h> #include <inttypes.h> -#include "buffer.h" +#include <xine/buffer.h> +#include <xine/xineutils.h> +#include <xine/xine_internal.h> #include "bswap.h" typedef struct video_db_s { @@ -1274,6 +1276,43 @@ int i; return ""; } + +static void code_to_text (char ascii[5], uint32_t code) +{ + int i; + for (i = 0; i < 4; ++i) + { + int byte = code & 0xFF; + ascii[i] = (byte < ' ') ? ' ' : (byte >= 0x7F) ? '.' : (char) byte; + code >>= 8; + } +} + +void _x_report_video_fourcc (xine_t *xine, const char *module, uint32_t code) +{ + if (code) + { + char ascii[5]; + code_to_text (ascii, code); + xprintf (xine, XINE_VERBOSITY_LOG, + _("%s: unknown video FourCC code %#x \"%s\"\n"), + module, code, ascii); + } +} + +void _x_report_audio_format_tag (xine_t *xine, const char *module, uint32_t code) +{ + if (code) + { + char ascii[5]; + code_to_text (ascii, code); + xprintf (xine, XINE_VERBOSITY_LOG, + _("%s: unknown audio format tag code %#x \"%s\"\n"), + module, code, ascii); + } +} + + void _x_bmiheader_le2me( xine_bmiheader *bih ) { /* OBS: fourcc must be read using machine endianness * so don't play with biCompression here! diff --git a/src/xine-engine/configfile.c b/src/xine-engine/configfile.c index cc53e646c..b334dfaa5 100644 --- a/src/xine-engine/configfile.c +++ b/src/xine-engine/configfile.c @@ -32,7 +32,13 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> -#include "configfile.h" +#include <xine/configfile.h> +#include "bswap.h" +#ifdef HAVE_FFMPEG_AVUTIL_H +# include <base64.h> +#else +# include <libavutil/base64.h> +#endif #define LOG_MODULE "configfile" #define LOG_VERBOSE @@ -40,8 +46,8 @@ #define LOG */ -#include "xineutils.h" -#include "xine_internal.h" +#include <xine/xineutils.h> +#include <xine/xine_internal.h> static const xine_config_entry_translation_t *config_entry_translation_user = NULL; static const xine_config_entry_translation_t config_entry_translation[] = { @@ -183,8 +189,6 @@ static const xine_config_entry_translation_t config_entry_translation[] = { { "video.pgx64_overlay_mode", "" }, { "video.pgx64_saturation", "video.output.pgx64_saturation" }, { "video.sdl_hw_accel", "video.device.sdl_hw_accel" }, - { "video.syncfb_default_repeat", "video.device.syncfb_default_repeat" }, - { "video.syncfb_device", "video.device.syncfb_device" }, { "video.unichrome_cpu_save", "video.device.unichrome_cpu_save" }, { "video.vertical_position", "video.output.vertical_position" }, { "video.vidix_blue_intensity", "video.output.vidix_blue_intensity" }, @@ -208,7 +212,7 @@ static const xine_config_entry_translation_t config_entry_translation[] = { static int config_section_enum(const char *sect) { - static char *known_section[] = { + static const char *const known_section[] = { "gui", "ui", "audio", @@ -461,6 +465,8 @@ static void config_reset_value(cfg_entry_t *entry) { entry->num_value = 0; } +static void config_shallow_copy(xine_cfg_entry_t *dest, cfg_entry_t *src); + static cfg_entry_t *config_register_key (config_values_t *this, const char *key, int exp_level, @@ -494,6 +500,14 @@ static cfg_entry_t *config_register_key (config_values_t *this, entry->callback_data = cb_data; } + /* we created a new entry, call the callback */ + if (this->new_entry_cb) { + xine_cfg_entry_t cb_entry; + + config_shallow_copy(&cb_entry, entry); + this->new_entry_cb(this->new_entry_cbdata, &cb_entry); + } + return entry; } @@ -1211,6 +1225,328 @@ static void config_unregister_cb (config_values_t *this, const char *key) { } } +static void config_set_new_entry_callback (config_values_t *this, xine_config_cb_t new_entry_cb, void* cbdata) { + pthread_mutex_lock(&this->config_lock); + this->new_entry_cb = new_entry_cb; + this->new_entry_cbdata = cbdata; + pthread_mutex_unlock(&this->config_lock); +} + +static void config_unset_new_entry_callback (config_values_t *this) { + pthread_mutex_lock(&this->config_lock); + this->new_entry_cb = NULL; + this->new_entry_cbdata = NULL; + pthread_mutex_unlock(&this->config_lock); +} + +static int put_int(uint8_t *buffer, int pos, int value) { + int32_t value_int32 = (int32_t)value; + + buffer[pos] = value_int32 & 0xFF; + buffer[pos + 1] = (value_int32 >> 8) & 0xFF; + buffer[pos + 2] = (value_int32 >> 16) & 0xFF; + buffer[pos + 3] = (value_int32 >> 24) & 0xFF; + + return 4; +} + +static int put_string(uint8_t *buffer, int pos, const char *value, int value_len) { + pos += put_int(buffer, pos, value_len); + memcpy(&buffer[pos], value, value_len); + + return 4 + value_len; +} + +static char* config_get_serialized_entry (config_values_t *this, const char *key) { + char *output = NULL; + cfg_entry_t *entry, *prev; + + pthread_mutex_lock(&this->config_lock); + config_lookup_entry_int(this, key, &entry, &prev); + + if (entry) { + /* now serialize this stuff + fields to serialize : + int type; + int range_min; + int range_max; + int exp_level; + int num_default; + int num_value; + char *key; + char *str_default; + char *description; + char *help; + char **enum_values; + */ + + int key_len = 0; + int str_default_len = 0; + int description_len = 0; + int help_len = 0; + unsigned long total_len; + int value_count; + int value_len[10]; + int pos = 0; + int i; + + if (entry->key) + key_len = strlen(entry->key); + if (entry->str_default) + str_default_len = strlen(entry->str_default); + if (entry->description) + description_len = strlen(entry->description); + if (entry->help) + help_len = strlen(entry->help); + + /* integers */ + /* value: 4 bytes */ + total_len = 6 * sizeof(int32_t); + + /* strings (size + char buffer) + * length: 4 bytes + * buffer: length bytes + */ + total_len += sizeof(int32_t) + key_len; + total_len += sizeof(int32_t) + str_default_len; + total_len += sizeof(int32_t) + description_len; + total_len += sizeof(int32_t) + help_len; + + /* enum values... + * value count: 4 bytes + * for each value: + * length: 4 bytes + * buffer: length bytes + */ + value_count = 0; + total_len += sizeof(int32_t); /* value count */ + + char **cur_value = entry->enum_values; + if (cur_value) { + while (*cur_value && (value_count < (sizeof(value_len) / sizeof(int) ))) { + value_len[value_count] = strlen(*cur_value); + total_len += sizeof(int32_t) + value_len[value_count]; + value_count++; + cur_value++; + } + } + + /* Now we have the length needed to serialize the entry and the length of each string */ + uint8_t *buffer = malloc (total_len); + if (!buffer) return NULL; + + /* Let's go */ + + /* the integers */ + pos += put_int(buffer, pos, entry->type); + pos += put_int(buffer, pos, entry->range_min); + pos += put_int(buffer, pos, entry->range_max); + pos += put_int(buffer, pos, entry->exp_level); + pos += put_int(buffer, pos, entry->num_default); + pos += put_int(buffer, pos, entry->num_value); + + /* the strings */ + pos += put_string(buffer, pos, entry->key, key_len); + pos += put_string(buffer, pos, entry->str_default, str_default_len); + pos += put_string(buffer, pos, entry->description, description_len); + pos += put_string(buffer, pos, entry->help, help_len); + + /* the enum stuff */ + pos += put_int(buffer, pos, value_count); + cur_value = entry->enum_values; + + for (i = 0; i < value_count; i++) { + pos += put_string(buffer, pos, *cur_value, value_len[i]); + cur_value++; + } + + /* and now the output encoding */ + /* We're going to encode total_len bytes in base64 + * libavutil's base64 encoding functions want the size to + * be at least len * 4 / 3 + 12, so let's use that! + */ + output = malloc(total_len * 4 / 3 + 12); + av_base64_encode(output, total_len * 4 / 3 + 12, buffer, total_len); + + free(buffer); + } + pthread_mutex_unlock(&this->config_lock); + + return output; + +} + +static int get_int(uint8_t *buffer, int buffer_size, int pos, int *value) { + int32_t value_int32; + + if ((pos + sizeof(int32_t)) > buffer_size) + return 0; + + value_int32 = _X_LE_32(&buffer[pos]); + *value = (int)value_int32; + return sizeof(int32_t); +} + +static int get_string(uint8_t *buffer, int buffer_size, int pos, char **value) { + int len; + int bytes = get_int(buffer, buffer_size, pos, &len); + *value = NULL; + + if (!bytes || (len < 0) || (len > 1024*64)) + return 0; + + char *str = malloc(len + 1); + pos += bytes; + memcpy(str, &buffer[pos], len); + str[len] = 0; + + *value = str; + return bytes + len; +} + +static char* config_register_serialized_entry (config_values_t *this, const char *value) { + /* + fields serialized : + int type; + int range_min; + int range_max; + int exp_level; + int num_default; + int num_value; + char *key; + char *str_default; + char *description; + char *help; + char **enum_values; + */ + int type; + int range_min; + int range_max; + int exp_level; + int num_default; + int num_value; + char *key = NULL; + char *str_default = NULL; + char *description = NULL; + char *help = NULL; + char **enum_values = NULL; + + int bytes; + int pos; + void *output = NULL; + size_t output_len; + int value_count = 0; + int i; + + output_len = strlen(value) * 3 / 4 + 1; + output = malloc(output_len); + av_base64_decode(output, value, output_len); + + pos = 0; + pos += bytes = get_int(output, output_len, pos, &type); + if (!bytes) goto exit; + + pos += bytes = get_int(output, output_len, pos, &range_min); + if (!bytes) goto exit; + + pos += bytes = get_int(output, output_len, pos, &range_max); + if (!bytes) goto exit; + + pos += bytes = get_int(output, output_len, pos, &exp_level); + if (!bytes) goto exit; + + pos += bytes = get_int(output, output_len, pos, &num_default); + if (!bytes) goto exit; + + pos += bytes = get_int(output, output_len, pos, &num_value); + if (!bytes) goto exit; + + pos += bytes = get_string(output, output_len, pos, &key); + if (!bytes) goto exit; + + pos += bytes = get_string(output, output_len, pos, &str_default); + if (!bytes) goto exit; + + pos += bytes = get_string(output, output_len, pos, &description); + if (!bytes) goto exit; + + pos += bytes = get_string(output, output_len, pos, &help); + if (!bytes) goto exit; + + pos += bytes = get_int(output, output_len, pos, &value_count); + if (!bytes) goto exit; + if ((value_count < 0) || (value_count > 256)) goto exit; + + enum_values = calloc (value_count + 1, sizeof(void*)); + for (i = 0; i < value_count; i++) { + pos += bytes = get_string(output, output_len, pos, &enum_values[i]); + if (!bytes) goto exit; + } + enum_values[value_count] = NULL; + +#ifdef LOG + printf("config entry deserialization:\n"); + printf(" key : %s\n", key); + printf(" type : %d\n", type); + printf(" exp_level : %d\n", exp_level); + printf(" num_default: %d\n", num_default); + printf(" num_value : %d\n", num_value); + printf(" str_default: %s\n", str_default); + printf(" range_min : %d\n", range_min); + printf(" range_max : %d\n", range_max); + printf(" description: %s\n", description); + printf(" help : %s\n", help); + printf(" enum : %d values\n", value_count); + + for (i = 0; i < value_count; i++) { + printf(" enum[%2d]: %s\n", i, enum_values[i]); + } + printf("\n"); +#endif + + switch (type) { + case XINE_CONFIG_TYPE_STRING: + switch (num_value) { + case 0: + this->register_string(this, key, str_default, description, help, exp_level, NULL, NULL); + break; + default: + this->register_filename(this, key, str_default, num_value, description, help, exp_level, NULL, NULL); + break; + } + break; + case XINE_CONFIG_TYPE_RANGE: + this->register_range(this, key, num_default, range_min, range_max, description, help, exp_level, NULL, NULL); + break; + case XINE_CONFIG_TYPE_ENUM: + this->register_enum(this, key, num_default, enum_values, description, help, exp_level, NULL, NULL); + break; + case XINE_CONFIG_TYPE_NUM: + this->register_num(this, key, num_default, description, help, exp_level, NULL, NULL); + break; + case XINE_CONFIG_TYPE_BOOL: + this->register_bool(this, key, num_default, description, help, exp_level, NULL, NULL); + break; + case XINE_CONFIG_TYPE_UNKNOWN: + break; + } + +exit: + /* cleanup */ + free(str_default); + free(description); + free(help); + free(output); + + if (enum_values) { + for (i = 0; i < value_count; i++) { + free(enum_values[i]); + } + free(enum_values); + } + + return key; +} config_values_t *_x_config_init (void) { @@ -1237,18 +1573,22 @@ config_values_t *_x_config_init (void) { pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&this->config_lock, &attr); - this->register_string = config_register_string; - this->register_filename = config_register_filename; - this->register_range = config_register_range; - this->register_enum = config_register_enum; - this->register_num = config_register_num; - this->register_bool = config_register_bool; - this->update_num = config_update_num; - this->update_string = config_update_string; - this->parse_enum = config_parse_enum; - this->lookup_entry = config_lookup_entry; - this->unregister_callback = config_unregister_cb; - this->dispose = config_dispose; + this->register_string = config_register_string; + this->register_filename = config_register_filename; + this->register_range = config_register_range; + this->register_enum = config_register_enum; + this->register_num = config_register_num; + this->register_bool = config_register_bool; + this->register_serialized_entry = config_register_serialized_entry; + this->update_num = config_update_num; + this->update_string = config_update_string; + this->parse_enum = config_parse_enum; + this->lookup_entry = config_lookup_entry; + this->unregister_callback = config_unregister_cb; + this->dispose = config_dispose; + this->set_new_entry_callback = config_set_new_entry_callback; + this->unset_new_entry_callback = config_unset_new_entry_callback; + this->get_serialized_entry = config_get_serialized_entry; return this; } diff --git a/src/xine-engine/configfile.h b/src/xine-engine/configfile.h deleted file mode 100644 index 4622f87fe..000000000 --- a/src/xine-engine/configfile.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (C) 2000-2004 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * config file management - */ - -#ifndef HAVE_CONFIGFILE_H -#define HAVE_CONFIGFILE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <pthread.h> - -#ifdef XINE_COMPILE -# include "xine.h" -#else -# include <xine.h> -#endif - -#define CONFIG_FILE_VERSION 2 - -/* - * config entries above this experience - * level must never be changed from MRL - */ -#define XINE_CONFIG_SECURITY 30 - - -typedef struct cfg_entry_s cfg_entry_t; -typedef struct config_values_s config_values_t; - -struct cfg_entry_s { - cfg_entry_t *next; - config_values_t *config; - - char *key; - int type; - - /* type unknown */ - char *unknown_value; - - /* type string */ - char *str_value; - char *str_default; - - /* common to range, enum, num, bool: */ - - int num_value; - int num_default; - - /* type range specific: */ - int range_min; - int range_max; - - /* type enum specific: */ - char **enum_values; - - /* help info for the user */ - char *description; - char *help; - - /* user experience level */ - int exp_level; - - /* callback function and data for live changeable values */ - xine_config_cb_t callback; - void *callback_data; -}; - -struct config_values_s { - - /* - * register config values - * - * these functions return the current value of the - * registered item, i.e. the default value if it was - * not found in the config file or the current value - * from the config file otherwise - */ - - char* (*register_string) (config_values_t *self, - const char *key, - const char *def_value, - const char *description, - const char *help, - int exp_level, - xine_config_cb_t changed_cb, - void *cb_data); - - char* (*register_filename) (config_values_t *self, - const char *key, - const char *def_value, - int req_type, - const char *description, - const char *help, - int exp_level, - xine_config_cb_t changed_cb, - void *cb_data); - - int (*register_range) (config_values_t *self, - const char *key, - int def_value, - int min, int max, - const char *description, - const char *help, - int exp_level, - xine_config_cb_t changed_cb, - void *cb_data); - - int (*register_enum) (config_values_t *self, - const char *key, - int def_value, - char **values, - const char *description, - const char *help, - int exp_level, - xine_config_cb_t changed_cb, - void *cb_data); - - int (*register_num) (config_values_t *self, - const char *key, - int def_value, - const char *description, - const char *help, - int exp_level, - xine_config_cb_t changed_cb, - void *cb_data); - - int (*register_bool) (config_values_t *self, - const char *key, - int def_value, - const char *description, - const char *help, - int exp_level, - xine_config_cb_t changed_cb, - void *cb_data); - - /* convenience function to update range, enum, num and bool values */ - void (*update_num) (config_values_t *self, const char *key, int value); - - /* convenience function to update string values */ - void (*update_string) (config_values_t *self, const char *key, const char *value); - - /* small utility function for enum handling */ - int (*parse_enum) (const char *str, const char **values); - - /* - * lookup config entries - * - * remember to call the changed_cb if it exists - * and you changed the value of this item - */ - - cfg_entry_t* (*lookup_entry) (config_values_t *self, const char *key); - - /* - * unregister callback function - */ - void (*unregister_callback) (config_values_t *self, const char *key); - - /* - * dispose of all config entries in memory - */ - void (*dispose) (config_values_t *self); - - /* - * config values are stored here: - */ - cfg_entry_t *first, *last, *cur; - - /* - * mutex for modification to the config - */ - pthread_mutex_t config_lock; - - /* - * current config file's version number - */ - int current_version; -}; - -/* - * allocate and init a new xine config object - */ -config_values_t *_x_config_init (void) XINE_MALLOC XINE_PROTECTED; - -/* - * interpret stream_setup part of mrls for config value changes - */ - -int _x_config_change_opt(config_values_t *config, const char *opt) XINE_PROTECTED; - - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/xine-engine/demux.c b/src/xine-engine/demux.c index 87cc18011..d61ca963a 100644 --- a/src/xine-engine/demux.c +++ b/src/xine-engine/demux.c @@ -42,9 +42,9 @@ #define LOG */ -#include "xine_internal.h" -#include "demuxers/demux.h" -#include "buffer.h" +#include <xine/xine_internal.h> +#include <xine/demux.h> +#include <xine/buffer.h> #ifdef WIN32 #include <winsock.h> @@ -200,7 +200,7 @@ void _x_demux_control_headers_done (xine_stream_t *stream) { buf_element_t *buf_video, *buf_audio; /* we use demux_action_pending to wake up sleeping spu decoders */ - stream->demux_action_pending = 1; + _x_action_raise(stream); /* allocate the buffers before grabbing the lock to prevent cyclic wait situations */ buf_video = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); @@ -252,7 +252,7 @@ void _x_demux_control_headers_done (xine_stream_t *stream) { } } - stream->demux_action_pending = 0; + _x_action_lower(stream); pthread_cond_signal(&stream->demux_resume); lprintf ("headers processed.\n"); @@ -342,7 +342,7 @@ static void *demux_loop (void *stream_gen) { status = stream->demux_plugin->send_chunk(stream->demux_plugin); /* someone may want to interrupt us */ - if( stream->demux_action_pending ) { + if (_x_action_pending(stream)) { struct timespec ts; ts = _x_compute_interval(100); pthread_cond_timedwait (&stream->demux_resume, &stream->demux_lock, &ts); @@ -429,9 +429,9 @@ int _x_demux_start_thread (xine_stream_t *stream) { lprintf ("start thread called\n"); - stream->demux_action_pending = 1; + _x_action_raise(stream); pthread_mutex_lock( &stream->demux_lock ); - stream->demux_action_pending = 0; + _x_action_lower(stream); pthread_cond_signal(&stream->demux_resume); if( !stream->demux_thread_running ) { @@ -460,10 +460,10 @@ int _x_demux_stop_thread (xine_stream_t *stream) { lprintf ("stop thread called\n"); - stream->demux_action_pending = 1; + _x_action_raise(stream); pthread_mutex_lock( &stream->demux_lock ); stream->demux_thread_running = 0; - stream->demux_action_pending = 0; + _x_action_lower(stream); pthread_cond_signal(&stream->demux_resume); /* At that point, the demuxer has sent the last audio/video buffer, @@ -492,7 +492,7 @@ int _x_demux_stop_thread (xine_stream_t *stream) { return 0; } -int _x_demux_read_header( input_plugin_t *input, unsigned char *buffer, off_t size){ +int _x_demux_read_header( input_plugin_t *input, void *buffer, off_t size){ int read_size; unsigned char *buf; @@ -517,6 +517,11 @@ int _x_demux_read_header( input_plugin_t *input, unsigned char *buffer, off_t si int _x_demux_check_extension (const char *mrl, const char *extensions){ char *last_dot, *e, *ext_copy, *ext_work; + int found = 0; + + /* An empty extensions string means that the by-extension method can't + be used, so consider those cases as always passing. */ + if ( extensions == NULL ) return 1; ext_copy = strdup(extensions); ext_work = ext_copy; @@ -524,15 +529,23 @@ int _x_demux_check_extension (const char *mrl, const char *extensions){ last_dot = strrchr (mrl, '.'); if (last_dot) { last_dot++; - while ( ( e = xine_strsep(&ext_work, " ")) != NULL ) { + } + + while ( ( e = xine_strsep(&ext_work, " ")) != NULL ) { + if ( strstr(e, ":/") ) { + if ( strncasecmp (mrl, e, strlen (e)) == 0 ) { + found = 1; + break; + } + } else if (last_dot) { if (strcasecmp (last_dot, e) == 0) { - free(ext_copy); - return 1; + found = 1; + break; } } } free(ext_copy); - return 0; + return found; } @@ -567,7 +580,7 @@ off_t _x_read_abort (xine_stream_t *stream, int fd, char *buf, off_t todo) { /* aborts current read if action pending. otherwise xine * cannot be stopped when no more data is available. */ - if( stream->demux_action_pending ) + if (_x_action_pending(stream)) return total; } else { break; @@ -608,6 +621,22 @@ int _x_action_pending (xine_stream_t *stream) { return stream->demux_action_pending; } +/* set demux_action_pending in a thread-safe way */ +void _x_action_raise (xine_stream_t *stream) +{ + pthread_mutex_lock(&stream->demux_action_lock); + stream->demux_action_pending++; + pthread_mutex_unlock(&stream->demux_action_lock); +} + +/* reset demux_action_pending in a thread-safe way */ +void _x_action_lower (xine_stream_t *stream) +{ + pthread_mutex_lock(&stream->demux_action_lock); + stream->demux_action_pending--; + pthread_mutex_unlock(&stream->demux_action_lock); +} + /* * demuxer helper function to send data to fifo, breaking into smaller * pieces (bufs) as needed. diff --git a/src/xine-engine/events.c b/src/xine-engine/events.c index a5680476f..5bd827c45 100644 --- a/src/xine-engine/events.c +++ b/src/xine-engine/events.c @@ -26,7 +26,7 @@ #define XINE_ENGINE_INTERNAL -#include "xine_internal.h" +#include <xine/xine_internal.h> xine_event_t *xine_event_get (xine_event_queue_t *queue) { diff --git a/src/xine-engine/info_helper.c b/src/xine-engine/info_helper.c index 9d0302cc1..85f43b357 100644 --- a/src/xine-engine/info_helper.c +++ b/src/xine-engine/info_helper.c @@ -35,7 +35,7 @@ #define XINE_ENGINE_INTERNAL -#include "info_helper.h" +#include <xine/info_helper.h> /* ******************* Stream Info *************************** */ diff --git a/src/xine-engine/info_helper.h b/src/xine-engine/info_helper.h deleted file mode 100644 index 666b94f08..000000000 --- a/src/xine-engine/info_helper.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2000-2003 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * stream metainfo helper functions - * hide some xine engine details from demuxers and reduce code duplication - * - * $id$ - */ - -#ifndef INFO_HELPER_H -#define INFO_HELPER_H - -#include <stdarg.h> -#include "xine_internal.h" - -/* - * set a stream info - * - * params: - * *stream the xine stream - * info stream info id (see xine.h, XINE_STREAM_INFO_*) - * value the value to assign - * - */ -void _x_stream_info_set(xine_stream_t *stream, int info, int value) XINE_PROTECTED; - -/* - * reset a stream info (internal ones only) - * - * params : - * *stream the xine stream - * info meta info id (see xine.h, XINE_STREAM_INFO_*) - * - */ -void _x_stream_info_reset(xine_stream_t *stream, int info) XINE_PROTECTED; - -/* - * reset a stream info (public ones only) - * - * params : - * *stream the xine stream - * info meta info id (see xine.h, XINE_STREAM_INFO_*) - * - */ -void _x_stream_info_public_reset(xine_stream_t *stream, int info) XINE_PROTECTED; - -/* - * retrieve stream info (internal ones only) - * - * params : - * *stream the xine stream - * info meta info id (see xine.h, XINE_STREAM_INFO_*) - * - */ -uint32_t _x_stream_info_get(xine_stream_t *stream, int info) XINE_PROTECTED; - -/* - * retrieve stream info (public ones only) - * - * params : - * *stream the xine stream - * info meta info id (see xine.h, XINE_STREAM_INFO_*) - * - */ -uint32_t _x_stream_info_get_public(xine_stream_t *stream, int info) XINE_PROTECTED; - -/* - * set a stream meta info - * - * params: - * *stream the xine stream - * info meta info id (see xine.h, XINE_META_INFO_*) - * *str null-terminated string (using current locale) - * - */ -void _x_meta_info_set(xine_stream_t *stream, int info, const char *str) XINE_PROTECTED; - -/* - * set a stream meta info - * - * params: - * *stream the xine stream - * info meta info id (see xine.h, XINE_META_INFO_*) - * *str null-terminated string (using utf8) - * - */ -void _x_meta_info_set_utf8(xine_stream_t *stream, int info, const char *str) XINE_PROTECTED; - -/* - * set a stream meta info - * - * params: - * *stream the xine stream - * info meta info id (see xine.h, XINE_META_INFO_*) - * *str null-terminated string (using encoding below) - * *enc charset encoding of the string - * - */ -void _x_meta_info_set_generic(xine_stream_t *stream, int info, const char *str, const char *enc) XINE_PROTECTED; - -/* - * set a stream meta multiple info - * - * params: - * *stream the xine stream - * info meta info id (see xine.h, XINE_META_INFO_*) - * ... one or more meta info, followed by a NULL pointer - * - */ -void _x_meta_info_set_multi(xine_stream_t *stream, int info, ...) XINE_SENTINEL XINE_PROTECTED; - -/* - * set a stream meta info - * - * params: - * *stream the xine stream - * info meta info id (see xine.h, XINE_META_INFO_*) - * *buf char buffer (not a null-terminated string) - * len length of the metainfo - * - */ -void _x_meta_info_n_set(xine_stream_t *stream, int info, const char *buf, int len) XINE_PROTECTED; - -/* - * reset a stream meta info (internal ones only) - * - * params : - * *stream the xine stream - * info meta info id (see xine.h, XINE_META_INFO_*) - * - */ -void _x_meta_info_reset(xine_stream_t *stream, int info) XINE_PROTECTED; - -/* - * reset a stream meta info (public ones only) - * - * params : - * *stream the xine stream - * info meta info id (see xine.h, XINE_META_INFO_*) - * - */ -void _x_meta_info_public_reset(xine_stream_t *stream, int info) XINE_PROTECTED; - -/* - * retrieve stream meta info (internal ones only) - * - * params : - * *stream the xine stream - * info meta info id (see xine.h, XINE_META_INFO_*) - * - */ -const char *_x_meta_info_get(xine_stream_t *stream, int info) XINE_PROTECTED; - -/* - * retrieve stream meta info (public ones only) - * - * params : - * *stream the xine stream - * info meta info id (see xine.h, XINE_META_INFO_*) - * - */ -const char *_x_meta_info_get_public(xine_stream_t *stream, int info) XINE_PROTECTED; - -#endif /* INFO_HELPER_H */ diff --git a/src/xine-engine/input_cache.c b/src/xine-engine/input_cache.c index e761fed38..40aaba660 100644 --- a/src/xine-engine/input_cache.c +++ b/src/xine-engine/input_cache.c @@ -33,7 +33,8 @@ #define LOG */ -#include "xine_internal.h" +#include <xine/xine_internal.h> +#include "xine_private.h" #include <assert.h> #define DEFAULT_BUFFER_SIZE 1024 @@ -61,8 +62,9 @@ typedef struct { /* * read data from input plugin and write it into file */ -static off_t cache_plugin_read(input_plugin_t *this_gen, char *buf, off_t len) { +static off_t cache_plugin_read(input_plugin_t *this_gen, void *buf_gen, off_t len) { cache_input_plugin_t *this = (cache_input_plugin_t *)this_gen; + char *buf = (char *)buf_gen; off_t read_len = 0; off_t main_read; @@ -344,7 +346,7 @@ static void cache_plugin_dispose(input_plugin_t *this_gen) { /* * create self instance, */ -input_plugin_t *_x_cache_plugin_get_instance (xine_stream_t *stream, int readahead_size) { +input_plugin_t *_x_cache_plugin_get_instance (xine_stream_t *stream) { cache_input_plugin_t *this; input_plugin_t *main_plugin = stream->input_plugin; diff --git a/src/xine-engine/input_rip.c b/src/xine-engine/input_rip.c index faeaae62d..c1cbbf043 100644 --- a/src/xine-engine/input_rip.c +++ b/src/xine-engine/input_rip.c @@ -64,7 +64,8 @@ # define CLR_RST "\e[0;39m" #endif -#include "xine_internal.h" +#include <xine/xine_internal.h> +#include "xine_private.h" #ifndef HAVE_FSEEKO # define fseeko fseek @@ -98,8 +99,9 @@ static off_t min_off(off_t a, off_t b) { /* * read data from input plugin and write it into file */ -static off_t rip_plugin_read(input_plugin_t *this_gen, char *buf, off_t len) { +static off_t rip_plugin_read(input_plugin_t *this_gen, void *buf_gen, off_t len) { rip_input_plugin_t *this = (rip_input_plugin_t *)this_gen; + char *buf = (char *)buf_gen; off_t retlen, npreview, nread, nwrite, nread_orig, nread_file; lprintf("reading %"PRId64" bytes (curpos = %"PRId64", savepos = %"PRId64")\n", len, this->curpos, this->savepos); diff --git a/src/xine-engine/io_helper.c b/src/xine-engine/io_helper.c index eef843906..1336fc790 100644 --- a/src/xine-engine/io_helper.c +++ b/src/xine-engine/io_helper.c @@ -38,7 +38,7 @@ #define XINE_ENGINE_INTERNAL -#include "io_helper.h" +#include <xine/io_helper.h> /* private constants */ #define XIO_FILE_READ 0 @@ -246,7 +246,7 @@ int _x_io_select (xine_stream_t *stream, int fd, int state, int timeout_msec) { * aborts current read if action pending. otherwise xine * cannot be stopped when no more data is available. */ - if (stream && stream->demux_action_pending) + if (stream && _x_action_pending(stream)) return XIO_ABORTED; break; case WAIT_ABANDONED: @@ -290,7 +290,7 @@ int _x_io_select (xine_stream_t *stream, int fd, int state, int timeout_msec) { * aborts current read if action pending. otherwise xine * cannot be stopped when no more data is available. */ - if (stream && stream->demux_action_pending) + if (stream && _x_action_pending(stream)) return XIO_ABORTED; total_time_usec += XIO_POLLING_INTERVAL; @@ -326,7 +326,8 @@ int _x_io_tcp_connect_finish(xine_stream_t *stream, int fd, int timeout_msec) { } -static off_t xio_rw_abort(xine_stream_t *stream, int fd, int cmd, char *buf, off_t todo) { +static off_t xio_rw_abort(xine_stream_t *stream, int fd, int cmd, void *buf_gen, off_t todo) { + uint8_t *buf = buf_gen; off_t ret = -1; off_t total = 0; @@ -413,19 +414,19 @@ static off_t xio_rw_abort(xine_stream_t *stream, int fd, int cmd, char *buf, off return total; } -off_t _x_io_tcp_read (xine_stream_t *stream, int s, char *buf, off_t todo) { +off_t _x_io_tcp_read (xine_stream_t *stream, int s, void *buf, off_t todo) { return xio_rw_abort (stream, s, XIO_TCP_READ, buf, todo); } -off_t _x_io_tcp_write (xine_stream_t *stream, int s, char *buf, off_t todo) { +off_t _x_io_tcp_write (xine_stream_t *stream, int s, void *buf, off_t todo) { return xio_rw_abort (stream, s, XIO_TCP_WRITE, buf, todo); } -off_t _x_io_file_read (xine_stream_t *stream, int s, char *buf, off_t todo) { +off_t _x_io_file_read (xine_stream_t *stream, int s, void *buf, off_t todo) { return xio_rw_abort (stream, s, XIO_FILE_READ, buf, todo); } -off_t _x_io_file_write (xine_stream_t *stream, int s, char *buf, off_t todo) { +off_t _x_io_file_write (xine_stream_t *stream, int s, void *buf, off_t todo) { return xio_rw_abort (stream, s, XIO_FILE_WRITE, buf, todo); } diff --git a/src/xine-engine/io_helper.h b/src/xine-engine/io_helper.h deleted file mode 100644 index 3e96e8dc1..000000000 --- a/src/xine-engine/io_helper.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2000-2003 the xine project, - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * abortable i/o helper functions - */ - -#ifndef IO_HELPER_H -#define IO_HELPER_H - -#include "xine_internal.h" - - -/* select states */ -#define XIO_READ_READY 1 -#define XIO_WRITE_READY 2 - -/* xine select return codes */ -#define XIO_READY 0 -#define XIO_ERROR 1 -#define XIO_ABORTED 2 -#define XIO_TIMEOUT 3 - - -/* - * Waits for a file descriptor/socket to change status. - * - * network input plugins should use this function in order to - * not freeze the engine. - * - * params : - * stream needed for aborting and reporting errors but may be NULL - * fd file/socket descriptor - * state XIO_READ_READY, XIO_WRITE_READY - * timeout_sec timeout in seconds - * - * An other thread can abort this function if stream != NULL by setting - * stream->demux_action_pending. - * - * return value : - * XIO_READY the file descriptor is ready for cmd - * XIO_ERROR an i/o error occured - * XIO_ABORTED command aborted by an other thread - * XIO_TIMEOUT the file descriptor is not ready after timeout_msec milliseconds - */ -int _x_io_select (xine_stream_t *stream, int fd, int state, int timeout_msec) XINE_PROTECTED; - - -/* - * open a tcp connection - * - * params : - * stream needed for reporting errors but may be NULL - * host address of target - * port port on target - * - * returns a socket descriptor or -1 if an error occured - */ -int _x_io_tcp_connect(xine_stream_t *stream, const char *host, int port) XINE_PROTECTED; - -/* - * wait for finish connection - * - * params : - * stream needed for aborting and reporting errors but may be NULL - * fd socket descriptor - * timeout_msec timeout in milliseconds - * - * return value: - * XIO_READY host respond, the socket is ready for cmd - * XIO_ERROR an i/o error occured - * XIO_ABORTED command aborted by an other thread - * XIO_TIMEOUT the file descriptor is not ready after timeout - */ -int _x_io_tcp_connect_finish(xine_stream_t *stream, int fd, int timeout_msec) XINE_PROTECTED; - -/* - * read from tcp socket checking demux_action_pending - * - * network input plugins should use this function in order to - * not freeze the engine. - * - * aborts with zero if no data is available and *abort is set - */ -off_t _x_io_tcp_read (xine_stream_t *stream, int s, char *buf, off_t todo) XINE_PROTECTED; - - -/* - * write to a tcp socket checking demux_action_pending - * - * network input plugins should use this function in order to - * not freeze the engine. - * - * aborts with zero if no data is available and *abort is set - */ -off_t _x_io_tcp_write (xine_stream_t *stream, int s, char *buf, off_t todo) XINE_PROTECTED; - -/* - * read from a file descriptor checking demux_action_pending - * - * the fifo input plugin should use this function in order to - * not freeze the engine. - * - * aborts with zero if no data is available and *abort is set - */ -off_t _x_io_file_read (xine_stream_t *stream, int fd, char *buf, off_t todo) XINE_PROTECTED; - - -/* - * write to a file descriptor checking demux_action_pending - * - * the fifo input plugin should use this function in order to - * not freeze the engine. - * - * aborts with zero if *abort is set - */ -off_t _x_io_file_write (xine_stream_t *stream, int fd, char *buf, off_t todo) XINE_PROTECTED; - -/* - * read a string from socket, return string length (same as strlen) - * the string is always '\0' terminated but given buffer size is never exceeded - * that is, _x_io_tcp_read_line(,,,X) <= (X-1) ; X > 0 - */ -int _x_io_tcp_read_line(xine_stream_t *stream, int sock, char *str, int size) XINE_PROTECTED; - -#endif diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c index 206f259e5..c86cc5f6e 100644 --- a/src/xine-engine/load_plugins.c +++ b/src/xine-engine/load_plugins.c @@ -40,26 +40,33 @@ #include <ctype.h> #include <signal.h> +#include <basedir.h> + #define LOG_MODULE "load_plugins" #define LOG_VERBOSE /* #define LOG +#define DEBUG */ #define XINE_ENABLE_EXPERIMENTAL_FEATURES 1 #define XINE_ENGINE_INTERNAL -#include "xine_internal.h" -#include "xine_plugin.h" -#include "plugin_catalog.h" -#include "demuxers/demux.h" -#include "input/input_plugin.h" -#include "video_out.h" -#include "post.h" -#include "metronom.h" -#include "configfile.h" -#include "xineutils.h" -#include "compat.h" +#include <xine/xine_internal.h> +#include <xine/xine_plugin.h> +#include <xine/plugin_catalog.h> +#include <xine/demux.h> +#include <xine/input_plugin.h> +#include <xine/video_out.h> +#include <xine/post.h> +#include <xine/metronom.h> +#include <xine/configfile.h> +#include <xine/xineutils.h> +#include <xine/compat.h> + +#include "xine_private.h" + +#define LINE_MAX_LENGTH (1024 * 32) /* 32 KiB */ #if 0 @@ -92,6 +99,7 @@ static void remove_segv_handler(void){ #endif #endif /* 0 */ +#define CACHE_CATALOG_VERSION 4 static const int plugin_iface_versions[] = { INPUT_PLUGIN_IFACE_VERSION, @@ -245,26 +253,26 @@ static void _decoder_priority_cb(void *data, xine_cfg_entry_t *cfg) { map_decoders((xine_t *)data); } -static plugin_info_t *_get_cached_info (xine_t *this, +static plugin_node_t *_get_cached_node (xine_t *this, char *filename, off_t filesize, time_t filemtime, - plugin_info_t *previous_info) { + plugin_node_t *previous_node) { xine_sarray_t *list = this->plugin_catalog->cache_list; int list_id, list_size; list_size = xine_sarray_size (list); for (list_id = 0; list_id < list_size; list_id++) { plugin_node_t *node = xine_sarray_get (list, list_id); - if( !previous_info && + if( !previous_node && node->file->filesize == filesize && node->file->filemtime == filemtime && !strcmp( node->file->filename, filename )) { - return node->info; + return node; } /* skip previously returned items */ - if( node->info == previous_info ) - previous_info = NULL; + if( node == previous_node ) + previous_node = NULL; } return NULL; @@ -294,6 +302,7 @@ static plugin_file_t *_insert_file (xine_t *this, static void _insert_node (xine_t *this, xine_sarray_t *list, plugin_file_t *file, + plugin_node_t *node_cache, plugin_info_t *info, int api_version){ @@ -333,6 +342,7 @@ static void _insert_node (xine_t *this, entry->file = file; entry->ref = 0; entry->priority = 0; /* default priority */ + entry->config_entry_list = (node_cache) ? node_cache->config_entry_list : NULL; switch (info->type & PLUGIN_TYPE_MASK){ @@ -377,9 +387,6 @@ static void _insert_node (xine_t *this, entry->priority = decoder_new->priority = decoder_old->priority; snprintf(key, sizeof(key), "engine.decoder_priorities.%s", info->id); - /* write the description on the heap because the config system - * does not strdup() it, so we have to provide a different pointer - * for each decoder */ for (i = 0; catalog->prio_desc[i]; i++); catalog->prio_desc[i] = _x_asprintf(_("priority for %s decoder"), info->id); this->config->register_num (this->config, @@ -479,7 +486,8 @@ static plugin_catalog_t *XINE_MALLOC _new_catalog(void){ return catalog; } -static void _register_plugins_internal(xine_t *this, plugin_file_t *file, plugin_info_t *info) { +static void _register_plugins_internal(xine_t *this, plugin_file_t *file, + plugin_node_t *node_cache, plugin_info_t *info) { _x_assert(this); _x_assert(info); @@ -505,7 +513,7 @@ static void _register_plugins_internal(xine_t *this, plugin_file_t *file, plugin int plugin_type = info->type & PLUGIN_TYPE_MASK; if ((plugin_type > 0) && (plugin_type <= PLUGIN_TYPE_MAX)) { - _insert_node (this, this->plugin_catalog->plugin_lists[plugin_type - 1], file, info, + _insert_node (this, this->plugin_catalog->plugin_lists[plugin_type - 1], file, node_cache, info, plugin_iface_versions[plugin_type - 1]); if ((plugin_type == PLUGIN_AUDIO_DECODER) || @@ -529,7 +537,8 @@ static void _register_plugins_internal(xine_t *this, plugin_file_t *file, plugin /* get next info */ if( file && !file->lib_handle ) { lprintf("get cached info\n"); - info = _get_cached_info (this, file->filename, file->filesize, file->filemtime, info); + node_cache = _get_cached_node (this, file->filename, file->filesize, file->filemtime, node_cache); + info = (node_cache) ? node_cache->info : NULL; } else { info++; } @@ -537,7 +546,7 @@ static void _register_plugins_internal(xine_t *this, plugin_file_t *file, plugin } void xine_register_plugins(xine_t *self, plugin_info_t *info) { - _register_plugins_internal(self, NULL, info); + _register_plugins_internal(self, NULL, NULL, info); } /* @@ -563,6 +572,7 @@ static void collect_plugins(xine_t *this, char *path){ while ((pEntry = readdir (dir)) != NULL) { void *lib = NULL; plugin_info_t *info = NULL; + plugin_node_t *node = NULL; struct stat statbuffer; @@ -605,7 +615,8 @@ static void collect_plugins(xine_t *this, char *path){ lib = NULL; /* get the first plugin_info_t */ - info = _get_cached_info (this, str, statbuffer.st_size, statbuffer.st_mtime, NULL); + node = _get_cached_node (this, str, statbuffer.st_size, statbuffer.st_mtime, NULL); + info = (node) ? node->info : NULL; #ifdef LOG if( info ) printf("load_plugins: using cached %s\n", str); @@ -626,7 +637,7 @@ static void collect_plugins(xine_t *this, char *path){ file = _insert_file(this, this->plugin_catalog->file_list, str, &statbuffer, lib); - _register_plugins_internal(this, file, info); + _register_plugins_internal(this, file, node, info); } else { const char *error = dlerror(); @@ -683,6 +694,25 @@ static inline int _plugin_info_equal(const plugin_info_t *a, return 1; } +static void _attach_entry_to_node (plugin_node_t *node, char *key) { + + if (!node->config_entry_list) { + node->config_entry_list = xine_list_new(); + } + + xine_list_push_back(node->config_entry_list, key); +} + +/* + * This callback is called by the config entry system when a plugin register a + * new config entry. + */ +static void _new_entry_cb (void *user_data, xine_cfg_entry_t *entry) { + plugin_node_t *node = (plugin_node_t *)user_data; + + _attach_entry_to_node(node, strdup(entry->key)); +} + static int _load_plugin_class(xine_t *this, plugin_node_t *node, void *data) { @@ -710,9 +740,17 @@ static int _load_plugin_class(xine_t *this, if ((info = dlsym(node->file->lib_handle, "xine_plugin_info"))) { /* TODO: use sigsegv handler */ - while (info->type != PLUGIN_NONE){ - if (_plugin_info_equal(info, target)){ - if ((node->plugin_class = info->init(this, data))) { + while (info->type != PLUGIN_NONE) { + if (_plugin_info_equal(info, target)) { + config_values_t *config = this->config; + + /* the callback is called for each entry registered by this plugin */ + lprintf("plugin init %s\n", node->info->id); + config->set_new_entry_callback(config, _new_entry_cb, node); + node->plugin_class = info->init(this, data); + config->unset_new_entry_callback(config); + + if (node->plugin_class) { inc_file_ref(node->file); return 1; } else { @@ -791,7 +829,11 @@ static void _load_required_plugins(xine_t *this, xine_sarray_t *list) { while (list_id < list_size) { plugin_node_t *node = xine_sarray_get(list, list_id); - if( (node->info->type & PLUGIN_MUST_PRELOAD) && !node->plugin_class ) { + /* + * preload plugins if not cached + */ + if( (node->info->type & PLUGIN_MUST_PRELOAD) && !node->plugin_class && + node->file->lib_handle ) { lprintf("preload plugin %s from %s\n", node->info->id, node->file->filename); @@ -821,7 +863,7 @@ static void load_required_plugins(xine_t *this) { /* * save plugin list information to file (cached catalog) */ -static void save_plugin_list(FILE *fp, xine_sarray_t *list) { +static void save_plugin_list(xine_t *this, FILE *fp, xine_sarray_t *list) { const plugin_node_t *node; const plugin_file_t *file; @@ -831,7 +873,6 @@ static void save_plugin_list(FILE *fp, xine_sarray_t *list) { const vo_info_t *vo_info; const ao_info_t *ao_info; const post_info_t *post_info; - int i; int list_id = 0; int list_size; @@ -886,8 +927,25 @@ static void save_plugin_list(FILE *fp, xine_sarray_t *list) { case PLUGIN_POST: post_info = node->info->special_info; - fprintf(fp, "post_type=%lu\n", (unsigned long)post_info->type); - break; + fprintf(fp, "post_type=%lu\n", (unsigned long)post_info->type); + break; + } + + /* config entries */ + if (node->config_entry_list) { + xine_list_iterator_t ite = xine_list_front(node->config_entry_list); + while (ite) { + char *key = xine_list_get_value(node->config_entry_list, ite); + + /* now serialize the config key */ + char *key_value = this->config->get_serialized_entry(this->config, key); + + lprintf(" config key: %s, serialization: %d bytes\n", key, strlen(key_value)); + fprintf(fp, "config_key=%s\n", key_value); + + free (key_value); + ite = xine_list_next(node->config_entry_list, ite); + } } fprintf(fp, "\n"); @@ -898,7 +956,7 @@ static void save_plugin_list(FILE *fp, xine_sarray_t *list) { /* * load plugin list information from file (cached catalog) */ -static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { +static void load_plugin_list(xine_t *this, FILE *fp, xine_sarray_t *plugins) { plugin_node_t *node; plugin_file_t *file; @@ -911,20 +969,29 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { int i; uint64_t llu; unsigned long lu; - char line[1024]; + char *line; char *value; + size_t line_len; int version_ok = 0; + line = malloc(LINE_MAX_LENGTH); + if (!line) + return; + node = NULL; file = NULL; - while (fgets (line, 1023, fp)) { + while (fgets (line, LINE_MAX_LENGTH, fp)) { if (line[0] == '#') continue; + line_len = strlen(line); + if (line_len < 3) + continue; - if( (value = strchr(line, '\r')) || (value = strchr(line, '\n')) ) - *value = (char) 0; /* eliminate any cr/lf */ + value = &line[line_len - 1]; + if( (*value == '\r') || (*value == '\n') ) + *value-- = (char) 0; /* eliminate any cr/lf */ - if( (value = strchr(line, '\r')) || (value = strchr(line, '\n')) ) + if( (*value == '\r') || (*value == '\n') ) *value = (char) 0; /* eliminate any cr/lf */ if (line[0] == '[' && version_ok) { @@ -1018,15 +1085,16 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { vo_info->visual_type = i; } else if( !strcmp("supported_types",line) && decoder_info ) { char *s; + uint32_t *supported_types; for( s = value, i = 0; s && sscanf(s," %lu",&lu) > 0; i++ ) { s = strchr(s+1, ' '); } - decoder_info->supported_types = calloc((i+1), sizeof(uint32_t)); - for( s = value, i = 0; s && sscanf(s," %lu",&lu) > 0; i++ ) { - decoder_info->supported_types[i] = lu; + supported_types = calloc((i+1), sizeof(uint32_t)); + for( s = value, i = 0; s && sscanf(s," %"SCNu32,&supported_types[i]) > 0; i++ ) { s = strchr(s+1, ' '); } + decoder_info->supported_types = supported_types; } else if( !strcmp("vo_priority",line) && vo_info ) { sscanf(value," %d",&i); vo_info->priority = i; @@ -1043,8 +1111,18 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { sscanf(value," %d",&i); input_info->priority = i; } else if( !strcmp("post_type",line) && post_info ) { - sscanf(value," %lu",&lu); - post_info->type = lu; + sscanf(value," %lu",&lu); + post_info->type = lu; + } else if( !strcmp("config_key",line) ) { + char* cfg_key; + + cfg_key = this->config->register_serialized_entry(this->config, value); + if (cfg_key) { + /* this node is a cached node */ + _attach_entry_to_node(node, cfg_key); + } else { + lprintf("failed to deserialize config entry key\n"); + } } } } @@ -1053,29 +1131,76 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { if( node ) { xine_sarray_add (plugins, node); } + + free (line); } +/** + * @brief Returns the complete filename for the plugins' cache file + * @param this Instance pointer, used for logging and libxdg-basedir. + * @param createdir If not zero, create the directory structure in which + * the file has to reside. + * @return If createdir was not zero, returns NULL if the directory hasn't + * been created; otherwise always returns a new string with the + * name of the cachefile. + * @internal + * + * @see XDG Base Directory specification: + * http://standards.freedesktop.org/basedir-spec/latest/index.html + */ +static char *catalog_filename(xine_t *this, int createdir) { + const char *const xdg_cache_home = xdgCacheHome(&this->basedir_handle); + char *cachefile = NULL; + + cachefile = xine_xmalloc( strlen(xdg_cache_home) + sizeof("/"PACKAGE"/plugins.cache") ); + strcpy(cachefile, xdg_cache_home); + + /* If we're going to create the directory structure, we concatenate + * piece by piece the path, so that we can try to create all the + * directories. + * If we don't need to create anything, we just concatenate the + * whole path at once. + */ + if ( createdir ) { + int result = 0; + + result = mkdir( cachefile, 0700 ); + if ( result != 0 && errno != EEXIST ) { + /** @todo Convert this to use xine's log facility */ + fprintf(stderr, _("Unable to create %s directory: %s\n"), cachefile, strerror(errno)); + free(cachefile); + return NULL; + } + + strcat(cachefile, "/"PACKAGE); + result = mkdir( cachefile, 0700 ); + if ( result != 0 && errno != EEXIST ) { + /** @todo Convert this to use xine's log facility */ + fprintf(stderr, _("Unable to create %s directory: %s\n"), cachefile, strerror(errno)); + free(cachefile); + return NULL; + } + + strcat(cachefile, "/plugins.cache"); + + } else + strcat(cachefile, "/"PACKAGE"/plugins.cache"); + + return cachefile; +} /* * save catalog to cache file */ static void save_catalog (xine_t *this) { - FILE *fp; - char *cachefile, *cachefile_new, *dirfile; - const char *relname = CACHE_CATALOG_FILE; - const char *dirname = CACHE_CATALOG_DIR; + char *const cachefile = catalog_filename(this, 1); + char *cachefile_new; - const char *const homedir = xine_get_homedir(); + if ( ! cachefile ) return; - cachefile = _x_asprintf("%s/%s", homedir, relname); cachefile_new = _x_asprintf("%s.new", cachefile); - /* make sure homedir (~/.xine) exists */ - dirfile = _x_asprintf("%s/%s", homedir, dirname); - mkdir (dirfile, 0755); - free (dirfile); - if( (fp = fopen(cachefile_new,"w")) != NULL ) { int i; @@ -1083,7 +1208,7 @@ static void save_catalog (xine_t *this) { fprintf(fp, "cache_catalog_version=%d\n\n", CACHE_CATALOG_VERSION); for (i = 0; i < PLUGIN_TYPE_MAX; i++) { - save_plugin_list (fp, this->plugin_catalog->plugin_lists[i]); + save_plugin_list (this, fp, this->plugin_catalog->plugin_lists[i]); } if (fclose(fp)) { @@ -1116,13 +1241,11 @@ static void save_catalog (xine_t *this) { static void load_cached_catalog (xine_t *this) { FILE *fp; - char *cachefile; - const char *relname = CACHE_CATALOG_FILE; - - cachefile = _x_asprintf("%s/%s", xine_get_homedir(), relname); + char *const cachefile = catalog_filename(this, 0); + /* It can't return NULL without creating directories */ if( (fp = fopen(cachefile,"r")) != NULL ) { - load_plugin_list (fp, this->plugin_catalog->cache_list); + load_plugin_list (this, fp, this->plugin_catalog->cache_list); fclose(fp); } free(cachefile); @@ -1158,7 +1281,7 @@ void _x_scan_plugins (xine_t *this) { homedir = strdup(xine_get_homedir()); this->plugin_catalog = _new_catalog(); - load_cached_catalog (this); + XINE_PROFILE(load_cached_catalog (this)); if ((pluginpath = getenv("XINE_PLUGIN_PATH")) != NULL && *pluginpath) { char *p = pluginpath; @@ -1201,11 +1324,11 @@ void _x_scan_plugins (xine_t *this) { xine_list_delete (plugindirs); free(homedir); - if ((_x_flags & XINE_FLAG_NO_WRITE_CACHE) == 0) - save_catalog (this); - load_required_plugins (this); + if ((_x_flags & XINE_FLAG_NO_WRITE_CACHE) == 0) + XINE_PROFILE(save_catalog (this)); + map_decoders (this); } @@ -1247,6 +1370,7 @@ void _x_free_input_plugin (xine_stream_t *stream, input_plugin_t *input) { plugin_node_t *node = input->node; input->dispose(input); + if (node) { pthread_mutex_lock(&catalog->lock); dec_node_ref(node); @@ -1261,7 +1385,7 @@ static int probe_mime_type (xine_t *self, plugin_node_t *node, const char *mime_ { const unsigned int mime_type_len = strlen (mime_type); demux_class_t *cls = (demux_class_t *)node->plugin_class; - const char *mime = cls->get_mimetypes (cls); + const char *mime = cls->mimetypes; while (mime) { while (*mime == ';' || isspace (*mime)) @@ -1311,7 +1435,7 @@ static demux_plugin_t *probe_demux (xine_stream_t *stream, int method1, int meth /* If detecting by MRL, try the MIME type first (but not text/plain)... */ stream->content_detection_method = METHOD_EXPLICIT; - if (methods[i] == METHOD_BY_EXTENSION && + if (methods[i] == METHOD_BY_MRL && stream->input_plugin->get_optional_data && stream->input_plugin->get_optional_data (stream->input_plugin, NULL, INPUT_OPTIONAL_DATA_DEMUX_MIME_TYPE) != INPUT_OPTIONAL_UNSUPPORTED && stream->input_plugin->get_optional_data (stream->input_plugin, &mime_type, INPUT_OPTIONAL_DATA_MIME_TYPE) != INPUT_OPTIONAL_UNSUPPORTED && @@ -1326,6 +1450,12 @@ static demux_plugin_t *probe_demux (xine_stream_t *stream, int method1, int meth /* ... then try the extension */ stream->content_detection_method = methods[i]; + if ( stream->content_detection_method == METHOD_BY_MRL && + ! _x_demux_check_extension(input->get_mrl(input), + ((demux_class_t *)node->plugin_class)->extensions) + ) + continue; + if ((plugin = ((demux_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream, input))) { inc_node_ref(node); plugin->node = node; @@ -1347,16 +1477,16 @@ demux_plugin_t *_x_find_demux_plugin (xine_stream_t *stream, input_plugin_t *inp switch (stream->xine->demux_strategy) { case XINE_DEMUX_DEFAULT_STRATEGY: - return probe_demux (stream, METHOD_BY_CONTENT, METHOD_BY_EXTENSION, input); + return probe_demux (stream, METHOD_BY_CONTENT, METHOD_BY_MRL, input); case XINE_DEMUX_REVERT_STRATEGY: - return probe_demux (stream, METHOD_BY_EXTENSION, METHOD_BY_CONTENT, input); + return probe_demux (stream, METHOD_BY_MRL, METHOD_BY_CONTENT, input); case XINE_DEMUX_CONTENT_STRATEGY: return probe_demux (stream, METHOD_BY_CONTENT, -1, input); case XINE_DEMUX_EXTENSION_STRATEGY: - return probe_demux (stream, METHOD_BY_EXTENSION, -1, input); + return probe_demux (stream, METHOD_BY_MRL, -1, input); default: xprintf (stream->xine, XINE_VERBOSITY_LOG, @@ -1385,6 +1515,13 @@ demux_plugin_t *_x_find_demux_plugin_by_name(xine_stream_t *stream, const char * if (strcasecmp(node->info->id, name) == 0) { if (node->plugin_class || _load_plugin_class(stream->xine, node, NULL)) { + + if ( stream->content_detection_method == METHOD_BY_MRL && + ! _x_demux_check_extension(input->get_mrl(input), + ((demux_class_t *)node->plugin_class)->extensions) + ) + continue; + if ((plugin = ((demux_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream, input))) { inc_node_ref(node); plugin->node = node; @@ -1417,7 +1554,7 @@ demux_plugin_t *_x_find_demux_plugin_last_probe(xine_stream_t *stream, const cha demux_plugin_t *plugin = NULL; methods[0] = METHOD_BY_CONTENT; - methods[1] = METHOD_BY_EXTENSION; + methods[1] = METHOD_BY_MRL; methods[2] = -1; i = 0; @@ -1442,6 +1579,14 @@ demux_plugin_t *_x_find_demux_plugin_last_probe(xine_stream_t *stream, const cha xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "load_plugin: probing '%s' (method %d)...\n", node->info->id, stream->content_detection_method ); if (node->plugin_class || _load_plugin_class(xine, node, NULL)) { + + if ( stream->content_detection_method == METHOD_BY_MRL && + ! _x_demux_check_extension(input->get_mrl(input), + ((demux_class_t *)node->plugin_class)->extensions) + ) + continue; + + if ((plugin = ((demux_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream, input))) { xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "load_plugins: using demuxer '%s' (instead of '%s')\n", node->info->id, last_demux_name); @@ -1485,6 +1630,7 @@ void _x_free_demux_plugin (xine_stream_t *stream, demux_plugin_t *demux) { plugin_node_t *node = demux->node; demux->dispose(demux); + if (node) { pthread_mutex_lock(&catalog->lock); dec_node_ref(node); @@ -1664,7 +1810,7 @@ xine_video_port_t *xine_new_framegrab_video_port (xine_t *this) { vo_driver_t *driver; xine_video_port_t *port; plugin_catalog_t *catalog = this->plugin_catalog; - char *id; + const char *id; int list_id, list_size; driver = NULL; @@ -1878,8 +2024,8 @@ void xine_close_video_driver (xine_t *this, xine_video_port_t *vo_port) { * get autoplay mrl list from input plugin */ -char **xine_get_autoplay_mrls (xine_t *this, const char *plugin_id, - int *num_mrls) { +const char * const *xine_get_autoplay_mrls (xine_t *this, const char *plugin_id, + int *num_mrls) { plugin_catalog_t *catalog; plugin_node_t *node; @@ -1976,7 +2122,13 @@ video_decoder_t *_x_get_video_decoder (xine_stream_t *stream, uint8_t stream_typ vd = ((video_decoder_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream); - if (vd) { + if (vd == (video_decoder_t*)1) { + /* HACK: plugin failed to instantiate because required resources are unavailable at that time, + but may be available later, so don't remove this plugin from catalog. */ + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + "load_plugins: plugin %s failed to instantiate, resources temporarily unavailable.\n", node->info->id); + } + else if (vd) { inc_node_ref(node); vd->node = node; xprintf(stream->xine, XINE_VERBOSITY_DEBUG, @@ -2314,7 +2466,7 @@ const char *const *xine_list_post_plugins(xine_t *xine) { return catalog->ids; } -const char *const *xine_list_post_plugins_typed(xine_t *xine, int type) { +const char *const *xine_list_post_plugins_typed(xine_t *xine, uint32_t type) { plugin_catalog_t *catalog = xine->plugin_catalog; plugin_node_t *node; int i; @@ -2352,7 +2504,7 @@ const char *const *xine_list_post_plugins_typed(xine_t *xine, int type) { else \ return NULL; \ } \ - return ic->get_description(ic); \ + return dgettext(ic->text_domain ? : XINE_TEXTDOMAIN, ic->description); \ } \ } \ return NULL; \ @@ -2480,7 +2632,7 @@ void xine_post_dispose(xine_t *xine, xine_post_t *post_gen) { * @param joining String to use to join the various strings together. * @param final_length The pre-calculated final length of the string. */ -static char *_x_concatenate_with_string(char const **strings, size_t count, char *joining, size_t final_length) { +static char *_x_concatenate_with_string(char const **strings, size_t count, const char *joining, size_t final_length) { size_t i; char *const result = malloc(final_length+1); /* Better be safe */ char *str = result; @@ -2517,7 +2669,7 @@ char *xine_get_file_extensions (xine_t *self) { plugin_node_t *const node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); if (node->plugin_class || _load_plugin_class(self, node, NULL)) { demux_class_t *const cls = (demux_class_t *)node->plugin_class; - if( (extensions[list_id] = cls->get_extensions(cls)) != NULL ) + if( (extensions[list_id] = cls->extensions) != NULL ) len += strlen(extensions[list_id]) +1; } } @@ -2556,7 +2708,7 @@ char *xine_get_mime_types (xine_t *self) { plugin_node_t *const node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); if (node->plugin_class || _load_plugin_class(self, node, NULL)) { demux_class_t *const cls = (demux_class_t *)node->plugin_class; - if( (mimetypes[list_id] = cls->get_mimetypes(cls)) != NULL ) + if( (mimetypes[list_id] = cls->mimetypes) != NULL ) len += strlen(mimetypes[list_id]); } } @@ -2602,7 +2754,7 @@ char *xine_get_demux_for_mime_type (xine_t *self, const char *mime_type) { } -static void dispose_plugin_list (xine_sarray_t *list) { +static void dispose_plugin_list (xine_sarray_t *list, int is_cache) { plugin_node_t *node; decoder_info_t *decoder_info; @@ -2629,7 +2781,7 @@ static void dispose_plugin_list (xine_sarray_t *list) { case PLUGIN_VIDEO_DECODER: decoder_info = (decoder_info_t *)node->info->special_info; - free (decoder_info->supported_types); + free ((void *)decoder_info->supported_types); default: free ((void *)node->info->special_info); @@ -2637,8 +2789,21 @@ static void dispose_plugin_list (xine_sarray_t *list) { } /* free info structure and string copies */ - free (node->info->id); + free ((void *)node->info->id); free (node->info); + + /* don't free the entry list if the node is cache */ + if (!is_cache) { + if (node->config_entry_list) { + xine_list_iterator_t ite = xine_list_front (node->config_entry_list); + while (ite) { + char *key = xine_list_get_value (node->config_entry_list, ite); + free (key); + ite = xine_list_next (node->config_entry_list, ite); + } + xine_list_delete(node->config_entry_list); + } + } free (node); } xine_sarray_delete(list); @@ -2671,10 +2836,10 @@ void _x_dispose_plugins (xine_t *this) { int i; for (i = 0; i < PLUGIN_TYPE_MAX; i++) { - dispose_plugin_list (this->plugin_catalog->plugin_lists[i]); + dispose_plugin_list (this->plugin_catalog->plugin_lists[i], 0); } - dispose_plugin_list (this->plugin_catalog->cache_list); + dispose_plugin_list (this->plugin_catalog->cache_list, 1); dispose_plugin_file_list (this->plugin_catalog->file_list); for (i = 0; this->plugin_catalog->prio_desc[i]; i++) diff --git a/src/xine-engine/lrb.c b/src/xine-engine/lrb.c index 89d4b2654..9acc2f1b6 100644 --- a/src/xine-engine/lrb.c +++ b/src/xine-engine/lrb.c @@ -23,7 +23,7 @@ #endif #include "lrb.h" -#include "xineutils.h" +#include <xine/xineutils.h> lrb_t *lrb_new (int max_num_entries, fifo_buffer_t *fifo) { diff --git a/src/xine-engine/lrb.h b/src/xine-engine/lrb.h index f64e50eab..dfac5e543 100644 --- a/src/xine-engine/lrb.h +++ b/src/xine-engine/lrb.h @@ -24,11 +24,7 @@ #ifndef HAVE_LRB_H #define HAVE_LRB_H -#ifdef XINE_COMPILE -# include "buffer.h" -#else -# include <xine/buffer.h> -#endif +#include <xine/buffer.h> typedef struct { diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index 8cd36f70f..0ee481d35 100644 --- a/src/xine-engine/metronom.c +++ b/src/xine-engine/metronom.c @@ -40,9 +40,9 @@ #define METRONOM_INTERNAL #define METRONOM_CLOCK_INTERNAL -#include "xine_internal.h" -#include "metronom.h" -#include "xineutils.h" +#include <xine/xine_internal.h> +#include <xine/metronom.h> +#include <xine/xineutils.h> #define MAX_AUDIO_DELTA 1600 #define AUDIO_SAMPLE_NUM 32768 @@ -848,7 +848,8 @@ static void metronom_unregister_scr (metronom_clock_t *this, scr_plugin_t *scr) this->scr_master = get_master_scr(this); } -static int metronom_sync_loop (metronom_clock_t *this) { +static void *metronom_sync_loop (void *const this_gen) { + metronom_clock_t *const this = (metronom_clock_t *const)this_gen; struct timeval tv; struct timespec ts; @@ -871,7 +872,7 @@ static int metronom_sync_loop (metronom_clock_t *this) { pthread_mutex_unlock (&this->lock); } - return 0; + return NULL; } static void metronom_exit (metronom_t *this) { @@ -987,7 +988,7 @@ metronom_clock_t *_x_metronom_clock_init(xine_t *xine) this->thread_running = 1; if ((err = pthread_create(&this->sync_thread, NULL, - (void*(*)(void*)) metronom_sync_loop, this)) != 0) + metronom_sync_loop, this)) != 0) xprintf(this->xine, XINE_VERBOSITY_NONE, "cannot create sync thread (%s)\n", strerror(err)); diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h deleted file mode 100644 index 946aa0991..000000000 --- a/src/xine-engine/metronom.h +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright (C) 2000-2004 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * metronom: general pts => virtual calculation/assoc - * - * virtual pts: unit 1/90000 sec, always increasing - * can be used for synchronization - * video/audio frame with same pts also have same vpts - * but pts is likely to differ from vpts - * - * the basic idea is: - * video_pts + video_wrap_offset = video_vpts - * audio_pts + audio_wrap_offset = audio_vpts - * - * - video_wrap_offset should be equal to audio_wrap_offset as to have - * perfect audio and video sync. They will differ on brief periods due - * discontinuity correction. - * - metronom should also interpolate vpts values most of the time as - * video_pts and audio_vpts are not given for every frame. - * - corrections to the frame rate may be needed to cope with bad - * encoded streams. - */ - -#ifndef HAVE_METRONOM_H -#define HAVE_METRONOM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <pthread.h> - -#ifdef XINE_COMPILE -# include "video_out.h" -# include "xine.h" -#else -# include <xine/video_out.h> -# include <xine.h> -#endif - -typedef struct metronom_s metronom_t ; -typedef struct metronom_clock_s metronom_clock_t; -typedef struct scr_plugin_s scr_plugin_t; - -/* metronom prebuffer can be adjusted with XINE_PARAM_METRONOM_PREBUFFER. - * it sets how much the first video/audio frame should be delayed to - * have some prebuffering at the output layers. reducing this value (about - * 1/8 sec) may result in faster seeking (good to simulate play backwards, - * for example). - */ -#define PREBUFFER_PTS_OFFSET 12000 - - /* see below */ -#define DISC_STREAMSTART 0 -#define DISC_RELATIVE 1 -#define DISC_ABSOLUTE 2 -#define DISC_STREAMSEEK 3 - -struct metronom_s { - - /* - * called by audio output driver to inform metronom about current audio - * samplerate - * - * parameter pts_per_smpls : 1/90000 sec per 65536 samples - */ - void (*set_audio_rate) (metronom_t *self, int64_t pts_per_smpls); - - /* - * called by video output driver for *every* frame - * - * parameter frame containing pts, scr, ... information - * - * will set vpts field in frame - * - * this function will also update video_wrap_offset if a discontinuity - * is detected (read the comentaries below about discontinuities). - * - */ - - void (*got_video_frame) (metronom_t *self, vo_frame_t *frame); - - /* - * called by audio output driver whenever audio samples are delivered to it - * - * parameter pts : pts for audio data if known, 0 otherwise - * nsamples : number of samples delivered - * - * return value: virtual pts for audio data - * - * this function will also update audio_wrap_offset if a discontinuity - * is detected (read the comentaries below about discontinuities). - * - */ - - int64_t (*got_audio_samples) (metronom_t *self, int64_t pts, - int nsamples); - - /* - * called by SPU decoder whenever a packet is delivered to it - * - * parameter pts : pts for SPU packet if known, 0 otherwise - * - * return value: virtual pts for SPU packet - * (this is the only pts to vpts function that cannot update the wrap_offset - * due to the lack of regularity on spu packets) - */ - - int64_t (*got_spu_packet) (metronom_t *self, int64_t pts); - - /* - * tell metronom about discontinuities. - * - * these functions are called due to a discontinuity detected at - * demux stage. - * - * there are different types of discontinuities: - * - * DISC_STREAMSTART : new stream starts, expect pts values to start - * from zero immediately - * DISC_RELATIVE : typically a wrap-around, expect pts with - * a specified offset from the former ones soon - * DISC_ABSOLUTE : typically a new menu stream (nav packets) - * pts will start from given value soon - * DISC_STREAMSEEK : used by video and audio decoder loop, - * when a buffer with BUF_FLAG_SEEK set is encountered; - * applies the necessary vpts offset for the seek in - * metronom, but keeps the vpts difference between - * audio and video, so that metronom doesn't cough - */ - void (*handle_audio_discontinuity) (metronom_t *self, int type, int64_t disc_off); - void (*handle_video_discontinuity) (metronom_t *self, int type, int64_t disc_off); - - /* - * set/get options for metronom, constants see below - */ - void (*set_option) (metronom_t *self, int option, int64_t value); - int64_t (*get_option) (metronom_t *self, int option); - - /* - * set a master metronom - * this is currently useful to sync independently generated streams - * (e.g. by post plugins) to the discontinuity domain of another - * metronom - */ - void (*set_master) (metronom_t *self, metronom_t *master); - - void (*exit) (metronom_t *self); - -#ifdef METRONOM_INTERNAL - /* - * metronom internal stuff - */ - xine_t *xine; - - metronom_t *master; - - int64_t pts_per_smpls; - - int64_t video_vpts; - int64_t spu_vpts; - int64_t audio_vpts; - int64_t audio_vpts_rmndr; /* the remainder for integer division */ - - int64_t vpts_offset; - - int64_t video_drift; - int64_t video_drift_step; - - int audio_samples; - int64_t audio_drift_step; - - int64_t prebuffer; - int64_t av_offset; - int64_t spu_offset; - - pthread_mutex_t lock; - - int have_video; - int have_audio; - int video_discontinuity_count; - int audio_discontinuity_count; - int discontinuity_handled_count; - pthread_cond_t video_discontinuity_reached; - pthread_cond_t audio_discontinuity_reached; - - int force_video_jump; - int force_audio_jump; - - int64_t img_duration; - int img_cpt; - int64_t last_video_pts; - int64_t last_audio_pts; - - int video_mode; -#endif -}; - -/* - * metronom options - */ - -#define METRONOM_AV_OFFSET 2 -#define METRONOM_ADJ_VPTS_OFFSET 3 -#define METRONOM_FRAME_DURATION 4 -#define METRONOM_SPU_OFFSET 5 -#define METRONOM_VPTS_OFFSET 6 -#define METRONOM_PREBUFFER 7 - -metronom_t *_x_metronom_init (int have_video, int have_audio, xine_t *xine) XINE_MALLOC XINE_PROTECTED; - -/* FIXME: reorder this structure on the next cleanup to remove the dummies */ -struct metronom_clock_s { - - /* - * set/get options for clock, constants see below - */ - void (*set_option) (metronom_clock_t *self, int option, int64_t value); - int64_t (*get_option) (metronom_clock_t *self, int option); - - /* - * system clock reference (SCR) functions - */ - -#ifdef METRONOM_CLOCK_INTERNAL - /* - * start clock (no clock reset) - * at given pts - */ - void (*start_clock) (metronom_clock_t *self, int64_t pts); - - - /* - * stop metronom clock - */ - void (*stop_clock) (metronom_clock_t *self); - - - /* - * resume clock from where it was stopped - */ - void (*resume_clock) (metronom_clock_t *self); -#else - void *dummy1; - void *dummy2; - void *dummy3; -#endif - - - /* - * get current clock value in vpts - */ - int64_t (*get_current_time) (metronom_clock_t *self); - - - /* - * adjust master clock to external timer (e.g. audio hardware) - */ - void (*adjust_clock) (metronom_clock_t *self, int64_t desired_pts); - -#ifdef METRONOM_CLOCK_INTERNAL - /* - * set clock speed - * for constants see xine_internal.h - */ - - int (*set_fine_speed) (metronom_clock_t *self, int speed); -#else - void *dummy4; -#endif - - /* - * (un)register a System Clock Reference provider at the metronom - */ - int (*register_scr) (metronom_clock_t *self, scr_plugin_t *scr); - void (*unregister_scr) (metronom_clock_t *self, scr_plugin_t *scr); - -#ifdef METRONOM_CLOCK_INTERNAL - void (*exit) (metronom_clock_t *self); - - xine_t *xine; - - scr_plugin_t *scr_master; - scr_plugin_t **scr_list; - pthread_t sync_thread; - int thread_running; - int scr_adjustable; -#else - void *dummy5; - void *dummy6; - void *dummy7; - void *dummy8; - pthread_t dummy9; - int dummy10; - int dummy11; -#endif - - int speed; - -#ifdef METRONOM_CLOCK_INTERNAL - pthread_mutex_t lock; - pthread_cond_t cancel; -#endif -}; - -metronom_clock_t *_x_metronom_clock_init(xine_t *xine) XINE_MALLOC XINE_PROTECTED; - -/* - * clock options - */ - -#define CLOCK_SCR_ADJUSTABLE 1 - -/* - * SCR (system clock reference) plugins - */ - -struct scr_plugin_s -{ - int interface_version; - - int (*get_priority) (scr_plugin_t *self); - - /* - * set/get clock speed - * - * for speed constants see xine_internal.h - * returns actual speed - */ - - int (*set_fine_speed) (scr_plugin_t *self, int speed); - - void (*adjust) (scr_plugin_t *self, int64_t vpts); - - void (*start) (scr_plugin_t *self, int64_t start_vpts); - - int64_t (*get_current) (scr_plugin_t *self); - - void (*exit) (scr_plugin_t *self); - - metronom_clock_t *clock; -}; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c index 6914f6386..cf54cac84 100644 --- a/src/xine-engine/osd.c +++ b/src/xine-engine/osd.c @@ -20,8 +20,6 @@ * OSD stuff (text and graphic primitives) */ -#define __OSD_C__ - #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -40,6 +38,8 @@ # include <iconv.h> #endif +#include <basedir.h> + #define LOG_MODULE "osd" #define LOG_VERBOSE /* @@ -48,11 +48,11 @@ #define XINE_ENGINE_INTERNAL -#include "xine_internal.h" +#include <xine/xine_internal.h> #include "xine-engine/bswap.h" -#include "xineutils.h" -#include "video_out.h" -#include "osd.h" +#include <xine/xineutils.h> +#include <xine/video_out.h> +#include <xine/osd.h> #ifdef HAVE_FT2 #include <ft2build.h> @@ -97,6 +97,100 @@ # define FT_LOAD_FLAGS (FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING) #endif +/* This text descriptions are used for config screen */ +static const char *const textpalettes_str[NUMBER_OF_TEXT_PALETTES+1] = { + "white-black-transparent", + "white-none-transparent", + "white-none-translucid", + "yellow-black-transparent", + NULL}; + +/* + Palette entries as used by osd fonts: + + 0: not used by font, always transparent + 1: font background, usually transparent, may be used to implement + translucid boxes where the font will be printed. + 2-5: transition between background and border (usually only alpha + value changes). + 6: font border. if the font is to be displayed without border this + will probably be adjusted to font background or near. + 7-9: transition between border and foreground + 10: font color (foreground) +*/ + +/* + The palettes below were made by hand, ie, i just throw + values that seemed to do the transitions i wanted. + This can surelly be improved a lot. [Miguel] +*/ + +static const clut_t textpalettes_color[NUMBER_OF_TEXT_PALETTES][TEXT_PALETTE_SIZE] = { +/* white, black border, transparent */ + { + CLUT_Y_CR_CB_INIT(0x00, 0x00, 0x00), /*0*/ + CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*1*/ + CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*2*/ + CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*3*/ + CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*4*/ + CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*5*/ + CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*6*/ + CLUT_Y_CR_CB_INIT(0x40, 0x80, 0x80), /*7*/ + CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), /*8*/ + CLUT_Y_CR_CB_INIT(0xc0, 0x80, 0x80), /*9*/ + CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*10*/ + }, + /* white, no border, transparent */ + { + CLUT_Y_CR_CB_INIT(0x00, 0x00, 0x00), /*0*/ + CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*1*/ + CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*2*/ + CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*3*/ + CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*4*/ + CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*5*/ + CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*6*/ + CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*7*/ + CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*8*/ + CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*9*/ + CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*10*/ + }, + /* white, no border, translucid */ + { + CLUT_Y_CR_CB_INIT(0x00, 0x00, 0x00), /*0*/ + CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), /*1*/ + CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), /*2*/ + CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), /*3*/ + CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), /*4*/ + CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), /*5*/ + CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), /*6*/ + CLUT_Y_CR_CB_INIT(0xa0, 0x80, 0x80), /*7*/ + CLUT_Y_CR_CB_INIT(0xc0, 0x80, 0x80), /*8*/ + CLUT_Y_CR_CB_INIT(0xe0, 0x80, 0x80), /*9*/ + CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*10*/ + }, + /* yellow, black border, transparent */ + { + CLUT_Y_CR_CB_INIT(0x00, 0x00, 0x00), /*0*/ + CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*1*/ + CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*2*/ + CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*3*/ + CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*4*/ + CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*5*/ + CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*6*/ + CLUT_Y_CR_CB_INIT(0x40, 0x84, 0x60), /*7*/ + CLUT_Y_CR_CB_INIT(0x70, 0x88, 0x40), /*8*/ + CLUT_Y_CR_CB_INIT(0xb0, 0x8a, 0x20), /*9*/ + CLUT_Y_CR_CB_INIT(0xff, 0x90, 0x00), /*10*/ + }, +}; + +static const uint8_t textpalettes_trans[NUMBER_OF_TEXT_PALETTES][TEXT_PALETTE_SIZE] = { + {0, 0, 3, 6, 8, 10, 12, 14, 15, 15, 15 }, + {0, 0, 0, 0, 0, 0, 2, 6, 9, 12, 15 }, + {0, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15 }, + {0, 0, 3, 6, 8, 10, 12, 14, 15, 15, 15 }, +}; + typedef struct osd_fontchar_s { uint8_t *bmp; uint16_t code; @@ -157,9 +251,16 @@ static osd_object_t *XINE_MALLOC osd_new_object (osd_renderer_t *this, int width osd->next = this->osds; this->osds = osd; + osd->video_window_x = 0; + osd->video_window_y = 0; + osd->video_window_width = 0; + osd->video_window_height = 0; + osd->extent_width = 0; + osd->extent_height = 0; osd->width = width; osd->height = height; osd->area = calloc(width, height); + osd->area_touched = 0; osd->x1 = width; osd->y1 = height; @@ -183,6 +284,66 @@ static osd_object_t *XINE_MALLOC osd_new_object (osd_renderer_t *this, int width return osd; } +/* + * osd extent must be set to achive video resolution independent osds + * both sizes must be > 0 to take effect. otherwise, video resolution + * will still be used. the extent defines the reference coordinate + * system which is matched to the video output area. + */ +static void osd_set_extent (osd_object_t *osd, int extent_width, int extent_height) { + + osd->extent_width = extent_width; + osd->extent_height = extent_height; +} + +/* + * osd video window defines an area withing osd extent where the + * video shall be scaled to while an osd is displayed on screen. + * both width and height must be > 0 to take effect. + */ +static void osd_set_video_window (osd_object_t *osd, int window_x, int window_y, int window_width, int window_height) { + + osd->video_window_x = window_x; + osd->video_window_y = window_y; + osd->video_window_width = window_width; + osd->video_window_height = window_height; +} + +static argb_layer_t *argb_layer_create() { + + argb_layer_t *argb_layer = (argb_layer_t *)calloc(1, sizeof (argb_layer_t)); + + pthread_mutex_init(&argb_layer->mutex, NULL); + return argb_layer; +} + +static void argb_layer_destroy(argb_layer_t *argb_layer) { + + pthread_mutex_destroy(&argb_layer->mutex); + free(argb_layer); +} + +void set_argb_layer_ptr(argb_layer_t **dst, argb_layer_t *src) { + + if (src) { + pthread_mutex_lock(&src->mutex); + ++src->ref_count; + pthread_mutex_unlock(&src->mutex); + } + + if (*dst) { + int free_argb_layer; + + pthread_mutex_lock(&(*dst)->mutex); + free_argb_layer = (0 == --(*dst)->ref_count); + pthread_mutex_unlock(&(*dst)->mutex); + + if (free_argb_layer) + argb_layer_destroy(*dst); + } + + *dst = src; +} /* @@ -242,12 +403,23 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { this->event.object.handle = osd->handle; memset( this->event.object.overlay, 0, sizeof(*this->event.object.overlay) ); + + set_argb_layer_ptr(&this->event.object.overlay->argb_layer, osd->argb_layer); + this->event.object.overlay->unscaled = unscaled; this->event.object.overlay->x = osd->display_x + osd->x1; this->event.object.overlay->y = osd->display_y + osd->y1; this->event.object.overlay->width = osd->x2 - osd->x1; this->event.object.overlay->height = osd->y2 - osd->y1; + this->event.object.overlay->video_window_x = osd->video_window_x; + this->event.object.overlay->video_window_y = osd->video_window_y; + this->event.object.overlay->video_window_width = osd->video_window_width; + this->event.object.overlay->video_window_height = osd->video_window_height; + + this->event.object.overlay->extent_width = osd->extent_width; + this->event.object.overlay->extent_height = osd->extent_height; + this->event.object.overlay->hili_top = 0; this->event.object.overlay->hili_bottom = this->event.object.overlay->height; this->event.object.overlay->hili_left = 0; @@ -255,57 +427,65 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { /* there will be at least that many rle objects (one for each row) */ this->event.object.overlay->num_rle = 0; - /* We will never need more rle objects than columns in any row - Rely on lazy page allocation to avoid us actually taking up - this much RAM */ - this->event.object.overlay->data_size = osd->width * osd->height; - rle_p = this->event.object.overlay->rle = - malloc(this->event.object.overlay->data_size * sizeof(rle_elem_t) ); - - for( y = osd->y1; y < osd->y2; y++ ) { + if (!osd->area_touched) { + /* avoid rle encoding when only argb_layer is modified */ + this->event.object.overlay->data_size = 0; + rle_p = this->event.object.overlay->rle = NULL; + } else { + /* We will never need more rle objects than columns in any row + Rely on lazy page allocation to avoid us actually taking up + this much RAM */ + this->event.object.overlay->data_size = osd->width * osd->height; + rle_p = this->event.object.overlay->rle = + malloc(this->event.object.overlay->data_size * sizeof(rle_elem_t) ); + + for( y = osd->y1; y < osd->y2; y++ ) { #ifdef DEBUG_RLE - lprintf("osd_show %p y = %d: ", osd, y); + lprintf("osd_show %p y = %d: ", osd, y); #endif - c = osd->area + y * osd->width + osd->x1; + c = osd->area + y * osd->width + osd->x1; - /* initialize a rle object with the first pixel's color */ - rle.len = 1; - rle.color = *c++; + /* initialize a rle object with the first pixel's color */ + rle.len = 1; + rle.color = *c++; - /* loop over the remaining pixels in the row */ - for( x = osd->x1 + rle.len; x < osd->x2; x++, c++ ) { - if( rle.color != *c ) { + /* loop over the remaining pixels in the row */ + for( x = osd->x1 + rle.len; x < osd->x2; x++, c++ ) { + if( rle.color != *c ) { #ifdef DEBUG_RLE - lprintf("(%d, %d), ", rle.len, rle.color); + lprintf("(%d, %d), ", rle.len, rle.color); #endif - *rle_p++ = rle; - this->event.object.overlay->num_rle++; + *rle_p++ = rle; + this->event.object.overlay->num_rle++; - rle.color = *c; - rle.len = 1; - } else { - rle.len++; + rle.color = *c; + rle.len = 1; + } else { + rle.len++; + } } - } #ifdef DEBUG_RLE - lprintf("(%d, %d)\n", rle.len, rle.color); + lprintf("(%d, %d)\n", rle.len, rle.color); #endif - *rle_p++ = rle; - this->event.object.overlay->num_rle++; - } + *rle_p++ = rle; + this->event.object.overlay->num_rle++; + } #ifdef DEBUG_RLE - lprintf("osd_show %p rle ends\n", osd); + lprintf("osd_show %p rle ends\n", osd); #endif - lprintf("num_rle = %d\n", this->event.object.overlay->num_rle); + lprintf("num_rle = %d\n", this->event.object.overlay->num_rle); - memcpy(this->event.object.overlay->hili_color, osd->color, sizeof(osd->color)); - memcpy(this->event.object.overlay->hili_trans, osd->trans, sizeof(osd->trans)); - memcpy(this->event.object.overlay->color, osd->color, sizeof(osd->color)); - memcpy(this->event.object.overlay->trans, osd->trans, sizeof(osd->trans)); + memcpy(this->event.object.overlay->hili_color, osd->color, sizeof(osd->color)); + memcpy(this->event.object.overlay->hili_trans, osd->trans, sizeof(osd->trans)); + memcpy(this->event.object.overlay->color, osd->color, sizeof(osd->color)); + memcpy(this->event.object.overlay->trans, osd->trans, sizeof(osd->trans)); + } this->event.event_type = OVERLAY_EVENT_SHOW; this->event.vpts = vpts; ovl_manager->add_event(ovl_manager, (void *)&this->event); + + set_argb_layer_ptr(&this->event.object.overlay->argb_layer, NULL); } else { /* osd empty - hide it */ _osd_hide(osd, vpts); @@ -385,11 +565,24 @@ static int osd_hide (osd_object_t *osd, int64_t vpts) { static void osd_clear (osd_object_t *osd) { lprintf("osd=%p\n",osd); - memset(osd->area, 0, osd->width * osd->height); + if (osd->area_touched) { + osd->area_touched = 0; + memset(osd->area, 0, osd->width * osd->height); + } + osd->x1 = osd->width; osd->y1 = osd->height; osd->x2 = 0; osd->y2 = 0; + + if (osd->argb_layer) { + pthread_mutex_lock(&osd->argb_layer->mutex); + osd->argb_layer->x1 = osd->x1; + osd->argb_layer->y1 = osd->y1; + osd->argb_layer->x2 = osd->x2; + osd->argb_layer->y2 = osd->y2; + pthread_mutex_unlock(&osd->argb_layer->mutex); + } } /* @@ -411,6 +604,7 @@ static void osd_point (osd_object_t *osd, int x, int y, int color) { osd->x2 = MAX(osd->x2, (x + 1)); osd->y1 = MIN(osd->y1, y); osd->y2 = MAX(osd->y2, (y + 1)); + osd->area_touched = 1; c = osd->area + y * osd->width + x; *c = color; @@ -470,6 +664,7 @@ static void osd_line (osd_object_t *osd, osd->x2 = MAX( osd->x2, x2 ); osd->y1 = MIN( osd->y1, y1 ); osd->y2 = MAX( osd->y2, y2 ); + osd->area_touched = 1; dx = x2 - x1; dy = y2 - y1; @@ -583,6 +778,7 @@ static void osd_filled_rect (osd_object_t *osd, osd->x2 = MAX( osd->x2, dx ); osd->y1 = MIN( osd->y1, y ); osd->y2 = MAX( osd->y2, dy ); + osd->area_touched = 1; dx -= x; dy -= y; @@ -819,6 +1015,93 @@ static int osd_renderer_unload_font(osd_renderer_t *this, char *fontname ) { } #ifdef HAVE_FT2 + +# ifdef HAVE_FONTCONFIG +/** + * @brief Look up a font name using FontConfig library + * @param osd The OSD object to load the font for. + * @param fontname Name of the font to look up. + * @param size Size of the font to look for. + * + * @return If the lookup was done correctly, a non-zero value is returned. + */ +static int osd_lookup_fontconfig( osd_object_t *osd, const char *const fontname, const int size ) { + FcPattern *pat = NULL, *match = NULL; + FcFontSet *fs = FcFontSetCreate(); + FcResult result; + + pat = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, fontname, FC_SIZE, FcTypeDouble, (double)size, NULL); + FcConfigSubstitute(NULL, pat, FcMatchPattern); + FcDefaultSubstitute(pat); + + match = FcFontMatch(NULL, pat, &result); + FcPatternDestroy(pat); + + if ( ! match ) { + FcFontSetDestroy(fs); + xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, + _("osd: error matching font %s with FontConfig"), fontname); + return 0; + } + FcFontSetAdd(fs, match); + + if ( fs->nfont != 0 ) { + FcChar8 *filename = NULL; + FcPatternGetString(fs->fonts[0], FC_FILE, 0, &filename); + if ( ! FT_New_Face(osd->ft2->library, (const char*)filename, 0, &osd->ft2->face) ) { + FcFontSetDestroy(fs); + return 1; + } + + xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, + _("osd: error loading font %s with FontConfig"), fontname); + return 0; + } else { + xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, + _("osd: error looking up font %s with FontConfig"), fontname); + return 0; + } +} +# endif /* HAVE_FONTCONFIG */ + +/** + * @brief Look up a font file using XDG data directories. + * @param osd The OSD object to load the font for. + * @param fontname Name (absolute or relative) of the font to look up. + * + * @return If the lookup was done correctly, a non-zero value is returned. + * + * @see XDG Base Directory specification: + * http://standards.freedesktop.org/basedir-spec/latest/index.html + */ +static int osd_lookup_xdg( osd_object_t *osd, const char *const fontname ) { + const char *const *data_dirs = xdgSearchableDataDirectories(&osd->renderer->stream->xine->basedir_handle); + + /* try load font from current directory or from an absolute path */ + if ( FT_New_Face(osd->ft2->library, fontname, 0, &osd->ft2->face) == FT_Err_Ok ) + return 1; + + if ( data_dirs ) + while( (*data_dirs) && *(*data_dirs) ) { + FT_Error fte = FT_Err_Ok; + char *fontpath = NULL; + fontpath = _x_asprintf("%s/"PACKAGE"/fonts/%s", *data_dirs, fontname); + + fte = FT_New_Face(osd->ft2->library, fontpath, 0, &osd->ft2->face); + + free(fontpath); + + if ( fte == FT_Err_Ok ) + return 1; + + data_dirs++; + } + + xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, + _("osd: error loading font %s with in XDG data directories.\n"), fontname); + return 0; +} + static int osd_set_font_freetype2( osd_object_t *osd, const char *fontname, int size ) { if (!osd->ft2) { osd->ft2 = calloc(1, sizeof(osd_ft2context_t)); @@ -836,67 +1119,18 @@ static int osd_set_font_freetype2( osd_object_t *osd, const char *fontname, int osd->ft2->face = NULL; } + do { /* while 0 */ #ifdef HAVE_FONTCONFIG - do { - FcPattern *pat = NULL, *match = NULL; - FcFontSet *fs = FcFontSetCreate(); - FcResult result; - - pat = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, fontname, FC_SIZE, FcTypeDouble, (double)size, NULL); - FcConfigSubstitute(NULL, pat, FcMatchPattern); - FcDefaultSubstitute(pat); - - match = FcFontMatch(NULL, pat, &result); - FcPatternDestroy(pat); - - if ( ! match ) { - FcFontSetDestroy(fs); - xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, - _("osd: error matching font %s with FontConfig"), fontname); + if ( osd_lookup_fontconfig(osd, fontname, size) ) break; - } - FcFontSetAdd(fs, match); - - if ( fs->nfont != 0 ) { - FcChar8 *filename = NULL; - FcPatternGetString(fs->fonts[0], FC_FILE, 0, &filename); - if ( ! FT_New_Face(osd->ft2->library, (const char*)filename, 0, &osd->ft2->face) ) { - FcFontSetDestroy(fs); - goto end; - } - - xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, - _("osd: error loading font %s with FontConfig"), fontname); - } else { - xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, - _("osd: error looking up font %s with FontConfig"), fontname); - } - } while(0); #endif - { - char pathname[1024]; - /* try load font from current directory */ - if ( !FT_New_Face(osd->ft2->library, fontname, 0, &osd->ft2->face) ) - goto end; - - /* try load font from home directory */ - snprintf(pathname, 1024, "%s/.xine/fonts/%s", xine_get_homedir(), fontname); - if ( !FT_New_Face(osd->ft2->library, pathname, 0, &osd->ft2->face) ) - goto end; - - /* try load font from xine font directory */ - snprintf(pathname, 1024, "%s/%s", XINE_FONTDIR, fontname); - if ( !FT_New_Face(osd->ft2->library, pathname, 0, &osd->ft2->face) ) - goto end; - - xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, - _("osd: error loading font %s with ft2\n"), fontname); - } + if ( osd_lookup_xdg(osd, fontname) ) + break; - osd_free_ft2 (osd); - return 0; + osd_free_ft2 (osd); + return 0; + } while(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")); @@ -1143,6 +1377,7 @@ static int osd_render_text (osd_object_t *osd, int x1, int y1, if( x1 < osd->x1 ) osd->x1 = x1; if( y1 < osd->y1 ) osd->y1 = y1; + osd->area_touched = 1; inbuf = text; inbytesleft = strlen(text); @@ -1467,6 +1702,12 @@ static void osd_free_object (osd_object_t *osd_to_close) { osd_to_close->handle = -1; /* handle will be freed */ } + if (osd_to_close->argb_layer) { + /* clear argb buffer pointer so that buffer may be freed safely after returning */ + this->set_argb_buffer(osd_to_close, NULL, 0, 0, 0, 0); + set_argb_layer_ptr(&osd_to_close->argb_layer, NULL); + } + pthread_mutex_lock (&this->osd_mutex); last = NULL; @@ -1528,6 +1769,7 @@ static void osd_draw_bitmap(osd_object_t *osd, uint8_t *bitmap, osd->x2 = MAX( osd->x2, x1+width ); osd->y1 = MIN( osd->y1, y1 ); osd->y2 = MAX( osd->y2, y1+height ); + osd->area_touched = 1; for( y=0; y<height; y++ ) { if ( palette_map ) { @@ -1546,21 +1788,64 @@ static void osd_draw_bitmap(osd_object_t *osd, uint8_t *bitmap, } } +static void osd_set_argb_buffer(osd_object_t *osd, uint32_t *argb_buffer, + int dirty_x, int dirty_y, int dirty_width, int dirty_height) +{ + if (!osd->argb_layer) + set_argb_layer_ptr(&osd->argb_layer, argb_layer_create()); + + if (osd->argb_layer->buffer != argb_buffer) { + dirty_x = 0; + dirty_y = 0; + dirty_width = osd->width; + dirty_height = osd->height; + } + + /* keep osd_object clipping behavior */ + osd->x1 = MIN( osd->x1, dirty_x ); + osd->x2 = MAX( osd->x2, dirty_x + dirty_width ); + osd->y1 = MIN( osd->y1, dirty_y ); + osd->y2 = MAX( osd->y2, dirty_y + dirty_height ); + + pthread_mutex_lock(&osd->argb_layer->mutex); + + /* argb layer update area accumulation */ + osd->argb_layer->x1 = MIN( osd->argb_layer->x1, dirty_x ); + osd->argb_layer->x2 = MAX( osd->argb_layer->x2, dirty_x + dirty_width ); + osd->argb_layer->y1 = MIN( osd->argb_layer->y1, dirty_y ); + osd->argb_layer->y2 = MAX( osd->argb_layer->y2, dirty_y + dirty_height ); + + osd->argb_layer->buffer = argb_buffer; + + pthread_mutex_unlock(&osd->argb_layer->mutex); +} + static uint32_t osd_get_capabilities (osd_object_t *osd) { osd_renderer_t *this = osd->renderer; uint32_t capabilities = 0; + uint32_t vo_capabilities; #ifdef HAVE_FT2 capabilities |= XINE_OSD_CAP_FREETYPE2; #endif this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 1); - if( this->stream->video_out->get_capabilities(this->stream->video_out) & - VO_CAP_UNSCALED_OVERLAY) - capabilities |= XINE_OSD_CAP_UNSCALED; + vo_capabilities = this->stream->video_out->get_capabilities(this->stream->video_out); this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1); + if (vo_capabilities & VO_CAP_UNSCALED_OVERLAY) + capabilities |= XINE_OSD_CAP_UNSCALED; + + if (vo_capabilities & VO_CAP_CUSTOM_EXTENT_OVERLAY) + capabilities |= XINE_OSD_CAP_CUSTOM_EXTENT; + + if (vo_capabilities & VO_CAP_ARGB_LAYER_OVERLAY) + capabilities |= XINE_OSD_CAP_ARGB_LAYER; + + if (vo_capabilities & VO_CAP_VIDEO_WINDOW_OVERLAY) + capabilities |= XINE_OSD_CAP_VIDEO_WINDOW; + return capabilities; } @@ -1572,7 +1857,6 @@ static uint32_t osd_get_capabilities (osd_object_t *osd) { osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) { osd_renderer_t *this; - char str[1024]; this = calloc(1, sizeof(osd_renderer_t)); this->stream = stream; @@ -1583,12 +1867,22 @@ osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) { /* * load available fonts */ + { + const char *const *data_dirs = xdgSearchableDataDirectories(&stream->xine->basedir_handle); + if ( data_dirs ) + while( (*data_dirs) && *(*data_dirs) ) { + /* sizeof("") takes care of the final NUL byte */ + char *fontpath = xine_xmalloc( strlen(*data_dirs) + sizeof("/"PACKAGE"/fonts/") ); + strcpy(fontpath, *data_dirs); + strcat(fontpath, "/"PACKAGE"/fonts/"); - osd_preload_fonts (this, XINE_FONTDIR); + osd_preload_fonts(this, fontpath); - snprintf (str, 1024, "%s/.xine/fonts", xine_get_homedir ()); + free(fontpath); - osd_preload_fonts (this, str); + data_dirs++; + } + } this->textpalette = this->stream->xine->config->register_enum (this->stream->xine->config, "ui.osd.text_palette", 0, @@ -1621,8 +1915,11 @@ osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) { this->get_text_size = osd_get_text_size; this->close = osd_renderer_close; this->draw_bitmap = osd_draw_bitmap; + this->set_argb_buffer = osd_set_argb_buffer; this->show_unscaled = osd_show_unscaled; this->get_capabilities = osd_get_capabilities; + this->set_extent = osd_set_extent; + this->set_video_window = osd_set_video_window; return this; } diff --git a/src/xine-engine/osd.h b/src/xine-engine/osd.h deleted file mode 100644 index 768fcb418..000000000 --- a/src/xine-engine/osd.h +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (C) 2000-2003 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * OSD stuff (text and graphic primitives) - */ - -#ifndef HAVE_OSD_H -#define HAVE_OSD_H - -#ifdef HAVE_ICONV -# include <iconv.h> -#endif - -#ifdef XINE_COMPILE -# include "video_overlay.h" -# ifdef __OSD_C__ -# include "alphablend.h" -# endif -#else -# include <xine/video_overlay.h> -#endif - -typedef struct osd_object_s osd_object_t; -typedef struct osd_renderer_s osd_renderer_t; -typedef struct osd_font_s osd_font_t; -typedef struct osd_ft2context_s osd_ft2context_t; - -struct osd_object_s { - osd_object_t *next; - osd_renderer_t *renderer; - - int width, height; /* work area dimentions */ - uint8_t *area; /* work area */ - int display_x,display_y; /* where to display it in screen */ - - /* clipping box inside work area */ - int x1, y1; - int x2, y2; - - uint32_t color[OVL_PALETTE_SIZE]; /* color lookup table */ - uint8_t trans[OVL_PALETTE_SIZE]; /* mixer key table */ - - int32_t handle; - -#ifdef HAVE_ICONV - iconv_t cd; /* iconv handle of encoding */ - char *encoding; /* name of encoding */ -#endif - - osd_font_t *font; - osd_ft2context_t *ft2; -}; - -/* this one is public */ -struct xine_osd_s { - osd_object_t osd; -}; - -struct osd_renderer_s { - - /* - * open a new osd object. this will allocated an empty (all zero) drawing - * area where graphic primitives may be used. - * It is ok to specify big width and height values. The render will keep - * track of the smallest changed area to not generate too big overlays. - * A default palette is initialized (i sugest keeping color 0 as transparent - * for the sake of simplicity) - */ - osd_object_t* (*new_object) (osd_renderer_t *this, int width, int height); - - /* - * free osd object - */ - void (*free_object) (osd_object_t *osd_to_close); - - - /* - * send the osd to be displayed at given pts (0=now) - * the object is not changed. there may be subsequent drawing on it. - */ - int (*show) (osd_object_t *osd, int64_t vpts ); - - /* - * send event to hide osd at given pts (0=now) - * the object is not changed. there may be subsequent drawing on it. - */ - int (*hide) (osd_object_t *osd, int64_t vpts ); - - /* - * draw point. - */ - void (*point) (osd_object_t *osd, int x, int y, int color); - - /* - * Bresenham line implementation on osd object - */ - void (*line) (osd_object_t *osd, - int x1, int y1, int x2, int y2, int color ); - - /* - * filled rectangle - */ - void (*filled_rect) (osd_object_t *osd, - int x1, int y1, int x2, int y2, int color ); - - /* - * set palette (color and transparency) - */ - void (*set_palette) (osd_object_t *osd, const uint32_t *color, const uint8_t *trans ); - - /* - * set on existing text palette - * (-1 to set used specified palette) - * - * color_base specifies the first color index to use for this text - * palette. The OSD palette is then modified starting at this - * color index, up to the size of the text palette. - * - * Use OSD_TEXT1, OSD_TEXT2, ... for some preasssigned color indices. - */ - void (*set_text_palette) (osd_object_t *osd, int palette_number, - int color_base ); - - /* - * get palette (color and transparency) - */ - void (*get_palette) (osd_object_t *osd, uint32_t *color, - uint8_t *trans); - - /* - * set position were overlay will be blended - */ - void (*set_position) (osd_object_t *osd, int x, int y); - - /* - * set the font of osd object - */ - - int (*set_font) (osd_object_t *osd, const char *fontname, int size); - - /* - * set encoding of text - * - * NULL ... no conversion (iso-8859-1) - * "" ... locale encoding - */ - int (*set_encoding) (osd_object_t *osd, const char *encoding); - - /* - * render text in current encoding on x,y position - * no \n yet - * - * The text is assigned the colors starting at the index specified by - * color_base up to the size of the text palette. - * - * Use OSD_TEXT1, OSD_TEXT2, ... for some preasssigned color indices. - */ - int (*render_text) (osd_object_t *osd, int x1, int y1, - const char *text, int color_base); - - /* - * get width and height of how text will be renderized - */ - int (*get_text_size) (osd_object_t *osd, const char *text, - int *width, int *height); - - /* - * close osd rendering engine - * loaded fonts are unloaded - * osd objects are closed - */ - void (*close) (osd_renderer_t *this); - - /* - * clear an osd object (empty drawing area) - */ - void (*clear) (osd_object_t *osd ); - - /* - * paste a bitmap with optional palette mapping - */ - void (*draw_bitmap) (osd_object_t *osd, uint8_t *bitmap, - int x1, int y1, int width, int height, - uint8_t *palette_map); - - /* - * send the osd to be displayed (unscaled) at given pts (0=now) - * the object is not changed. there may be subsequent drawing on it. - * overlay is blended at output (screen) resolution. - */ - int (*show_unscaled) (osd_object_t *osd, int64_t vpts ); - - /* - * see xine.h for defined XINE_OSD_CAP_ values. - */ - uint32_t (*get_capabilities) (osd_object_t *osd); - - /* private stuff */ - - pthread_mutex_t osd_mutex; - video_overlay_event_t event; - osd_object_t *osds; /* instances of osd */ - osd_font_t *fonts; /* loaded fonts */ - int textpalette; /* default textpalette */ - - xine_stream_t *stream; - -}; - -/* - * initialize the osd rendering engine - */ -osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) XINE_MALLOC; - - -/* - * The size of a text palette - */ - -#define TEXT_PALETTE_SIZE 11 - -/* - * Preassigned color indices for rendering text - * (more can be added, not exceeding OVL_PALETTE_SIZE) - */ - -#define OSD_TEXT1 (0 * TEXT_PALETTE_SIZE) -#define OSD_TEXT2 (1 * TEXT_PALETTE_SIZE) -#define OSD_TEXT3 (2 * TEXT_PALETTE_SIZE) -#define OSD_TEXT4 (3 * TEXT_PALETTE_SIZE) -#define OSD_TEXT5 (4 * TEXT_PALETTE_SIZE) -#define OSD_TEXT6 (5 * TEXT_PALETTE_SIZE) -#define OSD_TEXT7 (6 * TEXT_PALETTE_SIZE) -#define OSD_TEXT8 (7 * TEXT_PALETTE_SIZE) -#define OSD_TEXT9 (8 * TEXT_PALETTE_SIZE) -#define OSD_TEXT10 (9 * TEXT_PALETTE_SIZE) - -/* - * Defined palettes for rendering osd text - * (more can be added later) - */ - -#define NUMBER_OF_TEXT_PALETTES 4 -#define TEXTPALETTE_WHITE_BLACK_TRANSPARENT 0 -#define TEXTPALETTE_WHITE_NONE_TRANSPARENT 1 -#define TEXTPALETTE_WHITE_NONE_TRANSLUCID 2 -#define TEXTPALETTE_YELLOW_BLACK_TRANSPARENT 3 - -#ifdef __OSD_C__ - -/* This text descriptions are used for config screen */ -static const char *textpalettes_str[NUMBER_OF_TEXT_PALETTES+1] = { - "white-black-transparent", - "white-none-transparent", - "white-none-translucid", - "yellow-black-transparent", - NULL}; - - -/* - Palette entries as used by osd fonts: - - 0: not used by font, always transparent - 1: font background, usually transparent, may be used to implement - translucid boxes where the font will be printed. - 2-5: transition between background and border (usually only alpha - value changes). - 6: font border. if the font is to be displayed without border this - will probably be adjusted to font background or near. - 7-9: transition between border and foreground - 10: font color (foreground) -*/ - -/* - The palettes below were made by hand, ie, i just throw - values that seemed to do the transitions i wanted. - This can surelly be improved a lot. [Miguel] -*/ - -static const clut_t textpalettes_color[NUMBER_OF_TEXT_PALETTES][TEXT_PALETTE_SIZE] = { -/* white, black border, transparent */ - { - CLUT_Y_CR_CB_INIT(0x00, 0x00, 0x00), /*0*/ - CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*1*/ - CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*2*/ - CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*3*/ - CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*4*/ - CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*5*/ - CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*6*/ - CLUT_Y_CR_CB_INIT(0x40, 0x80, 0x80), /*7*/ - CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), /*8*/ - CLUT_Y_CR_CB_INIT(0xc0, 0x80, 0x80), /*9*/ - CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*10*/ - }, - /* white, no border, transparent */ - { - CLUT_Y_CR_CB_INIT(0x00, 0x00, 0x00), /*0*/ - CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*1*/ - CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*2*/ - CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*3*/ - CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*4*/ - CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*5*/ - CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*6*/ - CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*7*/ - CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*8*/ - CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*9*/ - CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*10*/ - }, - /* white, no border, translucid */ - { - CLUT_Y_CR_CB_INIT(0x00, 0x00, 0x00), /*0*/ - CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), /*1*/ - CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), /*2*/ - CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), /*3*/ - CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), /*4*/ - CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), /*5*/ - CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), /*6*/ - CLUT_Y_CR_CB_INIT(0xa0, 0x80, 0x80), /*7*/ - CLUT_Y_CR_CB_INIT(0xc0, 0x80, 0x80), /*8*/ - CLUT_Y_CR_CB_INIT(0xe0, 0x80, 0x80), /*9*/ - CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), /*10*/ - }, - /* yellow, black border, transparent */ - { - CLUT_Y_CR_CB_INIT(0x00, 0x00, 0x00), /*0*/ - CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*1*/ - CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*2*/ - CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*3*/ - CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*4*/ - CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*5*/ - CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), /*6*/ - CLUT_Y_CR_CB_INIT(0x40, 0x84, 0x60), /*7*/ - CLUT_Y_CR_CB_INIT(0x70, 0x88, 0x40), /*8*/ - CLUT_Y_CR_CB_INIT(0xb0, 0x8a, 0x20), /*9*/ - CLUT_Y_CR_CB_INIT(0xff, 0x90, 0x00), /*10*/ - }, -}; - -static const uint8_t textpalettes_trans[NUMBER_OF_TEXT_PALETTES][TEXT_PALETTE_SIZE] = { - {0, 0, 3, 6, 8, 10, 12, 14, 15, 15, 15 }, - {0, 0, 0, 0, 0, 0, 2, 6, 9, 12, 15 }, - {0, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15 }, - {0, 0, 3, 6, 8, 10, 12, 14, 15, 15, 15 }, -}; - -#endif /* __OSD_C__ */ - -#endif - diff --git a/src/xine-engine/plugin_catalog.h b/src/xine-engine/plugin_catalog.h deleted file mode 100644 index 010ec53bb..000000000 --- a/src/xine-engine/plugin_catalog.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2000-2003 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * xine-internal header: Definitions for plugin lists - */ - -#ifndef _PLUGIN_CATALOG_H -#define _PLUGIN_CATALOG_H - -#ifdef XINE_COMPILE -# include "xine_plugin.h" -# include "xineutils.h" -#else -# include <xine/xine_plugin.h> -# include <xine/xineutils.h> -#endif - -#define DECODER_MAX 128 -#define PLUGIN_MAX 256 - -/* the engine takes this many plugins for one stream type */ -#define PLUGINS_PER_TYPE 10 - -#define CACHE_CATALOG_VERSION 2 -#define CACHE_CATALOG_FILE ".xine/catalog.cache" -#define CACHE_CATALOG_DIR ".xine" - -typedef struct { - char *filename; - off_t filesize; - time_t filemtime; - int ref; /* count number of classes */ - void *lib_handle; - int no_unload; /* set if the file can't be unloaded */ -} plugin_file_t ; - -typedef struct { - plugin_file_t *file; - plugin_info_t *info; - void *plugin_class; - int ref; /* count intances of plugins */ - int priority; -} plugin_node_t ; - -struct plugin_catalog_s { - xine_sarray_t *plugin_lists[PLUGIN_TYPE_MAX]; - - xine_sarray_t *cache_list; - xine_list_t *file_list; - - plugin_node_t *audio_decoder_map[DECODER_MAX][PLUGINS_PER_TYPE]; - plugin_node_t *video_decoder_map[DECODER_MAX][PLUGINS_PER_TYPE]; - plugin_node_t *spu_decoder_map[DECODER_MAX][PLUGINS_PER_TYPE]; - - const char *ids[PLUGIN_MAX]; - - /* memory block for the decoder priority config entry descriptions */ - char *prio_desc[DECODER_MAX]; - - pthread_mutex_t lock; - - int plugin_count; - int decoder_count; -}; -typedef struct plugin_catalog_s plugin_catalog_t; - -/* - * load plugins into catalog - * - * all input+demux plugins will be fully loaded+initialized - * decoder plugins are loaded on demand - * video/audio output plugins have special load/probe functions - */ -void _x_scan_plugins (xine_t *this) XINE_PROTECTED; - - -/* - * dispose all currently loaded plugins (shutdown) - */ - -void _x_dispose_plugins (xine_t *this) XINE_PROTECTED; - -#endif diff --git a/src/xine-engine/post.c b/src/xine-engine/post.c index cb1da8acf..30e61acd4 100644 --- a/src/xine-engine/post.c +++ b/src/xine-engine/post.c @@ -25,7 +25,7 @@ #define POST_INTERNAL #define XINE_ENGINE_INTERNAL -#include "post.h" +#include <xine/post.h> #include <stdarg.h> @@ -90,6 +90,16 @@ static vo_frame_t *post_video_get_last_frame(xine_video_port_t *port_gen) { return frame; } +static xine_grab_video_frame_t *post_video_new_grab_video_frame(xine_video_port_t *port_gen) { + post_video_port_t *port = (post_video_port_t *)port_gen; + xine_grab_video_frame_t *frame; + + if (port->port_lock) pthread_mutex_lock(port->port_lock); + frame = port->original_port->new_grab_video_frame(port->original_port); + if (port->port_lock) pthread_mutex_unlock(port->port_lock); + return frame; +} + static void post_video_enable_ovl(xine_video_port_t *port_gen, int ovl_enable) { post_video_port_t *port = (post_video_port_t *)port_gen; @@ -144,6 +154,14 @@ static void post_video_flush(xine_video_port_t *port_gen) { if (port->port_lock) pthread_mutex_unlock(port->port_lock); } +static void post_video_trigger_drawing(xine_video_port_t *port_gen) { + post_video_port_t *port = (post_video_port_t *)port_gen; + + if (port->port_lock) pthread_mutex_lock(port->port_lock); + port->original_port->trigger_drawing(port->original_port); + if (port->port_lock) pthread_mutex_unlock(port->port_lock); +} + static int post_video_status(xine_video_port_t *port_gen, xine_stream_t *stream, int *width, int *height, int64_t *img_duration) { post_video_port_t *port = (post_video_port_t *)port_gen; @@ -187,6 +205,7 @@ static int post_video_rewire(xine_post_out_t *output_gen, void *data) { if (!new_port) return 0; + this->running_ticket->lock_port_rewiring(this->running_ticket, -1); this->running_ticket->revoke(this->running_ticket, 1); if (input_port->original_port->status(input_port->original_port, input_port->stream, @@ -197,6 +216,7 @@ static int post_video_rewire(xine_post_out_t *output_gen, void *data) { input_port->original_port = new_port; this->running_ticket->issue(this->running_ticket, 1); + this->running_ticket->unlock_port_rewiring(this->running_ticket); return 1; } @@ -213,11 +233,13 @@ post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_ port->new_port.open = post_video_open; port->new_port.get_frame = post_video_get_frame; port->new_port.get_last_frame = post_video_get_last_frame; + port->new_port.new_grab_video_frame = post_video_new_grab_video_frame; port->new_port.enable_ovl = post_video_enable_ovl; port->new_port.close = post_video_close; port->new_port.exit = post_video_exit; port->new_port.get_overlay_manager = post_video_get_overlay_manager; port->new_port.flush = post_video_flush; + port->new_port.trigger_drawing = post_video_trigger_drawing; port->new_port.status = post_video_status; port->new_port.get_property = post_video_get_property; port->new_port.set_property = post_video_set_property; @@ -378,9 +400,10 @@ vo_frame_t *_x_post_intercept_video_frame(vo_frame_t *frame, post_video_port_t * new_frame->dispose = port->new_frame->dispose ? port->new_frame->dispose : post_frame_dispose; - if (!port->new_frame->draw) { + if (!port->new_frame->draw || (port->route_preprocessing_procs && port->route_preprocessing_procs(port, frame))) { /* draw will most likely modify the frame, so the decoder - * should only request preprocessing when there is no new draw */ + * should only request preprocessing when there is no new draw + * but route_preprocessing_procs() can override this decision */ if (frame->proc_frame && !new_frame->proc_frame) new_frame->proc_frame = post_frame_proc_frame; if (frame->proc_slice && !new_frame->proc_slice) @@ -696,6 +719,7 @@ static int post_audio_rewire(xine_post_out_t *output_gen, void *data) { if (!new_port) return 0; + this->running_ticket->lock_port_rewiring(this->running_ticket, -1); this->running_ticket->revoke(this->running_ticket, 1); if (input_port->original_port->status(input_port->original_port, input_port->stream, @@ -706,6 +730,7 @@ static int post_audio_rewire(xine_post_out_t *output_gen, void *data) { input_port->original_port = new_port; this->running_ticket->issue(this->running_ticket, 1); + this->running_ticket->unlock_port_rewiring(this->running_ticket); return 1; } @@ -873,7 +898,7 @@ int _x_post_dispose(post_plugin_t *this) { /* since the plugin loader does not know, when the plugin gets disposed, * we have to handle the reference counter here */ pthread_mutex_lock(&this->xine->plugin_catalog->lock); - ((plugin_node_t *)this->node)->ref--; + this->node->ref--; pthread_mutex_unlock(&this->xine->plugin_catalog->lock); return 1; diff --git a/src/xine-engine/post.h b/src/xine-engine/post.h deleted file mode 100644 index f97b9ffca..000000000 --- a/src/xine-engine/post.h +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (C) 2000-2004 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * post plugin definitions - */ - -#ifndef XINE_POST_H -#define XINE_POST_H - -#ifdef XINE_COMPILE -# include "xine.h" -# include "video_out.h" -# include "audio_out.h" -# include "xine_internal.h" -# include "xineutils.h" -#else -# include <xine.h> -# include <xine/video_out.h> -# include <xine/audio_out.h> -# include <xine/xine_internal.h> -# include <xine/xineutils.h> -#endif - -#define POST_PLUGIN_IFACE_VERSION 9 - - -typedef struct post_class_s post_class_t; -typedef struct post_plugin_s post_plugin_t; -typedef struct post_in_s post_in_t; -typedef struct post_out_s post_out_t; - -struct post_class_s { - - /* - * open a new instance of this plugin class - */ - post_plugin_t* (*open_plugin) (post_class_t *this, int inputs, - xine_audio_port_t **audio_target, - xine_video_port_t **video_target); - - /* - * return short, human readable identifier for this plugin class - */ - char* (*get_identifier) (post_class_t *this); - - /* - * return human readable (verbose = 1 line) description for - * this plugin class - */ - char* (*get_description) (post_class_t *this); - - /* - * free all class-related resources - */ - - void (*dispose) (post_class_t *this); -}; - -struct post_plugin_s { - - /* public part of the plugin */ - xine_post_t xine_post; - - /* - * the connections announced by the plugin - * the plugin must fill these with xine_post_{in,out}_t on init - */ - xine_list_t *input; - xine_list_t *output; - - /* - * close down, free all resources - */ - void (*dispose) (post_plugin_t *this); - - /* has dispose been called */ - int dispose_pending; - - /* plugins don't have to init the stuff below */ - - /* - * the running ticket - * - * the plugin must assure to check for ticket revocation in - * intervals of finite length; this means that you must release - * the ticket before any operation that might block; - * note that all port functions are safe in this respect - * - * the running ticket is assigned to you by the engine - */ - xine_ticket_t *running_ticket; - - /* this is needed by the engine to decrement the reference counter - * on disposal of the plugin, but since this is useful, we expose it */ - xine_t *xine; - - /* used when the user requests a list of all inputs/outputs */ - const char **input_ids; - const char **output_ids; - - /* used by plugin loader */ - void *node; -}; - -/* helper function to initialize a post_plugin_t */ -void _x_post_init(post_plugin_t *post, int num_audio_inputs, int num_video_inputs) XINE_PROTECTED; - -struct post_in_s { - - /* public part of the input */ - xine_post_in_t xine_in; - - /* backward reference so that you have access to the post plugin */ - post_plugin_t *post; - - /* you can fill this to your liking */ - void *user_data; -}; - -struct post_out_s { - - /* public part of the output */ - xine_post_out_t xine_out; - - /* backward reference so that you have access to the post plugin */ - post_plugin_t *post; - - /* you can fill this to your liking */ - void *user_data; -}; - - -/* Post plugins work by intercepting calls to video or audio ports - * in the sense of the decorator design pattern. They reuse the - * functions of a given target port, but add own functionality in - * front of that port by creating a new port structure and filling in - * the function pointers with pointers to own functions that - * would do something and then call the original port function. - * - * Much the same is done with video frames which have their own - * set of functions attached that you might need to decorate. - */ - - -/* helper structure for intercepting video port calls */ -typedef struct post_video_port_s post_video_port_t; -struct post_video_port_s { - - /* the new public port with replaced function pointers */ - xine_video_port_t new_port; - - /* the original port to call its functions from inside yours */ - xine_video_port_t *original_port; - - /* if you want to decide yourself, whether a given frame should - * be intercepted, fill in this function; get_frame() acts as - * a template method and asks your function; return a boolean; - * the default is to intercept all frames */ - int (*intercept_frame)(post_video_port_t *self, vo_frame_t *frame); - - /* the new frame function pointers */ - vo_frame_t *new_frame; - - /* if you want to decide yourself, whether the overlay manager should - * be intercepted, fill in this function; get_overlay_manager() acts as - * a template method and asks your function; return a boolean; - * the default is _not_ to intercept the overlay manager */ - int (*intercept_ovl)(post_video_port_t *self); - - /* the new public overlay manager with replaced function pointers */ - video_overlay_manager_t *new_manager; - - /* the original manager to call its functions from inside yours */ - video_overlay_manager_t *original_manager; - - /* usage counter: how many objects are floating around that need - * these pointers to exist */ - int usage_count; - pthread_mutex_t usage_lock; - - /* the stream we are being fed by; NULL means no stream is connected; - * this may be an anonymous stream */ - xine_stream_t *stream; - - /* point to a mutex here, if you need some synchronization */ - pthread_mutex_t *port_lock; - pthread_mutex_t *frame_lock; - pthread_mutex_t *manager_lock; - - /* backward reference so that you have access to the post plugin - * when the call only gives you the port */ - post_plugin_t *post; - - /* you can fill this to your liking */ - void *user_data; - -#ifdef POST_INTERNAL - /* some of the above members are to be directly included here, but - * adding the structures would mean that post_video_port_t becomes - * depended of the sizes of these structs; solution: we add pointers - * above and have them point into the memory provided here; - * note that the overlay manager needs to be first so that we can - * reconstruct the post_video_port_t* from overlay manager calls */ - - /* any change here requires a change in _x_post_ovl_manager_to_port() - * below! */ - - video_overlay_manager_t manager_storage; - vo_frame_t frame_storage; - - /* this is used to keep a linked list of free vo_frame_t's */ - vo_frame_t *free_frame_slots; - pthread_mutex_t free_frames_lock; -#endif -}; - -/* use this to create a new decorated video port in which - * port functions will be replaced with own implementations; - * for convenience, this can also create a related post_in_t and post_out_t */ -post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_port_t *port, - post_in_t **input, post_out_t **output) XINE_PROTECTED; - -/* use this to decorate and to undecorate a frame so that its functions - * can be replaced with own implementations, decoration is usually done in - * get_frame(), undecoration in frame->free() */ -vo_frame_t *_x_post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *port) XINE_PROTECTED; -vo_frame_t *_x_post_restore_video_frame(vo_frame_t *frame, post_video_port_t *port) XINE_PROTECTED; - -/* when you want to pass a frame call on to the original issuer of the frame, - * you need to propagate potential changes up and down the pipe, so the usual - * procedure for this situation would be: - * - * _x_post_frame_copy_down(frame, frame->next); - * frame->next->function(frame->next); - * _x_post_frame_copy_up(frame, frame->next); - */ -void _x_post_frame_copy_down(vo_frame_t *from, vo_frame_t *to) XINE_PROTECTED; -void _x_post_frame_copy_up(vo_frame_t *to, vo_frame_t *from) XINE_PROTECTED; - -/* when you shortcut a frames usual draw() travel so that it will never reach - * the draw() function of the original issuer, you still have to do some - * housekeeping on the frame, before returning control up the pipe */ -void _x_post_frame_u_turn(vo_frame_t *frame, xine_stream_t *stream) XINE_PROTECTED; - -/* use this to create a new, trivially decorated overlay manager in which - * port functions can be replaced with own implementations */ -void _x_post_intercept_overlay_manager(video_overlay_manager_t *manager, post_video_port_t *port) XINE_PROTECTED; - -/* pointer retrieval functions */ -static inline post_video_port_t *_x_post_video_frame_to_port(vo_frame_t *frame) { - return (post_video_port_t *)frame->port; -} - -static inline post_video_port_t *_x_post_ovl_manager_to_port(video_overlay_manager_t *manager) { -#ifdef POST_INTERNAL - return (post_video_port_t *)( (uint8_t *)manager - - (uint8_t*)&(((post_video_port_t *)NULL)->manager_storage) ); -#else - return (post_video_port_t *)( (uint8_t *)manager - sizeof(post_video_port_t) ); -#endif -} - - -/* helper structure for intercepting audio port calls */ -typedef struct post_audio_port_s post_audio_port_t; -struct post_audio_port_s { - - /* the new public port with replaced function pointers */ - xine_audio_port_t new_port; - - /* the original port to call its functions from inside yours */ - xine_audio_port_t *original_port; - - /* usage counter: how many objects are floating around that need - * these pointers to exist */ - int usage_count; - pthread_mutex_t usage_lock; - - /* the stream we are being fed by; NULL means no stream is connected; - * this may be an anonymous stream */ - xine_stream_t *stream; - - /* some values remembered by port->open() */ - uint32_t bits; - uint32_t rate; - uint32_t mode; - - /* point to a mutex here, if you need some synchronization */ - pthread_mutex_t *port_lock; - - /* backward reference so that you have access to the post plugin - * when the call only gives you the port */ - post_plugin_t *post; - - /* you can fill this to your liking */ - void *user_data; -}; - -/* use this to create a new decorated audio port in which - * port functions will be replaced with own implementations */ -post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_port_t *port, - post_in_t **input, post_out_t **output) XINE_PROTECTED; - - -/* this will allow pending rewire operations, calling this at the beginning - * of decoder-called functions like get_buffer() and open() is a good idea - * (if you do not intercept get_buffer() or open(), this will be done automatically) */ -static inline void _x_post_rewire(post_plugin_t *post) { - if (post->running_ticket->ticket_revoked) - post->running_ticket->renew(post->running_ticket, 1); -} - -/* with these functions you can switch interruptions like rewiring or engine pausing - * off for a block of code; use this only when really necessary */ -static inline void _x_post_lock(post_plugin_t *post) { - post->running_ticket->acquire(post->running_ticket, 1); -} -static inline void _x_post_unlock(post_plugin_t *post) { - post->running_ticket->release(post->running_ticket, 1); - _x_post_rewire(post); -} - -/* the standard disposal operation; returns 1 if the plugin is really - * disposed and you should free everything you malloc()ed yourself */ -int _x_post_dispose(post_plugin_t *post) XINE_PROTECTED; - - -/* macros to handle usage counter */ - -/* WARNING! - * note that _x_post_dec_usage() can call dispose, so be sure to - * not use any potentially already freed memory after this */ - -#define _x_post_inc_usage(port) \ -do { \ - pthread_mutex_lock(&(port)->usage_lock); \ - (port)->usage_count++; \ - pthread_mutex_unlock(&(port)->usage_lock); \ -} while(0) - -#define _x_post_dec_usage(port) \ -do { \ - pthread_mutex_lock(&(port)->usage_lock); \ - (port)->usage_count--; \ - if ((port)->usage_count == 0) { \ - if ((port)->post->dispose_pending) { \ - pthread_mutex_unlock(&(port)->usage_lock); \ - (port)->post->dispose((port)->post); \ - } else \ - pthread_mutex_unlock(&(port)->usage_lock); \ - } else \ - pthread_mutex_unlock(&(port)->usage_lock); \ -} while(0) - - -/* macros to create parameter descriptors */ - -#define START_PARAM_DESCR( param_t ) \ -static param_t temp_s; \ -static xine_post_api_parameter_t temp_p[] = { - -#define PARAM_ITEM( param_type, var, enumv, min, max, readonly, descr ) \ -{ param_type, #var, sizeof(temp_s.var), \ - (char*)&temp_s.var-(char*)&temp_s, enumv, min, max, readonly, descr }, - -#define END_PARAM_DESCR( name ) \ - { POST_PARAM_TYPE_LAST, NULL, 0, 0, NULL, 0, 0, 1, NULL } \ -}; \ -static xine_post_api_descr_t name = { \ - sizeof( temp_s ), \ - temp_p \ -}; - -#endif diff --git a/src/xine-engine/refcounter.c b/src/xine-engine/refcounter.c index 23da4bdbc..216693e88 100644 --- a/src/xine-engine/refcounter.c +++ b/src/xine-engine/refcounter.c @@ -28,8 +28,8 @@ #define LOG */ -#include "xine_internal.h" -#include "refcounter.h" +#include <xine/xine_internal.h> +#include <xine/refcounter.h> refcounter_t* _x_new_refcounter(void *object, void (*destructor)(void *)) { diff --git a/src/xine-engine/refcounter.h b/src/xine-engine/refcounter.h deleted file mode 100644 index f157d8b6c..000000000 --- a/src/xine-engine/refcounter.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2000-2004 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - */ -#ifndef HAVE_REFCOUNTER_H -#define HAVE_REFCOUNTER_H - -#include <pthread.h> - -typedef struct { - pthread_mutex_t lock; - int count; - void* object; /* referenced object */ - void (*destructor)(void *); /* object destructor */ -} refcounter_t; - -typedef void (*refcounter_destructor)(void*); - -refcounter_t* _x_new_refcounter(void *object, refcounter_destructor destructor) XINE_MALLOC XINE_PROTECTED; - -int _x_refcounter_inc(refcounter_t *refcounter) XINE_PROTECTED; - -int _x_refcounter_dec(refcounter_t *refcounter) XINE_PROTECTED; - -void _x_refcounter_dispose(refcounter_t *refcounter) XINE_PROTECTED; - -#endif /* HAVE_REFCOUNTER_H */ diff --git a/src/xine-engine/resample.c b/src/xine-engine/resample.c index dcf14a215..c354bbd68 100644 --- a/src/xine-engine/resample.c +++ b/src/xine-engine/resample.c @@ -24,8 +24,8 @@ #include <string.h> #include <inttypes.h> -#include "attributes.h" -#include "resample.h" +#include <xine/attributes.h> +#include <xine/resample.h> /* contributed by paul flinders */ diff --git a/src/xine-engine/resample.h b/src/xine-engine/resample.h deleted file mode 100644 index 842434cf0..000000000 --- a/src/xine-engine/resample.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2000-2003 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * utilitiy functions for audio drivers - * - * FIXME: not all of them are implemented yet - */ - -#ifndef HAVE_RESAMPLE_H -#define HAVE_RESAMPLE_H - -#define RESAMPLE_MAX_CHANNELS 6 - -void _x_audio_out_resample_stereo(int16_t* last_sample, - int16_t* input_samples, uint32_t in_samples, - int16_t* output_samples, uint32_t out_samples) XINE_PROTECTED; - -void _x_audio_out_resample_mono(int16_t* last_sample, - int16_t* input_samples, uint32_t in_samples, - int16_t* output_samples, uint32_t out_samples) XINE_PROTECTED; - -void _x_audio_out_resample_4channel(int16_t* last_sample, - int16_t* input_samples, uint32_t in_samples, - int16_t* output_samples, uint32_t out_samples) XINE_PROTECTED; - -void _x_audio_out_resample_5channel(int16_t* last_sample, - int16_t* input_samples, uint32_t in_samples, - int16_t* output_samples, uint32_t out_samples) XINE_PROTECTED; - -void _x_audio_out_resample_6channel(int16_t* last_sample, - int16_t* input_samples, uint32_t in_samples, - int16_t* output_samples, uint32_t out_samples) XINE_PROTECTED; - -void _x_audio_out_resample_8to16(int8_t* input_samples, - int16_t* output_samples, uint32_t samples) XINE_PROTECTED; - -void _x_audio_out_resample_16to8(int16_t* input_samples, - int8_t* output_samples, uint32_t samples) XINE_PROTECTED; - -void _x_audio_out_resample_monotostereo(int16_t* input_samples, - int16_t* output_samples, uint32_t frames) XINE_PROTECTED; - -void _x_audio_out_resample_stereotomono(int16_t* input_samples, - int16_t* output_samples, uint32_t frames) XINE_PROTECTED; - -#endif diff --git a/src/xine-engine/scratch.c b/src/xine-engine/scratch.c index 39bb5927a..a15cd42d1 100644 --- a/src/xine-engine/scratch.c +++ b/src/xine-engine/scratch.c @@ -26,7 +26,6 @@ #include <stdio.h> #include <stdarg.h> -#include <string.h> /* For memset */ #define LOG_MODULE "scratch" #define LOG_VERBOSE @@ -34,8 +33,8 @@ #define LOG */ -#include "xineutils.h" -#include "scratch.h" +#include <xine/xineutils.h> +#include <xine/scratch.h> static void XINE_FORMAT_PRINTF(2, 0) scratch_printf (scratch_buffer_t *this, const char *format, va_list argp) diff --git a/src/xine-engine/scratch.h b/src/xine-engine/scratch.h deleted file mode 100644 index c0c927b97..000000000 --- a/src/xine-engine/scratch.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2000-2006 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * scratch buffer for log output - */ - -#ifndef HAVE_SCRATCH_H -#define HAVE_SCRATCH_H - -#include <stdarg.h> -#include <pthread.h> - -typedef struct scratch_buffer_s scratch_buffer_t; - -#define SCRATCH_LINE_LEN_MAX 1024 - -struct scratch_buffer_s { - - 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); - - void (*dispose) (scratch_buffer_t *this); - - char **lines; - char **ordered; - - int num_lines; - int cur; - - pthread_mutex_t lock; -}; - -scratch_buffer_t *_x_new_scratch_buffer (int num_lines) XINE_MALLOC XINE_PROTECTED; - -#endif diff --git a/src/xine-engine/spu.c b/src/xine-engine/spu.c new file mode 100644 index 000000000..9bc1de84c --- /dev/null +++ b/src/xine-engine/spu.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <xine/xine_internal.h> +#include <xine/spu.h> + +#define BLACK_OPACITY 67 +#define COLOUR_OPACITY 100 + +static void no_op (void *user_data, xine_cfg_entry_t *entry) +{ +} + +void _x_spu_misc_init (xine_t *this) +{ + this->config->register_range (this->config, "subtitles.bitmap.black_opacity", + BLACK_OPACITY, 0, 100, + _("opacity for the black parts of bitmapped subtitles"), + NULL, + 10, no_op, NULL); + this->config->register_range (this->config, "subtitles.bitmap.colour_opacity", + COLOUR_OPACITY, 0, 100, + _("opacity for the colour parts of bitmapped subtitles"), + NULL, + 10, no_op, NULL); +} + +void _x_spu_get_opacity (xine_t *this, xine_spu_opacity_t *opacity) +{ + cfg_entry_t *entry; + + entry = this->config->lookup_entry (this->config, "subtitles.bitmap.black_opacity"); + opacity->black = entry ? entry->num_value : BLACK_OPACITY; + entry = this->config->lookup_entry (this->config, "subtitles.bitmap.colour_opacity"); + opacity->colour = entry ? entry->num_value : COLOUR_OPACITY; +} + +int _x_spu_calculate_opacity (const clut_t *clut, uint8_t trans, const xine_spu_opacity_t *opacity) +{ + int value = (clut->y == 0 || (clut->y == 16 && clut->cb == 128 && clut->cr == 128)) + ? opacity->black + : opacity->colour; + return value * (255 - trans) / 100; +} diff --git a/src/xine-engine/spu_decoder.h b/src/xine-engine/spu_decoder.h deleted file mode 100644 index 4897a32a2..000000000 --- a/src/xine-engine/spu_decoder.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * spu_decoder_api.h - * - * Copyright (C) James Courtier-Dutton James@superbug.demon.co.uk - July 2001 - * - * This file is part of xine, a unix video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Make; see the file COPYING. If not, write to - * the Free Software Foundation, - * - */ - -#ifndef HAVE_SPU_API_H -#define HAVE_SPU_API_H - -#ifdef XINE_COMPILE -# include <inttypes.h> -# include "buffer.h" -#else -# include <xine/os_types.h> -# include <xine/buffer.h> -#endif - -#define SPU_DECODER_IFACE_VERSION 16 - -/* - * generic xine spu decoder plugin interface - */ - -typedef struct spu_decoder_class_s spu_decoder_class_t; -typedef struct spu_decoder_s spu_decoder_t; - -struct spu_decoder_class_s { - - /* - * open a new instance of this plugin class - */ - spu_decoder_t* (*open_plugin) (spu_decoder_class_t *this, xine_stream_t *stream); - - /* - * return short, human readable identifier for this plugin class - */ - char* (*get_identifier) (spu_decoder_class_t *this); - - /* - * return human readable (verbose = 1 line) description for - * this plugin class - */ - char* (*get_description) (spu_decoder_class_t *this); - - /* - * free all class-related resources - */ - void (*dispose) (spu_decoder_class_t *this); -}; - - -struct spu_decoder_s { - - /* - * decode data from buf and feed the overlay to overlay manager - */ - void (*decode_data) (spu_decoder_t *this, buf_element_t *buf); - - /* - * reset decoder after engine flush (prepare for new - * SPU data not related to recently decoded data) - */ - void (*reset) (spu_decoder_t *this); - - /* - * inform decoder that a time reference discontinuity has happened. - * that is, it must forget any currently held pts value - */ - void (*discontinuity) (spu_decoder_t *this); - - /* - * close down, free all resources - */ - void (*dispose) (spu_decoder_t *this); - - /* - * When the SPU decoder also handles data used in user interaction, - * you can query the related information here. The typical example - * for this is DVD NAV packets which are handled by the SPU decoder - * and can be received readily parsed from here. - * The caller and the decoder must agree on the structure which is - * passed here. - * This function pointer may be NULL, if the plugin does not have - * such functionality. - */ - int (*get_interact_info) (spu_decoder_t *this, void *data); - - /* - * When the SPU decoder also handles menu overlays for user inter- - * action, you can set a menu button here. The typical example for - * this is DVD menus. - * This function pointer may be NULL, if the plugin does not have - * such functionality. - */ - void (*set_button) (spu_decoder_t *this_gen, int32_t button, int32_t mode); - - void *node; /* used by plugin loader */ -}; - - -/* SPU decoders differ from video and audio decoders in one significant - * way: unlike audio and video, SPU streams are not continuous; - * this results in another difference, programmers have to consider: - * while both audio and video decoders are automatically blocked in - * their get_buffer()/get_frame() methods when the output cannot take - * any more data, this does not work for SPU, because it could take - * minutes before the next free slot becomes available and we must not - * block the decoder thread for that long; - * therefore, we provide a convenience function for SPU decoders which - * implements a wait until a timestamp sufficiently close to the VPTS - * of the next SPU is reached, but the waiting will end before that, - * if some outside condition requires us to release the decoder thread - * to other tasks; - * if this functions returns with 1, noone needs the decoder thread and - * you may continue waiting; if it returns 0, finish whatever you are - * doing and return; - * the usual pattern for SPU decoders is this: - * - * do { - * spu = prepare_spu(); - * int thread_vacant = _x_spu_decoder_sleep(this->stream, spu->vpts); - * int success = process_spu(spu); - * } while (!success && thread_vacant); - */ -int _x_spu_decoder_sleep(xine_stream_t *, int64_t next_spu_vpts) XINE_PROTECTED; - -#endif /* HAVE_SPUDEC_H */ diff --git a/src/xine-engine/tvmode.c b/src/xine-engine/tvmode.c deleted file mode 100644 index 1d6660f4f..000000000 --- a/src/xine-engine/tvmode.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2000-2003 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * tvmode - TV output selection - * - * Currently uses nvtvd (Dirk Thierbach <dthierbach@gmx.de>) - * for setting TV mode - * xine support hacked in by Matthias Hopf <mat@mshopf.de> - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -#include "xine_internal.h" -#include "xineutils.h" - -/* nvtv support is deprecated (and will be removed) - * these dummy functions are only here to prevent serious breakage - * until front ends are updated. - */ - -int xine_tvmode_switch (xine_t *this, int type, int width, int height, double fps) { - /* not supported: return regular mode */ - return 0; -} - -void xine_tvmode_size (xine_t *this, int *width, int *height, - double *pixelratio, double *fps) { -} - -int xine_tvmode_init (xine_t *this) { - return 0; -} - -void xine_tvmode_exit (xine_t *this) { -} - -void xine_tvmode_set_tvsystem(xine_t *self, xine_tvsystem system) { -} - -int xine_tvmode_use(xine_t *self, int use_tvmode) { - return 0; -} diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c index 8e8502968..7b0ac72c1 100644 --- a/src/xine-engine/video_decoder.c +++ b/src/xine-engine/video_decoder.c @@ -36,8 +36,9 @@ #define LOG */ -#include "xine_internal.h" -#include "xineutils.h" +#include <xine/xine_internal.h> +#include <xine/xineutils.h> +#include "xine_private.h" #include <sched.h> #define SPU_SLEEP_INTERVAL (90000/2) @@ -96,7 +97,7 @@ int _x_spu_decoder_sleep(xine_stream_t *stream, int64_t next_spu_vpts) thread_vacant = (stream->video_fifo->first->type != BUF_CONTROL_FLUSH_DECODER); /* we have to return if the demuxer needs us to release a buffer */ if (thread_vacant) - thread_vacant = !stream->demux_action_pending; + thread_vacant = !_x_action_pending(stream); } while (wait == SPU_SLEEP_INTERVAL && thread_vacant); diff --git a/src/xine-engine/video_decoder.h b/src/xine-engine/video_decoder.h deleted file mode 100644 index f7068cc13..000000000 --- a/src/xine-engine/video_decoder.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2000-2004 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * xine video decoder plugin interface - */ - -#ifndef HAVE_VIDEO_DECODER_H -#define HAVE_VIDEO_DECODER_H - -#ifdef XINE_COMPILE -# include <inttypes.h> -# include "buffer.h" -#else -# include <xine/os_types.h> -# include <xine/buffer.h> -#endif - -#define VIDEO_DECODER_IFACE_VERSION 18 - - -/* - * generic xine video decoder plugin interface - */ - -typedef struct video_decoder_class_s video_decoder_class_t; -typedef struct video_decoder_s video_decoder_t; - -struct video_decoder_class_s { - - /* - * open a new instance of this plugin class - */ - video_decoder_t* (*open_plugin) (video_decoder_class_t *this, xine_stream_t *stream); - - /* - * return short, human readable identifier for this plugin class - */ - char* (*get_identifier) (video_decoder_class_t *this); - - /* - * return human readable (verbose = 1 line) description for - * this plugin class - */ - char* (*get_description) (video_decoder_class_t *this); - - /* - * free all class-related resources - */ - void (*dispose) (video_decoder_class_t *this); -}; - - -struct video_decoder_s { - - /* - * decode data from buf and feed decoded frames to - * video output - */ - void (*decode_data) (video_decoder_t *this, buf_element_t *buf); - - /* - * reset decoder after engine flush (prepare for new - * video data not related to recently decoded data) - */ - void (*reset) (video_decoder_t *this); - - /* - * inform decoder that a time reference discontinuity has happened. - * that is, it must forget any currently held pts value - */ - void (*discontinuity) (video_decoder_t *this); - - /* - * flush out any frames that are still stored in the decoder - */ - void (*flush) (video_decoder_t *this); - - /* - * close down, free all resources - */ - void (*dispose) (video_decoder_t *this); - - - void *node; /*used by plugin loader */ - -}; - -#endif diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index a6d39f23f..cc428137e 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -45,10 +45,11 @@ #define LOG */ -#include "xine_internal.h" -#include "video_out.h" -#include "metronom.h" -#include "xineutils.h" +#include <xine/xine_internal.h> +#include <xine/video_out.h> +#include <xine/metronom.h> +#include <xine/xineutils.h> +#include <yuv2rgb.h> #define NUM_FRAME_BUFFERS 15 #define MAX_USEC_TO_SLEEP 20000 @@ -66,6 +67,24 @@ static vo_frame_t * crop_frame( xine_video_port_t *this_gen, vo_frame_t *img ); +typedef struct vos_grab_video_frame_s vos_grab_video_frame_t; +struct vos_grab_video_frame_s { + xine_grab_video_frame_t grab_frame; + + vos_grab_video_frame_t *next; + int finished; + xine_video_port_t *video_port; + vo_frame_t *vo_frame; + yuv2rgb_factory_t *yuv2rgb_factory; + yuv2rgb_t *yuv2rgb; + int vo_width, vo_height; + int grab_width, grab_height; + int y_stride, uv_stride; + int img_size; + uint8_t *img; +}; + + typedef struct { vo_frame_t *first; vo_frame_t *last; @@ -91,9 +110,13 @@ typedef struct { img_buf_fifo_t *free_img_buf_queue; img_buf_fifo_t *display_img_buf_queue; - vo_frame_t *last_frame; vo_frame_t *img_backup; + vo_frame_t *last_frame; + vos_grab_video_frame_t *pending_grab_request; + pthread_mutex_t grab_lock; + pthread_cond_t grab_cond; + uint32_t video_loop_running:1; uint32_t video_opened:1; @@ -133,6 +156,9 @@ typedef struct { int frame_drop_cpt; int frame_drop_suggested; int crop_left, crop_right, crop_top, crop_bottom; + pthread_mutex_t trigger_drawing_mutex; + pthread_cond_t trigger_drawing_cond; + int trigger_drawing; } vos_t; @@ -327,6 +353,288 @@ static void vo_frame_dec_lock (vo_frame_t *img) { pthread_mutex_unlock (&img->mutex); } + +/* + * functions for grabbing RGB images from displayed frames + */ +static void vo_dispose_grab_video_frame(xine_grab_video_frame_t *frame_gen) +{ + vos_grab_video_frame_t *frame = (vos_grab_video_frame_t *) frame_gen; + + if (frame->vo_frame) + vo_frame_dec_lock(frame->vo_frame); + + if (frame->yuv2rgb) + frame->yuv2rgb->dispose(frame->yuv2rgb); + + if (frame->yuv2rgb_factory) + frame->yuv2rgb_factory->dispose(frame->yuv2rgb_factory); + + free(frame->img); + free(frame->grab_frame.img); + free(frame); +} + + +static int vo_grab_grab_video_frame (xine_grab_video_frame_t *frame_gen) { + vos_grab_video_frame_t *frame = (vos_grab_video_frame_t *) frame_gen; + vos_t *this = (vos_t *) frame->video_port; + vo_frame_t *vo_frame; + int format, y_stride, uv_stride; + uint8_t *base[3]; + + if (frame->grab_frame.flags & XINE_GRAB_VIDEO_FRAME_FLAGS_WAIT_NEXT) { + struct timeval tvnow, tvdiff, tvtimeout; + struct timespec ts; + + /* calculate absolute timeout time */ + tvdiff.tv_sec = frame->grab_frame.timeout / 1000; + tvdiff.tv_usec = frame->grab_frame.timeout % 1000; + tvdiff.tv_usec *= 1000; + gettimeofday(&tvnow, NULL); + timeradd(&tvnow, &tvdiff, &tvtimeout); + ts.tv_sec = tvtimeout.tv_sec; + ts.tv_nsec = tvtimeout.tv_usec; + ts.tv_nsec *= 1000; + + pthread_mutex_lock(&this->grab_lock); + + /* insert grab request into grab queue */ + frame->next = this->pending_grab_request; + this->pending_grab_request = frame; + + /* wait until our request is finished */ + frame->finished = 0; + while (!frame->finished) { + if (pthread_cond_timedwait(&this->grab_cond, &this->grab_lock, &ts) == ETIMEDOUT) { + vos_grab_video_frame_t *prev = this->pending_grab_request; + while (prev) { + if (prev == frame) { + this->pending_grab_request = frame->next; + break; + } else if (prev->next == frame) { + prev->next = frame->next; + break; + } + prev = prev->next; + } + frame->next = NULL; + pthread_mutex_unlock(&this->grab_lock); + return 1; /* no frame available */ + } + } + + pthread_mutex_unlock(&this->grab_lock); + + vo_frame = frame->vo_frame; + frame->vo_frame = NULL; + if (!vo_frame) + return -1; /* error happened */ + } else { + pthread_mutex_lock(&this->grab_lock); + + /* use last displayed frame */ + vo_frame = this->last_frame; + if (!vo_frame) { + pthread_mutex_unlock(&this->grab_lock); + return 1; /* no frame available */ + } + if (vo_frame->format != XINE_IMGFMT_YV12 && vo_frame->format != XINE_IMGFMT_YUY2 && !vo_frame->proc_provide_standard_frame_data) { + pthread_mutex_unlock(&this->grab_lock); + return -1; /* error happened */ + } + vo_frame_inc_lock(vo_frame); + pthread_mutex_unlock(&this->grab_lock); + frame->grab_frame.vpts = vo_frame->vpts; + } + + int width = vo_frame->width; + int height = vo_frame->height; + + if (vo_frame->format == XINE_IMGFMT_YV12 || vo_frame->format == XINE_IMGFMT_YUY2) { + format = vo_frame->format; + y_stride = vo_frame->pitches[0]; + uv_stride = vo_frame->pitches[1]; + base[0] = vo_frame->base[0]; + base[1] = vo_frame->base[1]; + base[2] = vo_frame->base[2]; + } else { + /* retrieve standard format image data from output driver */ + xine_current_frame_data_t data; + memset(&data, 0, sizeof(data)); + vo_frame->proc_provide_standard_frame_data(vo_frame, &data); + if (data.img_size > frame->img_size) { + free(frame->img); + frame->img_size = data.img_size; + frame->img = calloc(data.img_size, sizeof(uint8_t)); + if (!frame->img) { + vo_frame_dec_lock(vo_frame); + return -1; /* error happened */ + } + } + data.img = frame->img; + vo_frame->proc_provide_standard_frame_data(vo_frame, &data); + format = data.format; + if (format == XINE_IMGFMT_YV12) { + y_stride = width; + uv_stride = width / 2; + base[0] = data.img; + base[1] = data.img + width * height; + base[2] = data.img + width * height + width * height / 4; + } else { // XINE_IMGFMT_YUY2 + y_stride = width * 2; + uv_stride = 0; + base[0] = data.img; + base[1] = NULL; + base[2] = NULL; + } + } + + /* take cropping parameters into account */ + int crop_left = (vo_frame->crop_left + frame->grab_frame.crop_left) & ~1; + int crop_right = (vo_frame->crop_right + frame->grab_frame.crop_right) & ~1; + int crop_top = vo_frame->crop_top + frame->grab_frame.crop_top; + int crop_bottom = vo_frame->crop_bottom + frame->grab_frame.crop_bottom; + + if (crop_left || crop_right || crop_top || crop_bottom) { + if ((width - crop_left - crop_right) >= 8) + width = width - crop_left - crop_right; + else + crop_left = crop_right = 0; + + if ((height - crop_top - crop_bottom) >= 8) + height = height - crop_top - crop_bottom; + else + crop_top = crop_bottom = 0; + + if (format == XINE_IMGFMT_YV12) { + base[0] += crop_top * y_stride + crop_left; + base[1] += crop_top/2 * uv_stride + crop_left/2; + base[2] += crop_top/2 * uv_stride + crop_left/2; + } else { // XINE_IMGFMT_YUY2 + base[0] += crop_top * y_stride + crop_left*2; + } + } + + /* if caller does not specify frame size we return the actual size of grabbed frame */ + if (frame->grab_frame.width <= 0) + frame->grab_frame.width = width; + if (frame->grab_frame.height <= 0) + frame->grab_frame.height = height; + + /* allocate grab frame image buffer */ + if (frame->grab_frame.width != frame->grab_width || frame->grab_frame.height != frame->grab_height) { + free(frame->grab_frame.img); + frame->grab_frame.img = NULL; + } + if (frame->grab_frame.img == NULL) { + frame->grab_frame.img = (uint8_t *) calloc(frame->grab_frame.width * frame->grab_frame.height, 3); + if (frame->grab_frame.img == NULL) { + vo_frame_dec_lock(vo_frame); + return -1; /* error happened */ + } + } + + /* initialize yuv2rgb factory */ + if (!frame->yuv2rgb_factory) { + frame->yuv2rgb_factory = yuv2rgb_factory_init(MODE_24_RGB, 0, NULL); + if (!frame->yuv2rgb_factory) { + vo_frame_dec_lock(vo_frame); + return -1; /* error happened */ + } + frame->yuv2rgb_factory->matrix_coefficients = 1; /* ITU-R Rec. 709 (1990) */ + frame->yuv2rgb_factory->set_csc_levels (frame->yuv2rgb_factory, 0, 128, 128); + } + + /* retrieve a yuv2rgb converter */ + if (!frame->yuv2rgb) { + frame->yuv2rgb = frame->yuv2rgb_factory->create_converter(frame->yuv2rgb_factory); + if (!frame->yuv2rgb) { + vo_frame_dec_lock(vo_frame); + return -1; /* error happened */ + } + } + + /* configure yuv2rgb converter */ + if (width != frame->vo_width || + height != frame->vo_height || + frame->grab_frame.width != frame->grab_width || + frame->grab_frame.height != frame->grab_height || + y_stride != frame->y_stride || + uv_stride != frame->uv_stride) { + frame->vo_width = width; + frame->vo_height = height; + frame->grab_width = frame->grab_frame.width; + frame->grab_height = frame->grab_frame.height; + frame->y_stride = y_stride; + frame->uv_stride = uv_stride; + frame->yuv2rgb->configure(frame->yuv2rgb, width, height, y_stride, uv_stride, frame->grab_width, frame->grab_height, frame->grab_width * 3); + } + + /* convert YUV to RGB image taking possible scaling into account */ + /* FIXME: have to swap U and V planes to get correct colors for YV12 frames?? */ + if(format == XINE_IMGFMT_YV12) + frame->yuv2rgb->yuv2rgb_fun(frame->yuv2rgb, frame->grab_frame.img, base[0], base[2], base[1]); + else + frame->yuv2rgb->yuy22rgb_fun(frame->yuv2rgb, frame->grab_frame.img, base[0]); + + vo_frame_dec_lock(vo_frame); + return 0; +} + + +static xine_grab_video_frame_t *vo_new_grab_video_frame(xine_video_port_t *this_gen) +{ + vos_grab_video_frame_t *frame = calloc(1, sizeof(vos_grab_video_frame_t)); + if (frame) { + frame->grab_frame.dispose = vo_dispose_grab_video_frame; + frame->grab_frame.grab = vo_grab_grab_video_frame; + frame->grab_frame.vpts = -1; + frame->grab_frame.timeout = XINE_GRAB_VIDEO_FRAME_DEFAULT_TIMEOUT; + frame->video_port = this_gen; + } + return (xine_grab_video_frame_t *)frame; +} + + +static void vo_grab_current_frame (vos_t *this, vo_frame_t *vo_frame, int64_t vpts) +{ + pthread_mutex_lock(&this->grab_lock); + + /* hold current frame for snapshot feature */ + if (this->last_frame) + vo_frame_dec_lock(this->last_frame); + vo_frame_inc_lock(vo_frame); + this->last_frame = vo_frame; + + /* process grab queue */ + vos_grab_video_frame_t *frame = this->pending_grab_request; + if (frame) { + while (frame) { + if (frame->vo_frame) + vo_frame_dec_lock(frame->vo_frame); + frame->vo_frame = NULL; + + if (vo_frame->format == XINE_IMGFMT_YV12 || vo_frame->format == XINE_IMGFMT_YUY2 || vo_frame->proc_provide_standard_frame_data) { + vo_frame_inc_lock(vo_frame); + frame->vo_frame = vo_frame; + frame->grab_frame.vpts = vpts; + } + + frame->finished = 1; + vos_grab_video_frame_t *next = frame->next; + frame->next = NULL; + frame = next; + } + + this->pending_grab_request = NULL; + pthread_cond_broadcast(&this->grab_cond); + } + + pthread_mutex_unlock(&this->grab_lock); +} + + /* call vo_driver->proc methods for the entire frame */ static void vo_frame_driver_proc(vo_frame_t *img) { @@ -954,8 +1262,8 @@ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts, img->vpts = cur_vpts; /* extra info of the backup is thrown away, because it is not up to date */ _x_extra_info_reset(img->extra_info); + img->future_frame = NULL; } - return img; } else { @@ -1014,6 +1322,13 @@ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts, * remove frame from display queue and show it */ + if ( img ) { + if ( img->next ) + img->future_frame = img->next; + else + img->future_frame = NULL; + } + img = vo_remove_from_img_buf_queue_int (this->display_img_buf_queue, 1, 0, 0, 0, 0, 0); pthread_mutex_unlock(&this->display_img_buf_queue->mutex); @@ -1050,12 +1365,7 @@ static void overlay_and_display_frame (vos_t *this, this->video_loop_running && this->overlay_enabled); } - /* hold current frame for snapshot feature */ - if( this->last_frame ) { - vo_frame_dec_lock( this->last_frame ); - } - vo_frame_inc_lock( img ); - this->last_frame = img; + vo_grab_current_frame (this, img, vpts); this->driver->display_frame (this->driver, img); @@ -1092,6 +1402,32 @@ static void check_redraw_needed (vos_t *this, int64_t vpts) { this->redraw_needed = 1; } +static int interruptable_sleep(vos_t *this, int usec_to_sleep) +{ + int timedout = 0; + + struct timeval now; + gettimeofday(&now, 0); + + pthread_mutex_lock (&this->trigger_drawing_mutex); + if (!this->trigger_drawing) { + struct timespec abstime; + abstime.tv_sec = now.tv_sec + usec_to_sleep / 1000000; + abstime.tv_nsec = now.tv_usec * 1000 + (usec_to_sleep % 1000000) * 1000; + + if (abstime.tv_nsec > 1000000000) { + abstime.tv_nsec -= 1000000000; + abstime.tv_sec++; + } + + timedout = pthread_cond_timedwait(&this->trigger_drawing_cond, &this->trigger_drawing_mutex, &abstime); + } + this->trigger_drawing = 0; + pthread_mutex_unlock (&this->trigger_drawing_mutex); + + return timedout; +} + /* special loop for paused mode * needed to update screen due overlay changes, resize, window * movement, brightness adjusting etc. @@ -1137,7 +1473,7 @@ static void paused_loop( vos_t *this, int64_t vpts ) } pthread_mutex_unlock( &this->free_img_buf_queue->mutex ); - xine_usec_sleep (20000); + interruptable_sleep(this, 20000); pthread_mutex_lock( &this->free_img_buf_queue->mutex ); } @@ -1280,7 +1616,11 @@ static void *video_out_loop (void *this_gen) { "video_out: vpts/clock error, next_vpts=%" PRId64 " cur_vpts=%" PRId64 "\n", next_frame_vpts,vpts); if (usec_to_sleep > 0) - xine_usec_sleep (usec_to_sleep); + { + /* honor trigger update only when a backup img is available */ + if (0 == interruptable_sleep(this, usec_to_sleep) && this->img_backup) + break; + } if (this->discard_frames) break; @@ -1307,10 +1647,13 @@ static void *video_out_loop (void *this_gen) { vo_frame_dec_lock( this->img_backup ); this->img_backup = NULL; } + + pthread_mutex_lock(&this->grab_lock); if (this->last_frame) { vo_frame_dec_lock( this->last_frame ); this->last_frame = NULL; } + pthread_mutex_unlock(&this->grab_lock); return NULL; } @@ -1442,6 +1785,14 @@ static int vo_get_property (xine_video_port_t *this_gen, int property) { ret = this->video_loop_running ? this->display_img_buf_queue->num_buffers : -1; break; + case VO_PROP_BUFS_FREE: + ret = this->video_loop_running ? this->free_img_buf_queue->num_buffers : -1; + break; + + case VO_PROP_BUFS_TOTAL: + ret = this->video_loop_running ? this->free_img_buf_queue->num_buffers_max : -1; + break; + case VO_PROP_NUM_STREAMS: pthread_mutex_lock(&this->streams_lock); ret = xine_list_size(this->streams); @@ -1464,6 +1815,8 @@ static int vo_get_property (xine_video_port_t *this_gen, int property) { ret = this->crop_bottom; break; + case XINE_PARAM_VO_SHARPNESS: + case XINE_PARAM_VO_NOISE_REDUCTION: case XINE_PARAM_VO_HUE: case XINE_PARAM_VO_SATURATION: case XINE_PARAM_VO_CONTRAST: @@ -1558,6 +1911,8 @@ static int vo_set_property (xine_video_port_t *this_gen, int property, int value ret = this->crop_bottom = value; break; + case XINE_PARAM_VO_SHARPNESS: + case XINE_PARAM_VO_NOISE_REDUCTION: case XINE_PARAM_VO_HUE: case XINE_PARAM_VO_SATURATION: case XINE_PARAM_VO_CONTRAST: @@ -1669,12 +2024,28 @@ static void vo_exit (xine_video_port_t *this_gen) { free (this->free_img_buf_queue); free (this->display_img_buf_queue); + pthread_cond_destroy(&this->trigger_drawing_cond); + pthread_mutex_destroy(&this->trigger_drawing_mutex); + + pthread_mutex_destroy(&this->grab_lock); + pthread_cond_destroy(&this->grab_cond); + free (this); } static vo_frame_t *vo_get_last_frame (xine_video_port_t *this_gen) { vos_t *this = (vos_t *) this_gen; - return this->last_frame; + vo_frame_t *last_frame; + + pthread_mutex_lock(&this->grab_lock); + + last_frame = this->last_frame; + if (last_frame) + vo_frame_inc_lock(last_frame); + + pthread_mutex_unlock(&this->grab_lock); + + return last_frame; } /* @@ -1738,6 +2109,15 @@ static void vo_flush (xine_video_port_t *this_gen) { } } +static void vo_trigger_drawing (xine_video_port_t *this_gen) { + vos_t *this = (vos_t *) this_gen; + + pthread_mutex_lock (&this->trigger_drawing_mutex); + this->trigger_drawing = 1; + pthread_cond_signal (&this->trigger_drawing_cond); + pthread_mutex_unlock (&this->trigger_drawing_mutex); +} + /* crop_frame() will allocate a new frame to copy in the given image * while cropping. maybe someday this will be an automatic post plugin. */ @@ -1827,12 +2207,14 @@ xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabon this->vo.open = vo_open; this->vo.get_frame = vo_get_frame; this->vo.get_last_frame = vo_get_last_frame; + this->vo.new_grab_video_frame = vo_new_grab_video_frame; this->vo.close = vo_close; this->vo.exit = vo_exit; this->vo.get_capabilities = vo_get_capabilities; this->vo.enable_ovl = vo_enable_overlay; this->vo.get_overlay_manager = vo_get_overlay_manager; this->vo.flush = vo_flush; + this->vo.trigger_drawing = vo_trigger_drawing; this->vo.get_property = vo_get_property; this->vo.set_property = vo_set_property; this->vo.status = vo_status; @@ -1845,9 +2227,13 @@ xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabon this->display_img_buf_queue = vo_new_img_buf_queue (); this->video_loop_running = 0; - this->last_frame = NULL; this->img_backup = NULL; + this->last_frame = NULL; + this->pending_grab_request = NULL; + pthread_mutex_init(&this->grab_lock, NULL); + pthread_cond_init(&this->grab_cond, NULL); + this->overlay_source = _x_video_overlay_new_manager(xine); this->overlay_source->init (this->overlay_source); this->overlay_enabled = 1; @@ -1926,6 +2312,9 @@ xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabon "were not scheduled for display in time, xine sends a notification."), 20, NULL, NULL); + pthread_mutex_init(&this->trigger_drawing_mutex, NULL); + pthread_cond_init(&this->trigger_drawing_cond, NULL); + this->trigger_drawing = 0; if (grabonly) { diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h deleted file mode 100644 index 9a4bd56c9..000000000 --- a/src/xine-engine/video_out.h +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Copyright (C) 2000-2004 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - * xine version of video_out.h - * - * vo_frame : frame containing yuv data and timing info, - * transferred between video_decoder and video_output - * - * vo_driver : lowlevel, platform-specific video output code - * - * vo_port : generic frame_handling code, uses - * a vo_driver for output - */ - -#ifndef HAVE_VIDEO_OUT_H -#define HAVE_VIDEO_OUT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <pthread.h> - -#ifdef XINE_COMPILE -# include "xine.h" -# include "buffer.h" -#else -# include <xine.h> -# include <xine/buffer.h> -#endif - - -typedef struct vo_frame_s vo_frame_t; -typedef struct vo_driver_s vo_driver_t; -typedef struct video_driver_class_s video_driver_class_t; -typedef struct vo_overlay_s vo_overlay_t; -typedef struct video_overlay_manager_s video_overlay_manager_t; - -/* public part, video drivers may add private fields - * - * Remember that adding new functions to this structure requires - * adaption of the post plugin decoration layer. Be sure to look into - * src/xine-engine/post.[ch]. - */ -struct vo_frame_s { - /* - * member functions - */ - - /* Duplicate picture data and acceleration specific data of a frame. */ - /* if the image format isn't already known by Xine. Currently this is needed */ - /* For all image formats except XINE_IMGFMT_YV12 and XINE_IMGFMT_YUY2 */ - void (*proc_duplicate_frame_data) (vo_frame_t *vo_img, vo_frame_t *src); - - /* tell video driver to copy/convert the whole of this frame, may be NULL */ - /* at least one of proc_frame() and proc_slice() MUST set the variable proc_called to 1 */ - void (*proc_frame) (vo_frame_t *vo_img); - - /* tell video driver to copy/convert a slice of this frame, may be NULL */ - /* at least one of proc_frame() and proc_slice() MUST set the variable proc_called to 1 */ - void (*proc_slice) (vo_frame_t *vo_img, uint8_t **src); - - /* tell video driver that the decoder starts a new field */ - void (*field) (vo_frame_t *vo_img, int which_field); - - /* append this frame to the display queue, - returns number of frames to skip if decoder is late */ - /* when the frame does not originate from a stream, it is legal to pass an anonymous stream */ - int (*draw) (vo_frame_t *vo_img, xine_stream_t *stream); - - /* lock frame as reference, must be paired with free. - * most decoders/drivers do not need to call this function since - * newly allocated frames are already locked once. - */ - void (*lock) (vo_frame_t *vo_img); - - /* this frame is no longer used by the decoder, video driver, etc */ - void (*free) (vo_frame_t *vo_img); - - /* free memory/resources for this frame */ - void (*dispose) (vo_frame_t *vo_img); - - /* - * public variables to decoders and vo drivers - * changing anything here will require recompiling them both - */ - int64_t pts; /* presentation time stamp (1/90000 sec) */ - int64_t vpts; /* virtual pts, generated by metronom */ - int bad_frame; /* e.g. frame skipped or based on skipped frame */ - int duration; /* frame length in time, in 1/90000 sec */ - - /* yv12 (planar) base[0]: y, base[1]: u, base[2]: v */ - /* yuy2 (interleaved) base[0]: yuyv..., base[1]: --, base[2]: -- */ - uint8_t *base[3]; - int pitches[3]; - - /* info that can be used for interlaced output (e.g. tv-out) */ - int top_field_first; - int repeat_first_field; - /* note: progressive_frame is set wrong on many mpeg2 streams. for - * that reason, this flag should be interpreted as a "hint". - */ - int progressive_frame; - int picture_coding_type; - - /* cropping to be done */ - int crop_left, crop_right, crop_top, crop_bottom; - - /* extra info coming from input or demuxers */ - extra_info_t *extra_info; - - /* additional information to be able to duplicate frames: */ - int width, height; - double ratio; /* aspect ratio */ - int format; /* IMGFMT_YV12 or IMGFMT_YUY2 */ - - int drawn; /* used by decoder, frame has already been drawn */ - int flags; /* remember the frame flags */ - int proc_called; /* track use of proc_*() methods */ - - /* Used to carry private data for accelerated plugins.*/ - void *accel_data; - - /* "backward" references to where this frame originates from */ - xine_video_port_t *port; - vo_driver_t *driver; - xine_stream_t *stream; - - /* displacement for overlays */ - int overlay_offset_x, overlay_offset_y; - - /* - * that part is used only by video_out.c for frame management - * obs: changing anything here will require recompiling vo drivers - */ - struct vo_frame_s *next; - int lock_counter; - pthread_mutex_t mutex; /* protect access to lock_count */ - - int id; /* debugging - track this frame */ - int is_first; -}; - - -/* - * Remember that adding new functions to this structure requires - * adaption of the post plugin decoration layer. Be sure to look into - * src/xine-engine/post.[ch]. - */ -struct xine_video_port_s { - - uint32_t (*get_capabilities) (xine_video_port_t *self); /* for constants see below */ - - /* open display driver for video output */ - /* when you are not a full-blown stream, but still need to open the port - * (e.g. you are a post plugin) it is legal to pass an anonymous stream */ - void (*open) (xine_video_port_t *self, xine_stream_t *stream); - - /* - * get_frame - allocate an image buffer from display driver - * - * params : width == width of video to display. - * height == height of video to display. - * ratio == aspect ration information - * format == FOURCC descriptor of image format - * flags == field/prediction flags - */ - vo_frame_t* (*get_frame) (xine_video_port_t *self, uint32_t width, - uint32_t height, double ratio, - int format, int flags); - - /* retrieves the last displayed frame (useful for taking snapshots) */ - vo_frame_t* (*get_last_frame) (xine_video_port_t *self); - - /* overlay stuff */ - void (*enable_ovl) (xine_video_port_t *self, int ovl_enable); - - /* get overlay manager */ - video_overlay_manager_t* (*get_overlay_manager) (xine_video_port_t *self); - - /* flush video_out fifo */ - void (*flush) (xine_video_port_t *self); - - /* Get/Set video property - * - * See VO_PROP_* bellow - */ - int (*get_property) (xine_video_port_t *self, int property); - int (*set_property) (xine_video_port_t *self, int property, int value); - - /* return true if port is opened for this stream, stream can be anonymous */ - int (*status) (xine_video_port_t *self, xine_stream_t *stream, - int *width, int *height, int64_t *img_duration); - - /* video driver is no longer used by decoder => close */ - /* when you are not a full-blown stream, but still need to close the port - * (e.g. you are a post plugin) it is legal to pass an anonymous stream */ - void (*close) (xine_video_port_t *self, xine_stream_t *stream); - - /* called on xine exit */ - void (*exit) (xine_video_port_t *self); - - /* the driver in use */ - vo_driver_t *driver; - -}; - -/* constants for the get/set property functions */ -#define VO_PROP_INTERLACED 0 -#define VO_PROP_ASPECT_RATIO 1 -#define VO_PROP_HUE 2 -#define VO_PROP_SATURATION 3 -#define VO_PROP_CONTRAST 4 -#define VO_PROP_BRIGHTNESS 5 -#define VO_PROP_COLORKEY 6 -#define VO_PROP_AUTOPAINT_COLORKEY 7 -#define VO_PROP_ZOOM_X 8 -#define VO_PROP_PAN_SCAN 9 -#define VO_PROP_TVMODE 10 -#define VO_PROP_MAX_NUM_FRAMES 11 -#define VO_PROP_GAMMA 12 -#define VO_PROP_ZOOM_Y 13 -#define VO_PROP_DISCARD_FRAMES 14 /* not used by drivers */ -#define VO_PROP_WINDOW_WIDTH 15 /* read-only */ -#define VO_PROP_WINDOW_HEIGHT 16 /* read-only */ -#define VO_PROP_BUFS_IN_FIFO 17 /* read-only */ -#define VO_PROP_NUM_STREAMS 18 /* read-only */ -#define VO_PROP_OUTPUT_WIDTH 19 /* read-only */ -#define VO_PROP_OUTPUT_HEIGHT 20 /* read-only */ -#define VO_PROP_OUTPUT_XOFFSET 21 /* read-only */ -#define VO_PROP_OUTPUT_YOFFSET 22 /* read-only */ -#define VO_NUM_PROPERTIES 23 - -/* number of colors in the overlay palette. Currently limited to 256 - at most, because some alphablend functions use an 8-bit index into - the palette. This should probably be classified as a bug. */ -#define OVL_PALETTE_SIZE 256 - -#define OVL_MAX_OPACITY 0x0f - -/* number of recent frames to keep in memory - these frames are needed by some deinterlace algorithms - FIXME: we need a method to flush the recent frames (new stream) -*/ -#define VO_NUM_RECENT_FRAMES 2 - -/* get_frame flags */ -#define VO_TOP_FIELD 1 -#define VO_BOTTOM_FIELD 2 -#define VO_BOTH_FIELDS (VO_TOP_FIELD | VO_BOTTOM_FIELD) -#define VO_PAN_SCAN_FLAG 4 -#define VO_INTERLACED_FLAG 8 -#define VO_NEW_SEQUENCE_FLAG 16 /* set after MPEG2 Sequence Header Code (used by XvMC) */ - -/* video driver capabilities */ -#define VO_CAP_YV12 0x00000001 /* driver can handle YUV 4:2:0 pictures */ -#define VO_CAP_YUY2 0x00000002 /* driver can handle YUY2 pictures */ -#define VO_CAP_XVMC_MOCOMP 0x00000004 /* driver can use XvMC motion compensation */ -#define VO_CAP_XVMC_IDCT 0x00000008 /* driver can use XvMC idct acceleration */ -#define VO_CAP_UNSCALED_OVERLAY 0x00000010 /* driver can blend overlay at output resolution */ -#define VO_CAP_CROP 0x00000020 /* driver can crop */ -#define VO_CAP_XXMC 0x00000040 /* driver can use extended XvMC */ - - -/* - * vo_driver_s contains the functions every display driver - * has to implement. The vo_new_port function (see below) - * should then be used to construct a vo_port using this - * driver. Some of the function pointers will be copied - * directly into xine_video_port_s, others will be called - * from generic vo functions. - */ - -#define VIDEO_OUT_DRIVER_IFACE_VERSION 21 - -struct vo_driver_s { - - uint32_t (*get_capabilities) (vo_driver_t *self); /* for constants see above */ - - /* - * allocate an vo_frame_t struct, - * the driver must supply the copy, field and dispose functions - */ - vo_frame_t* (*alloc_frame) (vo_driver_t *self); - - /* - * check if the given image fullfills the format specified - * (re-)allocate memory if necessary - */ - void (*update_frame_format) (vo_driver_t *self, vo_frame_t *img, - uint32_t width, uint32_t height, - double ratio, int format, int flags); - - /* display a given frame */ - void (*display_frame) (vo_driver_t *self, vo_frame_t *vo_img); - - /* overlay_begin and overlay_end are used by drivers suporting - * persistent overlays. they can be optimized to update only when - * overlay image has changed. - * - * sequence of operation (pseudo-code): - * overlay_begin(this,img,true_if_something_changed_since_last_blend ); - * while(visible_overlays) - * overlay_blend(this,img,overlay[i]); - * overlay_end(this,img); - * - * any function pointer from this group may be set to NULL. - */ - void (*overlay_begin) (vo_driver_t *self, vo_frame_t *vo_img, int changed); - void (*overlay_blend) (vo_driver_t *self, vo_frame_t *vo_img, vo_overlay_t *overlay); - void (*overlay_end) (vo_driver_t *self, vo_frame_t *vo_img); - - /* - * these can be used by the gui directly: - */ - int (*get_property) (vo_driver_t *self, int property); - int (*set_property) (vo_driver_t *self, - int property, int value); - void (*get_property_min_max) (vo_driver_t *self, - int property, int *min, int *max); - - /* - * general purpose communication channel between gui and driver - * - * this should be used to propagate events, display data, window sizes - * etc. to the driver - */ - int (*gui_data_exchange) (vo_driver_t *self, int data_type, - void *data); - - /* check if a redraw is needed (due to resize) - * this is only used for still frames, normal video playback - * must call that inside display_frame() function. - */ - int (*redraw_needed) (vo_driver_t *self); - - /* - * free all resources, close driver - */ - void (*dispose) (vo_driver_t *self); - - void *node; /* needed by plugin_loader */ -}; - -struct video_driver_class_s { - - /* - * open a new instance of this plugin class - */ - vo_driver_t* (*open_plugin) (video_driver_class_t *self, const void *visual); - - /* - * return short, human readable identifier for this plugin class - */ - char* (*get_identifier) (video_driver_class_t *self); - - /* - * return human readable (verbose = 1 line) description for - * this plugin class - */ - char* (*get_description) (video_driver_class_t *self); - - /* - * free all class-related resources - */ - void (*dispose) (video_driver_class_t *self); -}; - - -typedef struct rle_elem_s { - uint16_t len; - uint16_t color; -} rle_elem_t; - -struct vo_overlay_s { - - rle_elem_t *rle; /* rle code buffer */ - int data_size; /* useful for deciding realloc */ - int num_rle; /* number of active rle codes */ - int x; /* x start of subpicture area */ - int y; /* y start of subpicture area */ - int width; /* width of subpicture area */ - int height; /* height of subpicture area */ - - uint32_t color[OVL_PALETTE_SIZE]; /* color lookup table */ - uint8_t trans[OVL_PALETTE_SIZE]; /* mixer key table */ - int rgb_clut; /* true if clut was converted to rgb */ - - /* define a highlight area with different colors */ - int hili_top; - int hili_bottom; - int hili_left; - int hili_right; - uint32_t hili_color[OVL_PALETTE_SIZE]; - uint8_t hili_trans[OVL_PALETTE_SIZE]; - int hili_rgb_clut; /* true if clut was converted to rgb */ - - int unscaled; /* true if it should be blended unscaled */ -}; - - -/* API to video_overlay manager - * - * Remember that adding new functions to this structure requires - * adaption of the post plugin decoration layer. Be sure to look into - * src/xine-engine/post.[ch]. - */ -struct video_overlay_manager_s { - void (*init) (video_overlay_manager_t *this_gen); - - void (*dispose) (video_overlay_manager_t *this_gen); - - int32_t (*get_handle) (video_overlay_manager_t *this_gen, int object_type ); - - void (*free_handle) (video_overlay_manager_t *this_gen, int32_t handle); - - int32_t (*add_event) (video_overlay_manager_t *this_gen, void *event); - - void (*flush_events) (video_overlay_manager_t *this_gen ); - - int (*redraw_needed) (video_overlay_manager_t *this_gen, int64_t vpts ); - - void (*multiple_overlay_blend) (video_overlay_manager_t *this_gen, int64_t vpts, - vo_driver_t *output, vo_frame_t *vo_img, int enabled); -}; - -/* - * build a video_out_port from - * a given video driver - */ -xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabonly) XINE_MALLOC XINE_PROTECTED; - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/xine-engine/video_overlay.c b/src/xine-engine/video_overlay.c index 3216950e8..0052375bb 100644 --- a/src/xine-engine/video_overlay.c +++ b/src/xine-engine/video_overlay.c @@ -29,11 +29,11 @@ #include <sys/stat.h> #include <fcntl.h> -#include "buffer.h" -#include "xine_internal.h" +#include <xine/buffer.h> +#include <xine/xine_internal.h> #include "bswap.h" -#include "xineutils.h" -#include "video_overlay.h" +#include <xine/xineutils.h> +#include <xine/video_overlay.h> /* #define LOG_DEBUG @@ -174,6 +174,8 @@ static void internal_video_overlay_free_handle(video_overlay_t *this, int32_t ha pthread_mutex_lock( &this->objects_mutex ); if( this->objects[handle].overlay ) { + set_argb_layer_ptr(&this->objects[handle].overlay->argb_layer, NULL); + if( this->objects[handle].overlay->rle ) free( this->objects[handle].overlay->rle ); free( this->objects[handle].overlay ); @@ -396,6 +398,8 @@ static int video_overlay_event( video_overlay_t *this, int64_t vpts ) { #endif /* free any overlay associated with this event */ if (this->events[this_event].event->object.overlay != NULL) { + set_argb_layer_ptr(&this->events[this_event].event->object.overlay->argb_layer, NULL); + if( this->events[this_event].event->object.overlay->rle != NULL ) free( this->events[this_event].event->object.overlay->rle ); free(this->events[this_event].event->object.overlay); @@ -410,6 +414,8 @@ static int video_overlay_event( video_overlay_t *this, int64_t vpts ) { #endif /* free any overlay associated with this event */ if( this->events[this_event].event->object.overlay != NULL) { + set_argb_layer_ptr(&this->events[this_event].event->object.overlay->argb_layer, NULL); + if( this->events[this_event].event->object.overlay->rle != NULL ) free( this->events[this_event].event->object.overlay->rle ); free(this->events[this_event].event->object.overlay); diff --git a/src/xine-engine/video_overlay.h b/src/xine-engine/video_overlay.h deleted file mode 100644 index f2deb8a2b..000000000 --- a/src/xine-engine/video_overlay.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2000-2003 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - */ - -#ifndef HAVE_VIDEO_OVERLAY_H -#define HAVE_VIDEO_OVERLAY_H - -#ifdef XINE_COMPILE -# include "xine_internal.h" -#else -# include <xine/xine_internal.h> -#endif - -#ifdef __GNUC__ -#define CLUT_Y_CR_CB_INIT(_y,_cr,_cb) {y: (_y), cr: (_cr), cb: (_cb)} -#else -#define CLUT_Y_CR_CB_INIT(_y,_cr,_cb) { (_cb), (_cr), (_y) } -#endif - -#define MAX_OBJECTS 50 -#define MAX_EVENTS 50 -#define MAX_SHOWING 16 - -#define OVERLAY_EVENT_NULL 0 -#define OVERLAY_EVENT_SHOW 1 -#define OVERLAY_EVENT_HIDE 2 -#define OVERLAY_EVENT_MENU_BUTTON 3 -#define OVERLAY_EVENT_FREE_HANDLE 8 /* Frees a handle, previous allocated via get_handle */ - -/* number of colors in the overlay palette. Currently limited to 256 - at most, because some alphablend functions use an 8-bit index into - the palette. This should probably be classified as a bug. */ -/* FIXME: Also defines in video_out.h */ -#define OVL_PALETTE_SIZE 256 - -typedef struct vo_buttons_s { - int32_t type; /* 0:Button not valid, - 1:Button Valid, no auto_action, - 2:Button Valid, auto_action. - */ - - /* The following clipping coordinates are relative to the left upper corner - * of the OVERLAY, not of the target FRAME. Please do not mix them up! */ - int32_t hili_top; - int32_t hili_bottom; - int32_t hili_left; - int32_t hili_right; - int32_t up; - int32_t down; - int32_t left; - int32_t right; - uint32_t select_color[OVL_PALETTE_SIZE]; - uint8_t select_trans[OVL_PALETTE_SIZE]; - xine_event_t select_event; - uint32_t active_color[OVL_PALETTE_SIZE]; - uint8_t active_trans[OVL_PALETTE_SIZE]; - xine_event_t active_event; - int32_t hili_rgb_clut; /* true if clut was converted to rgb*/ - /* FIXME: Probably not needed ^^^ */ -} vo_buttons_t; - -typedef struct video_overlay_object_s { - int32_t handle; /* Used to match Show and Hide events. */ - uint32_t object_type; /* 0=Subtitle, 1=Menu */ - int64_t pts; /* Needed for Menu button compares */ - vo_overlay_t *overlay; /* The image data. */ - uint32_t palette_type; /* 1 Y'CrCB, 2 R'G'B' */ - uint32_t *palette; /* If NULL, no palette contained in this event. */ - int32_t buttonN; /* Current highlighed button. 0 means no info on which button to higlight */ - /* -1 means don't use this button info. */ - vo_buttons_t button[32]; /* Info regarding each button on the overlay */ -} video_overlay_object_t; - -/* This will hold all details of an event item, needed for event queue to function */ -typedef struct video_overlay_event_s { - uint32_t event_type; /* Show SPU, Show OSD, Hide etc. */ - int64_t vpts; /* Time when event will action. 0 means action now */ -/* Once video_out blend_yuv etc. can take rle_elem_t with Colour, blend and length information. - * we can remove clut and blend from this structure. - * This will allow for many more colours for OSD. - */ - video_overlay_object_t object; /* The image data. */ -} video_overlay_event_t; - -video_overlay_manager_t *_x_video_overlay_new_manager(xine_t *) XINE_MALLOC XINE_PROTECTED; - -#endif diff --git a/src/xine-engine/vo_scale.c b/src/xine-engine/vo_scale.c index e2b7ac9e4..e44fc4966 100644 --- a/src/xine-engine/vo_scale.c +++ b/src/xine-engine/vo_scale.c @@ -36,8 +36,8 @@ #define LOG */ -#include "xine_internal.h" -#include "vo_scale.h" +#include <xine/xine_internal.h> +#include <xine/vo_scale.h> /* * convert delivered height/width to ideal width/height @@ -315,28 +315,21 @@ void _x_vo_scale_translate_gui2video(vo_scale_t *this, *vid_y = y; } -/* - * Returns description of a given ratio code +/*/ + * @brief Table for description of a given ratio code. + * + * @note changing the size of the elements of the array will break + * ABI, so please don't do that unless you absolutely can't continue + * with the current size. */ - -char *_x_vo_scale_aspect_ratio_name(int a) { - - switch (a) { - case XINE_VO_ASPECT_AUTO: - return "auto"; - case XINE_VO_ASPECT_SQUARE: - return "square"; - case XINE_VO_ASPECT_4_3: - return "4:3"; - case XINE_VO_ASPECT_ANAMORPHIC: - return "16:9"; - case XINE_VO_ASPECT_DVB: - return "2:1"; - default: - return "unknown"; - } -} - +const char _x_vo_scale_aspect_ratio_name_table[][8] = { + "auto", /* XINE_VO_ASPECT_AUTO */ + "square", /* XINE_VO_ASPECT_SQUARE */ + "4:3", /* XINE_VO_ASPECT_4_3 */ + "16:9", /* XINE_VO_ASPECT_ANAMORPHIC */ + "2:1", /* XINE_VO_ASPECT_DVB */ + "unknown" /* All the rest */ +}; /* * config callbacks diff --git a/src/xine-engine/vo_scale.h b/src/xine-engine/vo_scale.h deleted file mode 100644 index fe2594eeb..000000000 --- a/src/xine-engine/vo_scale.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2000-2003 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * vo_scale.h - * - * keeps video scaling information - */ - -#ifndef HAVE_VO_SCALE_H -#define HAVE_VO_SCALE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef XINE_COMPILE -# include "configfile.h" -#else -# include <xine/configfile.h> -#endif - -typedef struct { - int x, y; - int w, h; -} vo_scale_rect_t; - -struct vo_scale_s { - - /* true if driver supports frame zooming */ - int support_zoom; - - /* forces direct mapping between frame pixels and screen pixels */ - int scaling_disabled; - - /* size / aspect ratio calculations */ - - /* - * "delivered" size: - * frame dimension / aspect as delivered by the decoder - * used (among other things) to detect frame size changes - * units: frame pixels - */ - int delivered_width; - int delivered_height; - double delivered_ratio; - - /* - * required cropping: - * units: frame pixels - */ - int crop_left; - int crop_right; - int crop_top; - int crop_bottom; - - /* - * displayed part of delivered images, - * taking zoom into account - * units: frame pixels - */ - int displayed_xoffset; - int displayed_yoffset; - int displayed_width; - int displayed_height; - double zoom_factor_x, zoom_factor_y; - - /* - * user's aspect selection - */ - int user_ratio; - - /* - * "gui" size / offset: - * what gui told us about where to display the video - * units: screen pixels - */ - int gui_x, gui_y; - int gui_width, gui_height; - int gui_win_x, gui_win_y; - - /* - * video + display pixel aspect - * One pixel of height 1 has this width - * This may be corrected by the driver in order to fit the video seamlessly - */ - double gui_pixel_aspect; - double video_pixel_aspect; - - /* - * "output" size: - * - * this is finally the ideal size "fitted" into the - * gui size while maintaining the aspect ratio - * units: screen pixels - */ - int output_width; - int output_height; - int output_xoffset; - int output_yoffset; - - - /* */ - int force_redraw; - - - /* gui callbacks */ - - void *user_data; - void (*frame_output_cb) (void *user_data, - int video_width, int video_height, - double video_pixel_aspect, - int *dest_x, int *dest_y, - int *dest_width, int *dest_height, - double *dest_pixel_aspect, - int *win_x, int *win_y); - - void (*dest_size_cb) (void *user_data, - int video_width, int video_height, - double video_pixel_aspect, - int *dest_width, int *dest_height, - double *dest_pixel_aspect); - - /* borders */ - vo_scale_rect_t border[4]; - - /* - * border ratios to determine image position in the - * viewport; these are set by user config - */ - double output_horizontal_position; - double output_vertical_position; - -}; - -typedef struct vo_scale_s vo_scale_t; - - -/* - * convert delivered height/width to ideal width/height - * taking into account aspect ratio and zoom factor - */ - -void _x_vo_scale_compute_ideal_size (vo_scale_t *self) XINE_PROTECTED; - - -/* - * make ideal width/height "fit" into the gui - */ - -void _x_vo_scale_compute_output_size (vo_scale_t *self) XINE_PROTECTED; - -/* - * return true if a redraw is needed due resizing, zooming, - * aspect ratio changing, etc. - */ - -int _x_vo_scale_redraw_needed (vo_scale_t *self) XINE_PROTECTED; - -/* - * - */ - -void _x_vo_scale_translate_gui2video(vo_scale_t *self, - int x, int y, - int *vid_x, int *vid_y) XINE_PROTECTED; - -/* - * Returns description of a given ratio code - */ - -char *_x_vo_scale_aspect_ratio_name(int a) XINE_PROTECTED; - -/* - * initialize rescaling struct - */ - -void _x_vo_scale_init(vo_scale_t *self, int support_zoom, - int scaling_disabled, config_values_t *config ) XINE_PROTECTED; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index 5a180c212..9a7e28a7f 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" /* FIXME-ABI Global variable. Done this way for ABI & API reasons... */ int _x_flags = 0; @@ -298,8 +303,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); @@ -321,12 +355,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); @@ -528,6 +565,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)) { @@ -538,6 +576,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; } @@ -552,6 +591,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)) { @@ -562,6 +602,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; } @@ -642,6 +683,7 @@ xine_stream_t *xine_stream_new (xine_t *this, pthread_mutex_init (&stream->info_mutex, NULL); pthread_mutex_init (&stream->meta_mutex, NULL); pthread_mutex_init (&stream->demux_lock, NULL); + pthread_mutex_init (&stream->demux_action_lock, NULL); pthread_mutex_init (&stream->demux_mutex, NULL); pthread_cond_init (&stream->demux_resume, NULL); pthread_mutex_init (&stream->event_queues_lock, NULL); @@ -708,9 +750,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; /* @@ -877,11 +920,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) { @@ -935,7 +979,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")); @@ -1011,7 +1055,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")); @@ -1198,7 +1242,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. @@ -1214,7 +1258,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); @@ -1240,11 +1284,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 ); @@ -1339,7 +1384,7 @@ static int play_internal (xine_stream_t *stream, int start_pos, int start_time) } /* hint demuxer thread we want to interrupt it */ - stream->demux_action_pending = 1; + _x_action_raise(stream); /* set normal speed */ if (_x_get_speed(stream) != XINE_SPEED_NORMAL) @@ -1358,7 +1403,7 @@ static int play_internal (xine_stream_t *stream, int start_pos, int start_time) pthread_mutex_lock( &stream->demux_lock ); /* demux_lock taken. now demuxer is suspended */ - stream->demux_action_pending = 0; + _x_action_lower(stream); pthread_cond_signal(&stream->demux_resume); /* set normal speed again (now that demuxer/input pair is suspended) @@ -1495,6 +1540,7 @@ static void xine_dispose_internal (xine_stream_t *stream) { pthread_cond_destroy (&stream->counter_changed); pthread_mutex_destroy (&stream->demux_mutex); pthread_cond_destroy (&stream->demux_resume); + pthread_mutex_destroy (&stream->demux_action_lock); pthread_mutex_destroy (&stream->demux_lock); pthread_mutex_destroy (&stream->first_frame_lock); pthread_cond_destroy (&stream->first_frame_reached); @@ -1575,6 +1621,8 @@ void xine_exit (xine_t *this) { WSACleanup(); #endif + xdgWipeHandle(&this->basedir_handle); + free (this); } @@ -1674,9 +1722,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]; - homedir_trail_slash = _x_asprintf("%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 || @@ -1695,7 +1743,6 @@ 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; } @@ -1706,8 +1753,12 @@ void xine_set_flags (xine_t *this, int flags) } 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. */ + setenv ("HOME", xine_get_homedir (), 0); /* libxdg-basedir needs $HOME */ + xdgInitHandle(&this->basedir_handle); /* * locks @@ -1723,7 +1774,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, "")) @@ -1985,7 +2036,7 @@ static int _x_get_current_frame_data (xine_stream_t *stream, int flags, int img_size_unknown) { vo_frame_t *frame; - size_t required_size; + size_t required_size = 0; stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); frame = stream->video_out->get_last_frame (stream->video_out); @@ -2020,6 +2071,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) @@ -2032,26 +2107,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 */ @@ -2087,11 +2157,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; } @@ -2158,16 +2231,15 @@ 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; +xine_grab_video_frame_t* xine_new_grab_video_frame (xine_stream_t *stream) { + xine_grab_video_frame_t *frame; + + if (stream->video_out->driver->new_grab_video_frame) + frame = stream->video_out->driver->new_grab_video_frame(stream->video_out->driver); + else + frame = stream->video_out->new_grab_video_frame(stream->video_out); + + return frame; } int xine_get_spu_lang (xine_stream_t *stream, int channel, char *lang) { @@ -2313,11 +2385,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; @@ -2356,3 +2423,146 @@ int _x_query_buffer_usage(xine_stream_t *stream, int *num_video_buffers, int *nu return ticket_acquired != 0; } + +static void _x_query_buffers_fix_data(xine_query_buffers_data_t *data) +{ + if (data->total < 0) + data->total = 0; + + if (data->ready < 0) + data->ready = 0; + + if (data->avail < 0) + data->avail = 0; + + /* fix race condition of not filling data atomically */ + if (data->ready + data->avail > data->total) + data->avail = data->total - data->ready; +} + +int _x_query_buffers(xine_stream_t *stream, xine_query_buffers_t *query) +{ + int ticket_acquired = -1; + + memset(query, 0, sizeof (*query)); + + if (stream->video_fifo) + { + query->vi.total = stream->video_fifo->buffer_pool_capacity; + query->vi.ready = stream->video_fifo->size(stream->video_fifo); + query->vi.avail = stream->video_fifo->num_free(stream->video_fifo); + _x_query_buffers_fix_data(&query->vi); + } + + if (stream->audio_fifo) + { + query->ai.total = stream->audio_fifo->buffer_pool_capacity; + query->ai.ready = stream->audio_fifo->size(stream->audio_fifo); + query->ai.avail = stream->audio_fifo->num_free(stream->audio_fifo); + _x_query_buffers_fix_data(&query->ai); + } + + if (stream->video_out || stream->audio_out) + ticket_acquired = stream->xine->port_ticket->acquire_nonblocking(stream->xine->port_ticket, 1); + + if (ticket_acquired > 0) + { + if (stream->video_out) + { + query->vo.total = stream->video_out->get_property(stream->video_out, VO_PROP_BUFS_TOTAL); + query->vo.ready = stream->video_out->get_property(stream->video_out, VO_PROP_BUFS_IN_FIFO); + query->vo.avail = stream->video_out->get_property(stream->video_out, VO_PROP_BUFS_FREE); + } + + if (stream->audio_out) + { + query->ao.total = stream->audio_out->get_property(stream->audio_out, AO_PROP_BUFS_TOTAL); + query->ao.ready = stream->audio_out->get_property(stream->audio_out, AO_PROP_BUFS_IN_FIFO); + query->ao.avail = stream->audio_out->get_property(stream->audio_out, AO_PROP_BUFS_FREE); + } + + stream->xine->port_ticket->release_nonblocking(stream->xine->port_ticket, 1); + } + + 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; +} diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c index 62de42678..ab1bafa1e 100644 --- a/src/xine-engine/xine_interface.c +++ b/src/xine-engine/xine_interface.c @@ -40,11 +40,11 @@ #define XINE_ENGINE_INTERNAL -#include "xine_internal.h" -#include "audio_out.h" -#include "video_out.h" -#include "demuxers/demux.h" -#include "post.h" +#include <xine/xine_internal.h> +#include <xine/audio_out.h> +#include <xine/video_out.h> +#include <xine/demux.h> +#include <xine/post.h> /* * version information / checking @@ -322,15 +322,6 @@ void xine_config_reset (xine_t *this) { pthread_mutex_unlock(&config->config_lock); } -#ifndef XINE_DISABLE_DEPRECATED_FEATURES -int xine_gui_send_vo_data (xine_stream_t *stream, - int type, void *data) { - - return stream->video_driver->gui_data_exchange (stream->video_driver, - type, data); -} -#endif - int xine_port_send_gui_data (xine_video_port_t *vo, int type, void *data) { @@ -474,6 +465,8 @@ void xine_set_param (xine_stream_t *stream, int param, int value) { stream->xine->verbosity = value; break; + case XINE_PARAM_VO_SHARPNESS: + case XINE_PARAM_VO_NOISE_REDUCTION: case XINE_PARAM_VO_HUE: case XINE_PARAM_VO_SATURATION: case XINE_PARAM_VO_CONTRAST: @@ -639,6 +632,8 @@ int xine_get_param (xine_stream_t *stream, int param) { ret = stream->xine->verbosity; break; + case XINE_PARAM_VO_SHARPNESS: + case XINE_PARAM_VO_NOISE_REDUCTION: case XINE_PARAM_VO_HUE: case XINE_PARAM_VO_SATURATION: case XINE_PARAM_VO_CONTRAST: @@ -860,6 +855,20 @@ void xine_osd_draw_bitmap(xine_osd_t *this, uint8_t *bitmap, this->osd.renderer->draw_bitmap(&this->osd, bitmap, x1, y1, width, height, palette_map); } +void xine_osd_set_argb_buffer(xine_osd_t *this, uint32_t *argb_buffer, + int dirty_x, int dirty_y, int dirty_width, int dirty_height) { + this->osd.renderer->set_argb_buffer(&this->osd, argb_buffer, dirty_x, dirty_y, dirty_width, dirty_height); +} + +void xine_osd_set_extent(xine_osd_t *this, int extent_width, int extent_height) { + this->osd.renderer->set_extent(&this->osd, extent_width, extent_height); +} + +void xine_osd_set_video_window(xine_osd_t *this, int window_x, int window_y, int window_width, int window_height) { + this->osd.renderer->set_video_window(&this->osd, window_x, window_y, window_width, window_height); +} + + const char *const *xine_post_list_inputs(xine_post_t *this_gen) { post_plugin_t *this = (post_plugin_t *)this_gen; return this->input_ids; @@ -957,7 +966,7 @@ int _x_message(xine_stream_t *stream, int type, ...) { va_list ap; char *s, *params; char *args[1025]; - static const char *std_explanation[] = { + static const char *const std_explanation[] = { "", N_("Warning:"), N_("Unknown host:"), diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h deleted file mode 100644 index af8817ac5..000000000 --- a/src/xine-engine/xine_internal.h +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Copyright (C) 2000-2005 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - */ - -#ifndef HAVE_XINE_INTERNAL_H -#define HAVE_XINE_INTERNAL_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * include public part of xine header - */ - -#ifdef XINE_COMPILE -# include "xine.h" -# include "refcounter.h" -# include "input/input_plugin.h" -# include "demuxers/demux.h" -# include "video_out.h" -# include "audio_out.h" -# include "metronom.h" -# include "osd.h" -# include "xineintl.h" -# include "plugin_catalog.h" -# include "video_decoder.h" -# include "audio_decoder.h" -# include "spu_decoder.h" -# include "scratch.h" -# include "broadcaster.h" -# include "io_helper.h" -# include "info_helper.h" -# include "alphablend.h" -#else -# include <xine.h> -# include <xine/refcounter.h> -# include <xine/input_plugin.h> -# include <xine/demux.h> -# include <xine/video_out.h> -# include <xine/audio_out.h> -# include <xine/metronom.h> -# include <xine/osd.h> -# include <xine/xineintl.h> -# include <xine/plugin_catalog.h> -# include <xine/video_decoder.h> -# include <xine/audio_decoder.h> -# include <xine/spu_decoder.h> -# include <xine/scratch.h> -# include <xine/broadcaster.h> -# include <xine/io_helper.h> -# include <xine/info_helper.h> -# include <xine/alphablend.h> -#endif - - -#define XINE_MAX_EVENT_LISTENERS 50 -#define XINE_MAX_EVENT_TYPES 100 -#define XINE_MAX_TICKET_HOLDER_THREADS 64 - -/* used by plugin loader */ -#define XINE_VERSION_CODE XINE_MAJOR_VERSION*10000+XINE_MINOR_VERSION*100+XINE_SUB_VERSION - - -/* - * log constants - */ - -#define XINE_LOG_MSG 0 /* warnings, errors, ... */ -#define XINE_LOG_PLUGIN 1 -#define XINE_LOG_TRACE 2 -#define XINE_LOG_NUM 3 /* # of log buffers defined */ - -#define XINE_STREAM_INFO_MAX 99 - -typedef struct xine_ticket_s xine_ticket_t; - -/* - * the "big" xine struct, holding everything together - */ - -struct xine_s { - - config_values_t *config; - - plugin_catalog_t *plugin_catalog; - - int demux_strategy; - char *save_path; - - /* log output that may be presented to the user */ - scratch_buffer_t *log_buffers[XINE_LOG_NUM]; - - int verbosity; - - xine_list_t *streams; - pthread_mutex_t streams_lock; - - metronom_clock_t *clock; - -#ifdef XINE_ENGINE_INTERNAL - xine_ticket_t *port_ticket; - pthread_mutex_t log_lock; - - xine_log_cb_t log_cb; - void *log_cb_user_data; -#endif -}; - -/* FIXME-ABI Some global flag bits */ -/* See xine_set_flags() */ -#ifdef XINE_ENGINE_INTERNAL -extern int _x_flags XINE_PROTECTED; -#endif - -/* - * xine thread tickets - */ - -struct xine_ticket_s { - - /* the ticket owner must assure to check for ticket revocation in - * intervals of finite length; this means that you must release - * the ticket before any operation that might block - * - * you must never write to this member directly - */ - int ticket_revoked; - - /* apply for a ticket; between acquire and relese of an irrevocable - * ticket (be sure to pair them properly!), it is guaranteed that you - * will never be blocked by ticket revocation */ - void (*acquire)(xine_ticket_t *self, int irrevocable); - - /* give a ticket back */ - void (*release)(xine_ticket_t *self, int irrevocable); - - /* renew a ticket, when it has been revoked, see ticket_revoked above; - * irrevocable must be set to one, if your thread might have acquired - * irrevocable tickets you don't know of; set it to zero only when - * you know that this is impossible */ - void (*renew)(xine_ticket_t *self, int irrevocable); - -#ifdef XINE_ENGINE_INTERNAL - /* allow handing out new tickets */ - void (*issue)(xine_ticket_t *self, int atomic); - - /* revoke all tickets and deny new ones; - * a pair of atomic revoke and issue cannot be interrupted by another - * revocation or by other threads acquiring tickets */ - void (*revoke)(xine_ticket_t *self, int atomic); - - /* behaves like acquire() but doesn't block the calling thread; when - * the thread would have been blocked, 0 is returned otherwise 1 - * this function acquires a ticket even if ticket revocation is active */ - int (*acquire_nonblocking)(xine_ticket_t *self, int irrevocable); - - /* behaves like release() but doesn't block the calling thread; should - * be used in combination with acquire_nonblocking() */ - void (*release_nonblocking)(xine_ticket_t *self, int irrevocable); - - void (*dispose)(xine_ticket_t *self); - - pthread_mutex_t lock; - pthread_mutex_t revoke_lock; - pthread_cond_t issued; - pthread_cond_t revoked; - int tickets_granted; - int irrevocable_tickets; - int pending_revocations; - int atomic_revoke; - pthread_t atomic_revoker_thread; - struct { - int count; - pthread_t holder; - } *holder_threads; - unsigned holder_thread_count; -#endif -}; - -/* - * xine event queue - */ - -struct xine_event_queue_s { - xine_list_t *events; - pthread_mutex_t lock; - pthread_cond_t new_event; - pthread_cond_t events_processed; - xine_stream_t *stream; - pthread_t *listener_thread; - xine_event_listener_cb_t callback; - int callback_running; - void *user_data; -}; - -/* - * xine_stream - per-stream parts of the xine engine - */ - -struct xine_stream_s { - - /* reference to xine context */ - xine_t *xine; - - /* metronom instance used by current stream */ - metronom_t *metronom; - - /* demuxers use input_plugin to read data */ - input_plugin_t *input_plugin; - - /* current content detection method, see METHOD_BY_xxx */ - int content_detection_method; - - /* used by video decoders */ - xine_video_port_t *video_out; - - /* demuxers send data to video decoders using this fifo */ - fifo_buffer_t *video_fifo; - - /* used by audio decoders */ - xine_audio_port_t *audio_out; - - /* demuxers send data to audio decoders using this fifo */ - fifo_buffer_t *audio_fifo; - - /* provide access to osd api */ - osd_renderer_t *osd_renderer; - - /* master/slave streams */ - xine_stream_t *master; /* usually a pointer to itself */ - xine_stream_t *slave; - - /* input_dvd uses this one. is it possible to add helper functions instead? */ - spu_decoder_t *spu_decoder_plugin; - - /* dxr3 use this one, should be possible to fix to use the port instead */ - vo_driver_t *video_driver; - - /* these definitely should be made private! */ - int audio_channel_auto; - int spu_decoder_streamtype; - int spu_channel_user; - int spu_channel_auto; - int spu_channel_letterbox; - int spu_channel; - -#ifdef XINE_ENGINE_INTERNAL - /* these are private variables, plugins must not access them */ - - int status; - - /* lock controlling speed change access */ - pthread_mutex_t speed_change_lock; - int ignore_speed_change; /* speed changes during stop can be disastrous */ - - input_class_t *eject_class; - demux_plugin_t *demux_plugin; - -/* vo_driver_t *video_driver;*/ - pthread_t video_thread; - int video_thread_created; - video_decoder_t *video_decoder_plugin; - int video_decoder_streamtype; - extra_info_t *video_decoder_extra_info; - int video_channel; - - pthread_t audio_thread; - int audio_thread_created; - audio_decoder_t *audio_decoder_plugin; - int audio_decoder_streamtype; - extra_info_t *audio_decoder_extra_info; - - uint32_t audio_track_map[50]; - int audio_track_map_entries; - uint32_t audio_type; - /* *_user: -2 => off - -1 => auto (use *_auto value) - >=0 => respect the user's choice - */ - int audio_channel_user; -/* int audio_channel_auto; */ - -/* spu_decoder_t *spu_decoder_plugin; */ -/* int spu_decoder_streamtype; */ - uint32_t spu_track_map[50]; - int spu_track_map_entries; -/* int spu_channel_user; */ -/* int spu_channel_auto; */ -/* int spu_channel_letterbox; */ - int spu_channel_pan_scan; -/* int spu_channel; */ - - /* lock for public xine player functions */ - pthread_mutex_t frontend_lock; - - /* stream meta information */ - /* NEVER access directly, use helpers (see info_helper.c) */ - pthread_mutex_t info_mutex; - int stream_info_public[XINE_STREAM_INFO_MAX]; - int stream_info[XINE_STREAM_INFO_MAX]; - pthread_mutex_t meta_mutex; - char *meta_info_public[XINE_STREAM_INFO_MAX]; - char *meta_info[XINE_STREAM_INFO_MAX]; - - /* seeking slowdown */ - int first_frame_flag; - pthread_mutex_t first_frame_lock; - pthread_cond_t first_frame_reached; - - /* wait for headers sent / stream decoding finished */ - pthread_mutex_t counter_lock; - pthread_cond_t counter_changed; - int header_count_audio; - int header_count_video; - int finished_count_audio; - int finished_count_video; - - /* event mechanism */ - xine_list_t *event_queues; - pthread_mutex_t event_queues_lock; - - /* demux thread stuff */ - pthread_t demux_thread; - int demux_thread_created; - int demux_thread_running; - pthread_mutex_t demux_lock; - int demux_action_pending; - pthread_cond_t demux_resume; - pthread_mutex_t demux_mutex; /* used in _x_demux_... functions to synchronize order of pairwise A/V buffer operations */ - - extra_info_t *current_extra_info; - pthread_mutex_t current_extra_info_lock; - int video_seek_count; - - xine_post_out_t video_source; - xine_post_out_t audio_source; - - int slave_is_subtitle; /* ... and will be automaticaly disposed */ - int slave_affection; /* what operations need to be propagated down to the slave? */ - - int err; - - broadcaster_t *broadcaster; - - refcounter_t *refcounter; - - int emergency_brake; /* something went really wrong and this stream must be - * stopped. usually due some fatal error on output - * layers as they cannot call xine_stop. */ - 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 -}; - -/* when explicitly noted, some functions accept an anonymous stream, - * which is a valid stream that does not want to be addressed. */ -#define XINE_ANON_STREAM ((xine_stream_t *)-1) - - -/* - * private function prototypes: - */ - -int _x_query_buffer_usage(xine_stream_t *stream, int *num_video_buffers, int *num_audio_buffers, int *num_video_frames, int *num_audio_frames) XINE_PROTECTED; - -void _x_handle_stream_end (xine_stream_t *stream, int non_user) XINE_PROTECTED; - -/* report message to UI. usually these are async errors */ - -int _x_message(xine_stream_t *stream, int type, ...) XINE_SENTINEL XINE_PROTECTED; - -/* flush the message queues */ - -void _x_flush_events_queues (xine_stream_t *stream) XINE_PROTECTED; - - -/* find and instantiate input and demux plugins */ - -input_plugin_t *_x_find_input_plugin (xine_stream_t *stream, const char *mrl) XINE_PROTECTED; -demux_plugin_t *_x_find_demux_plugin (xine_stream_t *stream, input_plugin_t *input) XINE_PROTECTED; -demux_plugin_t *_x_find_demux_plugin_by_name (xine_stream_t *stream, const char *name, input_plugin_t *input) XINE_PROTECTED; -demux_plugin_t *_x_find_demux_plugin_last_probe(xine_stream_t *stream, const char *last_demux_name, input_plugin_t *input) XINE_PROTECTED; -input_plugin_t *_x_rip_plugin_get_instance (xine_stream_t *stream, const char *filename) XINE_MALLOC XINE_PROTECTED; -input_plugin_t *_x_cache_plugin_get_instance (xine_stream_t *stream, int readahead_size) XINE_MALLOC XINE_PROTECTED; -void _x_free_input_plugin (xine_stream_t *stream, input_plugin_t *input) XINE_PROTECTED; -void _x_free_demux_plugin (xine_stream_t *stream, demux_plugin_t *demux) XINE_PROTECTED; - -/* create decoder fifos and threads */ - -int _x_video_decoder_init (xine_stream_t *stream) XINE_PROTECTED; -void _x_video_decoder_shutdown (xine_stream_t *stream) XINE_PROTECTED; - -int _x_audio_decoder_init (xine_stream_t *stream) XINE_PROTECTED; -void _x_audio_decoder_shutdown (xine_stream_t *stream) XINE_PROTECTED; - -/* extra_info operations */ -void _x_extra_info_reset( extra_info_t *extra_info ) XINE_PROTECTED; - -void _x_extra_info_merge( extra_info_t *dst, extra_info_t *src ) XINE_PROTECTED; - -void _x_get_current_info (xine_stream_t *stream, extra_info_t *extra_info, int size) XINE_PROTECTED; - - -/* demuxer helper functions from demux.c */ - -/* - * Flush audio and video buffers. It is called from demuxers on - * seek/stop, and may be useful when user input changes a stream and - * xine-lib has cached buffers that have yet to be played. - * - * warning: after clearing decoders fifos an absolute discontinuity - * indication must be sent. relative discontinuities are likely - * to cause "jumps" on metronom. - */ -void _x_demux_flush_engine (xine_stream_t *stream) XINE_PROTECTED; - -void _x_demux_control_nop (xine_stream_t *stream, uint32_t flags) XINE_PROTECTED; -void _x_demux_control_newpts (xine_stream_t *stream, int64_t pts, uint32_t flags) XINE_PROTECTED; -void _x_demux_control_headers_done (xine_stream_t *stream) XINE_PROTECTED; -void _x_demux_control_start (xine_stream_t *stream) XINE_PROTECTED; -void _x_demux_control_end (xine_stream_t *stream, uint32_t flags) XINE_PROTECTED; -int _x_demux_start_thread (xine_stream_t *stream) XINE_PROTECTED; -int _x_demux_stop_thread (xine_stream_t *stream) XINE_PROTECTED; -int _x_demux_read_header (input_plugin_t *input, unsigned char *buffer, off_t size) XINE_PROTECTED; -int _x_demux_check_extension (const char *mrl, const char *extensions) XINE_PROTECTED; - -off_t _x_read_abort (xine_stream_t *stream, int fd, char *buf, off_t todo) XINE_PROTECTED; - -int _x_action_pending (xine_stream_t *stream) XINE_PROTECTED; - -void _x_demux_send_data(fifo_buffer_t *fifo, uint8_t *data, int size, - int64_t pts, uint32_t type, uint32_t decoder_flags, - int input_normpos, int input_time, int total_time, - uint32_t frame_number) XINE_PROTECTED; - -int _x_demux_read_send_data(fifo_buffer_t *fifo, input_plugin_t *input, - int size, int64_t pts, uint32_t type, - uint32_t decoder_flags, off_t input_normpos, - int input_time, int total_time, - uint32_t frame_number) XINE_PROTECTED; - -void _x_demux_send_mrl_reference (xine_stream_t *stream, int alternative, - const char *mrl, const char *title, - int start_time, int duration) XINE_PROTECTED; - -/* - * MRL escaped-character decoding (overwrites the source string) - */ -void _x_mrl_unescape(char *mrl) XINE_PROTECTED; - -/* - * plugin_loader functions - * - */ - -/* on-demand loading of audio/video/spu decoder plugins */ - -video_decoder_t *_x_get_video_decoder (xine_stream_t *stream, uint8_t stream_type) XINE_PROTECTED; -void _x_free_video_decoder (xine_stream_t *stream, video_decoder_t *decoder) XINE_PROTECTED; -audio_decoder_t *_x_get_audio_decoder (xine_stream_t *stream, uint8_t stream_type) XINE_PROTECTED; -void _x_free_audio_decoder (xine_stream_t *stream, audio_decoder_t *decoder) XINE_PROTECTED; -spu_decoder_t *_x_get_spu_decoder (xine_stream_t *stream, uint8_t stream_type) XINE_PROTECTED; -void _x_free_spu_decoder (xine_stream_t *stream, spu_decoder_t *decoder) XINE_PROTECTED; -/* check for decoder availability - but don't try to initialize it */ -int _x_decoder_available (xine_t *xine, uint32_t buftype) XINE_PROTECTED; - -/* - * load_video_output_plugin - * - * load a specific video output plugin - */ - -vo_driver_t *_x_load_video_output_plugin(xine_t *this, - char *id, int visual_type, void *visual) XINE_PROTECTED; - -/* - * audio output plugin dynamic loading stuff - */ - -/* - * load_audio_output_plugin - * - * load a specific audio output plugin - */ - -ao_driver_t *_x_load_audio_output_plugin (xine_t *self, const char *id) XINE_PROTECTED; - - -void _x_set_speed (xine_stream_t *stream, int speed) XINE_PROTECTED; - -int _x_get_speed (xine_stream_t *stream) XINE_PROTECTED; - -void _x_set_fine_speed (xine_stream_t *stream, int speed) XINE_PROTECTED; - -int _x_get_fine_speed (xine_stream_t *stream) XINE_PROTECTED; - -void _x_select_spu_channel (xine_stream_t *stream, int channel) XINE_PROTECTED; - -int _x_get_audio_channel (xine_stream_t *stream) XINE_PROTECTED; - -int _x_get_spu_channel (xine_stream_t *stream) XINE_PROTECTED; - -/* - * internal events - */ - -/* sent by dvb frontend to inform ts demuxer of new pids */ -#define XINE_EVENT_PIDS_CHANGE 0x80000000 -/* sent by BluRay input plugin to inform ts demuxer about end of clip */ -#define XINE_EVENT_END_OF_CLIP 0x80000001 - -/* - * pids change event - inform ts demuxer of new pids - */ -typedef struct { - int vpid; /* video program id */ - int apid; /* audio program id */ -} xine_pids_data_t; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/xine-engine/xine_plugin.h b/src/xine-engine/xine_plugin.h deleted file mode 100644 index 3aa236ceb..000000000 --- a/src/xine-engine/xine_plugin.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2000-2003 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * generic plugin definitions - */ - -#ifndef XINE_PLUGIN_H -#define XINE_PLUGIN_H - -#define PLUGIN_NONE 0 -#define PLUGIN_INPUT 1 -#define PLUGIN_DEMUX 2 -#define PLUGIN_AUDIO_DECODER 3 -#define PLUGIN_VIDEO_DECODER 4 -#define PLUGIN_SPU_DECODER 5 -#define PLUGIN_AUDIO_OUT 6 -#define PLUGIN_VIDEO_OUT 7 -#define PLUGIN_POST 8 - -#define PLUGIN_TYPE_MAX PLUGIN_POST - -/* this flag may be or'ed with type in order to force preloading the plugin. - * very useful to register config items on xine initialization. - */ -#define PLUGIN_MUST_PRELOAD (1 << 7) - -/* this flag may be or'ed with type to prevent the plugin loader from unloading - * the plugin - */ -#define PLUGIN_NO_UNLOAD (1 << 6) - -#define PLUGIN_TYPE_MASK ((1 << 6) - 1) - -typedef struct { - uint8_t type; /* one of the PLUGIN_* constants above */ - uint8_t API; /* API version supported by this plugin */ - char *id; /* a name that identifies this plugin */ - uint32_t version; /* version number, increased every release */ - const void *special_info; /* plugin-type specific, see structs below */ - void *(*init)(xine_t *, void *); /* init the plugin class */ -} plugin_info_t; - - -/* special_info for a video output plugin */ -typedef struct { - int priority; /* priority of this plugin for auto-probing */ - int visual_type; /* visual type supported by this plugin */ -} vo_info_t; - -/* special info for a audio output plugin */ -typedef struct { - int priority; -} ao_info_t; - -/* special_info for a decoder plugin */ -typedef struct { - uint32_t *supported_types; /* streamtypes this decoder can handle */ - int priority; -} decoder_info_t; - -/* special info for a post plugin */ -typedef struct { - uint32_t type; /* type of the post plugin, use one of XINE_POST_TYPE_* */ -} post_info_t; - -/* special info for a demuxer plugin */ -typedef struct { - int priority; -} demuxer_info_t; - -/* special info for an input plugin */ -typedef struct { - int priority; -} input_info_t; - - -/* register a list of statically linked plugins - * info is a list of plugin_info_t terminated by PLUGIN_NONE - * example: - * plugin_info_t acme_plugin_info[] = { - * { PLUGIN_VIDEO_OUT, 21, "acme", XINE_VERSION_CODE, &vo_info_acme, - * init_class_acme }, - * { PLUGIN_NONE, 0, "", 0, NULL, NULL } - * }; - * - */ -void xine_register_plugins(xine_t *self, plugin_info_t *info) XINE_PROTECTED; - -#endif diff --git a/src/xine-engine/xine_private.h b/src/xine-engine/xine_private.h index 6bdebd4eb..6d74e93b6 100644 --- a/src/xine-engine/xine_private.h +++ b/src/xine-engine/xine_private.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2011 the xine project + * Copyright (C) 2000-2008 the xine project * * This file is part of xine, a free video player. * @@ -18,19 +18,27 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ -#ifndef HAVE_XINE_PRIVATE_H -#define HAVE_XINE_PRIVATE_H +/** + * @file + * @brief Declaration of internal, private functions for xine-lib. + * + * @internal These functions should not be used by neither plugins nor + * frontends. + */ + +#ifndef XINE_PRIVATE_H__ +#define XINE_PRIVATE_H__ #ifndef XINE_LIBRARY_COMPILE # error xine_private.h is for libxine private use only! #endif -#include "configure.h" +#include <config.h> +#include <xine/xine_internal.h> -/* Export internal only for functions that are unavailable to plugins */ -#if defined(SUPPORT_ATTRIBUTE_VISIBILITY_INTERNAL) -# define INTERNAL __attribute__((__visibility__("internal"))) -#elif defined(SUPPORT_ATTRIBUTE_VISIBILITY_DEFAULT) +#if SUPPORT_ATTRIBUTE_VISIBILITY_INTERNAL +# define INTERNAL __attribute__((visibility("internal"))) +#elif SUPPORT_ATTRIBUTE_VISIBILITY_DEFAULT # define INTERNAL __attribute__((__visibility__("default"))) #else # define INTERNAL @@ -40,8 +48,64 @@ extern "C" { #endif -/* - * make file descriptors and sockets uninheritable +/** + * @defgroup load_plugins Plugins loading + * @brief Functions related with plugins loading. + */ + +/** + * @ingroup load_plugins + * @brief Load plugins into catalog + * @param this xine instance + * + * All input and demux plugins will be fully loaded and initialized. + * Decoder plugins are loaded on demand. Video/audio output plugins + * have special load/probe functions + */ +void _x_scan_plugins (xine_t *this) INTERNAL; + +/** + * @ingroup load_plugins + * @brief Dispose (shutdown) all currently loaded plugins + * @param this xine instance + */ +void _x_dispose_plugins (xine_t *this) INTERNAL; + +///@{ +/** + * @defgroup + * @brief find and instantiate input and demux plugins + */ +input_plugin_t *_x_find_input_plugin (xine_stream_t *stream, const char *mrl) INTERNAL; +demux_plugin_t *_x_find_demux_plugin (xine_stream_t *stream, input_plugin_t *input) INTERNAL; +demux_plugin_t *_x_find_demux_plugin_by_name (xine_stream_t *stream, const char *name, input_plugin_t *input) INTERNAL; +demux_plugin_t *_x_find_demux_plugin_last_probe(xine_stream_t *stream, const char *last_demux_name, input_plugin_t *input) INTERNAL; +input_plugin_t *_x_rip_plugin_get_instance (xine_stream_t *stream, const char *filename) INTERNAL; +input_plugin_t *_x_cache_plugin_get_instance (xine_stream_t *stream) INTERNAL; +void _x_free_input_plugin (xine_stream_t *stream, input_plugin_t *input) INTERNAL; +void _x_free_demux_plugin (xine_stream_t *stream, demux_plugin_t *demux) INTERNAL; +///@} + +///@{ +/** + * @defgroup + * @brief create decoder fifos and threads +*/ + +int _x_video_decoder_init (xine_stream_t *stream) INTERNAL; +void _x_video_decoder_shutdown (xine_stream_t *stream) INTERNAL; + +int _x_audio_decoder_init (xine_stream_t *stream) INTERNAL; +void _x_audio_decoder_shutdown (xine_stream_t *stream) INTERNAL; +///@} + +/** + * @brief Benchmark available memcpy methods + */ +void xine_probe_fast_memcpy(xine_t *xine) INTERNAL; + +/** + * @brief Make file descriptors and sockets uninheritable */ int _x_set_file_close_on_exec(int fd) INTERNAL; diff --git a/src/xine-engine/xineintl.h b/src/xine-engine/xineintl.h deleted file mode 100644 index bb9c006ef..000000000 --- a/src/xine-engine/xineintl.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2000-2005 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - */ - -#ifndef HAVE_XINEINTL_H -#define HAVE_XINEINTL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <locale.h> - -#ifdef ENABLE_NLS -# include <libintl.h> -# define _(String) dgettext (XINE_TEXTDOMAIN, String) -# ifdef gettext_noop -# define N_(String) gettext_noop (String) -# else -# define N_(String) (String) -# endif -#else -/* Stubs that do something close enough. */ -# define textdomain(String) (String) -# define gettext(String) (String) -# define dgettext(Domain,Message) (Message) -# define dcgettext(Domain,Message,Type) (Message) -# define ngettext(Singular, Plural, IsPlural) (Singular) -# define bindtextdomain(Domain,Directory) (Domain) -# define _(String) (String) -# define N_(String) (String) -#endif - -#ifdef __cplusplus -} -#endif - -#endif |