diff options
Diffstat (limited to 'src')
225 files changed, 5512 insertions, 2065 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index cb6236033..ec4925407 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,11 +11,13 @@ SUBDIRS = \ demuxers \ libffmpeg \ libmpeg2 \ + libmpeg2new \ liba52 \ libspudec \ libspucc \ libspucmml \ libspudvb \ + libspuhdmv \ libsputext \ libdts \ libmad \ diff --git a/src/audio_out/Makefile.am b/src/audio_out/Makefile.am index b0c3d292e..07ad19c8d 100644 --- a/src/audio_out/Makefile.am +++ b/src/audio_out/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_CPPFLAGS = -DXINE_COMPILE @@ -49,6 +50,10 @@ if HAVE_JACK jack_module = xineplug_ao_out_jack.la endif +if HAVE_SNDIO +sndio_module = xineplug_ao_out_sndio.la +endif + ## # IMPORTANT: # --------- @@ -66,7 +71,8 @@ xineplug_LTLIBRARIES = xineplug_ao_out_none.la xineplug_ao_out_file.la \ $(pulseaudio_module) \ $(directx2_module) \ $(fusionsound_module) \ - $(jack_module) + $(jack_module) \ + $(sndio_module) xineplug_ao_out_none_la_SOURCES = audio_none_out.c xineplug_ao_out_none_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) @@ -110,7 +116,7 @@ xineplug_ao_out_arts_la_LDFLAGS = -avoid-version -module xineplug_ao_out_directx_la_SOURCES = audio_directx_out.c xineplug_ao_out_directx_la_CPPFLAGS = $(DIRECTX_CPPFLAGS) -xineplug_ao_out_directx_la_LIBADD = $(XINE_LIB) $(DIRECTX_AUDIO_LIBS) +xineplug_ao_out_directx_la_LIBADD = $(XINE_LIB) $(DIRECTX_AUDIO_LIBS) $(LTLIBINTL) xineplug_ao_out_directx_la_CFLAGS = $(VISIBILITY_FLAG) xineplug_ao_out_directx_la_LDFLAGS = -avoid-version -module @@ -131,7 +137,7 @@ xineplug_ao_out_pulseaudio_la_LDFLAGS = -avoid-version -module xineplug_ao_out_directx2_la_SOURCES = audio_directx2_out.c xineplug_ao_out_directx2_la_CPPFLAGS = $(DIRECTX_CPPFLAGS) -xineplug_ao_out_directx2_la_LIBADD = $(XINE_LIB) $(DIRECTX_AUDIO_LIBS) $(PTHREAD_LIBS) +xineplug_ao_out_directx2_la_LIBADD = $(XINE_LIB) $(DIRECTX_AUDIO_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_ao_out_directx2_la_CFLAGS = $(VISIBILITY_FLAG) xineplug_ao_out_directx2_la_LDFLAGS = -avoid-version -module @@ -144,3 +150,8 @@ xineplug_ao_out_jack_la_SOURCES = audio_jack_out.c xineplug_ao_out_jack_la_LIBADD = $(XINE_LIB) $(JACK_LIBS) $(LTLIBINTL) xineplug_ao_out_jack_la_CFLAGS = $(VISIBILITY_FLAG) $(JACK_CFLAGS) xineplug_ao_out_jack_la_LDFLAGS = -avoid-version -module + +xineplug_ao_out_sndio_la_SOURCES = audio_sndio_out.c +xineplug_ao_out_sndio_la_LIBADD = $(XINE_LIB) $(SNDIO_LIBS) +xineplug_ao_out_sndio_la_CFLAGS = $(VISIBILITY_FLAG) $(SNDIO_CFLAGS) +xineplug_ao_out_sndio_la_LDFLAGS = -avoid-version -module diff --git a/src/audio_out/audio_directx2_out.c b/src/audio_out/audio_directx2_out.c index e91e919fc..6bee2066c 100644 --- a/src/audio_out/audio_directx2_out.c +++ b/src/audio_out/audio_directx2_out.c @@ -143,9 +143,13 @@ typedef struct { * Defining them here allows us to get rid of the dxguid library during * the linking stage. *****************************************************************************/ -static const GUID IID_IDirectSoundNotify = { +static const GUID xine_IID_IDirectSoundNotify = { 0xB0210783, 0x89CD, 0x11D0, {0xAF, 0x08, 0x00, 0xA0, 0xC9, 0x25, 0xCD, 0x16} }; +#ifdef IID_IDirectSoundNotify +# undef IID_IDirectSoundNotify +#endif +#define IID_IDirectSoundNotify xine_IID_IDirectSoundNotify @@ -550,8 +554,6 @@ static size_t buffer_occupied_size(dx2_driver_t *this) { /* service thread working with direct sound buffer */ static void *buffer_service(void *data) { dx2_driver_t *this = (dx2_driver_t *)data; - DWORD ret; - size_t play_pos; size_t buffer_min; size_t data_in_buffer; diff --git a/src/audio_out/audio_directx_out.c b/src/audio_out/audio_directx_out.c index 7c99e97e2..21ba23d91 100644 --- a/src/audio_out/audio_directx_out.c +++ b/src/audio_out/audio_directx_out.c @@ -60,9 +60,13 @@ typedef unsigned char boolean; * the linking stage. *****************************************************************************/ #if 1 -static const GUID IID_IDirectSoundNotify = { +static const GUID xine_IID_IDirectSoundNotify = { 0xB0210783,0x89CD,0x11D0,{0xAF,0x08,0x00,0xA0,0xC9,0x25,0xCD,0x16} }; +#ifdef IID_IDirectSoundNotify +# undef IID_IDirectSoundNotify +#endif +#define IID_IDirectSoundNotify xine_IID_IDirectSoundNotify #endif diff --git a/src/audio_out/audio_jack_out.c b/src/audio_out/audio_jack_out.c index 8a77ab018..6394fd3e3 100644 --- a/src/audio_out/audio_jack_out.c +++ b/src/audio_out/audio_jack_out.c @@ -1,3 +1,6 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include <stdio.h> #include <errno.h> @@ -160,7 +163,7 @@ static int write_buffer_16 (jack_driver_t *this, unsigned char *data, int len) for (i = 0; i < samples; i++) { /* Read in 16bits, write out floats */ p_write = (float *) (&(this->buffer[write_pos])); - *p_write = ((float) (p_read[i])) / 32767.0f; + *p_write = ((float) (p_read[i])) / 32768.0f; write_pos = (write_pos + sizeof (float)) % BUFFSIZE; } this->write_pos = write_pos; @@ -305,19 +308,11 @@ static int jack_open_device (ao_driver_t *this_gen, char *jack_device, num_channels); goto err_out; } - /* Try to create a client called "xine" */ - if ((client = jack_client_new ("xine")) == 0) { - /* If that doesn't work it could be because running two copies of xine - try using a unique name */ - char client_name[20]; - sprintf (client_name, "xine (%d)", (int) getpid ()); - - if ((client = jack_client_new (client_name)) == 0) { - xprintf (this->xine, XINE_VERBOSITY_LOG, - "\njack_open_device: Error: Failed to connect to JACK server\n"); - xprintf (this->xine, XINE_VERBOSITY_LOG, - "jack_open_device: (did you start 'jackd' server?)\n"); - goto err_out; - } + /* Try to create a client called "xine[-NN]" */ + if ((client = jack_client_open ("xine", JackNullOption, NULL)) == 0) { + xprintf (this->xine, XINE_VERBOSITY_LOG, + "\njack_open_device: Error: Failed to connect to JACK server\n"); + goto err_out; } /* Save the new client */ @@ -715,19 +710,11 @@ static ao_driver_t *open_jack_plugin (audio_driver_class_t *class_gen, #define A52_PASSTHRU 12 int speakers; - /* Try to create a client called "xine" */ - if ((client = jack_client_new ("xine")) == 0) { - /* If that doesn't work it could be because running two copies of xine - try using a unique name */ - char name[20]; - sprintf (name, "xine (%d)", (int) getpid ()); - - if ((client = jack_client_new (name)) == 0) { - xprintf (class->xine, XINE_VERBOSITY_LOG, - "\nopen_jack_plugin: Error: Failed to connect to JACK server\n"); - xprintf (class->xine, XINE_VERBOSITY_LOG, - "open_jack_plugin: (did you start 'jackd' server?)\n"); - return 0; - } + /* Try to create a client called "xine[-NN]" */ + if ((client = jack_client_open ("xine", JackNullOption, NULL)) == 0) { + xprintf (class->xine, XINE_VERBOSITY_LOG, + "\nopen_jack_plugin: Error: Failed to connect to JACK server\n"); + return 0; } this = calloc(1, sizeof (jack_driver_t)); diff --git a/src/audio_out/audio_pulse_out.c b/src/audio_out/audio_pulse_out.c index 4b66fbaed..d4d19ce1b 100644 --- a/src/audio_out/audio_pulse_out.c +++ b/src/audio_out/audio_pulse_out.c @@ -235,7 +235,7 @@ static int connect_context(pulse_driver_t *this) { } if (!this->context) { - char fn[PATH_MAX], *p; + char fn[XINE_PATH_MAX], *p; if (pa_get_binary_name(fn, sizeof(fn))) p = pa_path_get_filename(fn); diff --git a/src/audio_out/audio_sndio_out.c b/src/audio_out/audio_sndio_out.c new file mode 100644 index 000000000..1d789b5e8 --- /dev/null +++ b/src/audio_out/audio_sndio_out.c @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2008 Brad Smith <brad@comstyle.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* ao plugin for sndio by Brad Smith <brad@comstyle.com>. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <fcntl.h> +#include <math.h> +#include <unistd.h> +#include <inttypes.h> +#include <pthread.h> + +#include <sndio.h> + +#include "xine_internal.h" +#include "xineutils.h" +#include "audio_out.h" +#include "bswap.h" + +#define GAP_TOLERANCE AO_MAX_GAP +#define PCT_TO_MIDI(p) (((p) * SIO_MAXVOL + 50) / 100) + +typedef struct { + audio_driver_class_t driver_class; + xine_t *xine; +} sndio_class_t; + +typedef struct sndio_driver_s { + ao_driver_t ao_driver; + xine_t *xine; + + struct sio_hdl *hdl; + long long realpos, playpos; + int capabilities; + + int num_channels; + u_int32_t bits_per_sample; + u_int32_t bytes_per_frame; + + struct { + int volume; + int mute; + } mixer; +} sndio_driver_t; + +/* + * Callback to notify of frames processed by the hw. It is + * called from the mail loop called from sio_write(). + */ +static void ao_sndio_onmove_cb(void *addr, int delta) +{ + sndio_driver_t *this = (sndio_driver_t *)addr; + + this->realpos += delta; +} + +/* + * Open the audio device for writing to. + */ +static int ao_sndio_open(ao_driver_t *this_gen, + uint32_t bits, uint32_t rate, int mode) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + struct sio_par par; + + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open bits=%d rate=%d, mode=%d\n", + bits, rate, mode); + + if (this->hdl != NULL) { + sio_close (this->hdl); + this->hdl = NULL; + } + + this->hdl = sio_open(NULL, SIO_PLAY, 0); + if (this->hdl == NULL) + goto bad; + + sio_initpar(&par); + + switch (mode) { + case AO_CAP_MODE_MONO: + par.pchan = 1; + break; + case AO_CAP_MODE_STEREO: + par.pchan = 2; + break; +#if 0 + case AO_CAP_MODE_4CHANNEL: + par.pchan = 4; + break; + case AO_CAP_MODE_4_1CHANNEL: + case AO_CAP_MODE_5CHANNEL: + case AO_CAP_MODE_5_1CHANNEL: + par.pchan = 6; + break; +#endif + default: + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open does not support the requested mode: 0x%X\n", + mode); + goto bad; + } + + switch (bits) { + case 8: + par.bits = 8; + par.sig = 0; + break; + case 16: + par.bits = 16; + par.sig = 1; + break; + default: + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open bits per sample not supported: %d\n", bits); + goto bad; + } + + par.rate = rate; + par.appbufsz = par.rate * 250 / 1000; /* 250ms buffer */ + + if (!sio_setpar(this->hdl, &par)) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open could not set params\n"); + goto bad; + } + + if (!sio_getpar(this->hdl, &par)) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open could not get params\n"); + goto bad; + } + + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open %d channels output\n", + par.pchan); + + this->num_channels = par.pchan; + this->bytes_per_frame = par.bps * par.pchan; + this->playpos = 0; + this->realpos = 0; + sio_onmove(this->hdl, ao_sndio_onmove_cb, this); + + if (!sio_start(this->hdl)) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open could not start\n"); + goto bad; + } + + return par.rate; + +bad: + if (this->hdl != NULL) + sio_close(this->hdl); + return 0; +} + +static int ao_sndio_num_channels(ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + return this->num_channels; +} + +static int ao_sndio_bytes_per_frame(ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + return this->bytes_per_frame; +} + +static int ao_sndio_get_gap_tolerance (ao_driver_t *this_gen) +{ + return GAP_TOLERANCE; +} + +static int ao_sndio_write(ao_driver_t *this_gen, int16_t *data, + uint32_t num_frames) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + size_t ret, size = num_frames * this->bytes_per_frame; + + ret = sio_write(this->hdl, data, size); + if (ret == 0) + return 0; + + this->playpos += num_frames; + + return 1; +} + +static int ao_sndio_delay (ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + int bufused; + + if (this->realpos < 0) + bufused = this->playpos; + else + bufused = this->playpos - this->realpos; + + return bufused; +} + +static void ao_sndio_close(ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_close called\n"); + + if (!sio_stop(this->hdl)) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_close could not stop\n"); + } + + sio_close(this->hdl); + this->hdl = NULL; +} + +static uint32_t ao_sndio_get_capabilities (ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + return this->capabilities; +} + +static void ao_sndio_exit(ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_exit called\n"); + + if (this->hdl != NULL) + sio_close(this->hdl); +} + +static int ao_sndio_get_property (ao_driver_t *this_gen, int property) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + switch (property) { + case AO_PROP_MIXER_VOL: + return this->mixer.volume; + break; + case AO_PROP_MUTE_VOL: + return this->mixer.mute; + break; + } + + return 0; +} + +static int ao_sndio_set_property (ao_driver_t *this_gen, int property, int value) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + int vol; + + if (this->hdl == NULL) + return 0; + + switch(property) { + case AO_PROP_MIXER_VOL: + this->mixer.volume = value; + if (!this->mixer.mute) + sio_setvol(this->hdl, PCT_TO_MIDI(this->mixer.volume)); + return this->mixer.volume; + break; + + case AO_PROP_MUTE_VOL: + this->mixer.mute = (value) ? 1 : 0; + vol = 0; + if (!this->mixer.mute) + vol = PCT_TO_MIDI(this->mixer.volume); + sio_setvol(this->hdl, vol); + return value; + break; + } + + return value; +} + +/* + * pause, resume, flush buffers + */ +static int ao_sndio_ctrl(ao_driver_t *this_gen, int cmd, ...) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + /* + * sndio pauses automatically if there are no more samples to play + * and resumes when there are samples again. So we leave this empty + * for the moment. + */ + + return 0; +} + +static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *data) +{ + sndio_class_t *class = (sndio_class_t *) class_gen; + sndio_driver_t *this; + + lprintf ("audio_sndio_out: open_plugin called\n"); + + this = calloc(1, sizeof (sndio_driver_t)); + if (!this) + return NULL; + + this->xine = class->xine; + + /* + * Set capabilities + */ + this->capabilities = AO_CAP_MODE_MONO | AO_CAP_MODE_STEREO | +#if 0 + AO_CAP_MODE_4CHANNEL | AO_CAP_MODE_4_1CHANNEL | + AO_CAP_MODE_5CHANNEL | AO_CAP_MODE_5_1CHANNEL | +#endif + AO_CAP_MIXER_VOL | AO_CAP_MUTE_VOL | AO_CAP_8BITS | + AO_CAP_16BITS; + + this->ao_driver.get_capabilities = ao_sndio_get_capabilities; + this->ao_driver.get_property = ao_sndio_get_property; + this->ao_driver.set_property = ao_sndio_set_property; + this->ao_driver.open = ao_sndio_open; + this->ao_driver.num_channels = ao_sndio_num_channels; + this->ao_driver.bytes_per_frame = ao_sndio_bytes_per_frame; + this->ao_driver.delay = ao_sndio_delay; + this->ao_driver.write = ao_sndio_write; + this->ao_driver.close = ao_sndio_close; + this->ao_driver.exit = ao_sndio_exit; + this->ao_driver.get_gap_tolerance = ao_sndio_get_gap_tolerance; + this->ao_driver.control = ao_sndio_ctrl; + + return &this->ao_driver; +} + +/* + * class functions + */ + +static char* get_identifier (audio_driver_class_t *this_gen) +{ + return "sndio"; +} + +static char* get_description (audio_driver_class_t *this_gen) +{ + return _("xine audio output plugin using sndio audio devices/drivers "); +} + +static void dispose_class (audio_driver_class_t *this_gen) +{ + sndio_class_t *this = (sndio_class_t *) this_gen; + + free(this); +} + +static void *init_class (xine_t *xine, void *data) +{ + sndio_class_t *this; + + lprintf ("audio_sndio_out: init class\n"); + + this = calloc(1, sizeof (sndio_class_t)); + if (!this) + return NULL; + + this->driver_class.open_plugin = open_plugin; + this->driver_class.get_identifier = get_identifier; + this->driver_class.get_description = get_description; + this->driver_class.dispose = dispose_class; + + this->xine = xine; + + return this; +} + +static const ao_info_t ao_info_sndio = { + 12 +}; + +/* + * exported plugin catalog entry + */ + +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_AUDIO_OUT, 8, "sndio", XINE_VERSION_CODE, &ao_info_sndio, init_class }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; diff --git a/src/combined/Makefile.am b/src/combined/Makefile.am index 03250ef67..6a43fed47 100644 --- a/src/combined/Makefile.am +++ b/src/combined/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common SUBDIRS = ffmpeg diff --git a/src/combined/demux_flac.c b/src/combined/demux_flac.c index ebba63701..fc638fe35 100644 --- a/src/combined/demux_flac.c +++ b/src/combined/demux_flac.c @@ -583,7 +583,7 @@ open_plugin (demux_class_t *class_gen, } break; case METHOD_BY_EXTENSION: { - char *ending, *mrl; + const char *ending, *mrl; mrl = input->get_mrl (input); @@ -715,22 +715,22 @@ open_plugin (demux_class_t *class_gen, /* FLAC Demuxer class */ -static char * +static const char * get_description (demux_class_t *this_gen) { return "FLAC demux plugin"; } -static char * +static const char * get_identifier (demux_class_t *this_gen) { return "FLAC"; } -static char * +static const char * get_extensions (demux_class_t *this_gen) { return "flac"; } -static char * +static const char * get_mimetypes (demux_class_t *this_gen) { return "audio/x-flac: flac: FLAC Audio;" "audio/flac: flac: FLAC Audio;"; diff --git a/src/combined/ffmpeg/Makefile.am b/src/combined/ffmpeg/Makefile.am index 4d7e70423..24cab7577 100644 --- a/src/combined/ffmpeg/Makefile.am +++ b/src/combined/ffmpeg/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common DEFAULT_INCLUDES = -I. @@ -13,11 +14,18 @@ link_ffmpeg = \ $(top_builddir)/src/libffmpeg/libavcodec/libpostproc/libpostprocess.la endif +ff_generated = \ + avcodec_video.list avcodec_audio.list \ + ff_video_list.h ff_audio_list.h + +BUILT_SOURCES = $(ff_generated) + # ffmpeg_config.h is generated by configure -DISTCLEANFILES = ffmpeg_config.h +DISTCLEANFILES = ffmpeg_config.h $(ff_generated) # this must always be included, even if the current machine has no DXR3... -EXTRA_DIST = ffmpeg_encoder.c +EXTRA_DIST = ffmpeg_encoder.c \ + xine_video.list xine_audio.list mkcodeclist.pl xineplug_LTLIBRARIES = xineplug_decode_ff.la xineplug_decode_dvaudio.la @@ -45,3 +53,29 @@ xineplug_decode_dvaudio_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) $(top_srcdir)/src/libffmpeg/libavcodec/libavcodec.la: make -C $(top_srcdir)/src/libffmpeg + +# Generation of ffmpeg->xine codec mapping lists (see xine_*.list). + +AV_CPP = $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) + +# Extract some CODEC_ID_* from avcodec.h. Requires some sed mangling. +avcodec_audio.list: AV_CODECS:=/CODEC_ID_PCM_S16LE/,/CODEC_ID_DVD_SUBTITLE/ +avcodec_video.list: AV_CODECS:=/CODEC_ID_MPEG1VIDEO/,/CODEC_ID_PCM_S16LE/ + +avcodec_audio.list avcodec_video.list: + echo '#include "$(srcdir)/ffmpeg_decoder.h"' | $(AV_CPP) - |\ + sed -e $(AV_CODECS)'! d; s/^[ \t]*//; s/[=,].*//; /^$$/ d' >$@ + +# Generate the mappings. These are #included where needed. +ff_%_list.h: $(srcdir)/mkcodeclist.pl avcodec_%.list $(srcdir)/xine_%.list + $(PERL) $^ $@ + +ff_audio_decoder.c: ff_audio_list.h +ff_video_decoder.c: ff_video_list.h + +# 'make report' prints tokens corresponding to any unhandled codecs. +report: avcodec_audio.list avcodec_video.list + @$(top_srcdir)/src/combined/ffmpeg/mkcodeclist.pl avcodec_audio.list xine_audio.list - audio + @$(top_srcdir)/src/combined/ffmpeg/mkcodeclist.pl avcodec_video.list xine_video.list - video + +.PHONY: report diff --git a/src/combined/ffmpeg/ff_audio_decoder.c b/src/combined/ffmpeg/ff_audio_decoder.c index e0d294113..24c193b44 100644 --- a/src/combined/ffmpeg/ff_audio_decoder.c +++ b/src/combined/ffmpeg/ff_audio_decoder.c @@ -73,45 +73,7 @@ typedef struct ff_audio_decoder_s { } ff_audio_decoder_t; -static const ff_codec_t ff_audio_lookup[] = { - {BUF_AUDIO_WMAV1, CODEC_ID_WMAV1, "MS Windows Media Audio 1 (ffmpeg)"}, - {BUF_AUDIO_WMAV2, CODEC_ID_WMAV2, "MS Windows Media Audio 2 (ffmpeg)"}, - {BUF_AUDIO_14_4, CODEC_ID_RA_144, "Real 14.4 (ffmpeg)"}, - {BUF_AUDIO_28_8, CODEC_ID_RA_288, "Real 28.8 (ffmpeg)"}, - {BUF_AUDIO_MPEG, CODEC_ID_MP3, "MP3 (ffmpeg)"}, - {BUF_AUDIO_MP3ADU, CODEC_ID_MP3ADU, "MPEG-3 adu (ffmpeg)"}, - {BUF_AUDIO_MSADPCM, CODEC_ID_ADPCM_MS, "MS ADPCM (ffmpeg)"}, - {BUF_AUDIO_QTIMAADPCM, CODEC_ID_ADPCM_IMA_QT, "QT IMA ADPCM (ffmpeg)"}, - {BUF_AUDIO_MSIMAADPCM, CODEC_ID_ADPCM_IMA_WAV, "MS IMA ADPCM (ffmpeg)"}, - {BUF_AUDIO_DK3ADPCM, CODEC_ID_ADPCM_IMA_DK3, "Duck DK3 ADPCM (ffmpeg)"}, - {BUF_AUDIO_DK4ADPCM, CODEC_ID_ADPCM_IMA_DK4, "Duck DK4 ADPCM (ffmpeg)"}, - {BUF_AUDIO_VQA_IMA, CODEC_ID_ADPCM_IMA_WS, "Westwood Studios IMA (ffmpeg)"}, - {BUF_AUDIO_SMJPEG_IMA, CODEC_ID_ADPCM_IMA_SMJPEG, "SMJPEG IMA (ffmpeg)"}, - {BUF_AUDIO_XA_ADPCM, CODEC_ID_ADPCM_XA, "CD-ROM/XA ADPCM (ffmpeg)"}, - {BUF_AUDIO_4X_ADPCM, CODEC_ID_ADPCM_4XM, "4X ADPCM (ffmpeg)"}, - {BUF_AUDIO_EA_ADPCM, CODEC_ID_ADPCM_EA, "Electronic Arts ADPCM (ffmpeg)"}, - {BUF_AUDIO_MULAW, CODEC_ID_PCM_MULAW, "mu-law logarithmic PCM (ffmpeg)"}, - {BUF_AUDIO_ALAW, CODEC_ID_PCM_ALAW, "A-law logarithmic PCM (ffmpeg)"}, - {BUF_AUDIO_ROQ, CODEC_ID_ROQ_DPCM, "RoQ DPCM (ffmpeg)"}, - {BUF_AUDIO_INTERPLAY, CODEC_ID_INTERPLAY_DPCM, "Interplay DPCM (ffmpeg)"}, - {BUF_AUDIO_MAC3, CODEC_ID_MACE3, "MACE 3:1 (ffmpeg)"}, - {BUF_AUDIO_MAC6, CODEC_ID_MACE6, "MACE 6:1 (ffmpeg)"}, - {BUF_AUDIO_XAN_DPCM, CODEC_ID_XAN_DPCM, "Origin Xan DPCM (ffmpeg)"}, - {BUF_AUDIO_VMD, CODEC_ID_VMDAUDIO, "Sierra VMD Audio (ffmpeg)"}, - {BUF_AUDIO_FLAC, CODEC_ID_FLAC, "FLAC (ffmpeg)"}, - {BUF_AUDIO_SHORTEN, CODEC_ID_SHORTEN, "Shorten (ffmpeg)"}, - {BUF_AUDIO_ALAC, CODEC_ID_ALAC, "ALAC (ffmpeg)"}, - {BUF_AUDIO_QDESIGN2, CODEC_ID_QDM2, "QDesign (ffmpeg)"}, - {BUF_AUDIO_COOK, CODEC_ID_COOK, "RealAudio Cooker (ffmpeg)"}, - {BUF_AUDIO_TRUESPEECH, CODEC_ID_TRUESPEECH, "TrueSpeech (ffmpeg)"}, - {BUF_AUDIO_TTA, CODEC_ID_TTA, "True Audio Lossless (ffmpeg)"}, - {BUF_AUDIO_SMACKER, CODEC_ID_SMACKAUDIO, "Smacker (ffmpeg)"}, - {BUF_AUDIO_FLVADPCM, CODEC_ID_ADPCM_SWF, "Flash ADPCM (ffmpeg)"}, - {BUF_AUDIO_WAVPACK, CODEC_ID_WAVPACK, "WavPack (ffmpeg)"}, - {BUF_AUDIO_AMR_NB, CODEC_ID_AMR_NB, "AMR narrow band (ffmpeg)"}, - {BUF_AUDIO_AMR_WB, CODEC_ID_AMR_WB, "AMR wide band (ffmpeg)"}, -}; - +#include "ff_audio_list.h" static void ff_audio_ensure_buffer_size(ff_audio_decoder_t *this, int size) { if (size > this->bufsize) { @@ -249,6 +211,8 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) if (extradata + data_len > this->size) break; /* abort early - extradata length is bad */ + if (extradata > INT_MAX - data_len) + break;/*integer overflow*/ this->context->extradata_size = data_len; this->context->extradata = malloc(this->context->extradata_size + @@ -367,6 +331,13 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) /* dispatch the decoded audio */ out = 0; while (out < decode_buffer_size) { + int stream_status = xine_get_status(this->stream); + + if (stream_status == XINE_STATUS_QUIT || stream_status == XINE_STATUS_STOP) { + this->size = 0; + return; + } + audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); if (audio_buffer->mem_size == 0) { @@ -500,115 +471,6 @@ void *init_audio_plugin (xine_t *xine, void *data) { return this; } -static uint32_t supported_audio_types[] = { - #ifdef CONFIG_WMAV1_DECODER - BUF_AUDIO_WMAV1, - #endif - #ifdef CONFIG_WMAV2_DECODER - BUF_AUDIO_WMAV2, - #endif - #ifdef CONFIG_RA_144_DECODER - BUF_AUDIO_14_4, - #endif - #ifdef CONFIG_RA_288_DECODER - BUF_AUDIO_28_8, - #endif - #ifdef CONFIG_MP3_DECODER - BUF_AUDIO_MPEG, - #endif - #ifdef CONFIG_ADPCM_MS_DECODER - BUF_AUDIO_MSADPCM, - #endif - #ifdef CONFIG_ADPCM_IMA_QT_DECODER - BUF_AUDIO_QTIMAADPCM, - #endif - #ifdef CONFIG_ADPCM_IMA_WAV_DECODER - BUF_AUDIO_MSIMAADPCM, - #endif - #ifdef CONFIG_ADPCM_IMA_DK3_DECODER - BUF_AUDIO_DK3ADPCM, - #endif - #ifdef CONFIG_ADPCM_IMA_DK4_DECODER - BUF_AUDIO_DK4ADPCM, - #endif - #ifdef CONFIG_ADPCM_IMA_WS_DECODER - BUF_AUDIO_VQA_IMA, - #endif - #ifdef CONFIG_ADPCM_IMA_SMJPEG_DECODER - BUF_AUDIO_SMJPEG_IMA, - #endif - #ifdef CONFIG_ADPCM_XA_DECODER - BUF_AUDIO_XA_ADPCM, - #endif - #ifdef CONFIG_ADPCM_4XM_DECODER - BUF_AUDIO_4X_ADPCM, - #endif - #ifdef CONFIG_ADPCM_EA_DECODER - BUF_AUDIO_EA_ADPCM, - #endif - #ifdef CONFIG_PCM_MULAW_DECODER - BUF_AUDIO_MULAW, - #endif - #ifdef CONFIG_PCM_ALAW_DECODER - BUF_AUDIO_ALAW, - #endif - #ifdef CONFIG_ROQ_DPCM_DECODER - BUF_AUDIO_ROQ, - #endif - #ifdef CONFIG_INTERPLAY_DPCM_DECODER - BUF_AUDIO_INTERPLAY, - #endif - #ifdef CONFIG_MACE3_DECODER - BUF_AUDIO_MAC3, - #endif - #ifdef CONFIG_MACE6_DECODER - BUF_AUDIO_MAC6, - #endif - #ifdef CONFIG_XAN_DPCM_DECODER - BUF_AUDIO_XAN_DPCM, - #endif - #ifdef CONFIG_VMDAUDIO_DECODER - BUF_AUDIO_VMD, - #endif - #ifdef CONFIG_FLAC_DECODER - BUF_AUDIO_FLAC, - #endif - #ifdef CONFIG_SHORTEN_DECODER - BUF_AUDIO_SHORTEN, - #endif - #ifdef CONFIG_ALAC_DECODER - BUF_AUDIO_ALAC, - #endif - #ifdef CONFIG_QDM2_DECODER - BUF_AUDIO_QDESIGN2, - #endif - #ifdef CONFIG_COOK_DECODER - BUF_AUDIO_COOK, - #endif - #ifdef CONFIG_TRUESPEECH_DECODER - BUF_AUDIO_TRUESPEECH, - #endif - #ifdef CONFIG_TTA_DECODER - BUF_AUDIO_TTA, - #endif - #ifdef CONFIG_SMACKAUDIO_DECODER - BUF_AUDIO_SMACKER, - #endif - #ifdef CONFIG_ADPCM_SWF_DECODER - BUF_AUDIO_FLVADPCM, - #endif - #ifdef CONFIG_WAVPACK_DECODER - BUF_AUDIO_WAVPACK, - #endif - #ifdef CONFIG_AMR_NB_DECODER - BUF_AUDIO_AMR_NB, - #endif - #ifdef CONFIG_AMR_WB_DECODER - BUF_AUDIO_AMR_WB, - #endif - 0 -}; - decoder_info_t dec_info_ffmpeg_audio = { supported_audio_types, /* supported types */ 7 /* priority */ diff --git a/src/combined/ffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c index a04d2feb6..98caac269 100644 --- a/src/combined/ffmpeg/ff_video_decoder.c +++ b/src/combined/ffmpeg/ff_video_decoder.c @@ -58,6 +58,12 @@ #define ENABLE_DIRECT_RENDERING +/* reordered_opaque appeared in libavcodec 51.68.0 */ +#define AVCODEC_HAS_REORDERED_OPAQUE +#if LIBAVCODEC_VERSION_INT < 0x334400 +# undef AVCODEC_HAS_REORDERED_OPAQUE +#endif + typedef struct ff_video_decoder_s ff_video_decoder_t; typedef struct ff_video_class_s { @@ -78,7 +84,14 @@ struct ff_video_decoder_s { xine_stream_t *stream; int64_t pts; +#ifdef AVCODEC_HAS_REORDERED_OPAQUE + uint64_t pts_tag_mask; + uint64_t pts_tag; + int pts_tag_counter; + int pts_tag_stable_counter; +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ int video_step; + int reported_video_step; uint8_t decoder_ok:1; uint8_t decoder_init_mode:1; @@ -212,6 +225,11 @@ static int get_buffer(AVCodecContext *context, AVFrame *av_frame){ av_frame->type= FF_BUFFER_TYPE_USER; +#ifdef AVCODEC_HAS_REORDERED_OPAQUE + /* take over pts for this frame to have it reordered */ + av_frame->reordered_opaque = context->reordered_opaque; +#endif + xine_list_push_back(this->dr1_frames, av_frame); return 0; @@ -244,85 +262,7 @@ static void release_buffer(struct AVCodecContext *context, AVFrame *av_frame){ } #endif -static const ff_codec_t ff_video_lookup[] = { - {BUF_VIDEO_MSMPEG4_V1, CODEC_ID_MSMPEG4V1, "Microsoft MPEG-4 v1 (ffmpeg)"}, - {BUF_VIDEO_MSMPEG4_V2, CODEC_ID_MSMPEG4V2, "Microsoft MPEG-4 v2 (ffmpeg)"}, - {BUF_VIDEO_MSMPEG4_V3, CODEC_ID_MSMPEG4V3, "Microsoft MPEG-4 v3 (ffmpeg)"}, - {BUF_VIDEO_WMV7, CODEC_ID_WMV1, "MS Windows Media Video 7 (ffmpeg)"}, - {BUF_VIDEO_WMV8, CODEC_ID_WMV2, "MS Windows Media Video 8 (ffmpeg)"}, - {BUF_VIDEO_WMV9, CODEC_ID_WMV3, "MS Windows Media Video 9 (ffmpeg)"}, - {BUF_VIDEO_VC1, CODEC_ID_VC1, "MS Windows Media Video VC-1 (ffmpeg)"}, - {BUF_VIDEO_MPEG4, CODEC_ID_MPEG4, "ISO MPEG-4 (ffmpeg)"}, - {BUF_VIDEO_XVID, CODEC_ID_MPEG4, "ISO MPEG-4 (XviD, ffmpeg)"}, - {BUF_VIDEO_DIVX5, CODEC_ID_MPEG4, "ISO MPEG-4 (DivX5, ffmpeg)"}, - {BUF_VIDEO_3IVX, CODEC_ID_MPEG4, "ISO MPEG-4 (3ivx, ffmpeg)"}, - {BUF_VIDEO_JPEG, CODEC_ID_MJPEG, "Motion JPEG (ffmpeg)"}, - {BUF_VIDEO_MJPEG, CODEC_ID_MJPEG, "Motion JPEG (ffmpeg)"}, - {BUF_VIDEO_MJPEG_B, CODEC_ID_MJPEGB, "Motion JPEG B (ffmpeg)"}, - {BUF_VIDEO_I263, CODEC_ID_H263I, "ITU H.263 (ffmpeg)"}, - {BUF_VIDEO_H263, CODEC_ID_H263, "H.263 (ffmpeg)"}, - {BUF_VIDEO_RV10, CODEC_ID_RV10, "Real Video 1.0 (ffmpeg)"}, - {BUF_VIDEO_RV20, CODEC_ID_RV20, "Real Video 2.0 (ffmpeg)"}, - {BUF_VIDEO_IV31, CODEC_ID_INDEO3, "Indeo Video 3.1 (ffmpeg)"}, - {BUF_VIDEO_IV32, CODEC_ID_INDEO3, "Indeo Video 3.2 (ffmpeg)"}, - {BUF_VIDEO_SORENSON_V1, CODEC_ID_SVQ1, "Sorenson Video 1 (ffmpeg)"}, - {BUF_VIDEO_SORENSON_V3, CODEC_ID_SVQ3, "Sorenson Video 3 (ffmpeg)"}, - {BUF_VIDEO_DV, CODEC_ID_DVVIDEO, "DV (ffmpeg)"}, - {BUF_VIDEO_HUFFYUV, CODEC_ID_HUFFYUV, "HuffYUV (ffmpeg)"}, - {BUF_VIDEO_VP31, CODEC_ID_VP3, "On2 VP3.1 (ffmpeg)"}, - {BUF_VIDEO_VP5, CODEC_ID_VP5, "On2 VP5 (ffmpeg)"}, - {BUF_VIDEO_VP6, CODEC_ID_VP6, "On2 VP6 (ffmpeg)"}, - {BUF_VIDEO_VP6F, CODEC_ID_VP6F, "On2 VP6 (ffmpeg)"}, - {BUF_VIDEO_4XM, CODEC_ID_4XM, "4X Video (ffmpeg)"}, - {BUF_VIDEO_CINEPAK, CODEC_ID_CINEPAK, "Cinepak (ffmpeg)"}, - {BUF_VIDEO_MSVC, CODEC_ID_MSVIDEO1, "Microsoft Video 1 (ffmpeg)"}, - {BUF_VIDEO_MSRLE, CODEC_ID_MSRLE, "Microsoft RLE (ffmpeg)"}, - {BUF_VIDEO_RPZA, CODEC_ID_RPZA, "Apple Quicktime Video/RPZA (ffmpeg)"}, - {BUF_VIDEO_CYUV, CODEC_ID_CYUV, "Creative YUV (ffmpeg)"}, - {BUF_VIDEO_ROQ, CODEC_ID_ROQ, "Id Software RoQ (ffmpeg)"}, - {BUF_VIDEO_IDCIN, CODEC_ID_IDCIN, "Id Software CIN (ffmpeg)"}, - {BUF_VIDEO_WC3, CODEC_ID_XAN_WC3, "Xan (ffmpeg)"}, - {BUF_VIDEO_VQA, CODEC_ID_WS_VQA, "Westwood Studios VQA (ffmpeg)"}, - {BUF_VIDEO_INTERPLAY, CODEC_ID_INTERPLAY_VIDEO, "Interplay MVE (ffmpeg)"}, - {BUF_VIDEO_FLI, CODEC_ID_FLIC, "FLIC Video (ffmpeg)"}, - {BUF_VIDEO_8BPS, CODEC_ID_8BPS, "Planar RGB (ffmpeg)"}, - {BUF_VIDEO_SMC, CODEC_ID_SMC, "Apple Quicktime Graphics/SMC (ffmpeg)"}, - {BUF_VIDEO_DUCKTM1, CODEC_ID_TRUEMOTION1,"Duck TrueMotion v1 (ffmpeg)"}, - {BUF_VIDEO_DUCKTM2, CODEC_ID_TRUEMOTION2,"Duck TrueMotion v2 (ffmpeg)"}, - {BUF_VIDEO_VMD, CODEC_ID_VMDVIDEO, "Sierra VMD Video (ffmpeg)"}, - {BUF_VIDEO_ZLIB, CODEC_ID_ZLIB, "ZLIB Video (ffmpeg)"}, - {BUF_VIDEO_MSZH, CODEC_ID_MSZH, "MSZH Video (ffmpeg)"}, - {BUF_VIDEO_ASV1, CODEC_ID_ASV1, "ASV v1 Video (ffmpeg)"}, - {BUF_VIDEO_ASV2, CODEC_ID_ASV2, "ASV v2 Video (ffmpeg)"}, - {BUF_VIDEO_ATIVCR1, CODEC_ID_VCR1, "ATI VCR-1 (ffmpeg)"}, - {BUF_VIDEO_FLV1, CODEC_ID_FLV1, "Flash Video (ffmpeg)"}, - {BUF_VIDEO_QTRLE, CODEC_ID_QTRLE, "Apple Quicktime Animation/RLE (ffmpeg)"}, - {BUF_VIDEO_H264, CODEC_ID_H264, "H.264/AVC (ffmpeg)"}, - {BUF_VIDEO_H261, CODEC_ID_H261, "H.261 (ffmpeg)"}, - {BUF_VIDEO_AASC, CODEC_ID_AASC, "Autodesk Video (ffmpeg)"}, - {BUF_VIDEO_LOCO, CODEC_ID_LOCO, "LOCO (ffmpeg)"}, - {BUF_VIDEO_QDRW, CODEC_ID_QDRAW, "QuickDraw (ffmpeg)"}, - {BUF_VIDEO_QPEG, CODEC_ID_QPEG, "Q-Team QPEG (ffmpeg)"}, - {BUF_VIDEO_TSCC, CODEC_ID_TSCC, "TechSmith Video (ffmpeg)"}, - {BUF_VIDEO_ULTI, CODEC_ID_ULTI, "IBM UltiMotion (ffmpeg)"}, - {BUF_VIDEO_WNV1, CODEC_ID_WNV1, "Winnow Video (ffmpeg)"}, - {BUF_VIDEO_XL, CODEC_ID_VIXL, "Miro/Pinnacle VideoXL (ffmpeg)"}, - {BUF_VIDEO_RT21, CODEC_ID_INDEO2, "Indeo/RealTime 2 (ffmpeg)"}, - {BUF_VIDEO_FPS1, CODEC_ID_FRAPS, "Fraps (ffmpeg)"}, - {BUF_VIDEO_MPEG, CODEC_ID_MPEG1VIDEO, "MPEG 1/2 (ffmpeg)"}, - {BUF_VIDEO_CSCD, CODEC_ID_CSCD, "CamStudio (ffmpeg)"}, - {BUF_VIDEO_AVS, CODEC_ID_AVS, "AVS (ffmpeg)"}, - {BUF_VIDEO_ALGMM, CODEC_ID_MMVIDEO, "American Laser Games MM (ffmpeg)"}, - {BUF_VIDEO_ZMBV, CODEC_ID_ZMBV, "Zip Motion Blocks Video (ffmpeg)"}, - {BUF_VIDEO_SMACKER, CODEC_ID_SMACKVIDEO, "Smacker (ffmpeg)"}, - {BUF_VIDEO_NUV, CODEC_ID_NUV, "NuppelVideo (ffmpeg)"}, - {BUF_VIDEO_KMVC, CODEC_ID_KMVC, "Karl Morton's Video Codec (ffmpeg)"}, - {BUF_VIDEO_FLASHSV, CODEC_ID_FLASHSV, "Flash Screen Video (ffmpeg)"}, - {BUF_VIDEO_CAVS, CODEC_ID_CAVS, "Chinese AVS (ffmpeg)"}, - {BUF_VIDEO_VMNC, CODEC_ID_VMNC, "VMware Screen Codec (ffmpeg)"}, - {BUF_VIDEO_THEORA_RAW, CODEC_ID_THEORA, "Theora (ffmpeg)"}, - {BUF_VIDEO_SNOW, CODEC_ID_SNOW, "Snow (ffmpeg)"}, -}; +#include "ff_video_list.h" static const char *const skip_loop_filter_enum_names[] = { "default", /* AVDISCARD_DEFAULT */ @@ -400,6 +340,22 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type) return; } + if (this->codec->id == CODEC_ID_VC1 && + (!this->bih.biWidth || !this->bih.biHeight)) { + /* VC1 codec must be re-opened with correct width and height. */ + avcodec_close(this->context); + + if (avcodec_open (this->context, this->codec) < 0) { + pthread_mutex_unlock(&ffmpeg_lock); + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + _("ffmpeg_video_dec: couldn't open decoder (pass 2)\n")); + free(this->context); + this->context = NULL; + _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HANDLED, 0); + return; + } + } + if (this->class->thread_count > 1) { avcodec_thread_init(this->context, this->class->thread_count); this->context->thread_count = this->class->thread_count; @@ -606,6 +562,10 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { su = this->av_frame->data[1]; sv = this->av_frame->data[2]; + /* Some segfaults & heap corruption have been observed with img->height, + * so we use this->bih.biHeight instead (which is the displayed height) + */ + if (this->context->pix_fmt == PIX_FMT_YUV410P) { yuv9_to_yv12( @@ -626,7 +586,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { img->pitches[2], /* width x height */ img->width, - img->height); + this->bih.biHeight); } else if (this->context->pix_fmt == PIX_FMT_YUV411P) { @@ -648,15 +608,15 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { img->pitches[2], /* width x height */ img->width, - img->height); + this->bih.biHeight); - } else if (this->context->pix_fmt == PIX_FMT_RGBA32) { + } else if (this->context->pix_fmt == PIX_FMT_RGB32) { int x, plane_ptr = 0; uint32_t *argb_pixels; uint32_t argb; - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { argb_pixels = (uint32_t *)sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; @@ -684,7 +644,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { uint8_t *src; uint16_t pixel16; - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { src = sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; @@ -713,7 +673,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { uint8_t *src; uint16_t pixel16; - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { src = sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; @@ -741,7 +701,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { int x, plane_ptr = 0; uint8_t *src; - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { src = sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; @@ -765,7 +725,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { int x, plane_ptr = 0; uint8_t *src; - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { src = sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; @@ -808,7 +768,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { v_palette[x] = COMPUTE_V(r, g, b); } - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { src = sy; for(x = 0; x < img->width; x++) { pixel = *src++; @@ -825,7 +785,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { } else { - for (y=0; y<img->height; y++) { + for (y = 0; y < this->bih.biHeight; y++) { xine_fast_memcpy (dy, sy, img->width); dy += img->pitches[0]; @@ -833,7 +793,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { sy += this->av_frame->linesize[0]; } - for (y=0; y<(img->height/2); y++) { + for (y = 0; y < this->bih.biHeight / 2; y++) { if (this->context->pix_fmt != PIX_FMT_YUV444P) { @@ -1174,6 +1134,97 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu } } +#ifdef AVCODEC_HAS_REORDERED_OPAQUE +static uint64_t ff_tag_pts(ff_video_decoder_t *this, uint64_t pts) +{ + return pts | this->pts_tag; +} + +static uint64_t ff_untag_pts(ff_video_decoder_t *this, uint64_t pts) +{ + if (this->pts_tag_mask == 0) + return pts; /* pts tagging inactive */ + + if (this->pts_tag != 0 && (pts & this->pts_tag_mask) != this->pts_tag) + return 0; /* reset pts if outdated while waiting for first pass (see below) */ + + return pts & ~this->pts_tag_mask; +} + +static void ff_check_pts_tagging(ff_video_decoder_t *this, uint64_t pts) +{ + if (this->pts_tag_mask == 0) + return; /* pts tagging inactive */ + if ((pts & this->pts_tag_mask) != this->pts_tag) { + this->pts_tag_stable_counter = 0; + return; /* pts still outdated */ + } + + /* the tag should be stable for 100 frames */ + this->pts_tag_stable_counter++; + + if (this->pts_tag != 0) { + if (this->pts_tag_stable_counter >= 100) { + /* first pass: reset pts_tag */ + this->pts_tag = 0; + this->pts_tag_stable_counter = 0; + } + } else if (pts == 0) + return; /* cannot detect second pass */ + else { + if (this->pts_tag_stable_counter >= 100) { + /* second pass: reset pts_tag_mask and pts_tag_counter */ + this->pts_tag_mask = 0; + this->pts_tag_counter = 0; + this->pts_tag_stable_counter = 0; + } + } +} + +static int ff_vc1_find_header(ff_video_decoder_t *this, buf_element_t *buf) +{ + uint8_t *p = buf->content; + + if (!p[0] && !p[1] && p[2] == 1 && p[3] == 0x0f) { + int i; + + this->context->extradata = calloc(1, buf->size); + this->context->extradata_size = 0; + + for (i = 0; i < buf->size && i < 128; i++) { + if (!p[i] && !p[i+1] && p[i+2]) { + lprintf("00 00 01 %02x at %d\n", p[i+3], i); + if (p[i+3] != 0x0e && p[i+3] != 0x0f) + break; + } + this->context->extradata[i] = p[i]; + this->context->extradata_size++; + } + + lprintf("ff_video_decoder: found VC1 sequence header\n"); + return 1; + } + + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "ffmpeg_video_dec: VC1 extradata missing !\n"); + return 0; +} + +static int ff_check_extradata(ff_video_decoder_t *this, unsigned int codec_type, buf_element_t *buf) +{ + if (this->context && this->context->extradata) + return 1; + + switch (codec_type) { + case BUF_VIDEO_VC1: + return ff_vc1_find_header(this, buf); + default:; + } + + return 1; +} + +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { uint8_t *chunk_buf = this->buf; AVRational avr00 = {0, 1}; @@ -1184,6 +1235,9 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { if (this->decoder_init_mode) { int codec_type = buf->type & 0xFFFF0000; + if (!ff_check_extradata(this, codec_type, buf)) + return; + /* init ffmpeg decoder */ init_video_codec(this, codec_type); init_postprocess(this); @@ -1198,6 +1252,16 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { this->size = 0; } +#ifdef AVCODEC_HAS_REORDERED_OPAQUE + if (this->size == 0) { + /* take over pts when we are about to buffer a frame */ + this->av_frame->reordered_opaque = ff_tag_pts(this, this->pts); + if (this->context) /* shouldn't be NULL */ + this->context->reordered_opaque = ff_tag_pts(this, this->pts); + this->pts = 0; + } +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ + /* data accumulation */ if (buf->size > 0) { if ((this->size == 0) && @@ -1250,6 +1314,12 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { len = avcodec_decode_video (this->context, this->av_frame, &got_picture, &chunk_buf[offset], this->size); + +#ifdef AVCODEC_HAS_REORDERED_OPAQUE + /* reset consumed pts value */ + this->context->reordered_opaque = ff_tag_pts(this, 0); +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ + lprintf("consumed size: %d, got_picture: %d\n", len, got_picture); if ((len <= 0) || (len > this->size)) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, @@ -1265,12 +1335,27 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { ff_check_bufsize(this, this->size); memmove (this->buf, &chunk_buf[offset], this->size); chunk_buf = this->buf; + +#ifdef AVCODEC_HAS_REORDERED_OPAQUE + /* take over pts for next access unit */ + this->av_frame->reordered_opaque = ff_tag_pts(this, this->pts); + this->context->reordered_opaque = ff_tag_pts(this, this->pts); + this->pts = 0; +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ } } } /* use externally provided video_step or fall back to stream's time_base otherwise */ - video_step_to_use = (this->video_step || !this->context->time_base.den) ? this->video_step : (int)(90000ll * this->context->time_base.num / this->context->time_base.den); + video_step_to_use = (this->video_step || !this->context->time_base.den) + ? this->video_step + : (int)(90000ll +#if LIBAVCODEC_VERSION_INT >= 0x341400 + * this->context->ticks_per_frame +#elif LIBAVCODEC_VERSION_INT >= 0x340000 +# warning Building without avcodec ticks_per_frame support; you should upgrade your libavcodec and recompile +#endif + * this->context->time_base.num / this->context->time_base.den); /* aspect ratio provided by ffmpeg, override previous setting */ if ((this->aspect_ratio_prio < 2) && @@ -1296,7 +1381,7 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { /* initialize the colorspace converter */ if (!this->cs_convert_init) { - if ((this->context->pix_fmt == PIX_FMT_RGBA32) || + if ((this->context->pix_fmt == PIX_FMT_RGB32) || (this->context->pix_fmt == PIX_FMT_RGB565) || (this->context->pix_fmt == PIX_FMT_RGB555) || (this->context->pix_fmt == PIX_FMT_BGR24) || @@ -1359,15 +1444,24 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { ff_convert_frame(this, img); } +#ifndef AVCODEC_HAS_REORDERED_OPAQUE img->pts = this->pts; this->pts = 0; +#else /* AVCODEC_HAS_REORDERED_OPAQUE */ + img->pts = ff_untag_pts(this, this->av_frame->reordered_opaque); + ff_check_pts_tagging(this, this->av_frame->reordered_opaque); /* only check for valid frames */ + this->av_frame->reordered_opaque = 0; +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ /* workaround for weird 120fps streams */ if( video_step_to_use == 750 ) { /* fallback to the VIDEO_PTS_MODE */ video_step_to_use = 0; } - + + if (video_step_to_use && video_step_to_use != this->reported_video_step) + _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, (this->reported_video_step = video_step_to_use)); + if (this->av_frame->repeat_pict) img->duration = video_step_to_use * 3 / 2; else @@ -1400,8 +1494,13 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { this->output_format, VO_BOTH_FIELDS|this->frame_flags); /* set PTS to allow early syncing */ +#ifndef AVCODEC_HAS_REORDERED_OPAQUE img->pts = this->pts; this->pts = 0; +#else /* AVCODEC_HAS_REORDERED_OPAQUE */ + img->pts = ff_untag_pts(this, this->av_frame->reordered_opaque); + this->av_frame->reordered_opaque = 0; +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ img->duration = video_step_to_use; @@ -1426,7 +1525,7 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { this->video_step = buf->decoder_info[0]; - _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, (this->reported_video_step = this->video_step)); } if (buf->decoder_flags & BUF_FLAG_PREVIEW) { @@ -1486,6 +1585,13 @@ static void ff_reset (video_decoder_t *this_gen) { if (this->is_mpeg12) mpeg_parser_reset(this->mpeg_parser); + +#ifdef AVCODEC_HAS_REORDERED_OPAQUE + this->pts_tag_mask = 0; + this->pts_tag = 0; + this->pts_tag_counter = 0; + this->pts_tag_stable_counter = 0; +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ } static void ff_discontinuity (video_decoder_t *this_gen) { @@ -1493,6 +1599,41 @@ static void ff_discontinuity (video_decoder_t *this_gen) { lprintf ("ff_discontinuity\n"); this->pts = 0; + +#ifdef AVCODEC_HAS_REORDERED_OPAQUE + /* + * there is currently no way to reset all the pts which are stored in the decoder. + * therefore, we add a unique tag (generated from pts_tag_counter) to pts (see + * ff_tag_pts()) and wait for it to appear on returned frames. + * until then, any retrieved pts value will be reset to 0 (see ff_untag_pts()). + * when we see the tag returned, pts_tag will be reset to 0. from now on, any + * untagged pts value is valid already. + * when tag 0 appears too, there are no tags left in the decoder so pts_tag_mask + * and pts_tag_counter will be reset to 0 too (see ff_check_pts_tagging()). + */ + this->pts_tag_counter++; + this->pts_tag_mask = 0; + this->pts_tag = 0; + this->pts_tag_stable_counter = 0; + { + /* pts values typically don't use the uppermost bits. therefore we put the tag there */ + int counter_mask = 1; + int counter = 2 * this->pts_tag_counter + 1; /* always set the uppermost bit in tag_mask */ + uint64_t tag_mask = 0x8000000000000000ull; + while (this->pts_tag_counter >= counter_mask) + { + /* + * mirror the counter into the uppermost bits. this allows us to enlarge mask as + * necessary and while previous taggings can still be detected to be outdated. + */ + if (counter & counter_mask) + this->pts_tag |= tag_mask; + this->pts_tag_mask |= tag_mask; + tag_mask >>= 1; + counter_mask <<= 1; + } + } +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ } static void ff_dispose (video_decoder_t *this_gen) { @@ -1669,237 +1810,6 @@ void *init_video_plugin (xine_t *xine, void *data) { return this; } -static uint32_t supported_video_types[] = { - #ifdef CONFIG_MSMPEG4V1_DECODER - BUF_VIDEO_MSMPEG4_V1, - #endif - #ifdef CONFIG_MSMPEG4V2_DECODER - BUF_VIDEO_MSMPEG4_V2, - #endif - #ifdef CONFIG_MSMPEG4V3_DECODER - BUF_VIDEO_MSMPEG4_V3, - #endif - #ifdef CONFIG_WMV1_DECODER - BUF_VIDEO_WMV7, - #endif - #ifdef CONFIG_WMV2_DECODER - BUF_VIDEO_WMV8, - #endif - #ifdef CONFIG_WMV3_DECODER - BUF_VIDEO_WMV9, - #endif - #ifdef CONFIG_VC1_DECODER - BUF_VIDEO_VC1, - #endif - #ifdef CONFIG_MPEG4_DECODER - BUF_VIDEO_MPEG4, - #endif - #ifdef CONFIG_MPEG4_DECODER - BUF_VIDEO_XVID, - #endif - #ifdef CONFIG_MPEG4_DECODER - BUF_VIDEO_DIVX5, - #endif - #ifdef CONFIG_MPEG4_DECODER - BUF_VIDEO_3IVX, - #endif - #ifdef CONFIG_MJPEG_DECODER - BUF_VIDEO_JPEG, - #endif - #ifdef CONFIG_MJPEG_DECODER - BUF_VIDEO_MJPEG, - #endif - #ifdef CONFIG_MJPEGB_DECODER - BUF_VIDEO_MJPEG_B, - #endif - #ifdef CONFIG_H263I_DECODER - BUF_VIDEO_I263, - #endif - #ifdef CONFIG_H263_DECODER - BUF_VIDEO_H263, - #endif - #ifdef CONFIG_RV10_DECODER - BUF_VIDEO_RV10, - #endif - #ifdef CONFIG_RV20_DECODER - BUF_VIDEO_RV20, - #endif - #ifdef CONFIG_INDEO3_DECODER - BUF_VIDEO_IV31, - #endif - #ifdef CONFIG_INDEO3_DECODER - BUF_VIDEO_IV32, - #endif - #ifdef CONFIG_SVQ1_DECODER - BUF_VIDEO_SORENSON_V1, - #endif - #ifdef CONFIG_SVQ3_DECODER - BUF_VIDEO_SORENSON_V3, - #endif - #ifdef CONFIG_DVVIDEO_DECODER - BUF_VIDEO_DV, - #endif - #ifdef CONFIG_HUFFYUV_DECODER - BUF_VIDEO_HUFFYUV, - #endif - #ifdef CONFIG_VP3_DECODER - BUF_VIDEO_VP31, - #endif - #ifdef CONFIG_VP5_DECODER - BUF_VIDEO_VP5, - #endif - #ifdef CONFIG_VP6_DECODER - BUF_VIDEO_VP6, - BUF_VIDEO_VP6F, - #endif - #ifdef CONFIG_4XM_DECODER - BUF_VIDEO_4XM, - #endif - #ifdef CONFIG_CINEPAK_DECODER - BUF_VIDEO_CINEPAK, - #endif - #ifdef CONFIG_MSVIDEO1_DECODER - BUF_VIDEO_MSVC, - #endif - #ifdef CONFIG_MSRLE_DECODER - BUF_VIDEO_MSRLE, - #endif - #ifdef CONFIG_RPZA_DECODER - BUF_VIDEO_RPZA, - #endif - #ifdef CONFIG_CYUV_DECODER - BUF_VIDEO_CYUV, - #endif - #ifdef CONFIG_ROQ_DECODER - BUF_VIDEO_ROQ, - #endif - #ifdef CONFIG_IDCIN_DECODER - BUF_VIDEO_IDCIN, - #endif - #ifdef CONFIG_XAN_WC3_DECODER - BUF_VIDEO_WC3, - #endif - #ifdef CONFIG_WS_VQA_DECODER - BUF_VIDEO_VQA, - #endif - #ifdef CONFIG_INTERPLAY_VIDEO_DECODER - BUF_VIDEO_INTERPLAY, - #endif - #ifdef CONFIG_FLIC_DECODER - BUF_VIDEO_FLI, - #endif - #ifdef CONFIG_8BPS_DECODER - BUF_VIDEO_8BPS, - #endif - #ifdef CONFIG_SMC_DECODER - BUF_VIDEO_SMC, - #endif - #ifdef CONFIG_TRUEMOTION1_DECODER - BUF_VIDEO_DUCKTM1, - #endif - #ifdef CONFIG_TRUEMOTION2_DECODER - BUF_VIDEO_DUCKTM2, - #endif - #ifdef CONFIG_VMDVIDEO_DECODER - BUF_VIDEO_VMD, - #endif - #ifdef CONFIG_ZLIB_DECODER - BUF_VIDEO_ZLIB, - #endif - #ifdef CONFIG_MSZH_DECODER - BUF_VIDEO_MSZH, - #endif - #ifdef CONFIG_ASV1_DECODER - BUF_VIDEO_ASV1, - #endif - #ifdef CONFIG_ASV2_DECODER - BUF_VIDEO_ASV2, - #endif - #ifdef CONFIG_VCR1_DECODER - BUF_VIDEO_ATIVCR1, - #endif - #ifdef CONFIG_FLV_DECODER - BUF_VIDEO_FLV1, - #endif - #ifdef CONFIG_QTRLE_DECODER - BUF_VIDEO_QTRLE, - #endif - #ifdef CONFIG_H264_DECODER - BUF_VIDEO_H264, - #endif - #ifdef CONFIG_H261_DECODER - BUF_VIDEO_H261, - #endif - #ifdef CONFIG_AASC_DECODER - BUF_VIDEO_AASC, - #endif - #ifdef CONFIG_LOCO_DECODER - BUF_VIDEO_LOCO, - #endif - #ifdef CONFIG_QDRAW_DECODER - BUF_VIDEO_QDRW, - #endif - #ifdef CONFIG_QPEG_DECODER - BUF_VIDEO_QPEG, - #endif - #ifdef CONFIG_TSCC_DECODER - BUF_VIDEO_TSCC, - #endif - #ifdef CONFIG_ULTI_DECODER - BUF_VIDEO_ULTI, - #endif - #ifdef CONFIG_WNV1_DECODER - BUF_VIDEO_WNV1, - #endif - #ifdef CONFIG_VIXL_DECODER - BUF_VIDEO_XL, - #endif - #ifdef CONFIG_INDEO2_DECODER - BUF_VIDEO_RT21, - #endif - #ifdef CONFIG_FRAPS_DECODER - BUF_VIDEO_FPS1, - #endif - #ifdef CONFIG_MPEG1VIDEO_DECODER - BUF_VIDEO_MPEG, - #endif - #ifdef CONFIG_CSCD_DECODER - BUF_VIDEO_CSCD, - #endif - #ifdef CONFIG_AVS_DECODER - BUF_VIDEO_AVS, - #endif - #ifdef CONFIG_MMVIDEO_DECODER - BUF_VIDEO_ALGMM, - #endif - #ifdef CONFIG_ZMBV_DECODER - BUF_VIDEO_ZMBV, - #endif - #ifdef CONFIG_SMACKVIDEO_DECODER - BUF_VIDEO_SMACKER, - #endif - #ifdef CONFIG_NUV_DECODER - BUF_VIDEO_NUV, - #endif - #ifdef CONFIG_KMVC_DECODER - BUF_VIDEO_KMVC, - #endif - #ifdef CONFIG_FLASHSV_DECODER - BUF_VIDEO_FLASHSV, - #endif - #ifdef CONFIG_CAVS_DECODER - BUF_VIDEO_CAVS, - #endif - #ifdef CONFIG_VMNC_DECODER - BUF_VIDEO_VMNC, - #endif - #ifdef CONFIG_SNOW_DECODER - BUF_VIDEO_SNOW, - #endif - BUF_VIDEO_THEORA_RAW, - 0 -}; - static uint32_t wmv8_video_types[] = { BUF_VIDEO_WMV8, 0 diff --git a/src/combined/ffmpeg/mkcodeclist.pl b/src/combined/ffmpeg/mkcodeclist.pl new file mode 100755 index 000000000..b4a10921a --- /dev/null +++ b/src/combined/ffmpeg/mkcodeclist.pl @@ -0,0 +1,95 @@ +#! /usr/bin/perl -w + +# Make codec lists for #inclusion by ff_*_decoder.c. +# Parameters: +# list of ffmpeg CODEC_ID_* (pre-processed, one per line) +# list of codecs recognised by xine-lib (see list for details) +# output file name, or "-" to generate a report on unhandled codecs + +my ($ffmpeg, $xine, $out) = @ARGV; +my $line; + +# Read in the ffmpeg codec IDs +my %codecs; +open LIST, "< $ffmpeg" or die $!; +$line = <LIST>; +while (defined $line) { + chomp $line; + $line =~ s/^CODEC_ID_//o; + $codecs{$line} = 0; + $line = <LIST>; +} +close LIST or die $!; + +# Read in the xine-lib codec IDs +my %config; +my @known; +my $type = 'audio'; # default type +my $Type = 'AUDIO'; +my ($a, $f, $t); +open LIST, "< $xine" or die $!; +while (defined ($line = <LIST>)) { + next if substr ($line, 0, 1) eq '#' or $line =~ /^\s*$/o; + chomp $line; + if (substr ($line, 0, 5) eq 'type=') { + # codec type; "FOO" in "BUF_FOO_BAR" + $type = substr ($line, 5); + $type =~ tr/A-Z/a-z/; + $Type = $type; + $Type =~ tr/a-z/A-Z/; + } elsif (substr ($line, 0, 7) eq 'config=') { + # "#ifdef CONFIG_FOO_DECODER" mappings + ($a, $f, $t) = split (/=/, $line, 3); + $config{$f} = $t; + } else { + # codec details + push @known, [split (/\s+/, $line, 3)]; + } +} +close LIST or die $!; + +# Look through the mappings. +# Mark what we can handle and report on what the installed ffmpeg can't +foreach $line (@known) { + if (defined $codecs{$line->[1]}) { + ++$codecs{$line->[1]}; + } else { + print "Ignored $line->[0] = $line->[1]\n"; + } +} + +my $w = ($out ne '-'); + +if ($w) { + # Write the C source code for the codec lists + open LIST, "> $out" or die $!; + print LIST "static const ff_codec_t ff_${type}_lookup[] = {\n" or die $!; + foreach $line (@known) { + next if $line->[0] eq '!'; + next unless defined $codecs{$line->[1]}; + print LIST " { BUF_${Type}_$line->[0], CODEC_ID_$line->[1], \"$line->[2] (ffmpeg)\" },\n" or die $!; + } + print LIST "};\n\nstatic uint32_t supported_${type}_types[] = {\n" or die $!; + foreach $line (@known) { + next if $line->[0] eq '!'; + next unless defined $codecs{$line->[1]}; + $a = $line->[1]; + $a = $config{$a} if defined $config{$a}; + if ($a eq '') { + print LIST " BUF_${Type}_$line->[0],\n" or die $!; + } else { + print LIST " #ifdef CONFIG_${a}_DECODER\n BUF_${Type}_$line->[0],\n #endif\n" or die $!; + } + } + print LIST " 0,\n};\n" or die $!; + close LIST or die $!; +} +else { + # Report on ffmpeg codecs which we don't handle + print "Unhandled $type codecs:\n"; + foreach $line (sort keys %codecs) { + print " $line\n" if $codecs{$line} == 0; + } +} + +exit 0; diff --git a/src/combined/ffmpeg/xine_audio.list b/src/combined/ffmpeg/xine_audio.list new file mode 100644 index 000000000..4b6932474 --- /dev/null +++ b/src/combined/ffmpeg/xine_audio.list @@ -0,0 +1,55 @@ +type=audio +config=MP3ADU= + +# xine-lib BUF_AUDIO_ ffmpeg CODEC_ID_ description or comment +# ("!"=ignore) (quote any "s) + +WMAV1 WMAV1 MS Windows Media Audio 1 +WMAV2 WMAV2 MS Windows Media Audio 2 +14_4 RA_144 Real 14.4 +28_8 RA_288 Real 28.8 +MPEG MP3 MP3 +MP3ADU MP3ADU MPEG-3 adu +MSADPCM ADPCM_MS MS ADPCM +QTIMAADPCM ADPCM_IMA_QT QT IMA ADPCM +MSIMAADPCM ADPCM_IMA_WAV MS IMA ADPCM +DK3ADPCM ADPCM_IMA_DK3 Duck DK3 ADPCM +DK4ADPCM ADPCM_IMA_DK4 Duck DK4 ADPCM +VQA_IMA ADPCM_IMA_WS Westwood Studios IMA +SMJPEG_IMA ADPCM_IMA_SMJPEG SMJPEG IMA +XA_ADPCM ADPCM_XA CD-ROM/XA ADPCM +4X_ADPCM ADPCM_4XM 4X ADPCM +EA_ADPCM ADPCM_EA Electronic Arts ADPCM +MULAW PCM_MULAW mu-law logarithmic PCM +ALAW PCM_ALAW A-law logarithmic PCM +ROQ ROQ_DPCM RoQ DPCM +INTERPLAY INTERPLAY_DPCM Interplay DPCM +MAC3 MACE3 MACE 3:1 +MAC6 MACE6 MACE 6:1 +XAN_DPCM XAN_DPCM Origin Xan DPCM +VMD VMDAUDIO Sierra VMD Audio +FLAC FLAC FLAC +SHORTEN SHORTEN Shorten +ALAC ALAC ALAC +QDESIGN2 QDM2 QDesign +COOK COOK RealAudio Cooker +TRUESPEECH TRUESPEECH TrueSpeech +TTA TTA True Audio Lossless +SMACKER SMACKAUDIO Smacker +FLVADPCM ADPCM_SWF Flash ADPCM +WAVPACK WAVPACK WavPack +AMR_NB AMR_NB AMR narrow band +AMR_WB AMR_WB AMR wide band + +# disabled codecs (ref. configure.ac) +! AAC +! AC3 +! ADPCM_ADX +! ADPCM_G726 +! DSICINAUDIO +! DVAUDIO +! IMC +! MP3ON4 +! SONIC +! SONIC_LS +! VORBIS diff --git a/src/combined/ffmpeg/xine_video.list b/src/combined/ffmpeg/xine_video.list new file mode 100644 index 000000000..a3c961d13 --- /dev/null +++ b/src/combined/ffmpeg/xine_video.list @@ -0,0 +1,109 @@ +type=video +config=VP6F=VP6 +config=FLV1=FLV +config=THEORA= + +# xine-lib BUF_VIDEO_ ffmpeg CODEC_ID_ description or comment +# ("!"=ignore) (quote any "s) + +MSMPEG4_V1 MSMPEG4V1 Microsoft MPEG-4 v1 +MSMPEG4_V2 MSMPEG4V2 Microsoft MPEG-4 v2 +MSMPEG4_V3 MSMPEG4V3 Microsoft MPEG-4 v3 +WMV7 WMV1 MS Windows Media Video 7 +WMV8 WMV2 MS Windows Media Video 8 +WMV9 WMV3 MS Windows Media Video 9 +VC1 VC1 MS Windows Media Video VC-1 +MPEG4 MPEG4 ISO MPEG-4 +XVID MPEG4 ISO MPEG-4 (XviD) +DIVX5 MPEG4 ISO MPEG-4 (DivX5) +3IVX MPEG4 ISO MPEG-4 (3ivx) +JPEG MJPEG Motion JPEG +MJPEG MJPEG Motion JPEG +MJPEG_B MJPEGB Motion JPEG B +I263 H263I ITU H.263 +H263 H263 H.263 +RV10 RV10 Real Video 1.0 +RV20 RV20 Real Video 2.0 +IV31 INDEO3 Indeo Video 3.1 +IV32 INDEO3 Indeo Video 3.2 +SORENSON_V1 SVQ1 Sorenson Video 1 +SORENSON_V3 SVQ3 Sorenson Video 3 +DV DVVIDEO DV +HUFFYUV HUFFYUV HuffYUV +VP31 VP3 On2 VP3.1 +VP5 VP5 On2 VP5 +VP6 VP6 On2 VP6 +VP6F VP6F On2 VP6 +4XM 4XM 4X Video +CINEPAK CINEPAK Cinepak +MSVC MSVIDEO1 Microsoft Video 1 +MSRLE MSRLE Microsoft RLE +RPZA RPZA Apple Quicktime Video/RPZA +CYUV CYUV Creative YUV +ROQ ROQ Id Software RoQ +IDCIN IDCIN Id Software CIN +WC3 XAN_WC3 Xan +VQA WS_VQA Westwood Studios VQA +INTERPLAY INTERPLAY_VIDEO Interplay MVE +FLI FLIC FLIC Video +8BPS 8BPS Planar RGB +SMC SMC Apple Quicktime Graphics/SMC +DUCKTM1 TRUEMOTION1 Duck TrueMotion v1 +DUCKTM2 TRUEMOTION2 Duck TrueMotion v2 +VMD VMDVIDEO Sierra VMD Video +ZLIB ZLIB ZLIB Video +MSZH MSZH MSZH Video +ASV1 ASV1 ASV v1 Video +ASV2 ASV2 ASV v2 Video +ATIVCR1 VCR1 ATI VCR-1 +FLV1 FLV1 Flash Video +QTRLE QTRLE Apple Quicktime Animation/RLE +H264 H264 H.264/AVC +H261 H261 H.261 +AASC AASC Autodesk Video +LOCO LOCO LOCO +QDRW QDRAW QuickDraw +QPEG QPEG Q-Team QPEG +TSCC TSCC TechSmith Video +ULTI ULTI IBM UltiMotion +WNV1 WNV1 Winnow Video +XL VIXL Miro/Pinnacle VideoXL +RT21 INDEO2 Indeo/RealTime 2 +FPS1 FRAPS Fraps +MPEG MPEG1VIDEO MPEG 1/2 +CSCD CSCD CamStudio +AVS AVS AVS +ALGMM MMVIDEO American Laser Games MM +ZMBV ZMBV Zip Motion Blocks Video +SMACKER SMACKVIDEO Smacker +NUV NUV NuppelVideo +KMVC KMVC Karl Morton's Video Codec +FLASHSV FLASHSV Flash Screen Video +CAVS CAVS Chinese AVS +VMNC VMNC VMware Screen Codec +THEORA_RAW THEORA Theora +SNOW SNOW Snow + +# disabled codecs (ref. configure.ac) +! BMP +! CLJR +! DSICINVIDEO +! FFV1 +! FFVHUFF +! GIF +! H263P +! JPEGLS +! LJPEG +! MDEC +! PAM +! PBM +! PGM +! PGMYUV +! PNG +! PPM +! RAWVIDEO +! SP5X +! TARGA +! TIERTEXSEQVIDEO +! TIFF +! XVID ⇒ MPEG4 diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am index 0875672b2..fe10947c5 100644 --- a/src/demuxers/Makefile.am +++ b/src/demuxers/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_CFLAGS = $(VISIBILITY_FLAG) @@ -74,10 +75,10 @@ xineplug_dmx_mpeg_pes_la_SOURCES = demux_mpeg_pes.c xineplug_dmx_mpeg_pes_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) xineplug_dmx_mpeg_ts_la_SOURCES = demux_ts.c -xineplug_dmx_mpeg_ts_la_LIBADD = $(XINE_LIB) +xineplug_dmx_mpeg_ts_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) xineplug_dmx_qt_la_SOURCES = demux_qt.c -xineplug_dmx_qt_la_LIBADD = $(XINE_LIB) $(ZLIB_LIBS) +xineplug_dmx_qt_la_LIBADD = $(XINE_LIB) $(ZLIB_LIBS) $(LTLIBINTL) xineplug_dmx_qt_la_CPPFLAGS = $(ZLIB_CPPFLAGS) xineplug_dmx_asf_la_SOURCES = demux_asf.c asfheader.c @@ -133,8 +134,8 @@ xineplug_dmx_image_la_LIBADD = $(XINE_LIB) xineplug_dmx_nsv_la_SOURCES = demux_nsv.c xineplug_dmx_nsv_la_LIBADD = $(XINE_LIB) -xineplug_dmx_matroska_la_SOURCES = demux_matroska.c ebml.c -xineplug_dmx_matroska_la_LIBADD = $(XINE_LIB) $(ZLIB_LIBS) +xineplug_dmx_matroska_la_SOURCES = demux_matroska.c demux_matroska-chapters.c ebml.c +xineplug_dmx_matroska_la_LIBADD = $(XINE_LIB) $(ZLIB_LIBS) $(LTLIBINTL) xineplug_dmx_matroska_la_CPPFLAGS = $(ZLIB_CPPFLAGS) xineplug_dmx_matroska_la_CFLAGS = $(AM_CFLAGS) -fno-strict-aliasing @@ -145,4 +146,4 @@ xineplug_dmx_flv_la_SOURCES = demux_flv.c xineplug_dmx_flv_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) xineinclude_HEADERS = demux.h -noinst_HEADERS = asfheader.h qtpalette.h group_games.h group_audio.h id3.h ebml.h matroska.h iff.h flacutils.h real_common.h +noinst_HEADERS = asfheader.h qtpalette.h group_games.h group_audio.h id3.h ebml.h matroska.h demux_matroska.h iff.h flacutils.h real_common.h diff --git a/src/demuxers/demux_4xm.c b/src/demuxers/demux_4xm.c index a02a4b597..397a271b8 100644 --- a/src/demuxers/demux_4xm.c +++ b/src/demuxers/demux_4xm.c @@ -190,8 +190,12 @@ static int open_fourxm_file(demux_fourxm_t *fourxm) { return 0; } const uint32_t current_track = _X_LE_32(&header[i + 8]); - if (current_track + 1 > fourxm->track_count) { + if (current_track >= fourxm->track_count) { fourxm->track_count = current_track + 1; + if (!fourxm->track_count || fourxm->track_count >= UINT_MAX / sizeof(audio_track_t)) { + free(header); + return 0; + } fourxm->tracks = realloc(fourxm->tracks, fourxm->track_count * sizeof(audio_track_t)); if (!fourxm->tracks) { diff --git a/src/demuxers/demux_aac.c b/src/demuxers/demux_aac.c index b8e6ec5c4..68a684ffa 100644 --- a/src/demuxers/demux_aac.c +++ b/src/demuxers/demux_aac.c @@ -173,7 +173,7 @@ static int demux_aac_send_chunk(demux_plugin_t *this_gen) { buf->extra_info->input_time = (8*current_pos) / (bitrate/1000); bytes_read = this->input->read(this->input, buf->content, buf->max_size); - if (bytes_read == 0) { + if (bytes_read <= 0) { buf->free_buffer(buf); this->status = DEMUX_FINISHED; return this->status; diff --git a/src/demuxers/demux_ac3.c b/src/demuxers/demux_ac3.c index 1acb12fcd..711bb0b45 100644 --- a/src/demuxers/demux_ac3.c +++ b/src/demuxers/demux_ac3.c @@ -311,13 +311,7 @@ static int demux_ac3_send_chunk (demux_plugin_t *this_gen) { this->frame_size); } - if (buf->size == 0) { - buf->free_buffer(buf); - this->status = DEMUX_FINISHED; - return this->status; - } - - if (buf->size == 0) { + if (buf->size <= 0) { buf->free_buffer(buf); this->status = DEMUX_FINISHED; return this->status; diff --git a/src/demuxers/demux_asf.c b/src/demuxers/demux_asf.c index 9d4191633..6c9ea631c 100644 --- a/src/demuxers/demux_asf.c +++ b/src/demuxers/demux_asf.c @@ -738,7 +738,10 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_demux_stream_t *str bufsize = stream->fifo->buffer_pool_buf_size; buf = stream->fifo->buffer_pool_alloc (stream->fifo); - this->input->read (this->input, buf->content, bufsize); + if (this->input->read (this->input, buf->content, bufsize) != bufsize) { + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: input buffer starved\n"); + return ; + } lprintf ("data: %d %d %d %d\n", buf->content[0], buf->content[1], buf->content[2], buf->content[3]); @@ -817,7 +820,10 @@ static void asf_send_buffer_defrag (demux_asf_t *this, asf_demux_stream_t *strea if( stream->frag_offset + frag_len > DEFRAG_BUFSIZE ) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: buffer overflow on defrag!\n"); } else { - this->input->read (this->input, &stream->buffer[stream->frag_offset], frag_len); + if (this->input->read (this->input, &stream->buffer[stream->frag_offset], frag_len) != frag_len) { + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: input buffer starved\n"); + return ; + } stream->frag_offset += frag_len; } @@ -1538,6 +1544,7 @@ static int demux_asf_parse_asx_references( demux_asf_t *this) { int buf_used = 0; int len; xml_node_t *xml_tree, *asx_entry, *asx_ref; + xml_parser_t *xml_parser; int result; @@ -1560,9 +1567,13 @@ static int demux_asf_parse_asx_references( demux_asf_t *this) { if(buf_used) buf[buf_used] = '\0'; - xml_parser_init(buf, buf_used, XML_PARSER_CASE_INSENSITIVE); - if((result = xml_parser_build_tree(&xml_tree)) != XML_PARSER_OK) + xml_parser = xml_parser_init_r(buf, buf_used, XML_PARSER_CASE_INSENSITIVE); + if((result = xml_parser_build_tree_r(xml_parser, &xml_tree)) != XML_PARSER_OK) { + xml_parser_finalize_r(xml_parser); goto failure; + } + + xml_parser_finalize_r(xml_parser); if(!strcasecmp(xml_tree->name, "ASX")) { /* Attributes: VERSION, PREVIEWMODE, BANNERBAR diff --git a/src/demuxers/demux_cdda.c b/src/demuxers/demux_cdda.c index 8e9ad3679..d48bb2a51 100644 --- a/src/demuxers/demux_cdda.c +++ b/src/demuxers/demux_cdda.c @@ -60,6 +60,7 @@ typedef struct { input_plugin_t *input; int status; + int send_newpts; int seek_flag; /* this is set when a seek just occurred */ } demux_cdda_t; @@ -91,9 +92,9 @@ static int demux_cdda_send_chunk (demux_plugin_t *this_gen) { buf->extra_info->input_time = buf->pts / 90; buf->decoder_flags |= BUF_FLAG_FRAME_END; - if (this->seek_flag) { - _x_demux_control_newpts(this->stream, buf->pts, BUF_FLAG_SEEK); - this->seek_flag = 0; + if (this->send_newpts) { + _x_demux_control_newpts(this->stream, buf->pts, this->seek_flag); + this->send_newpts = this->seek_flag = 0; } this->audio_fifo->put (this->audio_fifo, buf); @@ -146,9 +147,14 @@ static int demux_cdda_seek (demux_plugin_t *this_gen, off_t start_pos, int start this->input->seek(this->input, start_pos & ~3, SEEK_SET); else this->input->seek(this->input, start_time * CD_BYTES_PER_SECOND, SEEK_SET); - this->seek_flag = 1; + this->status = DEMUX_OK; - _x_demux_flush_engine (this->stream); + + this->send_newpts = 1; + if (playing) { + this->seek_flag = BUF_FLAG_SEEK; + _x_demux_flush_engine (this->stream); + } return this->status; } diff --git a/src/demuxers/demux_dts.c b/src/demuxers/demux_dts.c index 0606586cb..ed1f16d33 100644 --- a/src/demuxers/demux_dts.c +++ b/src/demuxers/demux_dts.c @@ -278,7 +278,7 @@ static int demux_dts_send_chunk (demux_plugin_t *this_gen) { this->frame_size); } - if (buf->size == 0) { + if (buf->size <= 0) { buf->free_buffer(buf); this->status = DEMUX_FINISHED; return this->status; diff --git a/src/demuxers/demux_flac.c b/src/demuxers/demux_flac.c index c14536040..c4132b767 100644 --- a/src/demuxers/demux_flac.c +++ b/src/demuxers/demux_flac.c @@ -33,6 +33,9 @@ #include <unistd.h> #include <string.h> #include <stdlib.h> +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#endif #define LOG_MODULE "demux_flac" #define LOG_VERBOSE diff --git a/src/demuxers/demux_matroska-chapters.c b/src/demuxers/demux_matroska-chapters.c new file mode 100644 index 000000000..aad8fe46d --- /dev/null +++ b/src/demuxers/demux_matroska-chapters.c @@ -0,0 +1,433 @@ +/* + * Copyright (C) 2009 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 + * + * demultiplexer for matroska streams: chapter handling + * + * TODO: + * - nested chapters + * + * Authors: + * Nicos Gollan <gtdev@spearhead.de> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define LOG_MODULE "demux_matroska_chapters" +#define LOG_VERBOSE +/* +#define LOG +*/ + +#include "xine_internal.h" +#include "xineutils.h" +#include "demux.h" + +#include "ebml.h" +#include "matroska.h" +#include "demux_matroska.h" + +/* TODO: this only handles one single (title, language, country) tuple. + * See the header for information. */ +static int parse_chapter_display(demux_matroska_t *this, matroska_chapter_t *chap, int level) { + ebml_parser_t *ebml = this->ebml; + int next_level = level+1; + char* tmp_name = NULL; + char* tmp_lang = NULL; + char* tmp_country = NULL; + + while (next_level == level+1) { + ebml_elem_t elem; + + if (!ebml_read_elem_head(ebml, &elem)) + return 0; + + switch (elem.id) { + + case MATROSKA_ID_CH_STRING: + tmp_name = ebml_alloc_read_ascii(ebml, &elem); + break; + + case MATROSKA_ID_CH_LANGUAGE: + tmp_lang = ebml_alloc_read_ascii(ebml, &elem); + break; + + case MATROSKA_ID_CH_COUNTRY: + tmp_country = ebml_alloc_read_ascii(ebml, &elem); + break; + + default: + lprintf("Unhandled ID (inside ChapterDisplay): 0x%x\n", elem.id); + if (!ebml_skip(ebml, &elem)) + return 0; + } + + next_level = ebml_get_next_level(ebml, &elem); + } + + if (NULL != chap->title) { + chap->title = tmp_name; + + free(chap->language); + chap->language = tmp_lang; + + free(chap->country); + chap->country = tmp_country; + } else if (tmp_lang != NULL && !strcmp("eng", tmp_lang) && (chap->language == NULL || strcmp("eng", chap->language))) { + free(chap->title); + chap->title = tmp_name; + + free(chap->language); + chap->language = tmp_lang; + + free(chap->country); + chap->country = tmp_country; + } else { + free(tmp_name); + free(tmp_lang); + free(tmp_country); + } + + return 1; +} + +static int parse_chapter_atom(demux_matroska_t *this, matroska_chapter_t *chap, int level) { + ebml_parser_t *ebml = this->ebml; + int next_level = level+1; + uint64_t num; + + chap->time_start = 0; + chap->time_end = 0; + chap->hidden = 0; + chap->enabled = 1; + + while (next_level == level+1) { + ebml_elem_t elem; + + if (!ebml_read_elem_head(ebml, &elem)) { + lprintf("invalid head\n"); + return 0; + } + + switch (elem.id) { + case MATROSKA_ID_CH_UID: + if (!ebml_read_uint(ebml, &elem, &chap->uid)) { + lprintf("invalid UID\n"); + return 0; + } + break; + + case MATROSKA_ID_CH_TIMESTART: + if (!ebml_read_uint(ebml, &elem, &chap->time_start)) { + lprintf("invalid start time\n"); + return 0; + } + /* convert to xine timing: Matroska timestamps are in nanoseconds, + * xine's PTS are in 1/90,000s */ + chap->time_start /= 100000; + chap->time_start *= 9; + break; + + case MATROSKA_ID_CH_TIMEEND: + if (!ebml_read_uint(ebml, &elem, &chap->time_end)) { + lprintf("invalid end time\n"); + return 0; + } + /* convert to xine timing */ + chap->time_end /= 100000; + chap->time_end *= 9; + break; + + case MATROSKA_ID_CH_DISPLAY: + if (!ebml_read_master(ebml, &elem)) + return 0; + + lprintf("ChapterDisplay\n"); + if(!parse_chapter_display(this, chap, level+1)) { + lprintf("invalid display information\n"); + return 0; + } + break; + + case MATROSKA_ID_CH_HIDDEN: + if (!ebml_read_uint(ebml, &elem, &num)) + return 0; + chap->hidden = (int)num; + break; + + case MATROSKA_ID_CH_ENABLED: + if (!ebml_read_uint(ebml, &elem, &num)) + return 0; + chap->enabled = (int)num; + break; + + case MATROSKA_ID_CH_ATOM: /* TODO */ + xprintf(this->stream->xine, XINE_VERBOSITY_NONE, + LOG_MODULE ": Warning: Nested chapters are not supported, playback may suffer!\n"); + if (!ebml_skip(ebml, &elem)) + return 0; + break; + + case MATROSKA_ID_CH_TRACK: /* TODO */ + xprintf(this->stream->xine, XINE_VERBOSITY_NONE, + LOG_MODULE ": Warning: Specific track information in chapters is not supported, playback may suffer!\n"); + if (!ebml_skip(ebml, &elem)) + return 0; + break; + + default: + lprintf("Unhandled ID (inside ChapterAtom): 0x%x\n", elem.id); + if (!ebml_skip(ebml, &elem)) + return 0; + } + + next_level = ebml_get_next_level(ebml, &elem); + } + + /* fallback information */ + /* FIXME: check allocations! */ + if (NULL == chap->title) { + chap->title = malloc(9); + if (chap->title != NULL) + strncpy(chap->title, "No title", 9); + } + + if (NULL == chap->language) { + chap->language = malloc(4); + if (chap->language != NULL) + strncpy(chap->language, "unk", 4); + } + + if (NULL == chap->country) { + chap->country = malloc(3); + if (chap->country != NULL) + strncpy(chap->country, "XX", 3); + } + + lprintf( "Chapter 0x%" PRIx64 ": %" PRIu64 "-%" PRIu64 "(pts), %s (%s). %shidden, %senabled.\n", + chap->uid, chap->time_start, chap->time_end, + chap->title, chap->language, + (chap->hidden ? "" : "not "), + (chap->enabled ? "" : "not ")); + + return 1; +} + +static void free_chapter(demux_matroska_t *this, matroska_chapter_t *chap) { + free(chap->title); + free(chap->language); + free(chap->country); + + free(chap); +} + +static int parse_edition_entry(demux_matroska_t *this, matroska_edition_t *ed) { + ebml_parser_t *ebml = this->ebml; + int next_level = 3; + uint64_t num; + int i; + + ed->hidden = 0; + ed->is_default = 0; + ed->ordered = 0; + + while (next_level == 3) { + ebml_elem_t elem; + + if (!ebml_read_elem_head(ebml, &elem)) + return 0; + + switch (elem.id) { + case MATROSKA_ID_CH_ED_UID: + if (!ebml_read_uint(ebml, &elem, &ed->uid)) + return 0; + break; + + case MATROSKA_ID_CH_ED_HIDDEN: + if (!ebml_read_uint(ebml, &elem, &num)) + return 0; + ed->hidden = (int)num; + break; + + case MATROSKA_ID_CH_ED_DEFAULT: + if (!ebml_read_uint(ebml, &elem, &num)) + return 0; + ed->is_default = (int)num; + break; + + case MATROSKA_ID_CH_ED_ORDERED: + if (!ebml_read_uint(ebml, &elem, &num)) + return 0; + ed->ordered = (int)num; + break; + + case MATROSKA_ID_CH_ATOM: + { + matroska_chapter_t *chapter = calloc(1, sizeof(matroska_chapter_t)); + if (NULL == chapter) + return 0; + + lprintf("ChapterAtom\n"); + if (!ebml_read_master(ebml, &elem)) + return 0; + + if (!parse_chapter_atom(this, chapter, next_level)) + return 0; + + /* resize chapters array if necessary */ + if (ed->num_chapters >= ed->cap_chapters) { + matroska_chapter_t** old_chapters = ed->chapters; + ed->cap_chapters += 10; + ed->chapters = realloc(ed->chapters, ed->cap_chapters * sizeof(matroska_chapter_t*)); + + if (NULL == ed->chapters) { + ed->chapters = old_chapters; + ed->cap_chapters -= 10; + return 0; + } + } + + ed->chapters[ed->num_chapters] = chapter; + ++ed->num_chapters; + + break; + } + + default: + lprintf("Unhandled ID (inside EditionEntry): 0x%x\n", elem.id); + if (!ebml_skip(ebml, &elem)) + return 0; + } + + next_level = ebml_get_next_level(ebml, &elem); + } + + xprintf( this->stream->xine, XINE_VERBOSITY_LOG, + LOG_MODULE ": Edition 0x%" PRIx64 ": %shidden, %sdefault, %sordered. %d chapters:\n", + ed->uid, + (ed->hidden ? "" : "not "), + (ed->is_default ? "" : "not "), + (ed->ordered ? "" : "not "), + ed->num_chapters ); + + for (i=0; i<ed->num_chapters; ++i) { + matroska_chapter_t* chap = ed->chapters[i]; + xprintf( this->stream->xine, XINE_VERBOSITY_LOG, + LOG_MODULE ": Chapter %d: %" PRIu64 "-%" PRIu64 "(pts), %s (%s). %shidden, %senabled.\n", + i+1, chap->time_start, chap->time_end, + chap->title, chap->language, + (chap->hidden ? "" : "not "), + (chap->enabled ? "" : "not ")); + } + + return 1; +} + +static void free_edition(demux_matroska_t *this, matroska_edition_t *ed) { + int i; + + for(i=0; i<ed->num_chapters; ++i) { + free_chapter(this, ed->chapters[i]); + } + free(ed->chapters); + free(ed); +} + +int matroska_parse_chapters(demux_matroska_t *this) { + ebml_parser_t *ebml = this->ebml; + int next_level = 2; + + while (next_level == 2) { + ebml_elem_t elem; + + if (!ebml_read_elem_head(ebml, &elem)) + return 0; + + switch (elem.id) { + case MATROSKA_ID_CH_EDITIONENTRY: + { + matroska_edition_t *edition = calloc(1, sizeof(matroska_edition_t)); + if (NULL == edition) + return 0; + + lprintf("EditionEntry\n"); + if (!ebml_read_master(ebml, &elem)) + return 0; + + if (!parse_edition_entry(this, edition)) + return 0; + + /* resize editions array if necessary */ + if (this->num_editions >= this->cap_editions) { + matroska_edition_t** old_editions = this->editions; + this->cap_editions += 10; + this->editions = realloc(this->editions, this->cap_editions * sizeof(matroska_edition_t*)); + + if (NULL == this->editions) { + this->editions = old_editions; + this->cap_editions -= 10; + return 0; + } + } + + this->editions[this->num_editions] = edition; + ++this->num_editions; + + break; + } + + default: + lprintf("Unhandled ID: 0x%x\n", elem.id); + if (!ebml_skip(ebml, &elem)) + return 0; + } + + next_level = ebml_get_next_level(ebml, &elem); + } + + return 1; +} + +void matroska_free_editions(demux_matroska_t *this) { + int i; + + for(i=0; i<this->num_editions; ++i) { + free_edition(this, this->editions[i]); + } + free(this->editions); + this->num_editions = 0; + this->cap_editions = 0; +} + +int matroska_get_chapter(demux_matroska_t *this, uint64_t tc, matroska_edition_t** ed) { + uint64_t block_pts = (tc * this->timecode_scale) / 100000 * 9; + int chapter_idx = 0; + + if (this->num_editions < 1) + return -1; + + while (chapter_idx < (*ed)->num_chapters && block_pts > (*ed)->chapters[chapter_idx]->time_start) + ++chapter_idx; + + if (chapter_idx > 0) + --chapter_idx; + + return chapter_idx; +} diff --git a/src/demuxers/demux_matroska.c b/src/demuxers/demux_matroska.c index ec75cb97a..9d224c62c 100644 --- a/src/demuxers/demux_matroska.c +++ b/src/demuxers/demux_matroska.c @@ -42,6 +42,7 @@ /* #define LOG */ + #include "xine_internal.h" #include "xineutils.h" #include "demux.h" @@ -50,89 +51,7 @@ #include "ebml.h" #include "matroska.h" - -#define NUM_PREVIEW_BUFFERS 10 - -#define MAX_STREAMS 128 -#define MAX_FRAMES 32 - -#define WRAP_THRESHOLD 90000 - -typedef struct { - int track_num; - off_t *pos; - uint64_t *timecode; - int num_entries; - -} matroska_index_t; - -typedef struct { - - demux_plugin_t demux_plugin; - - xine_stream_t *stream; - - input_plugin_t *input; - - int status; - - ebml_parser_t *ebml; - - /* segment element */ - ebml_elem_t segment; - uint64_t timecode_scale; - int duration; /* in millis */ - int preview_sent; - int preview_mode; - - /* meta seek info */ - int has_seekhead; - int seekhead_handled; - - /* seek info */ - matroska_index_t *indexes; - int num_indexes; - int first_cluster_found; - int skip_to_timecode; - int skip_for_track; - - /* tracks */ - int num_tracks; - int num_video_tracks; - int num_audio_tracks; - int num_sub_tracks; - - matroska_track_t *tracks[MAX_STREAMS]; - - /* block */ - uint8_t *block_data; - size_t block_data_size; - - /* current tracks */ - matroska_track_t *video_track; /* to remove */ - matroska_track_t *audio_track; /* to remove */ - matroska_track_t *sub_track; /* to remove */ - - int send_newpts; - int buf_flag_seek; - - /* seekhead parsing */ - int top_level_list_size; - int top_level_list_max_size; - off_t *top_level_list; - -} demux_matroska_t ; - -typedef struct { - - demux_class_t demux_class; - - /* class-wide, global variables here */ - - xine_t *xine; - -} demux_matroska_class_t; - +#include "demux_matroska.h" static void check_newpts (demux_matroska_t *this, int64_t pts, matroska_track_t *track) { @@ -206,10 +125,10 @@ static int parse_info(demux_matroska_t *this) { ebml_parser_t *ebml = this->ebml; int next_level = 2; double duration = 0.0; /* in matroska unit */ - + while (next_level == 2) { ebml_elem_t elem; - + if (!ebml_read_elem_head(ebml, &elem)) return 0; @@ -219,14 +138,22 @@ static int parse_info(demux_matroska_t *this) { if (!ebml_read_uint(ebml, &elem, &this->timecode_scale)) return 0; break; - case MATROSKA_ID_I_DURATION: { - + + case MATROSKA_ID_I_DURATION: lprintf("duration\n"); if (!ebml_read_float(ebml, &elem, &duration)) return 0; - } - break; - + break; + + case MATROSKA_ID_I_TITLE: + lprintf("title\n"); + if (NULL != this->title) + free(this->title); + + this->title = ebml_alloc_read_ascii(ebml, &elem); + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_TITLE, this->title); + break; + default: lprintf("Unhandled ID: 0x%x\n", elem.id); if (!ebml_skip(ebml, &elem)) @@ -240,6 +167,8 @@ static int parse_info(demux_matroska_t *this) { this->duration = (int)(duration * (double)this->timecode_scale / 1000000.0); lprintf("timecode_scale: %" PRId64 "\n", this->timecode_scale); lprintf("duration: %d\n", this->duration); + lprintf("title: %s\n", (NULL != this->title ? this->title : "(none)")); + return 1; } @@ -607,6 +536,8 @@ static void init_codec_xiph(demux_matroska_t *this, matroska_track_t *track) { int i; uint8_t *data; + if (track->codec_private_len < 3) + return; nb_lace = track->codec_private[0]; if (nb_lace != 2) return; @@ -614,6 +545,8 @@ static void init_codec_xiph(demux_matroska_t *this, matroska_track_t *track) { frame[0] = track->codec_private[1]; frame[1] = track->codec_private[2]; frame[2] = track->codec_private_len - frame[0] - frame[1] - 3; + if (frame[2] < 0) + return; data = track->codec_private + 3; for (i = 0; i < 3; i++) { @@ -1147,62 +1080,72 @@ static void handle_vobsub (demux_plugin_t *this_gen, matroska_track_t *track, static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { ebml_parser_t *ebml = this->ebml; int next_level = 3; - + while (next_level == 3) { ebml_elem_t elem; - + if (!ebml_read_elem_head(ebml, &elem)) return 0; switch (elem.id) { - case MATROSKA_ID_TR_NUMBER: { - uint64_t num; - lprintf("TrackNumber\n"); - if (!ebml_read_uint(ebml, &elem, &num)) - return 0; - track->track_num = num; - } - break; - - case MATROSKA_ID_TR_TYPE: { - uint64_t num; - lprintf("TrackType\n"); - if (!ebml_read_uint(ebml, &elem, &num)) - return 0; - track->track_type = num; - } - break; - - case MATROSKA_ID_TR_CODECID: { - char *codec_id = ebml_alloc_read_ascii (ebml, &elem); - lprintf("CodecID\n"); - if (!codec_id) - return 0; - track->codec_id = codec_id; - } - break; - - case MATROSKA_ID_TR_CODECPRIVATE: { - char *codec_private = malloc (elem.len); - lprintf("CodecPrivate\n"); - if (!ebml_read_binary(ebml, &elem, codec_private)) { - free(codec_private); - return 0; - } - track->codec_private = codec_private; - track->codec_private_len = elem.len; - } - break; - - case MATROSKA_ID_TR_LANGUAGE: { - char *language = ebml_alloc_read_ascii (ebml, &elem); - lprintf("Language\n"); - if (!language) - return 0; - track->language = language; - } - break; - + case MATROSKA_ID_TR_NUMBER: + { + uint64_t num; + lprintf("TrackNumber\n"); + if (!ebml_read_uint(ebml, &elem, &num)) + return 0; + track->track_num = num; + } + break; + + case MATROSKA_ID_TR_TYPE: + { + uint64_t num; + lprintf("TrackType\n"); + if (!ebml_read_uint(ebml, &elem, &num)) + return 0; + track->track_type = num; + } + break; + + case MATROSKA_ID_TR_CODECID: + { + char *codec_id = ebml_alloc_read_ascii (ebml, &elem); + lprintf("CodecID\n"); + if (!codec_id) + return 0; + track->codec_id = codec_id; + } + break; + + case MATROSKA_ID_TR_CODECPRIVATE: + { + char *codec_private; + if (elem.len >= 0x80000000) + return 0; + codec_private = malloc (elem.len); + if (! codec_private) + return 0; + lprintf("CodecPrivate\n"); + if (!ebml_read_binary(ebml, &elem, codec_private)) { + free(codec_private); + return 0; + } + track->codec_private = codec_private; + track->codec_private_len = elem.len; + } + break; + + case MATROSKA_ID_TR_LANGUAGE: + { + char *language = ebml_alloc_read_ascii (ebml, &elem); + lprintf("Language\n"); + if (!language) + return 0; + track->language = language; + } + break; + case MATROSKA_ID_TV: lprintf("Video\n"); if (track->video_track) @@ -1212,8 +1155,8 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { return 0; if ((elem.len > 0) && !parse_video_track(this, track->video_track)) return 0; - break; - + break; + case MATROSKA_ID_TA: lprintf("Audio\n"); if (track->audio_track) @@ -1223,38 +1166,54 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { return 0; if ((elem.len > 0) && !parse_audio_track(this, track->audio_track)) return 0; - break; - - case MATROSKA_ID_TR_FLAGDEFAULT: { - uint64_t val; - - lprintf("Default\n"); - if (!ebml_read_uint(ebml, &elem, &val)) - return 0; - track->default_flag = (int)val; - } - break; + break; - case MATROSKA_ID_TR_DEFAULTDURATION: { - uint64_t val; + case MATROSKA_ID_TR_FLAGDEFAULT: + { + uint64_t val; - if (!ebml_read_uint(ebml, &elem, &val)) - return 0; - track->default_duration = val; - lprintf("Default Duration: %"PRIu64"\n", track->default_duration); - } - break; + lprintf("Default\n"); + if (!ebml_read_uint(ebml, &elem, &val)) + return 0; + track->default_flag = (int)val; + } + break; - case MATROSKA_ID_CONTENTENCODINGS: { - lprintf("ContentEncodings\n"); - if (!ebml_read_master (ebml, &elem)) - return 0; - if ((elem.len > 0) && !parse_content_encodings(this, track)) - return 0; - } - break; + case MATROSKA_ID_TR_DEFAULTDURATION: + { + uint64_t val; + + if (!ebml_read_uint(ebml, &elem, &val)) + return 0; + track->default_duration = val; + lprintf("Default Duration: %"PRIu64"\n", track->default_duration); + } + break; + + case MATROSKA_ID_CONTENTENCODINGS: + { + lprintf("ContentEncodings\n"); + if (!ebml_read_master (ebml, &elem)) + return 0; + if ((elem.len > 0) && !parse_content_encodings(this, track)) + return 0; + } + break; + + case MATROSKA_ID_TR_UID: + { + uint64_t val; + + if (!ebml_read_uint(ebml, &elem, &val)) { + lprintf("Track UID (invalid)\n"); + return 0; + } + + track->uid = val; + lprintf("Track UID: 0x%" PRIx64 "\n", track->uid); + } + break; - case MATROSKA_ID_TR_UID: case MATROSKA_ID_TR_FLAGENABLED: case MATROSKA_ID_TR_FLAGLACING: case MATROSKA_ID_TR_MINCACHE: @@ -1275,32 +1234,37 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { } next_level = ebml_get_next_level(ebml, &elem); } - + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - "demux_matroska: Track %d, %s %s\n", - track->track_num, - (track->codec_id ? track->codec_id : ""), - (track->language ? track->language : "")); + "demux_matroska: Track %d, %s %s\n", + track->track_num, + (track->codec_id ? track->codec_id : ""), + (track->language ? track->language : "")); if (track->codec_id) { void (*init_codec)(demux_matroska_t *, matroska_track_t *) = NULL; if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_VFW_FOURCC)) { xine_bmiheader *bih; - lprintf("MATROSKA_CODEC_ID_V_VFW_FOURCC\n"); - bih = (xine_bmiheader*)track->codec_private; - _x_bmiheader_le2me(bih); + if (track->codec_private_len >= sizeof(xine_bmiheader)) { + lprintf("MATROSKA_CODEC_ID_V_VFW_FOURCC\n"); + bih = (xine_bmiheader*)track->codec_private; + _x_bmiheader_le2me(bih); - track->buf_type = _x_fourcc_to_buf_video(bih->biCompression); - init_codec = init_codec_video; + track->buf_type = _x_fourcc_to_buf_video(bih->biCompression); + init_codec = init_codec_video; + } } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_UNCOMPRESSED)) { } else if ((!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_SP)) || - (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_ASP)) || - (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_AP))) { + (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_ASP)) || + (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_AP))) { xine_bmiheader *bih; - + lprintf("MATROSKA_CODEC_ID_V_MPEG4_*\n"); + if (track->codec_private_len > 0x7fffffff - sizeof(xine_bmiheader)) + track->codec_private_len = 0x7fffffff - sizeof(xine_bmiheader); + /* create a bitmap info header struct for MPEG 4 */ bih = calloc(1, sizeof(xine_bmiheader) + track->codec_private_len); bih->biSize = sizeof(xine_bmiheader) + track->codec_private_len; @@ -1308,20 +1272,23 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { bih->biWidth = track->video_track->pixel_width; bih->biHeight = track->video_track->pixel_height; _x_bmiheader_le2me(bih); - + /* add bih extra data */ memcpy(bih + 1, track->codec_private, track->codec_private_len); free(track->codec_private); track->codec_private = (uint8_t *)bih; track->codec_private_len = bih->biSize; track->buf_type = BUF_VIDEO_MPEG4; - + /* init as a vfw decoder */ init_codec = init_codec_video; } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_AVC)) { xine_bmiheader *bih; - + lprintf("MATROSKA_CODEC_ID_V_MPEG4_AVC\n"); + if (track->codec_private_len > 0x7fffffff - sizeof(xine_bmiheader)) + track->codec_private_len = 0x7fffffff - sizeof(xine_bmiheader); + /* create a bitmap info header struct for h264 */ bih = calloc(1, sizeof(xine_bmiheader) + track->codec_private_len); bih->biSize = sizeof(xine_bmiheader) + track->codec_private_len; @@ -1329,14 +1296,14 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { bih->biWidth = track->video_track->pixel_width; bih->biHeight = track->video_track->pixel_height; _x_bmiheader_le2me(bih); - + /* add bih extra data */ memcpy(bih + 1, track->codec_private, track->codec_private_len); free(track->codec_private); track->codec_private = (uint8_t *)bih; track->codec_private_len = bih->biSize; track->buf_type = BUF_VIDEO_H264; - + /* init as a vfw decoder */ init_codec = init_codec_video; } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MSMPEG4V3)) { @@ -1357,7 +1324,7 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { track->handle_content = handle_realvideo; init_codec = init_codec_real; } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_REAL_RV40)) { - + lprintf("MATROSKA_CODEC_ID_V_REAL_RV40\n"); track->buf_type = BUF_VIDEO_RV40; track->handle_content = handle_realvideo; @@ -1369,8 +1336,8 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { track->buf_type = BUF_VIDEO_THEORA_RAW; init_codec = init_codec_xiph; } else if ((!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_MPEG1_L1)) || - (!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_MPEG1_L2)) || - (!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_MPEG1_L3))) { + (!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_MPEG1_L2)) || + (!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_MPEG1_L3))) { lprintf("MATROSKA_CODEC_ID_A_MPEG1\n"); track->buf_type = BUF_AUDIO_MPEG; init_codec = init_codec_audio; @@ -1382,7 +1349,7 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { lprintf("MATROSKA_CODEC_ID_A_AC3\n"); track->buf_type = BUF_AUDIO_A52; init_codec = init_codec_audio; - + } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_DTS)) { lprintf("MATROSKA_CODEC_ID_A_DTS\n"); track->buf_type = BUF_AUDIO_DTS; @@ -1398,13 +1365,15 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { xine_waveformatex *wfh; lprintf("MATROSKA_CODEC_ID_A_ACM\n"); - wfh = (xine_waveformatex*)track->codec_private; - _x_waveformatex_le2me(wfh); + if (track->codec_private_len >= sizeof(xine_waveformatex)) { + wfh = (xine_waveformatex*)track->codec_private; + _x_waveformatex_le2me(wfh); - track->buf_type = _x_formattag_to_buf_audio(wfh->wFormatTag); - init_codec = init_codec_audio; + track->buf_type = _x_formattag_to_buf_audio(wfh->wFormatTag); + init_codec = init_codec_audio; + } } else if (!strncmp(track->codec_id, MATROSKA_CODEC_ID_A_AAC, - sizeof(MATROSKA_CODEC_ID_A_AAC) - 1)) { + sizeof(MATROSKA_CODEC_ID_A_AAC) - 1)) { lprintf("MATROSKA_CODEC_ID_A_AAC\n"); track->buf_type = BUF_AUDIO_AAC; init_codec = init_codec_aac; @@ -1424,17 +1393,17 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { track->buf_type = BUF_AUDIO_ATRK; init_codec = init_codec_real; } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_S_TEXT_UTF8) || - !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_UTF8)) { + !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_UTF8)) { lprintf("MATROSKA_CODEC_ID_S_TEXT_UTF8\n"); track->buf_type = BUF_SPU_OGM; track->handle_content = handle_sub_utf8; } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_S_TEXT_SSA) || - !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_SSA)) { + !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_SSA)) { lprintf("MATROSKA_CODEC_ID_S_TEXT_SSA\n"); track->buf_type = BUF_SPU_OGM; track->handle_content = handle_sub_ssa; } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_S_TEXT_ASS) || - !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_ASS)) { + !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_ASS)) { lprintf("MATROSKA_CODEC_ID_S_TEXT_ASS\n"); track->buf_type = BUF_SPU_OGM; track->handle_content = handle_sub_ssa; @@ -1447,7 +1416,7 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { track->buf_type = BUF_SPU_DVD; track->handle_content = handle_vobsub; init_codec = init_codec_vobsub; - + /* Enable autodetection of the zlib compression, unless it was * explicitely set. Most vobsubs are compressed with zlib but * are not declared as such. @@ -1483,12 +1452,17 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { break; } - if (init_codec) + if (init_codec) { + if (! track->fifo) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "demux_matroska: Error: fifo not set up for track of type type %" PRIu32 "\n", track->track_type); + return 0; + } init_codec(this, track); - + } } } - + return 1; } @@ -1507,6 +1481,12 @@ static int parse_tracks(demux_matroska_t *this) { case MATROSKA_ID_TR_ENTRY: { matroska_track_t *track; + /* bail out early if no more tracks can be handled! */ + if (this->num_tracks >= MAX_STREAMS) { + lprintf("Too many tracks!\n"); + return 0; + } + /* alloc and initialize a track with 0 */ track = calloc(1, sizeof(matroska_track_t)); track->compress_algo = MATROSKA_COMPRESS_NONE; @@ -1520,29 +1500,7 @@ static int parse_tracks(demux_matroska_t *this) { this->num_tracks++; } break; - - default: - lprintf("Unhandled ID: 0x%x\n", elem.id); - if (!ebml_skip(ebml, &elem)) - return 0; - } - next_level = ebml_get_next_level(ebml, &elem); - } - return 1; -} - -static int parse_chapters(demux_matroska_t *this) { - ebml_parser_t *ebml = this->ebml; - int next_level = 2; - - while (next_level == 2) { - ebml_elem_t elem; - - if (!ebml_read_elem_head(ebml, &elem)) - return 0; - - switch (elem.id) { default: lprintf("Unhandled ID: 0x%x\n", elem.id); if (!ebml_skip(ebml, &elem)) @@ -1553,7 +1511,6 @@ static int parse_chapters(demux_matroska_t *this) { return 1; } - static int parse_cue_trackposition(demux_matroska_t *this, int *track_num, int64_t *pos) { ebml_parser_t *ebml = this->ebml; @@ -1811,6 +1768,11 @@ static int read_block_data (demux_matroska_t *this, size_t len) { alloc_block_data(this, len); /* block datas */ + if (! this->block_data) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "demux_matroska: memory allocation error\n"); + return 0; + } if (this->input->read(this->input, this->block_data, len) != len) { off_t pos = this->input->get_current_pos(this->input); xprintf(this->stream->xine, XINE_VERBOSITY_LOG, @@ -1838,7 +1800,7 @@ static int parse_block (demux_matroska_t *this, size_t block_size, uint8_t *data; uint8_t flags; int gap, lacing, num_len; - int timecode_diff; + int16_t timecode_diff; int64_t pts, xduration; int decoder_flags = 0; @@ -1848,7 +1810,7 @@ static int parse_block (demux_matroska_t *this, size_t block_size, data += num_len; /* timecode_diff is signed */ - timecode_diff = parse_int16(data); + timecode_diff = (int16_t)parse_int16(data); data += 2; flags = *data; @@ -2049,6 +2011,31 @@ static int parse_block (demux_matroska_t *this, size_t block_size, return 1; } +static int parse_simpleblock(demux_matroska_t *this, size_t block_len, uint64_t cluster_timecode, uint64_t block_duration) +{ + int has_block = 0; + off_t block_pos = 0; + off_t file_len = 0; + int normpos = 0; + int is_key = 1; + + lprintf("simpleblock\n"); + block_pos = this->input->get_current_pos(this->input); + file_len = this->input->get_length(this->input); + if( file_len ) + normpos = (int) ( (double) block_pos * 65535 / file_len ); + + if (!read_block_data(this, block_len)) + return 0; + + has_block = 1; + /* we have the duration, we can parse the block now */ + if (!parse_block(this, block_len, cluster_timecode, block_duration, + normpos, is_key)) + return 0; + return 1; +} + static int parse_block_group(demux_matroska_t *this, uint64_t cluster_timecode, uint64_t cluster_duration) { @@ -2111,9 +2098,52 @@ static int parse_block_group(demux_matroska_t *this, return 1; } +static int demux_matroska_seek (demux_plugin_t*, off_t, int, int); + +static void handle_events(demux_matroska_t *this) { + xine_event_t* event; + + while ((event = xine_event_get(this->event_queue))) { + if (this->num_editions > 0) { + matroska_edition_t* ed = this->editions[0]; + int chapter_idx = matroska_get_chapter(this, this->last_timecode, &ed); + uint64_t next_time; + + if (chapter_idx < 0) { + xine_event_free(event); + continue; + } + + switch(event->type) { + case XINE_EVENT_INPUT_NEXT: + if (chapter_idx < ed->num_chapters-1) { + next_time = ed->chapters[chapter_idx+1]->time_start / 90; + demux_matroska_seek((demux_plugin_t*)this, 0, next_time, 1); + } + break; + + /* TODO: should this try to implement common "start of chapter" + * functionality? */ + case XINE_EVENT_INPUT_PREVIOUS: + if (chapter_idx > 0) { + next_time = ed->chapters[chapter_idx-1]->time_start / 90; + demux_matroska_seek((demux_plugin_t*)this, 0, next_time, 1); + } + break; + + default: + break; + } + } + + xine_event_free(event); + } +} + static int parse_cluster(demux_matroska_t *this) { ebml_parser_t *ebml = this->ebml; - int next_level = 2; + int this_level = ebml->level; + int next_level = this_level; uint64_t timecode = 0; uint64_t duration = 0; @@ -2130,7 +2160,9 @@ static int parse_cluster(demux_matroska_t *this) { this->first_cluster_found = 1; } - while (next_level == 2) { + handle_events(this); + + while (next_level == this_level) { ebml_elem_t elem; if (!ebml_read_elem_head(ebml, &elem)) @@ -2154,6 +2186,11 @@ static int parse_cluster(demux_matroska_t *this) { if ((elem.len > 0) && !parse_block_group(this, timecode, duration)) return 0; break; + case MATROSKA_ID_CL_SIMPLEBLOCK: + lprintf("simpleblock\n"); + if (!parse_simpleblock(this, elem.len, timecode, duration)) + return 0; + break; case MATROSKA_ID_CL_BLOCK: lprintf("block\n"); if (!ebml_skip(ebml, &elem)) @@ -2166,6 +2203,49 @@ static int parse_cluster(demux_matroska_t *this) { } next_level = ebml_get_next_level(ebml, &elem); } + + /* at this point, we MUST have a timecode (according to format spec). + * Use that to find the chapter we are in, and adjust the title. + * + * TODO: this only looks at the chapters in the first edition. + */ + + this->last_timecode = timecode; + + if (this->num_editions <= 0) + return 1; + matroska_edition_t *ed = this->editions[0]; + + if (ed->num_chapters <= 0) + return 1; + + /* fix up a makeshift title if none has been set yet (e.g. filename) */ + if (NULL == this->title && NULL != _x_meta_info_get(this->stream, XINE_META_INFO_TITLE)) + this->title = strdup(_x_meta_info_get(this->stream, XINE_META_INFO_TITLE)); + + if (NULL == this->title) + this->title = strdup("(No title)"); + + if (NULL == this->title) { + lprintf("Failed to determine a valid stream title!\n"); + return 1; + } + + int chapter_idx = matroska_get_chapter(this, timecode, &ed); + if (chapter_idx < 0) { + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_TITLE, this->title); + return 1; + } + + xine_ui_data_t uidata = { + .str = {0, }, + .str_len = 0, + }; + + uidata.str_len = snprintf(uidata.str, sizeof(uidata.str), "%s / (%d) %s", + this->title, chapter_idx+1, ed->chapters[chapter_idx]->title); + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_TITLE, uidata.str); + return 1; } @@ -2300,6 +2380,7 @@ static int parse_top_level_head(demux_matroska_t *this, int *next_level) { ebml_elem_t elem; int ret_value = 1; off_t current_pos; + current_pos = this->input->get_current_pos(this->input); lprintf("current_pos: %" PRIdMAX "\n", (intmax_t)current_pos); @@ -2338,7 +2419,7 @@ static int parse_top_level_head(demux_matroska_t *this, int *next_level) { lprintf("Chapters\n"); if (!ebml_read_master (ebml, &elem)) return 0; - if ((elem.len > 0) && !parse_chapters(this)) + if ((elem.len > 0) && !matroska_parse_chapters(this)) return 0; break; case MATROSKA_ID_CLUSTER: @@ -2702,6 +2783,8 @@ static void demux_matroska_dispose (demux_plugin_t *this_gen) { demux_matroska_t *this = (demux_matroska_t *) this_gen; int i; + free(this->block_data); + /* free tracks */ for (i = 0; i < this->num_tracks; i++) { matroska_track_t *track; @@ -2719,7 +2802,7 @@ static void demux_matroska_dispose (demux_plugin_t *this_gen) { free (track->audio_track); if (track->sub_track) free (track->sub_track); - + free (track); } /* Free the cues. */ @@ -2731,12 +2814,17 @@ static void demux_matroska_dispose (demux_plugin_t *this_gen) { } if (this->indexes) free(this->indexes); - - /* Free the top_level elem list */ + + /* Free the top_level elem list */ if (this->top_level_list) free(this->top_level_list); + free(this->title); + + matroska_free_editions(this); + dispose_ebml_parser(this->ebml); + xine_event_dispose_queue(this->event_queue); free (this); } @@ -2750,7 +2838,13 @@ static int demux_matroska_get_stream_length (demux_plugin_t *this_gen) { static uint32_t demux_matroska_get_capabilities (demux_plugin_t *this_gen) { - return DEMUX_CAP_SPULANG | DEMUX_CAP_AUDIOLANG; + demux_matroska_t* this = (demux_matroska_t*)this_gen; + uint32_t caps = DEMUX_CAP_SPULANG | DEMUX_CAP_AUDIOLANG; + + if(this->num_editions > 0 && this->editions[0]->num_chapters > 0) + caps |= DEMUX_CAP_CHAPTERS; + + return caps; } @@ -2881,11 +2975,18 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str if (strcmp(ebml->doctype, "matroska")) goto error; + this->event_queue = xine_event_new_queue(this->stream); + return &this->demux_plugin; error: dispose_ebml_parser(ebml); - free(this); + + if (NULL != this) { + xine_event_dispose_queue(this->event_queue); + free(this); + } + return NULL; } diff --git a/src/demuxers/demux_matroska.h b/src/demuxers/demux_matroska.h new file mode 100644 index 000000000..a62aba498 --- /dev/null +++ b/src/demuxers/demux_matroska.h @@ -0,0 +1,150 @@ +/* + * 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 + * + * demultiplexer for matroska streams: shared header + */ + +#ifndef _DEMUX_MATROSKA_H_ +#define _DEMUX_MATROSKA_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <ctype.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <zlib.h> + +#include "xine_internal.h" +#include "demux.h" +#include "buffer.h" +#include "bswap.h" + +#include "ebml.h" +#include "matroska.h" + +#define NUM_PREVIEW_BUFFERS 10 + +#define MAX_STREAMS 128 +#define MAX_FRAMES 32 + +#define WRAP_THRESHOLD 90000 + +typedef struct { + int track_num; + off_t *pos; + uint64_t *timecode; + int num_entries; + +} matroska_index_t; + +typedef struct { + + demux_plugin_t demux_plugin; + + xine_stream_t *stream; + + input_plugin_t *input; + + int status; + + ebml_parser_t *ebml; + + /* segment element */ + ebml_elem_t segment; + uint64_t timecode_scale; + int duration; /* in millis */ + int preview_sent; + int preview_mode; + char *title; + + /* meta seek info */ + int has_seekhead; + int seekhead_handled; + + /* seek info */ + matroska_index_t *indexes; + int num_indexes; + int first_cluster_found; + int skip_to_timecode; + int skip_for_track; + + /* tracks */ + int num_tracks; + int num_video_tracks; + int num_audio_tracks; + int num_sub_tracks; + + matroska_track_t *tracks[MAX_STREAMS]; + + /* maintain editions, number and capacity */ + int num_editions, cap_editions; + matroska_edition_t **editions; + + /* block */ + uint8_t *block_data; + size_t block_data_size; + + /* current tracks */ + matroska_track_t *video_track; /* to remove */ + matroska_track_t *audio_track; /* to remove */ + matroska_track_t *sub_track; /* to remove */ + uint64_t last_timecode; + + int send_newpts; + int buf_flag_seek; + + /* seekhead parsing */ + int top_level_list_size; + int top_level_list_max_size; + off_t *top_level_list; + + /* event handling (chapter navigation) */ + xine_event_queue_t *event_queue; +} demux_matroska_t ; + +typedef struct { + + demux_class_t demux_class; + + /* class-wide, global variables here */ + + xine_t *xine; + +} demux_matroska_class_t; + +/* "entry points" for chapter handling. + * The parser descends into "Chapters" elements at the _parse_ function, + * and editions care about cleanup internally. */ +int matroska_parse_chapters(demux_matroska_t*); +void matroska_free_editions(demux_matroska_t*); + +/* Search an edition for the chapter matching a given timecode. + * + * Return: chapter index, or -1 if none is found. + * + * TODO: does not handle chapter end times yet. + */ +int matroska_get_chapter(demux_matroska_t*, uint64_t, matroska_edition_t**); + +#endif /* _DEMUX_MATROSKA_H_ */ diff --git a/src/demuxers/demux_mng.c b/src/demuxers/demux_mng.c index 0fcdb24ff..d0d83ff80 100644 --- a/src/demuxers/demux_mng.c +++ b/src/demuxers/demux_mng.c @@ -104,7 +104,12 @@ static mng_bool mymng_close_stream(mng_handle mngh){ static mng_bool mymng_read_stream(mng_handle mngh, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread){ demux_mng_t *this = (demux_mng_t*)mng_get_userdata(mngh); - *bytesread = this->input->read(this->input, buffer, size); + off_t n = this->input->read(this->input, buffer, size); + if (n < 0) { + *bytesread = 0; + return MNG_FALSE; + } + *bytesread = n; return MNG_TRUE; } @@ -112,6 +117,9 @@ static mng_bool mymng_read_stream(mng_handle mngh, mng_ptr buffer, mng_uint32 si static mng_bool mymng_process_header(mng_handle mngh, mng_uint32 width, mng_uint32 height){ demux_mng_t *this = (demux_mng_t*)mng_get_userdata(mngh); + if (width > 0x8000 || height > 0x8000) + return MNG_FALSE; + this->bih.biWidth = (width + 7) & ~7; this->bih.biHeight = height; this->left_edge = (this->bih.biWidth - width) / 2; diff --git a/src/demuxers/demux_mod.c b/src/demuxers/demux_mod.c index bffcf36d8..de3e29ca8 100644 --- a/src/demuxers/demux_mod.c +++ b/src/demuxers/demux_mod.c @@ -130,9 +130,16 @@ static int probe_mod_file(demux_mod_t *this) { /* returns 1 if the MOD file was opened successfully, 0 otherwise */ static int open_mod_file(demux_mod_t *this) { int total_read; + off_t input_length; /* Get size and create buffer */ - this->filesize = this->input->get_length(this->input); + input_length = this->input->get_length(this->input); + /* Avoid potential issues with signed variables and e.g. read() returning -1 */ + if (input_length > 0x7FFFFFFF || input_length < 0) { + xine_log(this->stream->xine, XINE_LOG_PLUGIN, "modplug - size overflow\n"); + return 0; + } + this->filesize = input_length; this->buffer = (char *)malloc(this->filesize); if(!this->buffer) { xine_log(this->stream->xine, XINE_LOG_PLUGIN, "modplug - allocation failure\n"); @@ -171,6 +178,8 @@ static int open_mod_file(demux_mod_t *this) { this->copyright = strdup(""); this->mod_length = ModPlug_GetLength(this->mpfile); + if (this->mod_length < 1) + this->mod_length = 1; /* avoids -ve & div-by-0 */ return 1; } @@ -372,7 +381,19 @@ static const char *get_extensions (demux_class_t *this_gen) { } static const char *get_mimetypes (demux_class_t *this_gen) { - return NULL; + return "audio/x-mod: mod: SoundTracker/NoiseTracker/ProTracker Module;" + "audio/mod: mod: SoundTracker/NoiseTracker/ProTracker Module;" + "audio/it: it: ImpulseTracker Module;" + "audio/x-it: it: ImpulseTracker Module;" + "audio/x-stm: stm: ScreamTracker 2 Module;" + "audio/x-s3m: s3m: ScreamTracker 3 Module;" + "audio/s3m: s3m: ScreamTracker 3 Module;" + "application/playerpro: 669: 669 Tracker Module;" + "application/adrift: amf: ADRIFT Module File;" + "audio/med: med: Amiga MED/OctaMED Tracker Module Sound File;" + "audio/x-amf: amf: ADRIFT Module File;" + "audio/x-xm: xm: FastTracker II Audio;" + "audio/xm: xm: FastTracker II Audio;"; } static void class_dispose (demux_class_t *this_gen) { diff --git a/src/demuxers/demux_mpc.c b/src/demuxers/demux_mpc.c index 9b27e5954..220e1b8b6 100644 --- a/src/demuxers/demux_mpc.c +++ b/src/demuxers/demux_mpc.c @@ -209,7 +209,7 @@ static int demux_mpc_send_chunk(demux_plugin_t *this_gen) { /* Read data */ bytes_read = this->input->read(this->input, buf->content, bytes_to_read); - if(bytes_read == 0) { + if(bytes_read <= 0) { buf->free_buffer(buf); this->status = DEMUX_FINISHED; return this->status; diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c index 026d2a88e..ae0a50ae6 100644 --- a/src/demuxers/demux_mpeg.c +++ b/src/demuxers/demux_mpeg.c @@ -281,6 +281,10 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) if((this->dummy_space[0] & 0xE0) == 0x20) { buf = this->input->read_block (this->input, this->video_fifo, len-1); + if (! buf) { + this->status = DEMUX_FINISHED; + return; + } track = (this->dummy_space[0] & 0x1f); @@ -300,6 +304,10 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) int spu_id = this->dummy_space[1] & 0x03; buf = this->input->read_block (this->input, this->video_fifo, len-1); + if (! buf) { + this->status = DEMUX_FINISHED; + return; + } buf->type = BUF_SPU_SVCD + spu_id; buf->pts = pts; @@ -320,6 +328,10 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) if((this->dummy_space[0] & 0xfc) == 0x00) { buf = this->input->read_block (this->input, this->video_fifo, len-1); + if (! buf) { + this->status = DEMUX_FINISHED; + return; + } buf->type = BUF_SPU_CVD + (this->dummy_space[0] & 0x03); buf->pts = pts; @@ -332,7 +344,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) if((this->dummy_space[0] & 0xf0) == 0x80) { /* read rest of header - AC3 */ - i = this->input->read (this->input, this->dummy_space+1, 3); + this->input->read (this->input, this->dummy_space+1, 3); /* contents */ for (i = len - 4; i > 0; i -= (this->audio_fifo) @@ -378,6 +390,10 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) i = this->input->read (this->input, this->dummy_space+1, 6); buf = this->input->read_block (this->input, this->video_fifo, len-7); + if (! buf) { + this->status = DEMUX_FINISHED; + return; + } buf->type = BUF_AUDIO_LPCM_BE + track; buf->decoder_flags |= BUF_FLAG_SPECIAL; @@ -433,7 +449,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) header_len -= 5 ; } - i = this->input->read (this->input, this->dummy_space, header_len); + this->input->read (this->input, this->dummy_space, header_len); for (i = len; i > 0; i -= (this->audio_fifo) ? this->audio_fifo->buffer_pool_buf_size : this->video_fifo->buffer_pool_buf_size) { @@ -505,7 +521,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) } /* read rest of header */ - i = this->input->read (this->input, this->dummy_space, header_len); + this->input->read (this->input, this->dummy_space, header_len); /* contents */ @@ -922,7 +938,7 @@ static void demux_mpeg_resync (demux_mpeg_t *this, uint32_t buf) { if (pos == len) { len = this->input->read(this->input, dummy_buf, sizeof(dummy_buf)); pos = 0; - if (len == 0) { + if (len <= 0) { this->status = DEMUX_FINISHED; break; } diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c index 3ecb88d04..55eb0ce81 100644 --- a/src/demuxers/demux_mpeg_block.c +++ b/src/demuxers/demux_mpeg_block.c @@ -69,9 +69,6 @@ typedef struct demux_mpeg_block_s { char cur_mrl[256]; - uint8_t *scratch; - void *scratch_base; - int64_t nav_last_end_pts; int64_t nav_last_start_pts; int64_t last_pts[2]; @@ -1176,7 +1173,6 @@ static void demux_mpeg_block_dispose (demux_plugin_t *this_gen) { demux_mpeg_block_t *this = (demux_mpeg_block_t *) this_gen; - free (this->scratch_base); free (this); } @@ -1189,18 +1185,19 @@ static int demux_mpeg_block_get_status (demux_plugin_t *this_gen) { static int demux_mpeg_detect_blocksize(demux_mpeg_block_t *this, input_plugin_t *input) { + uint8_t scratch[4]; input->seek(input, 2048, SEEK_SET); - if (!input->read(input, this->scratch, 4)) + if (input->read(input, scratch, 4) != 4) return 0; - if (this->scratch[0] || this->scratch[1] - || (this->scratch[2] != 0x01) || (this->scratch[3] != 0xba)) { + if (scratch[0] || scratch[1] + || (scratch[2] != 0x01) || (scratch[3] != 0xba)) { input->seek(input, 2324, SEEK_SET); - if (!input->read(input, this->scratch, 4)) + if (input->read(input, scratch, 4) != 4) return 0; - if (this->scratch[0] || this->scratch[1] - || (this->scratch[2] != 0x01) || (this->scratch[3] != 0xba)) + if (scratch[0] || scratch[1] + || (scratch[2] != 0x01) || (scratch[3] != 0xba)) return 0; return 2324; @@ -1385,7 +1382,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_optional_data = demux_mpeg_block_get_optional_data; this->demux_plugin.demux_class = class_gen; - this->scratch = xine_xmalloc_aligned (512, 4096, &this->scratch_base); this->status = DEMUX_FINISHED; lprintf ("open_plugin:detection_method=%d\n", @@ -1397,13 +1393,14 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str /* use demux_mpeg for non-block devices */ if (!(input->get_capabilities(input) & INPUT_CAP_BLOCK)) { - free (this->scratch_base); free (this); return NULL; } if (((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) ) { + uint8_t scratch[5] = {0xff, 0xff, 0xff, 0xff, 0xff}; /* result of input->read() won't matter */ + this->blocksize = input->get_blocksize(input); lprintf("open_plugin:blocksize=%d\n",this->blocksize); @@ -1411,28 +1408,25 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->blocksize = demux_mpeg_detect_blocksize( this, input ); if (!this->blocksize) { - free (this->scratch_base); free (this); return NULL; } input->seek(input, 0, SEEK_SET); - if (input->read(input, this->scratch, this->blocksize)) { + if (input->read(input, scratch, 5)) { lprintf("open_plugin:read worked\n"); - if (this->scratch[0] || this->scratch[1] - || (this->scratch[2] != 0x01) || (this->scratch[3] != 0xba)) { + if (scratch[0] || scratch[1] + || (scratch[2] != 0x01) || (scratch[3] != 0xba)) { lprintf("open_plugin:scratch failed\n"); - free (this->scratch_base); free (this); return NULL; } /* if it's a file then make sure it's mpeg-2 */ if ( !input->get_blocksize(input) - && ((this->scratch[4]>>4) != 4) ) { - free (this->scratch_base); + && ((scratch[4]>>4) != 4) ) { free (this); return NULL; } @@ -1446,7 +1440,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str break; } } - free (this->scratch_base); free (this); return NULL; } @@ -1467,7 +1460,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str ending = strrchr(mrl, '.'); if (!ending) { - free (this->scratch_base); free (this); return NULL; } @@ -1477,7 +1469,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->blocksize = 2048; demux_mpeg_block_accept_input(this, input); } else { - free (this->scratch_base); free (this); return NULL; } @@ -1495,7 +1486,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->blocksize = demux_mpeg_detect_blocksize( this, input ); if (!this->blocksize) { - free (this->scratch_base); free (this); return NULL; } @@ -1505,7 +1495,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str break; default: - free (this->scratch_base); free (this); return NULL; } diff --git a/src/demuxers/demux_mpeg_pes.c b/src/demuxers/demux_mpeg_pes.c index d9ac952d8..9715e1254 100644 --- a/src/demuxers/demux_mpeg_pes.c +++ b/src/demuxers/demux_mpeg_pes.c @@ -1173,7 +1173,7 @@ static int32_t parse_video_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elemen b->size = 0; b->pts = 0; b->type = buf_type; - b->decoder_flags = BUF_FLAG_FRAME_END; + b->decoder_flags = BUF_FLAG_FRAME_END | (this->preview_mode ? BUF_FLAG_PREVIEW : 0); this->video_fifo->put (this->video_fifo, b); } } @@ -1187,7 +1187,7 @@ static int32_t parse_video_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elemen if (this->mpeg12_h264_detected & 1) { uint8_t *t = buf->content + buf->size; if (buf->size >=4 && t[-1] == 10 && t[-2] == 0x01 && t[-3] == 0x00 && t[-4] == 0x00) /* end of sequence */ - buf->decoder_flags = BUF_FLAG_FRAME_END; + buf->decoder_flags = BUF_FLAG_FRAME_END | (this->preview_mode ? BUF_FLAG_PREVIEW : 0); } } else { buf->size = buf->max_size - result; @@ -1225,7 +1225,7 @@ static int32_t parse_video_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elemen if ((this->mpeg12_h264_detected & 1) && todo_length <= 0) { uint8_t *t = buf->content + buf->size; if (buf->size >= 4 && t[-1] == 10 && t[-2] == 0x01 && t[-3] == 0x00 && t[-4] == 0x00) /* end of sequence */ - buf->decoder_flags = BUF_FLAG_FRAME_END; + buf->decoder_flags = BUF_FLAG_FRAME_END | (this->preview_mode ? BUF_FLAG_PREVIEW : 0); } this->video_fifo->put (this->video_fifo, buf); @@ -1686,7 +1686,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str if (((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) ) { input->seek(input, 0, SEEK_SET); - if (input->read(input, (char *)this->scratch, 6)) { + if (input->read(input, (char *)this->scratch, 6) == 6) { lprintf("open_plugin:read worked\n"); if (this->scratch[0] || this->scratch[1] diff --git a/src/demuxers/demux_mpgaudio.c b/src/demuxers/demux_mpgaudio.c index 3c3576fd2..a87de5f97 100644 --- a/src/demuxers/demux_mpgaudio.c +++ b/src/demuxers/demux_mpgaudio.c @@ -65,11 +65,13 @@ /* Xing header stuff */ #define XING_TAG FOURCC_TAG('X', 'i', 'n', 'g') #define INFO_TAG FOURCC_TAG('I', 'n', 'f', 'o') +#define LAME_TAG FOURCC_TAG('L', 'A', 'M', 'E') #define XING_FRAMES_FLAG 0x0001 #define XING_BYTES_FLAG 0x0002 #define XING_TOC_FLAG 0x0004 #define XING_VBR_SCALE_FLAG 0x0008 #define XING_TOC_LENGTH 100 +#define LAME_HEADER_LENGTH 0xC0 /* Xing header stuff */ #define VBRI_TAG FOURCC_TAG('V', 'B', 'R', 'I') @@ -96,6 +98,10 @@ typedef struct { uint32_t stream_size; uint8_t toc[XING_TOC_LENGTH]; uint32_t vbr_scale; + + /* Lame extension */ + uint16_t start_delay; + uint16_t end_delay; } xing_header_t; /* Vbri Vbr Header struct */ @@ -402,9 +408,21 @@ static xing_header_t *XINE_MALLOC parse_xing_header(mpg_audio_frame_t *frame, xing->vbr_scale = -1; if (xing->flags & XING_VBR_SCALE_FLAG) { if (ptr >= (buf + bufsize - 4)) goto exit_error; - xing->vbr_scale = _X_BE_32(ptr); + xing->vbr_scale = _X_BE_32(ptr); ptr += 4; lprintf("vbr_scale: %d\n", xing->vbr_scale); } + + /* LAME extension */ + /* see http://gabriel.mp3-tech.org/mp3infotag.html */ + ptr -= 0x9C; /* move offset to match LAME header specs */ + if (ptr + LAME_HEADER_LENGTH >= (buf + bufsize - 4)) goto exit_error; + if (_X_BE_32(&ptr[0x9C]) == LAME_TAG) { + lprintf("Lame header found\n"); + xing->start_delay = (ptr[0xb1] << 4) | (ptr[0xb2] >> 4); + xing->end_delay = ((ptr[0xb2] & 0x0f) << 4) | ptr[0xb3]; + lprintf("start delay : %d samples\n", xing->start_delay); + lprintf("end delay : %d samples\n", xing->end_delay); + } } else { lprintf("Xing header not found\n"); } @@ -613,7 +631,22 @@ static int parse_frame_payload(demux_mpgaudio_t *this, buf->size = this->cur_frame.size; buf->type = BUF_AUDIO_MPEG; buf->decoder_info[0] = 1; - buf->decoder_flags = decoder_flags|BUF_FLAG_FRAME_END; + buf->decoder_flags = decoder_flags | BUF_FLAG_FRAME_END; + + /* send encoder padding */ + if (this->xing_header) { + if (frame_pos == this->mpg_frame_start) { + lprintf("sending a start padding of %d samples.\n", this->xing_header->start_delay); + buf->decoder_flags = buf->decoder_flags | BUF_FLAG_AUDIO_PADDING; + buf->decoder_info[1] = this->xing_header->start_delay; + buf->decoder_info[2] = 0; + } else if ((frame_pos + this->cur_frame.size) == this->mpg_frame_end) { + lprintf("sending a end padding of %d samples.\n", this->xing_header->end_delay); + buf->decoder_flags = buf->decoder_flags | BUF_FLAG_AUDIO_PADDING; + buf->decoder_info[1] = 0; + buf->decoder_info[2] = this->xing_header->end_delay; + } + } lprintf("send buffer: size=%d, pts=%"PRId64"\n", buf->size, pts); this->audio_fifo->put(this->audio_fifo, buf); @@ -768,9 +801,18 @@ static int demux_mpgaudio_send_chunk (demux_plugin_t *this_gen) { demux_mpgaudio_t *this = (demux_mpgaudio_t *) this_gen; - if (!demux_mpgaudio_next (this, 0, 0)) - this->status = DEMUX_FINISHED; + if (!demux_mpgaudio_next (this, 0, 0)) { + /* Hack: send 8 zero bytes to flush the libmad decoder */ + buf_element_t *buf; + buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo); + buf->type = BUF_AUDIO_MPEG; + buf->decoder_flags = BUF_FLAG_FRAME_END; + buf->size = 8; + memset(buf->content, 0, buf->size); + this->audio_fifo->put(this->audio_fifo, buf); + this->status = DEMUX_FINISHED; + } return this->status; } diff --git a/src/demuxers/demux_nsf.c b/src/demuxers/demux_nsf.c index 60d5049d9..926ea97e1 100644 --- a/src/demuxers/demux_nsf.c +++ b/src/demuxers/demux_nsf.c @@ -124,7 +124,7 @@ static int demux_nsf_send_chunk(demux_plugin_t *this_gen) { buf->type = BUF_AUDIO_NSF; bytes_read = this->input->read(this->input, buf->content, buf->max_size); - if (bytes_read == 0) { + if (bytes_read <= 0) { /* the file has been completely loaded, free the buffer and start * sending control buffers */ buf->free_buffer(buf); diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c index 9e9de45aa..e3a9b20c4 100644 --- a/src/demuxers/demux_ogg.c +++ b/src/demuxers/demux_ogg.c @@ -237,7 +237,7 @@ static int read_ogg_packet (demux_ogg_t *this) { while (ogg_sync_pageout(&this->oy,&this->og)!=1) { buffer = ogg_sync_buffer(&this->oy, CHUNKSIZE); bytes = this->input->read(this->input, buffer, CHUNKSIZE); - if (bytes == 0) { + if (bytes <= 0) { if (total == 0) { lprintf("read_ogg_packet read nothing\n"); return 0; diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c index 1fa9b4327..2039e54d3 100644 --- a/src/demuxers/demux_qt.c +++ b/src/demuxers/demux_qt.c @@ -738,6 +738,8 @@ static void parse_meta_atom(qt_info *info, unsigned char *meta_atom) { if (current_atom == ART_ATOM) { string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1; + if (string_size <= 0) + continue; info->artist = xine_xmalloc(string_size); if (info->artist) { strncpy(info->artist, &meta_atom[i + 20], string_size - 1); @@ -745,6 +747,8 @@ static void parse_meta_atom(qt_info *info, unsigned char *meta_atom) { } } else if (current_atom == NAM_ATOM) { string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1; + if (string_size <= 0) + continue; info->name = xine_xmalloc(string_size); if (info->name) { strncpy(info->name, &meta_atom[i + 20], string_size - 1); @@ -752,6 +756,8 @@ static void parse_meta_atom(qt_info *info, unsigned char *meta_atom) { } } else if (current_atom == ALB_ATOM) { string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1; + if (string_size <= 0) + continue; info->album = xine_xmalloc(string_size); if (info->album) { strncpy(info->album, &meta_atom[i + 20], string_size - 1); @@ -759,6 +765,8 @@ static void parse_meta_atom(qt_info *info, unsigned char *meta_atom) { } } else if (current_atom == GEN_ATOM) { string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1; + if (string_size <= 0) + continue; info->genre = xine_xmalloc(string_size); if (info->genre) { strncpy(info->genre, &meta_atom[i + 20], string_size - 1); @@ -766,6 +774,8 @@ static void parse_meta_atom(qt_info *info, unsigned char *meta_atom) { } } else if (current_atom == TOO_ATOM) { string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1; + if (string_size <= 0) + continue; info->comment = xine_xmalloc(string_size); if (info->comment) { strncpy(info->comment, &meta_atom[i + 20], string_size - 1); @@ -773,6 +783,8 @@ static void parse_meta_atom(qt_info *info, unsigned char *meta_atom) { } } else if (current_atom == WRT_ATOM) { string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1; + if (string_size <= 0) + continue; info->composer = xine_xmalloc(string_size); if (info->composer) { strncpy(info->composer, &meta_atom[i + 20], string_size - 1); @@ -780,6 +792,8 @@ static void parse_meta_atom(qt_info *info, unsigned char *meta_atom) { } } else if (current_atom == DAY_ATOM) { string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1; + if (string_size <= 0) + continue; info->year = xine_xmalloc(string_size); if (info->year) { strncpy(info->year, &meta_atom[i + 20], string_size - 1); @@ -947,6 +961,10 @@ static qt_error parse_trak_atom (qt_trak *trak, /* allocate space for each of the properties unions */ trak->stsd_atoms_count = _X_BE_32(&trak_atom[i + 8]); + if (trak->stsd_atoms_count <= 0) { + last_error = QT_HEADER_TROUBLE; + goto free_trak; + } trak->stsd_atoms = calloc(trak->stsd_atoms_count, sizeof(properties_t)); if (!trak->stsd_atoms) { last_error = QT_NO_MEMORY; @@ -958,6 +976,10 @@ static qt_error parse_trak_atom (qt_trak *trak, for (k = 0; k < trak->stsd_atoms_count; k++) { current_stsd_atom_size = _X_BE_32(&trak_atom[atom_pos - 4]); + if (current_stsd_atom_size < 4) { + last_error = QT_HEADER_TROUBLE; + goto free_trak; + } if (trak->type == MEDIA_VIDEO) { @@ -1513,7 +1535,8 @@ static qt_error parse_trak_atom (qt_trak *trak, } else if (current_atom == STTS_ATOM) { /* there should only be one of these atoms */ - if (trak->time_to_sample_table) { + if (trak->time_to_sample_table + || current_atom_size < 12 || current_atom_size >= UINT_MAX) { last_error = QT_HEADER_TROUBLE; goto free_trak; } @@ -1523,6 +1546,11 @@ static qt_error parse_trak_atom (qt_trak *trak, debug_atom_load(" qt stts atom (time-to-sample atom): %d entries\n", trak->time_to_sample_count); + if (trak->time_to_sample_count > (current_atom_size - 12) / 8) { + last_error = QT_HEADER_TROUBLE; + goto free_trak; + } + trak->time_to_sample_table = (time_to_sample_table_t *)calloc( trak->time_to_sample_count+1, sizeof(time_to_sample_table_t)); if (!trak->time_to_sample_table) { @@ -1575,13 +1603,16 @@ static qt_error parse_reference_atom (reference_t *ref, qt_atom current_atom; unsigned int current_atom_size; + if (ref_atom_size >= 0x80000000) + return QT_NOT_A_VALID_FILE; + /* initialize reference atom */ ref->url = NULL; ref->data_rate = 0; ref->qtim_version = 0; /* traverse through the atom looking for the key atoms */ - for (i = ATOM_PREAMBLE_SIZE; i < ref_atom_size - 4; i++) { + for (i = ATOM_PREAMBLE_SIZE; i + 4 < ref_atom_size; i++) { current_atom_size = _X_BE_32(&ref_atom[i - 4]); current_atom = _X_BE_32(&ref_atom[i]); @@ -1589,15 +1620,22 @@ static qt_error parse_reference_atom (reference_t *ref, if (current_atom == RDRF_ATOM) { size_t string_size = _X_BE_32(&ref_atom[i + 12]); size_t url_offset = 0; + int http = 0; - if (string_size >= current_atom_size || i + string_size >= ref_atom_size) + if (string_size >= current_atom_size || string_size >= ref_atom_size - i) return QT_NOT_A_VALID_FILE; /* if the URL starts with "http://", copy it */ if ( memcmp(&ref_atom[i + 16], "http://", 7) && memcmp(&ref_atom[i + 16], "rtsp://", 7) && base_mrl ) - url_offset = strlen(base_mrl); + { + /* We need a "qt" prefix hack for Apple trailers */ + http = !strncasecmp (base_mrl, "http://", 7); + url_offset = strlen(base_mrl) + 2 * http; + } + if (url_offset >= 0x80000000) + return QT_NOT_A_VALID_FILE; /* otherwise, append relative URL to base MRL */ string_size += url_offset; @@ -1605,7 +1643,7 @@ static qt_error parse_reference_atom (reference_t *ref, ref->url = xine_xmalloc(string_size + 1); if ( url_offset ) - strcpy(ref->url, base_mrl); + sprintf (ref->url, "%s%s", http ? "qt" : "", base_mrl); memcpy(ref->url + url_offset, &ref_atom[i + 16], _X_BE_32(&ref_atom[i + 12])); @@ -2181,7 +2219,7 @@ static qt_error open_qt_file(qt_info *info, input_plugin_t *input, } /* check if moov is compressed */ - if (_X_BE_32(&moov_atom[12]) == CMOV_ATOM) { + if (_X_BE_32(&moov_atom[12]) == CMOV_ATOM && moov_atom_size >= 0x28) { info->compressed_header = 1; diff --git a/src/demuxers/demux_rawdv.c b/src/demuxers/demux_rawdv.c index 86f777ec6..d95fc9125 100644 --- a/src/demuxers/demux_rawdv.c +++ b/src/demuxers/demux_rawdv.c @@ -302,7 +302,8 @@ static int demux_raw_dv_seek (demux_plugin_t *this_gen, } if( !start_pos && start_time ) { - start_pos = (start_time * 90 / this->duration) * this->frame_size; + /* Upcast start_time in case sizeof(off_t) > sizeof(int) */ + start_pos = ((off_t) start_time * 90 / this->duration) * this->frame_size; } start_pos = start_pos - (start_pos % this->frame_size); diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c index aa4dfc26b..774c74e2c 100644 --- a/src/demuxers/demux_real.c +++ b/src/demuxers/demux_real.c @@ -42,6 +42,9 @@ #include <string.h> #include <stdlib.h> #include <ctype.h> +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#endif #define LOG_MODULE "demux_real" #define LOG_VERBOSE @@ -265,8 +268,12 @@ static void real_parse_index(demux_real_t *this) { this->input->seek(this->input, original_pos, SEEK_SET); } -static mdpr_t *real_parse_mdpr(const char *data) { - mdpr_t *mdpr=malloc(sizeof(mdpr_t)); +static mdpr_t *real_parse_mdpr(const char *data, const unsigned int size) +{ + if (size < 38) + return NULL; + + mdpr_t *mdpr=calloc(sizeof(mdpr_t), 1); mdpr->stream_number=_X_BE_16(&data[2]); mdpr->max_bit_rate=_X_BE_32(&data[4]); @@ -278,17 +285,29 @@ static mdpr_t *real_parse_mdpr(const char *data) { mdpr->duration=_X_BE_32(&data[28]); mdpr->stream_name_size=data[32]; + if (size < 38 + mdpr->stream_name_size) + goto fail; mdpr->stream_name=malloc(mdpr->stream_name_size+1); + if (!mdpr->stream_name) + goto fail; memcpy(mdpr->stream_name, &data[33], mdpr->stream_name_size); mdpr->stream_name[(int)mdpr->stream_name_size]=0; mdpr->mime_type_size=data[33+mdpr->stream_name_size]; + if (size < 38 + mdpr->stream_name_size + mdpr->mime_type_size) + goto fail; mdpr->mime_type=malloc(mdpr->mime_type_size+1); + if (!mdpr->mime_type) + goto fail; memcpy(mdpr->mime_type, &data[34+mdpr->stream_name_size], mdpr->mime_type_size); mdpr->mime_type[(int)mdpr->mime_type_size]=0; mdpr->type_specific_len=_X_BE_32(&data[34+mdpr->stream_name_size+mdpr->mime_type_size]); + if (size < 38 + mdpr->stream_name_size + mdpr->mime_type_size + mdpr->type_specific_data) + goto fail; mdpr->type_specific_data=malloc(mdpr->type_specific_len); + if (!mdpr->type_specific_data) + goto fail; memcpy(mdpr->type_specific_data, &data[38+mdpr->stream_name_size+mdpr->mime_type_size], mdpr->type_specific_len); @@ -308,6 +327,13 @@ static mdpr_t *real_parse_mdpr(const char *data) { #endif return mdpr; + +fail: + free (mdpr->stream_name); + free (mdpr->mime_type); + free (mdpr->type_specific_data); + free (mdpr); + return NULL; } static void real_free_mdpr (mdpr_t *mdpr) { @@ -318,9 +344,15 @@ static void real_free_mdpr (mdpr_t *mdpr) { } static void real_parse_audio_specific_data (demux_real_t *this, - real_stream_t * stream, - uint8_t * data) + real_stream_t * stream) { + if (stream->mdpr->type_specific_len < 46) { + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + "demux_real: audio data size smaller than header length!\n"); + return; + } + + uint8_t * data = stream->mdpr->type_specific_data; const uint32_t coded_frame_size = _X_BE_32 (data+24); const uint16_t codec_data_length = _X_BE_16 (data+40); const uint16_t coded_frame_size2 = _X_BE_16 (data+42); @@ -359,9 +391,14 @@ static void real_parse_audio_specific_data (demux_real_t *this, * stream->frame_size = stream->w / stream->sps * stream->h * stream->sps; * but it looks pointless? the compiler will probably optimise it away, I suppose? */ - stream->frame_size = stream->w * stream->h; + if (stream->w < 32768 && stream->h < 32768) { + stream->frame_size = stream->w * stream->h; + stream->frame_buffer = calloc(stream->frame_size, 1); + } else { + stream->frame_size = 0; + stream->frame_buffer = NULL; + } - stream->frame_buffer = calloc(stream->frame_size, 1); stream->frame_num_bytes = 0; stream->sub_packet_cnt = 0; @@ -430,9 +467,14 @@ static void real_parse_headers (demux_real_t *this) { case MDPR_TAG: case CONT_TAG: { + if (chunk_size < PREAMBLE_SIZE+1) { + this->status = DEMUX_FINISHED; + return; + } chunk_size -= PREAMBLE_SIZE; uint8_t *const chunk_buffer = malloc(chunk_size); - if (this->input->read(this->input, chunk_buffer, chunk_size) != + if (! chunk_buffer || + this->input->read(this->input, chunk_buffer, chunk_size) != chunk_size) { free (chunk_buffer); this->status = DEMUX_FINISHED; @@ -475,9 +517,14 @@ static void real_parse_headers (demux_real_t *this) { continue; } - mdpr_t *const mdpr = real_parse_mdpr (chunk_buffer); + mdpr_t *const mdpr = real_parse_mdpr (chunk_buffer, chunk_size); lprintf ("parsing type specific data...\n"); + if (!mdpr) { + free (chunk_buffer); + this->status = DEMUX_FINISHED; + return; + } if(!strcmp(mdpr->mime_type, "audio/X-MP3-draft-00")) { lprintf ("mpeg layer 3 audio detected...\n"); @@ -487,7 +534,8 @@ static void real_parse_headers (demux_real_t *this) { this->audio_streams[this->num_audio_streams].index = NULL; this->audio_streams[this->num_audio_streams].mdpr = mdpr; this->num_audio_streams++; - } else if(_X_BE_32(mdpr->type_specific_data) == RA_TAG) { + } else if(_X_BE_32(mdpr->type_specific_data) == RA_TAG && + mdpr->type_specific_len >= 6) { if(this->num_audio_streams == MAX_AUDIO_STREAMS) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_real: maximum number of audio stream exceeded\n"); @@ -498,26 +546,30 @@ static void real_parse_headers (demux_real_t *this) { lprintf("audio version %d detected\n", version); - char *fourcc_ptr = NULL; + char *fourcc_ptr = "\0\0\0"; switch(version) { case 3: /* Version 3 header stores fourcc after meta info - cheat by reading backwards from the * end of the header instead of having to parse it all */ - fourcc_ptr = mdpr->type_specific_data + mdpr->type_specific_len - 5; + if (mdpr->type_specific_len >= 5) + fourcc_ptr = mdpr->type_specific_data + mdpr->type_specific_len - 5; break; case 4: { - const uint8_t len = *(mdpr->type_specific_data + 56); - fourcc_ptr = mdpr->type_specific_data + 58 + len; + if (mdpr->type_specific_len >= 57) { + const uint8_t len = *(mdpr->type_specific_data + 56); + if (mdpr->type_specific_len >= 62 + len) + fourcc_ptr = mdpr->type_specific_data + 58 + len; + } } break; case 5: - fourcc_ptr = mdpr->type_specific_data + 66; + if (mdpr->type_specific_len >= 70) + fourcc_ptr = mdpr->type_specific_data + 66; break; default: lprintf("unsupported audio header version %d\n", version); goto unknown; } - lprintf("fourcc = %.4s\n", fourcc_ptr); const uint32_t fourcc = _X_ME_32(fourcc_ptr); @@ -528,11 +580,11 @@ static void real_parse_headers (demux_real_t *this) { this->audio_streams[this->num_audio_streams].mdpr = mdpr; real_parse_audio_specific_data (this, - &this->audio_streams[this->num_audio_streams], - mdpr->type_specific_data); + &this->audio_streams[this->num_audio_streams]); this->num_audio_streams++; - } else if(_X_BE_32(mdpr->type_specific_data + 4) == VIDO_TAG) { + } else if(_X_BE_32(mdpr->type_specific_data + 4) == VIDO_TAG && + mdpr->type_specific_len >= 34) { if(this->num_video_streams == MAX_VIDEO_STREAMS) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, diff --git a/src/demuxers/demux_realaudio.c b/src/demuxers/demux_realaudio.c index 1c39c6208..44449667c 100644 --- a/src/demuxers/demux_realaudio.c +++ b/src/demuxers/demux_realaudio.c @@ -202,11 +202,19 @@ static int open_ra_file(demux_ra_t *this) { this->h = _X_BE_16 (this->header+40); this->cfs = _X_BE_32 (this->header+24); - this->frame_len = this->w * this->h; - this->frame_size = this->frame_len * sps; - - this->frame_buffer = calloc(this->frame_size, 1); - _x_assert(this->frame_buffer != NULL); + if (this->w < 0x8000 && this->h < 0x8000) { + uint64_t fs; + this->frame_len = this->w * this->h; + fs = (uint64_t) this->frame_len * sps; + if (fs < 0x80000000) { + this->frame_size = fs; + this->frame_buffer = calloc(this->frame_size, 1); + } + } + if (! this->frame_buffer) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: malloc failed\n"); + return 0; + } if (this->audio_type == BUF_AUDIO_28_8 || this->audio_type == BUF_AUDIO_SIPRO) this->block_align = this->cfs; diff --git a/src/demuxers/demux_shn.c b/src/demuxers/demux_shn.c index 4d932305c..ccc34b57f 100644 --- a/src/demuxers/demux_shn.c +++ b/src/demuxers/demux_shn.c @@ -88,7 +88,7 @@ static int demux_shn_send_chunk(demux_plugin_t *this_gen) { buf->pts = 0; bytes_read = this->input->read(this->input, buf->content, buf->max_size); - if (bytes_read == 0) { + if (bytes_read <= 0) { buf->free_buffer(buf); this->status = DEMUX_FINISHED; return this->status; diff --git a/src/demuxers/demux_slave.c b/src/demuxers/demux_slave.c index 28a89a973..abb4d01e5 100644 --- a/src/demuxers/demux_slave.c +++ b/src/demuxers/demux_slave.c @@ -90,10 +90,11 @@ static int demux_slave_next (demux_slave_t *this) { /* fill the scratch buffer */ n = this->input->read(this->input, &this->scratch[this->scratch_used], SCRATCH_SIZE - this->scratch_used); - this->scratch_used += n; + if (n > 0) + this->scratch_used += n; this->scratch[this->scratch_used] = '\0'; - if( !n ) { + if (n <= 0) { lprintf("connection closed\n"); this->status = DEMUX_FINISHED; return 0; diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c index 55e06c033..e52c4c765 100644 --- a/src/demuxers/demux_ts.c +++ b/src/demuxers/demux_ts.c @@ -33,6 +33,11 @@ * Date Author * ---- ------ * + * 8-Apr-2009 Petri Hintukainen <phi@sdf-eu.org> + * - support for 192-byte packets (HDMV/BluRay) + * - support for audio inside PES PID 0xfd (HDMV/BluRay) + * - demux HDMV/BluRay bitmap subtitles + * * 28-Nov-2004 Mike Lampard <mlampard> * - Added support for PMT sections larger than 1 ts packet * @@ -172,9 +177,9 @@ #define SYNC_BYTE 0x47 #define MIN_SYNCS 3 -#define NPKT_PER_READ 100 +#define NPKT_PER_READ 96 // 96*188 = 94*192 -#define BUF_SIZE (NPKT_PER_READ * PKT_SIZE) +#define BUF_SIZE (NPKT_PER_READ * (PKT_SIZE + 4)) #define MAX_PES_BUF_SIZE 2048 @@ -218,8 +223,9 @@ ISO_14496_PART2_VIDEO = 0x10, /* ISO/IEC 14496-2 Visual (MPEG-4) */ ISO_14496_PART3_AUDIO = 0x11, /* ISO/IEC 14496-3 Audio with LATM transport syntax */ ISO_14496_PART10_VIDEO = 0x1b, /* ISO/IEC 14496-10 Video (MPEG-4 part 10/AVC, aka H.264) */ - STREAM_VIDEO_MPEG = 0x80, - STREAM_AUDIO_AC3 = 0x81, + STREAM_VIDEO_MPEG = 0x80, + STREAM_AUDIO_AC3 = 0x81, + STREAM_SPU_BITMAP_HDMV = 0x90, } streamType; #define WRAP_THRESHOLD 270000 @@ -227,6 +233,11 @@ #define PTS_AUDIO 0 #define PTS_VIDEO 1 +#undef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#undef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) + /* ** ** DATA STRUCTURES @@ -288,6 +299,10 @@ typedef struct { int status; + int hdmv; /* -1 = unknown, 0 = mpeg-ts, 1 = hdmv/m2ts */ + int pkt_size; /* TS packet size */ + int pkt_offset; /* TS packet offset */ + int blockSize; int rate; int media_num; @@ -446,12 +461,12 @@ static void check_newpts( demux_ts_t *this, int64_t pts, int video ) } /* Send a BUF_SPU_DVB to let xine know of that channel. */ -static void demux_send_special_spu_buf( demux_ts_t *this, int spu_channel ) +static void demux_send_special_spu_buf( demux_ts_t *this, uint32_t spu_type, int spu_channel ) { buf_element_t *buf; buf = this->video_fifo->buffer_pool_alloc( this->video_fifo ); - buf->type = BUF_SPU_DVB|spu_channel; + buf->type = spu_type|spu_channel; buf->content = buf->mem; buf->size = 0; this->video_fifo->put( this->video_fifo, buf ); @@ -504,6 +519,10 @@ static void demux_ts_update_spu_channel(demux_ts_t *this) #endif } + if ((this->media[this->spu_media].type & BUF_MAJOR_MASK) == BUF_SPU_HDMV) { + buf->type = BUF_SPU_HDMV; + } + this->video_fifo->put(this->video_fifo, buf); } @@ -741,7 +760,18 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m, p += header_len + 9; packet_len -= header_len + 3; - if (stream_id == 0xbd) { + if (m->descriptor_tag == STREAM_SPU_BITMAP_HDMV) { + long payload_len = ((buf[4] << 8) | buf[5]) - header_len - 3; + + m->content = p; + m->size = packet_len; + m->type |= BUF_SPU_HDMV; + m->buf->decoder_info[2] = payload_len; + return 1; + + } else + + if (stream_id == 0xbd || stream_id == 0xfd /* HDMV */) { int spu_id; @@ -1413,7 +1443,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num lang->media_index = this->media_num; this->media[this->media_num].type = no; demux_ts_pes_new(this, this->media_num, pid, this->video_fifo, stream[0]); - demux_send_special_spu_buf( this, no ); + demux_send_special_spu_buf( this, BUF_SPU_DVB, no ); #ifdef TS_LOG printf("demux_ts: DVBSUB: pid 0x%.4x: %s page %ld %ld type %2.2x\n", pid, lang->desc.lang, @@ -1426,6 +1456,29 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num } break; + case STREAM_SPU_BITMAP_HDMV: + if (this->hdmv > 0) { + if (pid >= 0x1200 && pid < 0x1300) { + /* HDMV Presentation Graphics / SPU */ + demux_ts_spu_lang *lang = &this->spu_langs[this->spu_langs_count]; + + memset(lang->desc.lang, 0, sizeof(lang->desc.lang)); + /*memcpy(lang->desc.lang, &stream[pos], 3);*/ + /*lang->desc.lang[3] = 0;*/ + lang->pid = pid; + lang->media_index = this->media_num; + this->media[this->media_num].type = this->spu_langs_count; + demux_ts_pes_new(this, this->media_num, pid, this->video_fifo, stream[0]); + demux_send_special_spu_buf( this, BUF_SPU_HDMV, this->spu_langs_count ); + this->spu_langs_count++; +#ifdef TS_PMT_LOG + printf("demux_ts: HDMV subtitle stream_type: 0x%.2x pid: 0x%.4x\n", + stream[0], pid); +#endif + break; + } + } + /* fall thru */ default: /* This following section handles all the cases where the audio track info is stored in PMT user info with stream id >= 0x80 @@ -1512,10 +1565,10 @@ static int sync_correct(demux_ts_t*this, uint8_t *buf, int32_t npkt_read) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: about to resync!\n"); for (p=0; p < npkt_read; p++) { - for(n=0; n < PKT_SIZE; n++) { + for(n=0; n < this->pkt_size; n++) { sync_ok = 1; for (i=0; i < MIN(MIN_SYNCS, npkt_read - p); i++) { - if (buf[n + ((i+p) * PKT_SIZE)] != SYNC_BYTE) { + if (buf[this->pkt_offset + n + ((i+p) * this->pkt_size)] != SYNC_BYTE) { sync_ok = 0; break; } @@ -1527,13 +1580,13 @@ static int sync_correct(demux_ts_t*this, uint8_t *buf, int32_t npkt_read) { if (sync_ok) { /* Found sync, fill in */ - memmove(&buf[0], &buf[n + p * PKT_SIZE], - ((PKT_SIZE * (npkt_read - p)) - n)); + memmove(&buf[0], &buf[n + p * this->pkt_size], + ((this->pkt_size * (npkt_read - p)) - n)); read_length = this->input->read(this->input, - &buf[(PKT_SIZE * (npkt_read - p)) - n], - n + p * PKT_SIZE); + &buf[(this->pkt_size * (npkt_read - p)) - n], + n + p * this->pkt_size); /* FIXME: when read_length is not as required... we now stop demuxing */ - if (read_length != (n + p * PKT_SIZE)) { + if (read_length != (n + p * this->pkt_size)) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts_tsync_correct: sync found, but read failed\n"); return 0; @@ -1552,6 +1605,32 @@ static int sync_detect(demux_ts_t*this, uint8_t *buf, int32_t npkt_read) { sync_ok = 1; + if (this->hdmv) { + this->pkt_size = PKT_SIZE + 4; + this->pkt_offset = 4; + for (i=0; i < MIN(MIN_SYNCS, npkt_read - 3); i++) { + if (buf[this->pkt_offset + i * this->pkt_size] != SYNC_BYTE) { + sync_ok = 0; + break; + } + } + if (sync_ok) { + if (this->hdmv < 0) { + /* fix npkt_read (packet size is 192, not 188) */ + this->npkt_read = npkt_read * PKT_SIZE / this->pkt_size; + } + this->hdmv = 1; + return sync_ok; + } + if (this->hdmv > 0) + return sync_correct(this, buf, npkt_read); + + /* plain ts */ + this->hdmv = 0; + this->pkt_size = PKT_SIZE; + this->pkt_offset = 0; + } + for (i=0; i < MIN(MIN_SYNCS, npkt_read); i++) { if (buf[i * PKT_SIZE] != SYNC_BYTE) { sync_ok = 0; @@ -1575,15 +1654,15 @@ static unsigned char * demux_synchronise(demux_ts_t* this) { /* NEW: handle read returning less packets than NPKT_PER_READ... */ do { read_length = this->input->read(this->input, this->buf, - PKT_SIZE * NPKT_PER_READ); - if (read_length % PKT_SIZE) { + this->pkt_size * NPKT_PER_READ); + if (read_length < 0 || read_length % this->pkt_size) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: read returned %d bytes (not a multiple of %d!)\n", - read_length, PKT_SIZE); + read_length, this->pkt_size); this->status = DEMUX_FINISHED; return NULL; } - this->npkt_read = read_length / PKT_SIZE; + this->npkt_read = read_length / this->pkt_size; #ifdef TS_READ_STATS this->rstat[this->npkt_read]++; @@ -1610,7 +1689,7 @@ static unsigned char * demux_synchronise(demux_ts_t* this) { return NULL; } } - return_pointer = &(this->buf)[PKT_SIZE * this->packet_number]; + return_pointer = &(this->buf)[this->pkt_offset + this->pkt_size * this->packet_number]; this->packet_number++; return return_pointer; } @@ -1758,7 +1837,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) { /* * Discard packets that are obviously bad. */ - if (sync_byte != 0x47) { + if (sync_byte != SYNC_BYTE) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux error! invalid ts sync byte %.2x\n", sync_byte); return; @@ -2170,6 +2249,32 @@ static int demux_ts_get_optional_data(demux_plugin_t *this_gen, } } +static int detect_ts(uint8_t *buf, size_t len, int ts_size) +{ + int i, j; + int try_again, ts_detected = 0; + size_t packs = len / ts_size - 2; + + for (i = 0; i < ts_size; i++) { + try_again = 0; + if (buf[i] == SYNC_BYTE) { + for (j = 1; j < packs; j++) { + if (buf[i + j*ts_size] != SYNC_BYTE) { + try_again = 1; + break; + } + } + if (try_again == 0) { +#ifdef TS_LOG + printf ("demux_ts: found 0x47 pattern at offset %d\n", i); +#endif + ts_detected = 1; + } + } + } + + return ts_detected; +} static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, @@ -2177,38 +2282,21 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, demux_ts_t *this; int i; + int hdmv = -1; switch (stream->content_detection_method) { case METHOD_BY_CONTENT: { uint8_t buf[2069]; - int i, j; - int try_again, ts_detected; - if (!_x_demux_read_header(input, buf, 2069)) + if (!_x_demux_read_header(input, buf, sizeof(buf))) return NULL; - ts_detected = 0; - - for (i = 0; i < 188; i++) { - try_again = 0; - if (buf[i] == 0x47) { - for (j = 1; j <= 10; j++) { - if (buf[i + j*188] != 0x47) { - try_again = 1; - break; - } - } - if (try_again == 0) { -#ifdef TS_LOG - printf ("demux_ts: found 0x47 pattern at offset %d\n", i); -#endif - ts_detected = 1; - } - } - } - - if (!ts_detected) + if (detect_ts(buf, sizeof(buf), PKT_SIZE)) + hdmv = 0; + else if (detect_ts(buf, sizeof(buf), PKT_SIZE+4)) + hdmv = 1; + else return NULL; } break; @@ -2216,6 +2304,11 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, case METHOD_BY_EXTENSION: { const char *const mrl = input->get_mrl (input); + if (_x_demux_check_extension (mrl, "m2ts mts")) + hdmv = 1; + else + hdmv = 0; + /* check extension */ const char *const extensions = class_gen->get_extensions (class_gen); @@ -2301,7 +2394,12 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, /* dvb */ this->event_queue = xine_event_new_queue (this->stream); - + + /* HDMV */ + this->hdmv = hdmv; + this->pkt_offset = (hdmv > 0) ? 4 : 0; + this->pkt_size = PKT_SIZE + this->pkt_offset; + this->numPreview=0; return &this->demux_plugin; diff --git a/src/demuxers/demux_tta.c b/src/demuxers/demux_tta.c index 68305a444..7853c8182 100644 --- a/src/demuxers/demux_tta.c +++ b/src/demuxers/demux_tta.c @@ -21,6 +21,10 @@ * Inspired by tta libavformat demuxer by Alex Beregszaszi */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define LOG_MODULE "demux_tta" #define LOG_VERBOSE @@ -54,7 +58,7 @@ typedef struct { uint32_t samplerate; uint32_t data_length; uint32_t crc32; - } __attribute__((__packed__)) tta; + } XINE_PACKED tta; uint8_t buffer[22]; /* This is the size of the header */ } header; } demux_tta_t; @@ -126,6 +130,10 @@ static int demux_tta_send_chunk(demux_plugin_t *this_gen) { /* buf->extra_info->input_time = this->current_sample / this->samplerate; */ bytes_read = this->input->read(this->input, buf->content, ( bytes_to_read > buf->max_size ) ? buf->max_size : bytes_to_read); + if (bytes_read < 0) { + this->status = DEMUX_FINISHED; + break; + } buf->size = bytes_read; diff --git a/src/demuxers/demux_vox.c b/src/demuxers/demux_vox.c index d646a756f..1b34106ad 100644 --- a/src/demuxers/demux_vox.c +++ b/src/demuxers/demux_vox.c @@ -77,7 +77,7 @@ static int demux_vox_send_chunk (demux_plugin_t *this_gen) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = BUF_AUDIO_DIALOGIC_IMA; bytes_read = this->input->read(this->input, buf->content, buf->max_size); - if (bytes_read == 0) { + if (bytes_read <= 0) { buf->free_buffer(buf); this->status = DEMUX_FINISHED; return this->status; diff --git a/src/demuxers/demux_wav.c b/src/demuxers/demux_wav.c index 5fbec7b69..99c50ad67 100644 --- a/src/demuxers/demux_wav.c +++ b/src/demuxers/demux_wav.c @@ -66,6 +66,7 @@ typedef struct { off_t data_start; off_t data_size; + int send_newpts; int seek_flag; /* this is set when a seek just occurred */ } demux_wav_t; @@ -186,9 +187,9 @@ static int demux_wav_send_chunk(demux_plugin_t *this_gen) { current_pts *= 90000; current_pts /= this->wave->nAvgBytesPerSec; - if (this->seek_flag) { - _x_demux_control_newpts(this->stream, current_pts, BUF_FLAG_SEEK); - this->seek_flag = 0; + if (this->send_newpts) { + _x_demux_control_newpts(this->stream, current_pts, this->seek_flag); + this->send_newpts = this->seek_flag = 0; } while (remaining_sample_bytes) { @@ -209,11 +210,16 @@ static int demux_wav_send_chunk(demux_plugin_t *this_gen) { buf->size = remaining_sample_bytes; remaining_sample_bytes -= buf->size; - if (this->input->read(this->input, buf->content, buf->size) != + off_t read; + if ((read = this->input->read(this->input, buf->content, buf->size)) != buf->size) { - buf->free_buffer(buf); - this->status = DEMUX_FINISHED; - break; + if (read == 0) { + buf->free_buffer(buf); + this->status = DEMUX_FINISHED; + break; + } else { + buf->size = read; + } } #if 0 @@ -284,10 +290,13 @@ static int demux_wav_seek (demux_plugin_t *this_gen, start_pos = (off_t) ( (double) start_pos / 65535 * this->data_size ); - this->seek_flag = 1; this->status = DEMUX_OK; - _x_demux_flush_engine (this->stream); + this->send_newpts = 1; + if (playing) { + this->seek_flag = 1; + _x_demux_flush_engine (this->stream); + } /* if input is non-seekable, do not proceed with the rest of this * seek function */ if (!INPUT_IS_SEEKABLE(this->input)) diff --git a/src/demuxers/demux_yuv_frames.c b/src/demuxers/demux_yuv_frames.c index c5ca363ed..089207f58 100644 --- a/src/demuxers/demux_yuv_frames.c +++ b/src/demuxers/demux_yuv_frames.c @@ -126,13 +126,19 @@ static void demux_yuv_frames_send_headers (demux_plugin_t *this_gen){ if(_x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_AUDIO)) { buf = this->input->read_block(this->input, this->audio_fifo, 0); - this->audio_fifo->put(this->audio_fifo, buf); + if (buf) + this->audio_fifo->put(this->audio_fifo, buf); + else + this->status = DEMUX_FINISHED; } if(_x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_VIDEO)) { buf = this->input->read_block(this->input, this->video_fifo, 0); - this->video_fifo->put(this->video_fifo, buf); + if (buf) + this->video_fifo->put(this->video_fifo, buf); + else + this->status = DEMUX_FINISHED; } this->status = DEMUX_OK; diff --git a/src/demuxers/id3.c b/src/demuxers/id3.c index ba8f50676..070ca2650 100644 --- a/src/demuxers/id3.c +++ b/src/demuxers/id3.c @@ -241,7 +241,7 @@ static int id3v2_parse_header(input_plugin_t *input, uint8_t *mp3_frame_header, lprintf("tag: ID3 v2.%d.%d\n", mp3_frame_header[3], tag_header->revision); lprintf("flags: %d\n", tag_header->flags); - lprintf("size: %d\n", tag_header->size); + lprintf("size: %zu\n", tag_header->size); return 1; } else { return 0; @@ -259,9 +259,9 @@ static int id3v22_parse_frame_header(input_plugin_t *input, if (len == ID3V22_FRAME_HEADER_SIZE) { frame_header->id = (buf[0] << 16) + (buf[1] << 8) + buf[2]; - frame_header->size = _X_BE_24_synchsafe(&buf[3]); + frame_header->size = _X_BE_24(&buf[3]); - lprintf("frame: %c%c%c: size: %d\n", buf[0], buf[1], buf[2], + lprintf("frame: %c%c%c: size: %zu\n", buf[0], buf[1], buf[2], frame_header->size); return 1; @@ -275,8 +275,8 @@ static int id3v22_interp_frame(input_plugin_t *input, id3v22_frame_header_t *frame_header) { char *buf; int enc; - const size_t bufsize = frame_header->size +1; - if ( bufsize <= 2 ) /* frames has to be _at least_ 1 byte */ + const size_t bufsize = frame_header->size + 2; + if ( bufsize < 3 ) /* frames has to be _at least_ 1 byte */ return 0; buf = malloc(bufsize); @@ -286,6 +286,8 @@ static int id3v22_interp_frame(input_plugin_t *input, } if (input->read (input, buf, frame_header->size) == frame_header->size) { + buf[frame_header->size] = 0; + buf[frame_header->size + 1] = 0; enc = buf[0]; if( enc >= ID3_ENCODING_COUNT ) enc = 0; @@ -373,7 +375,7 @@ static int id3v22_parse_tag(input_plugin_t *input, while ((pos + ID3V22_FRAME_HEADER_SIZE) <= tag_header.size) { if (id3v22_parse_frame_header(input, &tag_frame_header)) { pos += ID3V22_FRAME_HEADER_SIZE; - if (tag_frame_header.id && tag_frame_header.size) { + if (tag_frame_header.id) { if ((pos + tag_frame_header.size) <= tag_header.size) { if (!id3v22_interp_frame(input, stream, &tag_frame_header)) { xprintf(stream->xine, XINE_VERBOSITY_DEBUG, @@ -417,7 +419,7 @@ static int id3v23_parse_frame_header(input_plugin_t *input, frame_header->size = _X_BE_32(&buf[4]); frame_header->flags = _X_BE_16(buf + 8); - lprintf("frame: %c%c%c%c, size: %d, flags: %X\n", buf[0], buf[1], buf[2], buf[3], + lprintf("frame: %c%c%c%c, size: %zu, flags: %X\n", buf[0], buf[1], buf[2], buf[3], frame_header->size, frame_header->flags); return 1; @@ -432,7 +434,7 @@ static int id3v23_parse_frame_ext_header(input_plugin_t *input, if (input->read (input, buf, 4) == 4) { - frame_ext_header->size = _X_BE_32_synchsafe(&buf[0]); + frame_ext_header->size = _X_BE_32(&buf[0]); if (frame_ext_header->size == 6) { if (input->read (input, buf + 4, 6) == 6) { @@ -453,11 +455,11 @@ static int id3v23_parse_frame_ext_header(input_plugin_t *input, } } else { - lprintf("invalid ext header size: %d\n", frame_ext_header->size); + lprintf("invalid ext header size: %zu\n", frame_ext_header->size); return 0; } - lprintf("ext header: size: %d, flags: %X, padding_size: %d, crc: %d\n", + lprintf("ext header: size: %zu, flags: %X, padding_size: %d, crc: %d\n", frame_ext_header->size, frame_ext_header->flags, frame_ext_header->padding_size, frame_ext_header->crc); return 1; @@ -471,8 +473,8 @@ static int id3v23_interp_frame(input_plugin_t *input, id3v23_frame_header_t *frame_header) { char *buf; int enc; - const size_t bufsize = frame_header->size +1; - if ( bufsize <= 2 ) /* frames has to be _at least_ 1 byte */ + const size_t bufsize = frame_header->size + 2; + if ( bufsize < 3 ) /* frames has to be _at least_ 1 byte */ return 0; buf = malloc(bufsize); @@ -483,6 +485,7 @@ static int id3v23_interp_frame(input_plugin_t *input, if (input->read (input, buf, frame_header->size) == frame_header->size) { buf[frame_header->size] = 0; + buf[frame_header->size + 1] = 0; enc = buf[0]; if( enc >= ID3_ENCODING_COUNT ) enc = 0; @@ -570,7 +573,7 @@ static int id3v23_parse_tag(input_plugin_t *input, while ((pos + ID3V23_FRAME_HEADER_SIZE) <= tag_header.size) { if (id3v23_parse_frame_header(input, &tag_frame_header)) { pos += ID3V23_FRAME_HEADER_SIZE; - if (tag_frame_header.id && tag_frame_header.size) { + if (tag_frame_header.id) { if ((pos + tag_frame_header.size) <= tag_header.size) { if (!id3v23_interp_frame(input, stream, &tag_frame_header)) { xprintf(stream->xine, XINE_VERBOSITY_DEBUG, @@ -585,7 +588,7 @@ static int id3v23_parse_tag(input_plugin_t *input, pos += tag_frame_header.size; } else { /* end of frames, the rest is padding */ - lprintf("skipping padding %d bytes\n", tag_header.size - pos); + lprintf("skipping padding %zu bytes\n", tag_header.size - pos); input->seek (input, tag_header.size - pos, SEEK_CUR); return 1; } @@ -628,10 +631,10 @@ static int id3v24_parse_frame_header(input_plugin_t *input, len = input->read (input, buf, ID3V24_FRAME_HEADER_SIZE); if (len == ID3V24_FRAME_HEADER_SIZE) { frame_header->id = _X_BE_32(buf); - frame_header->size = _X_BE_32_synchsafe(&buf[4]); + frame_header->size = _X_BE_32(&buf[4]); frame_header->flags = _X_BE_16(&buf[8]); - lprintf("frame: %c%c%c%c, size: %d, flags: %X\n", buf[0], buf[1], buf[2], buf[3], + lprintf("frame: %c%c%c%c, size: %zu, flags: %X\n", buf[0], buf[1], buf[2], buf[3], frame_header->size, frame_header->flags); return 1; @@ -646,7 +649,7 @@ static int id3v24_parse_ext_header(input_plugin_t *input, if (input->read (input, buf, 4) == 4) { - frame_ext_header->size = _X_BE_32_synchsafe(&buf[0]); + frame_ext_header->size = _X_BE_32(&buf[0]); if (input->read (input, buf, 2) == 2) { uint8_t flags_size = buf[0]; @@ -711,7 +714,7 @@ static int id3v24_parse_ext_header(input_plugin_t *input, } else { return 0; } - lprintf("ext header: size: %d, flags: %X, crc: %d, restrictions: %8X\n", + lprintf("ext header: size: %zu, flags: %X, crc: %d, restrictions: %8X\n", frame_ext_header->size, frame_ext_header->flags, frame_ext_header->crc, frame_ext_header->restrictions); return 1; @@ -725,8 +728,8 @@ static int id3v24_interp_frame(input_plugin_t *input, id3v24_frame_header_t *frame_header) { char *buf; int enc; - const size_t bufsize = frame_header->size +1; - if ( bufsize <= 2 ) /* frames has to be _at least_ 1 byte */ + const size_t bufsize = frame_header->size + 2; + if ( bufsize < 3 ) /* frames has to be _at least_ 1 byte */ return 0; buf = malloc(bufsize); @@ -737,6 +740,7 @@ static int id3v24_interp_frame(input_plugin_t *input, if (input->read (input, buf, frame_header->size) == frame_header->size) { buf[frame_header->size] = 0; + buf[frame_header->size + 1] = 0; enc = buf[0]; if( enc >= ID3_ENCODING_COUNT ) enc = 0; @@ -826,7 +830,7 @@ static int id3v24_parse_tag(input_plugin_t *input, while ((pos + ID3V24_FRAME_HEADER_SIZE) <= tag_header.size) { if (id3v24_parse_frame_header(input, &tag_frame_header)) { pos += ID3V24_FRAME_HEADER_SIZE; - if (tag_frame_header.id && tag_frame_header.size) { + if (tag_frame_header.id) { if ((pos + tag_frame_header.size) <= tag_header.size) { if (!id3v24_interp_frame(input, stream, &tag_frame_header)) { xprintf(stream->xine, XINE_VERBOSITY_DEBUG, diff --git a/src/demuxers/matroska.h b/src/demuxers/matroska.h index 23af84af0..b32725b3b 100644 --- a/src/demuxers/matroska.h +++ b/src/demuxers/matroska.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2007 the xine project + * Copyright (C) 2000-2009 the xine project * * This file is part of xine, a free video player. * @@ -16,6 +16,8 @@ * 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 + * + * Matroska EBML stream handling */ #ifndef MATROSKA_H #define MATROSKA_H @@ -62,6 +64,7 @@ #define MATROSKA_ID_CL_BLOCKGROUP 0xA0 #define MATROSKA_ID_CL_BLOCK 0xA1 #define MATROSKA_ID_CL_BLOCKVIRTUAL 0xA2 +#define MATROSKA_ID_CL_SIMPLEBLOCK 0xA3 #define MATROSKA_ID_CL_BLOCKADDITIONS 0x75A1 #define MATROSKA_ID_CL_BLOCKMORE 0xA6 #define MATROSKA_ID_CL_BLOCKADDID 0xEE @@ -168,10 +171,16 @@ /* Chapters */ #define MATROSKA_ID_CHAPTERS 0x1043A770 #define MATROSKA_ID_CH_EDITIONENTRY 0x45B9 +#define MATROSKA_ID_CH_ED_UID 0x45BC +#define MATROSKA_ID_CH_ED_HIDDEN 0x45BD +#define MATROSKA_ID_CH_ED_DEFAULT 0x45DB +#define MATROSKA_ID_CH_ED_ORDERED 0x45DD #define MATROSKA_ID_CH_ATOM 0xB6 #define MATROSKA_ID_CH_UID 0x73C4 #define MATROSKA_ID_CH_TIMESTART 0x91 #define MATROSKA_ID_CH_TIMEEND 0x92 +#define MATROSKA_ID_CH_HIDDEN 0x98 +#define MATROSKA_ID_CH_ENABLED 0x4598 #define MATROSKA_ID_CH_TRACK 0x8F #define MATROSKA_ID_CH_TRACKNUMBER 0x89 #define MATROSKA_ID_CH_DISPLAY 0x80 @@ -182,6 +191,46 @@ /* Tags */ #define MATROSKA_ID_TAGS 0x1254C367 +/* Chapter (used in tracks) */ +typedef struct { + uint64_t uid; + uint64_t time_start; + uint64_t time_end; + /* if not 0, the chapter could e.g. be used for skipping, but not + * be shown in the chapter list */ + int hidden; + /* disabled chapters should be skipped during playback (using this + * would require parsing control blocks) */ + int enabled; + /* Tracks this chapter belongs to. + * Remember that elements can occur in any order, so in theory the + * chapters could become available before the tracks do. + * TODO: currently unused + */ + /* uint64_t* tracks; */ + /* Chapter titles and locale information + * TODO: chapters can have multiple sets of those, i.e. several tuples + * (title, language, country). The current implementation picks from + * those by the following rules: + * 1) remember the first element + * 2) overwrite with an element where language=="eng" + */ + char* title; + char* language; + char* country; +} matroska_chapter_t; + +/* Edition */ +typedef struct { + uint64_t uid; + unsigned int hidden; + unsigned int is_default; + unsigned int ordered; + + int num_chapters, cap_chapters; + matroska_chapter_t** chapters; +} matroska_edition_t; + /* Matroska Track */ typedef struct { int flag_interlaced; @@ -213,7 +262,8 @@ typedef struct { typedef struct matroska_track_s matroska_track_t; struct matroska_track_s { int track_num; - + uint64_t uid; + uint32_t track_type; uint64_t default_duration; char *language; diff --git a/src/dxr3/Makefile.am b/src/dxr3/Makefile.am index f1a61ce12..3c2cbafbc 100644 --- a/src/dxr3/Makefile.am +++ b/src/dxr3/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_CFLAGS = $(X_CFLAGS) $(LIBFAME_CFLAGS) diff --git a/src/dxr3/dxr3_decode_spu.c b/src/dxr3/dxr3_decode_spu.c index 1fe2373b4..82c8f8da0 100644 --- a/src/dxr3/dxr3_decode_spu.c +++ b/src/dxr3/dxr3_decode_spu.c @@ -17,6 +17,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* dxr3 spu decoder plugin. * Accepts the spu data from xine and sends it directly to the diff --git a/src/dxr3/dxr3_decode_video.c b/src/dxr3/dxr3_decode_video.c index 496ef143e..e68ba2b5c 100644 --- a/src/dxr3/dxr3_decode_video.c +++ b/src/dxr3/dxr3_decode_video.c @@ -17,6 +17,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* dxr3 video decoder plugin. * Accepts the video data from xine and sends it directly to the diff --git a/src/dxr3/video_out_dxr3.c b/src/dxr3/video_out_dxr3.c index 3e7c9ab08..189824183 100644 --- a/src/dxr3/video_out_dxr3.c +++ b/src/dxr3/video_out_dxr3.c @@ -21,7 +21,7 @@ /* mpeg1 encoding video out plugin for the dxr3. * * modifications to the original dxr3 video out plugin by - * Mike Lampard <mike at web2u.com.au> + * Mike Lampard <mlampard at users.sourceforge.net> * this first standalone version by * Harm van der Heijden <hrm at users.sourceforge.net> */ diff --git a/src/input/Makefile.am b/src/input/Makefile.am index 81dd62eca..998fc6c81 100644 --- a/src/input/Makefile.am +++ b/src/input/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common EXTRA_DIST = input_dvd.c input_vcd.c input_gnome_vfs.c input_rtp.c @@ -45,6 +46,9 @@ endif if WIN32 else in_rtp = xineplug_inp_rtp.la +endif + +if DVB in_dvb = xineplug_inp_dvb.la endif diff --git a/src/input/http_helper.c b/src/input/http_helper.c index 279d3ff05..db93b9b45 100644 --- a/src/input/http_helper.c +++ b/src/input/http_helper.c @@ -29,8 +29,18 @@ #include "xine_internal.h" #include "http_helper.h" + +const char *_x_url_user_agent (const char *url) +{ + if (!strncasecmp (url, "qthttp://", 9)) + return "QuickTime"; /* needed for Apple trailers */ + return NULL; +} + int _x_parse_url (char *url, char **proto, char** host, int *port, - char **user, char **password, char **uri) { + char **user, char **password, char **uri, + const char **user_agent) +{ char *start = NULL; char *authcolon = NULL; char *at = NULL; @@ -63,6 +73,9 @@ int _x_parse_url (char *url, char **proto, char** host, int *port, end = start + strlen(start) - 1; *proto = strndup(url, start - url); + if (user_agent) + *user_agent = _x_url_user_agent (url); + /* user:password */ start += 3; at = strchr(start, '@'); @@ -185,6 +198,7 @@ int _x_parse_url (char *url, char **proto, char** host, int *port, } else *it = start[i]; } + *it = '\0'; } } } else { @@ -257,7 +271,7 @@ static int check_url(char *url, int ok) { printf("--------------------------------\n"); printf("url=%s\n", url); res = _x_parse_url (url, - &proto, &host, &port, &user, &password, &uri); + &proto, &host, &port, &user, &password, &uri, NULL); if (res) { printf("proto=%s, host=%s, port=%d, user=%s, password=%s, uri=%s\n", proto, host, port, user, password, uri); diff --git a/src/input/http_helper.h b/src/input/http_helper.h index 3ce3f2b7c..68299a2ea 100644 --- a/src/input/http_helper.h +++ b/src/input/http_helper.h @@ -24,6 +24,16 @@ #define HTTP_HELPER_H /* + * user agent finder, using modified protcol names + * {proto}://... + * e.g. "qthttp://example.com/foo.mov" → "QuickTime" + * + * return: + * NULL or user agent prefix + */ +const char *_x_url_user_agent (const char *url); + +/* * url parser * {proto}://{user}:{password}@{host}:{port}{uri} * {proto}://{user}:{password}@{[host]}:{port}{uri} @@ -33,7 +43,8 @@ * 1 valid url */ int _x_parse_url (char *url, char **proto, char** host, int *port, - char **user, char **password, char **uri); + char **user, char **password, char **uri, + const char **user_agent); /* * canonicalise url, given base diff --git a/src/input/input_cdda.c b/src/input/input_cdda.c index 996460832..70bd34f35 100644 --- a/src/input/input_cdda.c +++ b/src/input/input_cdda.c @@ -71,6 +71,8 @@ #define DEFAULT_CDDA_DEVICE "/vol/dev/aliases/cdrom0" #elif defined(WIN32) #define DEFAULT_CDDA_DEVICE "d:\\" +#elif defined(__OpenBSD__) +#define DEFAULT_CDDA_DEVICE "/dev/rcd0c" #else #define DEFAULT_CDDA_DEVICE "/dev/cdrom" #endif @@ -111,7 +113,7 @@ typedef struct _cdrom_toc { *************************************************************************/ #define MAX_TRACKS 99 -#define CACHED_FRAMES 500 +#define CACHED_FRAMES 100 typedef struct { int start; @@ -611,7 +613,7 @@ static int read_cdrom_frames(cdda_input_plugin_t *this_gen, int frame, int num_f return 0; } -#elif defined(__FreeBSD_kernel__) || defined(__NetBSD__) +#elif defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) #include <sys/cdio.h> @@ -624,7 +626,7 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { struct ioc_toc_header tochdr; #if defined(__FreeBSD_kernel__) struct ioc_read_toc_single_entry tocentry; -#elif defined(__NetBSD__) +#elif defined(__NetBSD__) || defined(__OpenBSD__) struct ioc_read_toc_entry tocentry; struct cd_toc_entry data; #endif @@ -659,7 +661,7 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { perror("CDIOREADTOCENTRY"); return -1; } -#elif defined(__NetBSD__) +#elif defined(__NetBSD__) || defined(__OpenBSD__) memset(&data, 0, sizeof(data)); tocentry.data_len = sizeof(data); tocentry.data = &data; @@ -680,7 +682,7 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { (tocentry.entry.addr.msf.minute * CD_SECONDS_PER_MINUTE * CD_FRAMES_PER_SECOND) + (tocentry.entry.addr.msf.second * CD_FRAMES_PER_SECOND) + tocentry.entry.addr.msf.frame; -#elif defined(__NetBSD__) +#elif defined(__NetBSD__) || defined(__OpenBSD__) toc->toc_entries[i-1].track_mode = (tocentry.data->control & 0x04) ? 1 : 0; toc->toc_entries[i-1].first_frame_minute = tocentry.data->addr.msf.minute; toc->toc_entries[i-1].first_frame_second = tocentry.data->addr.msf.second; @@ -702,7 +704,7 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { perror("CDIOREADTOCENTRY"); return -1; } -#elif defined(__NetBSD__) +#elif defined(__NetBSD__) || defined(__OpenBSD__) memset(&data, 0, sizeof(data)); tocentry.data_len = sizeof(data); tocentry.data = &data; @@ -723,7 +725,7 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { (tocentry.entry.addr.msf.minute * CD_SECONDS_PER_MINUTE * CD_FRAMES_PER_SECOND) + (tocentry.entry.addr.msf.second * CD_FRAMES_PER_SECOND) + tocentry.entry.addr.msf.frame; -#elif defined(__NetBSD__) +#elif defined(__NetBSD__) || defined(__OpenBSD__) toc->leadout_track.track_mode = (tocentry.data->control & 0x04) ? 1 : 0; toc->leadout_track.first_frame_minute = tocentry.data->addr.msf.minute; toc->leadout_track.first_frame_second = tocentry.data->addr.msf.second; @@ -761,7 +763,7 @@ static int read_cdrom_frames(cdda_input_plugin_t *this_gen, int frame, int num_f perror("CDIOCREADAUDIO"); return -1; } -#elif defined(__NetBSD__) +#elif defined(__NetBSD__) || defined(__OpenBSD__) scsireq_t req; int nblocks = 1; @@ -1431,6 +1433,73 @@ static int _cdda_cddb_handle_code(char *buf) { return err; } +static inline char *_cdda_append (/*const*/ char *first, const char *second) +{ + if (!first) + return strdup (second); + + char *result = (char *) realloc (first, strlen (first) + strlen (second) + 1); + strcat (result, second); + return result; +} + +static void _cdda_parse_cddb_info (cdda_input_plugin_t *this, char *buffer, char **dtitle) +{ + /* buffer should be no more than 2048 bytes... */ + char buf[2048]; + int track_no; + + if (sscanf (buffer, "DTITLE=%s", &buf[0]) == 1) { + char *pt = strchr (buffer, '='); + if (pt) { + ++pt; + + *dtitle = _cdda_append (*dtitle, pt); + pt = strdup (*dtitle); + + char *title = strstr (pt, " / "); + if (title) + { + *title = 0; + title += 3; + free (this->cddb.disc_artist); + this->cddb.disc_artist = strdup (pt); + } + else + title = pt; + + free (this->cddb.disc_title); + this->cddb.disc_title = strdup (title); + + free (pt); + } + } + else if (sscanf (buffer, "DYEAR=%s", &buf[0]) == 1) { + char *pt = strchr (buffer, '='); + if (pt && strlen (pt) == 5) + this->cddb.disc_year = strdup (pt + 1); + } + else if(sscanf(buffer, "DGENRE=%s", &buf[0]) == 1) { + char *pt = strchr(buffer, '='); + if (pt) + this->cddb.disc_category = strdup (pt + 1); + } + else if (sscanf (buffer, "TTITLE%d=%s", &track_no, &buf[0]) == 2) { + char *pt = strchr(buffer, '='); + this->cddb.track[track_no].title = _cdda_append (this->cddb.track[track_no].title, pt + 1); + } + else if (!strncmp (buffer, "EXTD=", 5)) + { + if (!this->cddb.disc_year) + { + int nyear; + char *y = strstr (buffer, "YEAR:"); + if (y && sscanf (y + 5, "%4d", &nyear) == 1) + asprintf (&this->cddb.disc_year, "%d", nyear); + } + } +} + /* * Try to load cached cddb infos */ @@ -1463,82 +1532,16 @@ static int _cdda_load_cached_cddb_infos(cdda_input_plugin_t *this) { return 0; } else { - char buffer[256], *ln; - char buf[256]; - int tnum; + char buffer[2048], *ln; char *dtitle = NULL; - while ((ln = fgets(buffer, 255, fd)) != NULL) { - - buffer[strlen(buffer) - 1] = '\0'; - - if (sscanf(buffer, "DTITLE=%s", &buf[0]) == 1) { - char *pt, *artist, *title; - - pt = strchr(buffer, '='); - if (pt) { - pt++; - - if (dtitle != NULL) - { - dtitle = (char *) realloc(dtitle, strlen(dtitle) + strlen(pt) + 1); - strcat(dtitle, pt); - pt = dtitle; - } - dtitle = strdup(pt); - - artist = pt; - title = strstr(pt, " / "); - if (title) { - *title++ = '\0'; - title += 2; - } - else { - title = artist; - artist = NULL; - } - - if (artist) - this->cddb.disc_artist = strdup(artist); - - this->cddb.disc_title = strdup(title); - } - } - else if (sscanf(buffer, "DYEAR=%s", &buf[0]) == 1) { - char *pt; + while ((ln = fgets(buffer, sizeof (buffer) - 1, fd)) != NULL) { - pt = strrchr(buffer, '='); - pt++; - if (pt != NULL && strlen(pt) == 4) - this->cddb.disc_year = strdup(pt); - } - else if (sscanf(buffer, "TTITLE%d=%s", &tnum, &buf[0]) == 2) { - char *pt; - - pt = strchr(buffer, '='); - if (pt) - pt++; - if (this->cddb.track[tnum].title == NULL) - this->cddb.track[tnum].title = strdup(pt); - else - { - this->cddb.track[tnum].title - = (char *) realloc(this->cddb.track[tnum].title, strlen(this->cddb.track[tnum].title) + strlen(pt) + 1); - strcat(this->cddb.track[tnum].title, pt); - } - } - else { - if (!strncmp(buffer, "EXTD=", 5)) { - char *y; - int nyear; - - y = strstr(buffer, "YEAR:"); - if (y && this->cddb.disc_year == NULL) { - if (sscanf(y+5, "%4d", &nyear) == 1) - asprintf(&this->cddb.disc_year, "%d", nyear); - } - } - } + int length = strlen (buffer); + if (length && buffer[length - 1] == '\n') + buffer[length - 1] = '\0'; + + _cdda_parse_cddb_info (this, buffer, &dtitle); } fclose(fd); free(dtitle); @@ -1726,7 +1729,7 @@ static int _cdda_cddb_retrieve(cdda_input_plugin_t *this) { memset(&buffer, 0, sizeof(buffer)); err = _cdda_cddb_socket_read(this, buffer, sizeof(buffer) - 1); - if (err < 0 || (((err = _cdda_cddb_handle_code(buffer)) != 200) && (err != 210))) { + if (err < 0 || (((err = _cdda_cddb_handle_code(buffer)) != 200) && (err != 210) && (err != 211))) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_cdda: cddb query command returned error code '%03d'.\n", err); _cdda_cddb_socket_close(this); @@ -1747,7 +1750,7 @@ static int _cdda_cddb_retrieve(cdda_input_plugin_t *this) { } } - if (err == 210) { + if ((err == 210) || (err == 211)) { memset(&buffer, 0, sizeof(buffer)); err = _cdda_cddb_socket_read(this, buffer, sizeof(buffer) - 1); if (err < 0) { @@ -1801,82 +1804,13 @@ static int _cdda_cddb_retrieve(cdda_input_plugin_t *this) { memset(&buffercache, 0, sizeof(buffercache)); while (strcmp(buffer, ".")) { - char buf[2048]; - int tnum; size_t bufsize = strlen(buffercache); memset(&buffer, 0, sizeof(buffer)); _cdda_cddb_socket_read(this, buffer, sizeof(buffer) - 1); snprintf(buffercache + bufsize, sizeof(buffercache) - bufsize, "%s\n", buffer); - if (sscanf(buffer, "DTITLE=%s", &buf[0]) == 1) { - char *pt, *artist, *title; - - pt = strrchr(buffer, '='); - if (pt) { - pt++; - - if (dtitle != NULL) - { - dtitle = (char *) realloc(dtitle, strlen(dtitle) + strlen(pt) + 1); - strcat(dtitle, pt); - pt = dtitle; - } - dtitle = strdup(pt); - - artist = pt; - title = strstr(pt, " / "); - if (title) { - *title++ = '\0'; - title += 2; - } - else { - title = artist; - artist = NULL; - } - - if (artist) { - this->cddb.disc_artist = strdup(artist); - } - this->cddb.disc_title = strdup(title); - } - } - else if(sscanf(buffer, "DYEAR=%s", &buf[0]) == 1) { - char *pt; - - pt = strrchr(buffer, '='); - pt++; - if (pt != NULL && strlen(pt) == 4) - this->cddb.disc_year = strdup(pt); - } - else if (sscanf(buffer, "TTITLE%d=%s", &tnum, &buf[0]) == 2) { - char *pt; - - pt = strrchr(buffer, '='); - if (pt) { - pt++; - if (this->cddb.track[tnum].title == NULL) - this->cddb.track[tnum].title = strdup(pt); - else - { - this->cddb.track[tnum].title - = (char *) realloc(this->cddb.track[tnum].title, strlen(this->cddb.track[tnum].title) + strlen(pt) + 1); - strcat(this->cddb.track[tnum].title, pt); - } - } - } - else { - if (!strncmp(buffer, "EXTD=", 5)) { - char *y; - int nyear; - - y = strstr(buffer, "YEAR:"); - if (y && this->cddb.disc_year == NULL) { - if (sscanf(y+5, "%4d", &nyear) == 1) - asprintf(&this->cddb.disc_year, "%d", nyear); - } - } - } + _cdda_parse_cddb_info (this, buffer, &dtitle); } free(dtitle); @@ -2084,9 +2018,9 @@ static int cdda_open(cdda_input_plugin_t *this_gen, hASPI = LoadLibrary( "wnaspi32.dll" ); if( hASPI != NULL ) { - (FARPROC) lpGetSupport = GetProcAddress( hASPI, + lpGetSupport = GetProcAddress( hASPI, "GetASPI32SupportInfo" ); - (FARPROC) lpSendCommand = GetProcAddress( hASPI, + lpSendCommand = GetProcAddress( hASPI, "SendASPI32Command" ); } @@ -2224,26 +2158,18 @@ static int cdda_close(cdda_input_plugin_t *this_gen) { static uint32_t cdda_plugin_get_capabilities (input_plugin_t *this_gen) { - return INPUT_CAP_SEEKABLE | INPUT_CAP_BLOCK; + return INPUT_CAP_SEEKABLE; } static off_t cdda_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) { - /* only allow reading in block-sized chunks */ - - return 0; -} - -static buf_element_t *cdda_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, - off_t nlen) { - cdda_input_plugin_t *this = (cdda_input_plugin_t *) this_gen; - buf_element_t *buf; - unsigned char frame_data[CD_RAW_FRAME_SIZE]; int err = 0; - if (nlen != CD_RAW_FRAME_SIZE) + /* only allow reading in block-sized chunks */ + + if (len != CD_RAW_FRAME_SIZE) return 0; if (this->current_frame > this->last_frame) @@ -2277,14 +2203,26 @@ static buf_element_t *cdda_plugin_read_block (input_plugin_t *this_gen, fifo_buf if( err < 0 ) return 0; - memcpy(frame_data, this->cache[this->current_frame-this->cache_first], CD_RAW_FRAME_SIZE); + memcpy(buf, this->cache[this->current_frame-this->cache_first], CD_RAW_FRAME_SIZE); this->current_frame++; + return CD_RAW_FRAME_SIZE; +} + +static buf_element_t *cdda_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, + off_t nlen) { + + buf_element_t *buf; + buf = fifo->buffer_pool_alloc(fifo); buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; - buf->size = CD_RAW_FRAME_SIZE; - memcpy(buf->mem, frame_data, CD_RAW_FRAME_SIZE); + + buf->size = cdda_plugin_read(this_gen, buf->content, nlen); + if (buf->size == 0) { + buf->free_buffer(buf); + buf = NULL; + } return buf; } @@ -2322,7 +2260,7 @@ static off_t cdda_plugin_get_length (input_plugin_t *this_gen) { static uint32_t cdda_plugin_get_blocksize (input_plugin_t *this_gen) { - return CD_RAW_FRAME_SIZE; + return 0; } static const char* cdda_plugin_get_mrl (input_plugin_t *this_gen) { @@ -2489,6 +2427,9 @@ static int cdda_plugin_open (input_plugin_t *this_gen ) { } lprintf("Track %d Title: %s\n", this->track+1, pt); + char tracknum[4]; + snprintf(tracknum, 4, "%d", this->track+1); + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_TRACK_NUMBER, tracknum); _x_meta_info_set_utf8(this->stream, XINE_META_INFO_TITLE, pt); } diff --git a/src/input/input_dvb.c b/src/input/input_dvb.c index 0fa5ba971..54c40087e 100644 --- a/src/input/input_dvb.c +++ b/src/input/input_dvb.c @@ -67,7 +67,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include "config.h" #endif /* pthread.h must be included first so rest of the headers are imported @@ -286,7 +286,7 @@ typedef struct { xine_t *xine; - char *mrls[5]; + char *mrls[6]; int numchannels; @@ -2602,6 +2602,12 @@ static buf_element_t *dvb_plugin_read_block (input_plugin_t *this_gen, buf_element_t *buf = fifo->buffer_pool_alloc (fifo); int total_bytes; + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; @@ -2869,6 +2875,8 @@ static int dvb_plugin_open(input_plugin_t * this_gen) if (lastchannel.num_value) { if (xine_config_lookup_entry(this->class->xine, "media.dvb.last_channel", &lastchannel)){ this->channel = lastchannel.num_value -1; + if (this->channel < 0 || this->channel >= num_channels) + this->channel = 0; /* out of range? default */ }else{ xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("input_dvb: invalid channel specification, defaulting to channel 0\n")); this->channel = 0; diff --git a/src/input/input_dvd.c b/src/input/input_dvd.c index a845d7628..4f8827dbd 100644 --- a/src/input/input_dvd.c +++ b/src/input/input_dvd.c @@ -53,7 +53,9 @@ #include <dlfcn.h> #ifndef WIN32 +#if ! defined(__GNU__) #include <sys/mount.h> +#endif #include <sys/wait.h> #include <sys/poll.h> @@ -115,6 +117,9 @@ /* There really isn't a default on Windows! */ #define DVD_PATH "d:\\" #define RDVD_PATH "d:\\" +#elif defined(__OpenBSD__) +#define DVD_PATH "/dev/rcd0c" +#define RDVD_PATH "/dev/rcd0c" #else #define DVD_PATH "/dev/dvd" #define RDVD_PATH "/dev/rdvd" @@ -850,6 +855,9 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen, static off_t dvd_plugin_read (input_plugin_t *this_gen, char *ch_buf, off_t len) { /* dvd_input_plugin_t *this = (dvd_input_plugin_t*)this_gen; */ + if (len < 4) + return -1; + /* FIXME: Tricking the demux_mpeg_block plugin */ ch_buf[0] = 0; ch_buf[1] = 0; diff --git a/src/input/input_file.c b/src/input/input_file.c index 774f6b081..2187f0007 100644 --- a/src/input/input_file.c +++ b/src/input/input_file.c @@ -145,6 +145,9 @@ static int check_mmap_file(file_input_plugin_t *this) { static off_t file_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) { file_input_plugin_t *this = (file_input_plugin_t *) this_gen; + if (len < 0) + return -1; + #ifdef HAVE_MMAP if ( check_mmap_file(this) ) { off_t l = len; @@ -166,6 +169,13 @@ static buf_element_t *file_plugin_read_block (input_plugin_t *this_gen, fifo_buf file_input_plugin_t *this = (file_input_plugin_t *) this_gen; buf_element_t *buf = fifo->buffer_pool_alloc (fifo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->type = BUF_DEMUX_BLOCK; #ifdef HAVE_MMAP diff --git a/src/input/input_gnome_vfs.c b/src/input/input_gnome_vfs.c index 0848b9206..a3dfafdd5 100644 --- a/src/input/input_gnome_vfs.c +++ b/src/input/input_gnome_vfs.c @@ -121,6 +121,13 @@ gnomevfs_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t total_bytes; buf_element_t *buf = fifo->buffer_pool_alloc (fifo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; diff --git a/src/input/input_http.c b/src/input/input_http.c index 169a0d384..4eece116f 100644 --- a/src/input/input_http.c +++ b/src/input/input_http.c @@ -91,6 +91,8 @@ typedef struct { char *host; int port; char *uri; + + const char *user_agent; char preview[MAX_PREVIEW_SIZE]; off_t preview_size; @@ -421,6 +423,9 @@ static off_t http_plugin_read (input_plugin_t *this_gen, num_bytes = 0; + if (nlen < 0) + return -1; + if (this->curpos < this->preview_size) { if (nlen > (this->preview_size - this->curpos)) @@ -437,7 +442,7 @@ static off_t http_plugin_read (input_plugin_t *this_gen, n = nlen - num_bytes; - if (n) { + if (n > 0) { int read_bytes; read_bytes = http_plugin_read_int (this, &buf[num_bytes], n); @@ -503,6 +508,13 @@ static buf_element_t *http_plugin_read_block (input_plugin_t *this_gen, fifo_buf off_t total_bytes; buf_element_t *buf = fifo->buffer_pool_alloc (fifo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; @@ -554,7 +566,7 @@ static off_t http_plugin_seek(input_plugin_t *this_gen, off_t offset, int origin if ((origin == SEEK_CUR) && (offset >= 0)) { for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { - if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) ) + if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 ) return this->curpos; } @@ -576,7 +588,7 @@ static off_t http_plugin_seek(input_plugin_t *this_gen, off_t offset, int origin offset -= this->curpos; for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { - if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) ) + if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 ) return this->curpos; } @@ -679,7 +691,8 @@ static int http_plugin_open (input_plugin_t *this_gen ) { if (!_x_parse_url(this->mrl, &this->proto, &this->host, &this->port, - &this->user, &this->password, &this->uri)) { + &this->user, &this->password, &this->uri, + &this->user_agent)) { _x_message(this->stream, XINE_MSG_GENERAL_WARNING, "malformed url", NULL); return 0; } @@ -778,10 +791,12 @@ static int http_plugin_open (input_plugin_t *this_gen ) { } buflen += snprintf(this->buf + buflen, BUFSIZE - buflen, - "User-Agent: xine/%s\015\012" + "User-Agent: %s%sxine/%s\015\012" "Accept: */*\015\012" "Icy-MetaData: 1\015\012" "\015\012", + this->user_agent ? this->user_agent : "", + this->user_agent ? " " : "", VERSION); if (_x_io_tcp_write (this->stream, this->fh, this->buf, buflen) != buflen) { _x_message(this->stream, XINE_MSG_CONNECTION_REFUSED, "couldn't send request", NULL); @@ -996,6 +1011,7 @@ static int http_plugin_open (input_plugin_t *this_gen ) { this->preview_size = http_plugin_read_int (this, this->preview, MAX_PREVIEW_SIZE); } if (this->preview_size < 0) { + this->preview_size = 0; xine_log (this->stream->xine, XINE_LOG_MSG, _("input_http: read error %d\n"), errno); return -12; } @@ -1018,7 +1034,8 @@ static input_plugin_t *http_class_get_instance (input_class_t *cls_gen, xine_str if (strncasecmp (mrl, "http://", 7) && strncasecmp (mrl, "unsv://", 7) && - strncasecmp (mrl, "peercast://pls/", 15)) { + strncasecmp (mrl, "peercast://pls/", 15) && + !_x_url_user_agent (mrl) /* user agent hacks */) { return NULL; } this = calloc(1, sizeof(http_input_plugin_t)); diff --git a/src/input/input_mms.c b/src/input/input_mms.c index 158b40448..cd88a0609 100644 --- a/src/input/input_mms.c +++ b/src/input/input_mms.c @@ -122,6 +122,13 @@ static buf_element_t *mms_plugin_read_block (input_plugin_t *this_gen, lprintf ("mms_plugin_read_block: %"PRId64" bytes...\n", todo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; diff --git a/src/input/input_net.c b/src/input/input_net.c index 391f33a60..d9da27b54 100644 --- a/src/input/input_net.c +++ b/src/input/input_net.c @@ -253,6 +253,9 @@ static off_t net_plugin_read (input_plugin_t *this_gen, lprintf("reading %" PRIdMAX " bytes...\n", (intmax_t)len); + if (len < 0) + return -1; + total=0; if (this->curpos < this->preview_size) { n = this->preview_size - this->curpos; @@ -288,6 +291,13 @@ static buf_element_t *net_plugin_read_block (input_plugin_t *this_gen, buf_element_t *buf = fifo->buffer_pool_alloc (fifo); off_t total_bytes; + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; @@ -331,7 +341,7 @@ static off_t net_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin if ((origin == SEEK_CUR) && (offset >= 0)) { for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { - if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) ) + if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 ) return this->curpos; } @@ -353,7 +363,7 @@ static off_t net_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin offset -= this->curpos; for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { - if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) ) + if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 ) return this->curpos; } diff --git a/src/input/input_pnm.c b/src/input/input_pnm.c index 669d24d28..f609695d5 100644 --- a/src/input/input_pnm.c +++ b/src/input/input_pnm.c @@ -83,7 +83,8 @@ static off_t pnm_plugin_read (input_plugin_t *this_gen, lprintf ("pnm_plugin_read: %"PRId64" bytes ...\n", len); n = pnm_read (this->pnm, buf, len); - this->curpos += n; + if (n >= 0) + this->curpos += n; return n; } @@ -96,6 +97,13 @@ static buf_element_t *pnm_plugin_read_block (input_plugin_t *this_gen, lprintf ("pnm_plugin_read_block: %"PRId64" bytes...\n", todo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; @@ -123,10 +131,16 @@ static off_t pnm_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin if ((origin == SEEK_CUR) && (offset >= 0)) { for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { - this->curpos += pnm_plugin_read (this_gen, this->scratch, BUFSIZE); + off_t n = pnm_plugin_read (this_gen, this->scratch, BUFSIZE); + if (n <= 0) + return this->curpos; + this->curpos += n; } - this->curpos += pnm_plugin_read (this_gen, this->scratch, offset); + off_t n = pnm_plugin_read (this_gen, this->scratch, offset); + if (n <= 0) + return this->curpos; + this->curpos += n; } return this->curpos; diff --git a/src/input/input_pvr.c b/src/input/input_pvr.c index 009c76939..a9c92e42e 100644 --- a/src/input/input_pvr.c +++ b/src/input/input_pvr.c @@ -424,6 +424,9 @@ static uint32_t pvr_plugin_get_capabilities (input_plugin_t *this_gen) { static off_t pvr_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) { /*pvr_input_plugin_t *this = (pvr_input_plugin_t *) this_gen;*/ + if (len < 4) + return -1; + /* FIXME: Tricking the demux_mpeg_block plugin */ buf[0] = 0; buf[1] = 0; @@ -1204,6 +1207,14 @@ static buf_element_t *pvr_plugin_read_block (input_plugin_t *this_gen, fifo_buff return NULL; } + buf = fifo->buffer_pool_alloc (fifo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer(buf); + return NULL; + } + if( this->scr_tunning == -2 ) speed = this->speed_before_pause; @@ -1227,7 +1238,6 @@ static buf_element_t *pvr_plugin_read_block (input_plugin_t *this_gen, fifo_buff pvr_event_handler(this); - buf = fifo->buffer_pool_alloc (fifo); buf->content = buf->mem; pthread_mutex_lock(&this->lock); diff --git a/src/input/input_rtp.c b/src/input/input_rtp.c index 66fcba87e..90bae6670 100644 --- a/src/input/input_rtp.c +++ b/src/input/input_rtp.c @@ -453,6 +453,9 @@ static off_t rtp_plugin_read (input_plugin_t *this_gen, struct timespec timeout; off_t copied = 0; + if (length < 0) + return -1; + while(length > 0) { off_t n; @@ -524,6 +527,12 @@ static buf_element_t *rtp_plugin_read_block (input_plugin_t *this_gen, buf_element_t *buf = fifo->buffer_pool_alloc (fifo); int total_bytes; + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; @@ -609,11 +618,14 @@ static int rtp_plugin_get_optional_data (input_plugin_t *this_gen, if (data_type == INPUT_OPTIONAL_DATA_PREVIEW) { if (!this->preview_read_done) { this->preview_size = rtp_plugin_read(this_gen, this->preview, MAX_PREVIEW_SIZE); + if (this->preview_size < 0) + this->preview_size = 0; lprintf("Preview data length = %d\n", this->preview_size); this->preview_read_done = 1; } - memcpy(data, this->preview, this->preview_size); + if (this->preview_size) + memcpy(data, this->preview, this->preview_size); return this->preview_size; } else { diff --git a/src/input/input_rtsp.c b/src/input/input_rtsp.c index 110c4d4b6..fad395e0b 100644 --- a/src/input/input_rtsp.c +++ b/src/input/input_rtsp.c @@ -84,7 +84,8 @@ static off_t rtsp_plugin_read (input_plugin_t *this_gen, lprintf ("rtsp_plugin_read: %"PRId64" bytes ...\n", len); n = rtsp_session_read (this->rtsp, buf, len); - this->curpos += n; + if (n > 0) + this->curpos += n; return n; } @@ -97,6 +98,13 @@ static buf_element_t *rtsp_plugin_read_block (input_plugin_t *this_gen, lprintf ("rtsp_plugin_read_block: %"PRId64" bytes...\n", todo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; @@ -123,10 +131,16 @@ static off_t rtsp_plugin_seek (input_plugin_t *this_gen, off_t offset, int origi if ((origin == SEEK_CUR) && (offset >= 0)) { for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { - this->curpos += rtsp_plugin_read (this_gen, this->scratch, BUFSIZE); + off_t n = rtsp_plugin_read (this_gen, this->scratch, BUFSIZE); + if (n <= 0) + return this->curpos; + this->curpos += n; } - this->curpos += rtsp_plugin_read (this_gen, this->scratch, offset); + off_t n = rtsp_plugin_read (this_gen, this->scratch, offset); + if (n <= 0) + return this->curpos; + this->curpos += n; } return this->curpos; diff --git a/src/input/input_smb.c b/src/input/input_smb.c index 3d495f04e..e49eaa889 100644 --- a/src/input/input_smb.c +++ b/src/input/input_smb.c @@ -69,6 +69,8 @@ smb_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) smb_input_t *this = (smb_input_t *) this_gen; off_t n, num_bytes; + if (len < 0) + return -1; num_bytes = 0; while (num_bytes < len) @@ -89,6 +91,13 @@ smb_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t total_bytes; buf_element_t *buf = fifo->buffer_pool_alloc (fifo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; diff --git a/src/input/input_stdin_fifo.c b/src/input/input_stdin_fifo.c index 0ae841b4b..64b8d748c 100644 --- a/src/input/input_stdin_fifo.c +++ b/src/input/input_stdin_fifo.c @@ -85,6 +85,8 @@ static off_t stdin_plugin_read (input_plugin_t *this_gen, off_t n, total; lprintf ("reading %"PRId64" bytes...\n", len); + if (len < 0) + return -1; total=0; if (this->curpos < this->preview_size) { @@ -121,6 +123,13 @@ static buf_element_t *stdin_plugin_read_block (input_plugin_t *this_gen, fifo_bu /* stdin_input_plugin_t *this = (stdin_input_plugin_t *) this_gen; */ buf_element_t *buf = fifo->buffer_pool_alloc (fifo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; @@ -146,7 +155,7 @@ static off_t stdin_plugin_seek (input_plugin_t *this_gen, off_t offset, int orig if ((origin == SEEK_CUR) && (offset >= 0)) { for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { - if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) ) + if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 ) return this->curpos; } @@ -168,7 +177,7 @@ static off_t stdin_plugin_seek (input_plugin_t *this_gen, off_t offset, int orig offset -= this->curpos; for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { - if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) ) + if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 ) return this->curpos; } @@ -270,6 +279,8 @@ static int stdin_plugin_open (input_plugin_t *this_gen ) { this->preview_size = stdin_plugin_read (&this->input_plugin, this->preview, MAX_PREVIEW_SIZE); + if (this->preview_size < 0) + this->preview_size = 0; this->curpos = 0; return 1; diff --git a/src/input/input_vcd.c b/src/input/input_vcd.c index 760910a01..c99f57f09 100644 --- a/src/input/input_vcd.c +++ b/src/input/input_vcd.c @@ -92,7 +92,7 @@ typedef struct { #if defined (__linux__) || defined(__sun) struct cdrom_tochdr tochdr; struct cdrom_tocentry tocent[100]; -#elif defined (__FreeBSD_kernel__) +#elif defined (__FreeBSD_kernel__) || defined (__OpenBSD__) struct ioc_toc_header tochdr; struct cd_toc_entry *tocent; off_t cur_sec; @@ -117,7 +117,7 @@ typedef struct { int cur_track; -#if defined (__linux__) || defined(__sun) || defined (__FreeBSD_kernel__) +#if defined (__linux__) || defined(__sun) || defined (__FreeBSD_kernel__) || defined (__OpenBSD__) uint8_t cur_min, cur_sec, cur_frame; #endif @@ -177,7 +177,7 @@ static int input_vcd_read_toc (vcd_input_class_t *this, int fd) { return 0; } -#elif defined (__FreeBSD_kernel__) +#elif defined (__FreeBSD_kernel__) || defined (__OpenBSD__) static int input_vcd_read_toc (vcd_input_class_t *this, int fd) { struct ioc_read_toc_entry te; @@ -393,7 +393,7 @@ static off_t vcd_plugin_read (input_plugin_t *this_gen, memcpy (buf, data.data, VCDSECTORSIZE); /* FIXME */ return VCDSECTORSIZE; } -#elif defined (__FreeBSD_kernel__) +#elif defined (__FreeBSD_kernel__) || defined (__OpenBSD__) static off_t vcd_plugin_read (input_plugin_t *this_gen, char *buf, off_t nlen) { vcd_input_plugin_t *this = (vcd_input_plugin_t *) this_gen; @@ -531,7 +531,7 @@ static buf_element_t *vcd_plugin_read_block (input_plugin_t *this_gen, memcpy (buf->mem, data.data, VCDSECTORSIZE); /* FIXME */ return buf; } -#elif defined (__FreeBSD_kernel__) +#elif defined (__FreeBSD_kernel__) || defined (__OpenBSD__) static buf_element_t *vcd_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t nlen) { @@ -690,7 +690,7 @@ static off_t vcd_plugin_seek (input_plugin_t *this_gen, return offset ; /* FIXME */ } -#elif defined (__FreeBSD_kernel__) +#elif defined (__FreeBSD_kernel__) || defined (__OpenBSD__) static off_t vcd_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) { @@ -764,7 +764,7 @@ static off_t vcd_plugin_get_length (input_plugin_t *this_gen) { return (off_t) 0; } -#elif defined (__FreeBSD_kernel__) +#elif defined (__FreeBSD_kernel__) || defined (__OpenBSD__) static off_t vcd_plugin_get_length (input_plugin_t *this_gen) { vcd_input_plugin_t *this = (vcd_input_plugin_t *) this_gen; off_t len ; @@ -859,6 +859,10 @@ static int vcd_plugin_open (input_plugin_t *this_gen) { this->cur_min = this->cls->tocent[this->cur_track].cdte_addr.msf.minute; this->cur_sec = this->cls->tocent[this->cur_track].cdte_addr.msf.second; this->cur_frame = this->cls->tocent[this->cur_track].cdte_addr.msf.frame; +#elif defined (__OpenBSD__) + this->cur_min = this->cls->tocent[this->cur_track + 1 - this->cls->tochdr.starting_track].addr.msf.minute; + this->cur_sec = this->cls->tocent[this->cur_track + 1 - this->cls->tochdr.starting_track].addr.msf.second; + this->cur_frame = this->cls->tocent[this->cur_track + 1 - this->cls->tochdr.starting_track].addr.msf.frame; #elif defined (__FreeBSD_kernel__) { int bsize = 2352; diff --git a/src/input/libdvdnav/bswap.h b/src/input/libdvdnav/bswap.h index 2a2d222fe..23f0251d6 100644 --- a/src/input/libdvdnav/bswap.h +++ b/src/input/libdvdnav/bswap.h @@ -20,7 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <config.h> +#include "config.h" #if defined(WORDS_BIGENDIAN) /* All bigendian systems are fine, just ignore the swaps. */ diff --git a/src/input/libdvdnav/diff_against_cvs.patch b/src/input/libdvdnav/diff_against_cvs.patch index 202474fef..6df704e2a 100644 --- a/src/input/libdvdnav/diff_against_cvs.patch +++ b/src/input/libdvdnav/diff_against_cvs.patch @@ -323,7 +323,7 @@ diff -u -p -u -r1.5 dvd_reader.h -#ifdef _MSC_VER +#ifdef HAVE_CONFIG_H - #include <config.h> + #include "config.h" +#endif +#ifdef _MSC_VER diff --git a/src/input/libdvdnav/dvd_reader.c b/src/input/libdvdnav/dvd_reader.c index eff1977fc..1e0d3016b 100644 --- a/src/input/libdvdnav/dvd_reader.c +++ b/src/input/libdvdnav/dvd_reader.c @@ -30,7 +30,9 @@ #include <string.h> #include <unistd.h> #include <limits.h> +#ifdef HAVE_DIRENT_H #include <dirent.h> +#endif #ifndef HAVE_GETTIMEOFDAY # ifdef WIN32 diff --git a/src/input/libdvdnav/dvd_reader.h b/src/input/libdvdnav/dvd_reader.h index e1b051c00..c7b3f9df8 100644 --- a/src/input/libdvdnav/dvd_reader.h +++ b/src/input/libdvdnav/dvd_reader.h @@ -22,7 +22,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include "config.h" #endif #ifdef _MSC_VER diff --git a/src/input/libdvdnav/md5.c b/src/input/libdvdnav/md5.c index 2bfdddee4..16b7b0690 100644 --- a/src/input/libdvdnav/md5.c +++ b/src/input/libdvdnav/md5.c @@ -21,7 +21,7 @@ /* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */ #ifdef HAVE_CONFIG_H -# include <config.h> +# include "config.h" #endif #include <sys/types.h> diff --git a/src/input/libdvdnav/remap.c b/src/input/libdvdnav/remap.c index 43c81c66f..df0be29ce 100644 --- a/src/input/libdvdnav/remap.c +++ b/src/input/libdvdnav/remap.c @@ -216,6 +216,7 @@ remap_t* remap_loadmap( char *title) { remap_add_node( map, tmp); } } + close (fp); /* ignoring errors... */ if (map->nblocks == 0 && map->debug == 0) return NULL; return map; diff --git a/src/input/libreal/asmrp.c b/src/input/libreal/asmrp.c index 970fcb0f7..902c59d42 100644 --- a/src/input/libreal/asmrp.c +++ b/src/input/libreal/asmrp.c @@ -32,6 +32,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <stdio.h> #include <string.h> diff --git a/src/input/libreal/real.c b/src/input/libreal/real.c index c0e11fa00..dcb90bcd0 100644 --- a/src/input/libreal/real.c +++ b/src/input/libreal/real.c @@ -21,6 +21,10 @@ * adopted from joschkas real tools. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <string.h> diff --git a/src/input/libreal/rmff.c b/src/input/libreal/rmff.c index 41f85d3ae..2d3fcc613 100644 --- a/src/input/libreal/rmff.c +++ b/src/input/libreal/rmff.c @@ -21,6 +21,10 @@ * adopted from joschkas real tools */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define LOG_MODULE "rmff" #define LOG_VERBOSE /* @@ -330,12 +334,14 @@ static rmff_prop_t *rmff_scan_prop(const char *data) { return prop; } -static rmff_mdpr_t *rmff_scan_mdpr(const char *data) { - - rmff_mdpr_t *mdpr = malloc(sizeof(rmff_mdpr_t)); +static rmff_mdpr_t *rmff_scan_mdpr(const char *data) +{ + rmff_mdpr_t *mdpr = calloc(sizeof(rmff_mdpr_t), 1); mdpr->object_id=_X_BE_32(data); mdpr->size=_X_BE_32(&data[4]); + if (mdpr->size < 46) + goto fail; mdpr->object_version=_X_BE_16(&data[8]); if (mdpr->object_version != 0) { @@ -351,21 +357,40 @@ static rmff_mdpr_t *rmff_scan_mdpr(const char *data) { mdpr->duration=_X_BE_32(&data[36]); mdpr->stream_name_size=data[40]; + if (mdpr->size < 46 + mdpr->stream_name_size) + goto fail; mdpr->stream_name = malloc(mdpr->stream_name_size+1); + if (!mdpr->stream_name) + goto fail; memcpy(mdpr->stream_name, &data[41], mdpr->stream_name_size); mdpr->stream_name[mdpr->stream_name_size]=0; mdpr->mime_type_size=data[41+mdpr->stream_name_size]; + if (mdpr->size < 46 + mdpr->stream_name_size + mdpr->mime_type_size) + goto fail; mdpr->mime_type = malloc(mdpr->mime_type_size+1); + if (!mdpr->mime_type) + goto fail; memcpy(mdpr->mime_type, &data[42+mdpr->stream_name_size], mdpr->mime_type_size); mdpr->mime_type[mdpr->mime_type_size]=0; mdpr->type_specific_len=_X_BE_32(&data[42+mdpr->stream_name_size+mdpr->mime_type_size]); + if (mdpr->size < 46 + mdpr->stream_name_size + mdpr->mime_type_size + mdpr->type_specific_data) + goto fail; mdpr->type_specific_data = malloc(mdpr->type_specific_len); + if (!mdpr->type_specific_data) + goto fail; memcpy(mdpr->type_specific_data, &data[46+mdpr->stream_name_size+mdpr->mime_type_size], mdpr->type_specific_len); return mdpr; + +fail: + free (mdpr->stream_name); + free (mdpr->mime_type); + free (mdpr->type_specific_data); + free (mdpr); + return NULL; } static rmff_cont_t *rmff_scan_cont(const char *data) { @@ -463,8 +488,11 @@ rmff_header_t *rmff_scan_header(const char *data) { break; case MDPR_TAG: mdpr=rmff_scan_mdpr(ptr); - chunk_size=mdpr->size; - header->streams[mdpr->stream_number]=mdpr; + if (mdpr) /* FIXME: what to do if NULL? */ + { + chunk_size=mdpr->size; + header->streams[mdpr->stream_number]=mdpr; + } break; case CONT_TAG: header->cont=rmff_scan_cont(ptr); diff --git a/src/input/libreal/sdpplin.c b/src/input/libreal/sdpplin.c index c1fab49c1..a07cb3360 100644 --- a/src/input/libreal/sdpplin.c +++ b/src/input/libreal/sdpplin.c @@ -19,6 +19,10 @@ * * sdp/sdpplin parser. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #define LOG_MODULE "sdpplin" #define LOG_VERBOSE diff --git a/src/input/librtsp/rtsp.c b/src/input/librtsp/rtsp.c index 07769064a..8d0d45ec5 100644 --- a/src/input/librtsp/rtsp.c +++ b/src/input/librtsp/rtsp.c @@ -22,7 +22,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include "config.h" #endif #include <unistd.h> @@ -255,7 +255,7 @@ static int rtsp_get_answers(rtsp_t *s) { } } else { - lprintf("setting session id to: %s\n", buf); + lprintf("setting session id to: %s\n", tmp); s->session=strdup(tmp); } diff --git a/src/input/librtsp/rtsp_session.c b/src/input/librtsp/rtsp_session.c index 4e636410d..88103aa7d 100644 --- a/src/input/librtsp/rtsp_session.c +++ b/src/input/librtsp/rtsp_session.c @@ -20,6 +20,10 @@ * high level interface to rtsp servers. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> diff --git a/src/input/mms.c b/src/input/mms.c index ab1983955..8ba33e704 100644 --- a/src/input/mms.c +++ b/src/input/mms.c @@ -290,7 +290,7 @@ static int send_command (mms_t *this, int command, #ifdef USE_ICONV static iconv_t string_utf16_open() { - return iconv_open("UTF-16LE", nl_langinfo(CODESET)); + return iconv_open("UTF-16LE", "UTF-8"); } static void string_utf16_close(iconv_t url_conv) { @@ -698,7 +698,7 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { report_progress (stream, 0); if (!_x_parse_url (this->url, &this->proto, &this->host, &this->port, - &this->user, &this->password, &this->uri)) { + &this->user, &this->password, &this->uri, NULL)) { lprintf ("invalid url\n"); goto fail; } @@ -771,10 +771,17 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { /* command 0x5 */ { mms_buffer_t command_buffer; - char *path = this->uri; - size_t pathlen = strlen(path); + char *path, *unescaped; + size_t pathlen; + + unescaped = strdup (this->uri); + if (!unescaped) + goto fail; + _x_mrl_unescape (unescaped); /* remove the first '/' */ + path = unescaped; + pathlen = strlen (path); if (pathlen > 1) { path++; pathlen--; @@ -785,6 +792,7 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */ mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */ string_utf16 (url_conv, this->scmd_body + command_buffer.pos, path, pathlen); + free (unescaped); if (!send_command (this, 5, 1, 0xffffffff, pathlen * 2 + 12)) goto fail; } diff --git a/src/input/mmsh.c b/src/input/mmsh.c index 4ee7ed07d..2cc27c3b1 100644 --- a/src/input/mmsh.c +++ b/src/input/mmsh.c @@ -649,7 +649,7 @@ mmsh_t *mmsh_connect (xine_stream_t *stream, const char *url, int bandwidth) { report_progress (stream, 0); if (!_x_parse_url (this->url, &this->proto, &this->host, &this->port, - &this->user, &this->password, &this->uri)) { + &this->user, &this->password, &this->uri, NULL)) { xine_log (this->stream->xine, XINE_LOG_MSG, _("invalid url\n")); goto fail; } diff --git a/src/input/pnm.c b/src/input/pnm.c index cbd245e7b..aabdbde96 100644 --- a/src/input/pnm.c +++ b/src/input/pnm.c @@ -22,7 +22,7 @@ */ #ifdef HAVE_CONFIG_H -# include <config.h> +# include "config.h" #endif #include <unistd.h> diff --git a/src/input/vcd/Makefile.am b/src/input/vcd/Makefile.am index 31ec6a44c..61eac753b 100644 --- a/src/input/vcd/Makefile.am +++ b/src/input/vcd/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common SUBDIRS = libcdio libvcd diff --git a/src/input/vcd/libcdio/MSWindows/aspi32.c b/src/input/vcd/libcdio/MSWindows/aspi32.c index 238a4b4e9..e62f8a089 100644 --- a/src/input/vcd/libcdio/MSWindows/aspi32.c +++ b/src/input/vcd/libcdio/MSWindows/aspi32.c @@ -162,9 +162,9 @@ have_aspi( HMODULE *hASPI, return false; } - (FARPROC) *lpGetSupport = GetProcAddress( *hASPI, + *lpGetSupport = (FARPROC)GetProcAddress( *hASPI, "GetASPI32SupportInfo" ); - (FARPROC) *lpSendCommand = GetProcAddress( *hASPI, + *lpSendCommand = (FARPROC)GetProcAddress( *hASPI, "SendASPI32Command" ); /* make sure that we've got both function addresses */ diff --git a/src/input/vcd/xineplug_inp_vcd.c b/src/input/vcd/xineplug_inp_vcd.c index 55b7f9b84..50382ee7e 100644 --- a/src/input/vcd/xineplug_inp_vcd.c +++ b/src/input/vcd/xineplug_inp_vcd.c @@ -20,7 +20,7 @@ /* These are plugin routines called by the xine engine. See Chapter 4. Extending xine's input - http://xinehq.de/index.php/hackersguide/index.php?resource=5.3&action=default#INPUT + http://www.xine-project.org/hackersguide#INPUT and the comments in input_plugin.h This is what is referred to below a "the xine plugin spec" diff --git a/src/liba52/Makefile.am b/src/liba52/Makefile.am index 508ea9c1b..b13170076 100644 --- a/src/liba52/Makefile.am +++ b/src/liba52/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common if A52 diff --git a/src/liba52/xine_a52_decoder.c b/src/liba52/xine_a52_decoder.c index 0f9ed3ad5..47babce7a 100644 --- a/src/liba52/xine_a52_decoder.c +++ b/src/liba52/xine_a52_decoder.c @@ -27,7 +27,7 @@ /* avoid compiler warnings */ #define _BSD_SOURCE 1 -#include <config.h> +#include "config.h" #include <stdlib.h> #include <unistd.h> diff --git a/src/libdts/Makefile.am b/src/libdts/Makefile.am index 1329dd49c..b7ec60016 100644 --- a/src/libdts/Makefile.am +++ b/src/libdts/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common if DTS diff --git a/src/libdts/xine_dts_decoder.c b/src/libdts/xine_dts_decoder.c index 669ae85da..eba750110 100644 --- a/src/libdts/xine_dts_decoder.c +++ b/src/libdts/xine_dts_decoder.c @@ -21,6 +21,10 @@ * 09-12-2001 DTS passthrough inprovements (C) James Courtier-Dutton */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #ifndef __sun /* required for swab() */ #define _XOPEN_SOURCE 500 diff --git a/src/libfaad/Makefile.am b/src/libfaad/Makefile.am index f36fb608a..92bab83fb 100644 --- a/src/libfaad/Makefile.am +++ b/src/libfaad/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common SUBDIRS = codebook diff --git a/src/libfaad/common.h b/src/libfaad/common.h index 4d2769526..4419f1eb5 100644 --- a/src/libfaad/common.h +++ b/src/libfaad/common.h @@ -36,7 +36,7 @@ extern "C" { #endif #ifdef HAVE_CONFIG_H -# include <config.h> +# include "config.h" #endif #if 1 diff --git a/src/libfaad/xine_faad_decoder.c b/src/libfaad/xine_faad_decoder.c index 9c657610e..b90bc701f 100644 --- a/src/libfaad/xine_faad_decoder.c +++ b/src/libfaad/xine_faad_decoder.c @@ -18,6 +18,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <unistd.h> #include <string.h> diff --git a/src/libmad/Makefile.am b/src/libmad/Makefile.am index c879645c5..56339cc72 100644 --- a/src/libmad/Makefile.am +++ b/src/libmad/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_CFLAGS = -DOPT_SPEED diff --git a/src/libmad/xine_mad_decoder.c b/src/libmad/xine_mad_decoder.c index 31b313818..cb8c52831 100644 --- a/src/libmad/xine_mad_decoder.c +++ b/src/libmad/xine_mad_decoder.c @@ -22,7 +22,7 @@ #include <stdlib.h> #include <string.h> -#include <config.h> +#include "config.h" #ifdef HAVE_MAD_H #include <mad.h> @@ -84,6 +84,9 @@ typedef struct mad_decoder_s { uint8_t buffer[INPUT_BUF_SIZE]; int bytes_in_buffer; int preview_mode; + int start_padding; + int end_padding; + int needs_more_data; } mad_decoder_t; @@ -98,6 +101,9 @@ static void mad_reset (audio_decoder_t *this_gen) { this->pts = 0; this->bytes_in_buffer = 0; this->preview_mode = 0; + this->start_padding = 0; + this->end_padding = 0; + this->needs_more_data = 0; mad_synth_init (&this->synth); mad_stream_init (&this->stream); @@ -187,6 +193,17 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { if (this->bytes_in_buffer < MAD_MIN_SIZE) return; + if (!this->needs_more_data) { + this->pts = buf->pts; + if (buf->decoder_flags & BUF_FLAG_AUDIO_PADDING) { + this->start_padding = buf->decoder_info[1]; + this->end_padding = buf->decoder_info[2]; + } else { + this->start_padding = 0; + this->end_padding = 0; + } + } + while (1) { if (mad_frame_decode (&this->frame, &this->stream) != 0) { @@ -204,6 +221,8 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { switch (this->stream.error) { case MAD_ERROR_BUFLEN: + /* libmad wants more data */ + this->needs_more_data = 1; return; default: @@ -284,7 +303,24 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { nsamples = pcm->length; left_ch = pcm->samples[0]; right_ch = pcm->samples[1]; - + + /* padding */ + if (this->start_padding || this->end_padding) { + /* check padding validity */ + if (nsamples < (this->start_padding + this->end_padding)) { + lprintf("invalid padding data"); + this->start_padding = 0; + this->end_padding = 0; + } + lprintf("nsamples=%d, start_padding=%d, end_padding=%d\n", + nsamples, this->start_padding, this->end_padding); + nsamples -= this->start_padding + this->end_padding; + left_ch += this->start_padding; + right_ch += this->start_padding; + } + audio_buffer->num_frames = nsamples; + audio_buffer->vpts = this->pts; + while (nsamples--) { /* output sample(s) in 16-bit signed little-endian PCM */ @@ -315,14 +351,21 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { this->xstream->audio_out->put_buffer (this->xstream->audio_out, audio_buffer, this->xstream); + this->pts = buf->pts; buf->pts = 0; - + if (buf->decoder_flags & BUF_FLAG_AUDIO_PADDING) { + this->start_padding = buf->decoder_info[1]; + this->end_padding = buf->decoder_info[2]; + buf->decoder_info[1] = 0; + buf->decoder_info[2] = 0; + } else { + this->start_padding = 0; + this->end_padding = 0; + } } - - lprintf ("decode worked\n"); + lprintf ("decode worked\n"); } - } - + } } } diff --git a/src/libmpeg2/Makefile.am b/src/libmpeg2/Makefile.am index 9895aa5d7..849e56363 100644 --- a/src/libmpeg2/Makefile.am +++ b/src/libmpeg2/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common xineplug_LTLIBRARIES = xineplug_decode_mpeg2.la @@ -22,7 +23,7 @@ xineplug_decode_mpeg2_la_SOURCES = \ xine_mpeg2_decoder.c \ libmpeg2_accel.c -xineplug_decode_mpeg2_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) -lm +xineplug_decode_mpeg2_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(LTLIBINTL) -lm xineplug_decode_mpeg2_la_CFLAGS = $(VISIBILITY_FLAG) $(LIBMPEG2_CFLAGS) xineplug_decode_mpeg2_la_LDFLAGS = $(xineplug_ldflags) diff --git a/src/libmpeg2/motion_comp.c b/src/libmpeg2/motion_comp.c index 8779c1296..f8faa3ee5 100644 --- a/src/libmpeg2/motion_comp.c +++ b/src/libmpeg2/motion_comp.c @@ -68,7 +68,7 @@ void mpeg2_mc_init (uint32_t mm_accel) mpeg2_mc = mpeg2_mc_altivec; } else #endif -#ifdef ARCH_SPARC +#if defined(ARCH_SPARC) && defined(ENABLE_VIS) if (mm_accel & MM_ACCEL_SPARC_VIS) { #ifdef LOG fprintf (stderr, "Using VIS for motion compensation\n"); diff --git a/src/libmpeg2/slice_xvmc_vld.c b/src/libmpeg2/slice_xvmc_vld.c index 7e370a519..cd4eca0a2 100644 --- a/src/libmpeg2/slice_xvmc_vld.c +++ b/src/libmpeg2/slice_xvmc_vld.c @@ -17,6 +17,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "video_out.h" #include "mpeg2.h" diff --git a/src/libmpeg2/xine_mpeg2_decoder.c b/src/libmpeg2/xine_mpeg2_decoder.c index 123374a08..b136ee861 100644 --- a/src/libmpeg2/xine_mpeg2_decoder.c +++ b/src/libmpeg2/xine_mpeg2_decoder.c @@ -20,6 +20,10 @@ * stuff needed to turn libmpeg2 into a xine decoder plugin */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> diff --git a/src/libmpeg2new/Makefile.am b/src/libmpeg2new/Makefile.am index 49959da86..8b05a5444 100644 --- a/src/libmpeg2new/Makefile.am +++ b/src/libmpeg2new/Makefile.am @@ -1,13 +1,18 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common -SUBDIRS = libmpeg2 +SUBDIRS = include libmpeg2 -xineplug_LTLIBRARIES = xineplug_decode_mpeg2.la +if ENABLE_MPEG2NEW +mpeg2new_module = xineplug_decode_mpeg2new.la +endif -xineplug_decode_mpeg2_la_SOURCES = \ - xine_mpeg2_decoder.c +xineplug_LTLIBRARIES = $(mpeg2new_module) -xineplug_decode_mpeg2_la_CFLAGS = $(VISIBILITY_FLAG) $(LIBMPEG2_CFLAGS) -xineplug_decode_mpeg2_la_LIBADD = $(XINE_LIB) ./libmpeg2/libmpeg2.la -xineplug_decode_mpeg2_la_LDFLAGS = $(xineplug_ldflags) +xineplug_decode_mpeg2new_la_SOURCES = \ + xine_mpeg2new_decoder.c + +xineplug_decode_mpeg2new_la_CFLAGS = $(VISIBILITY_FLAG) $(LIBMPEG2_CFLAGS) +xineplug_decode_mpeg2new_la_LIBADD = $(XINE_LIB) libmpeg2/libmpeg2.la +xineplug_decode_mpeg2new_la_LDFLAGS = $(xineplug_ldflags) diff --git a/src/libmpeg2new/include/Makefile.am b/src/libmpeg2new/include/Makefile.am index 302d01cb1..91d5575ee 100644 --- a/src/libmpeg2new/include/Makefile.am +++ b/src/libmpeg2new/include/Makefile.am @@ -1,3 +1,4 @@ -pkginclude_HEADERS = mpeg2.h mpeg2convert.h +include $(top_builddir)/misc/Makefile.plugins +include $(top_srcdir)/misc/Makefile.common -EXTRA_DIST = video_out.h mmx.h alpha_asm.h vis.h attributes.h tendra.h +EXTRA_DIST = video_out.h mmx.h alpha_asm.h vis.h attributes.h tendra.h mpeg2.h mpeg2convert.h diff --git a/src/libmpeg2new/include/attributes.h b/src/libmpeg2new/include/attributes.h index eefbc0dd1..92db86e7e 100644 --- a/src/libmpeg2new/include/attributes.h +++ b/src/libmpeg2new/include/attributes.h @@ -22,11 +22,7 @@ */ /* use gcc attribs to align critical data structures */ -#ifdef ATTRIBUTE_ALIGNED_MAX -#define ATTR_ALIGN(align) __attribute__ ((__aligned__ ((ATTRIBUTE_ALIGNED_MAX < align) ? ATTRIBUTE_ALIGNED_MAX : align))) -#else -#define ATTR_ALIGN(align) -#endif +#include "../../xine-utils/attributes.h" #ifdef HAVE_BUILTIN_EXPECT #define likely(x) __builtin_expect ((x) != 0, 1) diff --git a/src/libmpeg2new/libmpeg2/Makefile.am b/src/libmpeg2new/libmpeg2/Makefile.am index f99894f12..0bfeda1ce 100644 --- a/src/libmpeg2new/libmpeg2/Makefile.am +++ b/src/libmpeg2new/libmpeg2/Makefile.am @@ -1,13 +1,20 @@ include $(top_srcdir)/misc/Makefile.common -noinst_LTLIBRARIES = libmpeg2.la libmpeg2arch.la +if ENABLE_MPEG2NEW +mpeg2new_libs = libmpeg2.la libmpeg2arch.la +endif + +noinst_LTLIBRARIES = $(mpeg2new_libs) libmpeg2_la_SOURCES = alloc.c header.c decode.c slice.c motion_comp.c idct.c libmpeg2_la_LIBADD = libmpeg2arch.la +AM_CPPFLAGS = -I$(srcdir)/../include + libmpeg2arch_la_SOURCES = motion_comp_mmx.c idct_mmx.c \ motion_comp_altivec.c idct_altivec.c \ motion_comp_alpha.c idct_alpha.c \ motion_comp_vis.c \ cpu_accel.c cpu_state.c +EXTRA_DIST = mpeg2_internal.h vlc.h diff --git a/src/libmpeg2new/libmpeg2/motion_comp_alpha.c b/src/libmpeg2new/libmpeg2/motion_comp_alpha.c index 05cd55084..73f6625d2 100644 --- a/src/libmpeg2new/libmpeg2/motion_comp_alpha.c +++ b/src/libmpeg2new/libmpeg2/motion_comp_alpha.c @@ -26,10 +26,10 @@ #include <inttypes.h> -#include "mpeg2.h" -#include "attributes.h" +#include "../include/mpeg2.h" +#include "../include/attributes.h" #include "mpeg2_internal.h" -#include "alpha_asm.h" +#include "../include/alpha_asm.h" static inline uint64_t avg2 (uint64_t a, uint64_t b) { diff --git a/src/libmpeg2new/libmpeg2/motion_comp_altivec.c b/src/libmpeg2new/libmpeg2/motion_comp_altivec.c index 4356aa6e7..cc1b72f56 100644 --- a/src/libmpeg2new/libmpeg2/motion_comp_altivec.c +++ b/src/libmpeg2new/libmpeg2/motion_comp_altivec.c @@ -30,8 +30,8 @@ #endif #include <inttypes.h> -#include "mpeg2.h" -#include "attributes.h" +#include "../include/mpeg2.h" +#include "../include/attributes.h" #include "mpeg2_internal.h" typedef vector signed char vector_s8_t; diff --git a/src/libmpeg2new/libmpeg2/motion_comp_vis.c b/src/libmpeg2new/libmpeg2/motion_comp_vis.c index 54c0f7e75..e4b61aaa7 100644 --- a/src/libmpeg2new/libmpeg2/motion_comp_vis.c +++ b/src/libmpeg2new/libmpeg2/motion_comp_vis.c @@ -22,14 +22,14 @@ #include "config.h" -#ifdef ARCH_SPARC +#if defined(ARCH_SPARC) && defined(ENABLE_VIS) #include <inttypes.h> -#include "mpeg2.h" -#include "attributes.h" +#include "../include/mpeg2.h" +#include "../include/attributes.h" #include "mpeg2_internal.h" -#include "vis.h" +#include "../include/vis.h" /* The trick used in some of this file is the formula from the MMX * motion comp code, which is: @@ -2058,4 +2058,4 @@ static void MC_avg_xy_8_vis (uint8_t * dest, const uint8_t * _ref, MPEG2_MC_EXTERN(vis); -#endif /* !(ARCH_SPARC) */ +#endif /* defined(ARCH_SPARC) && defined(ENABLE_VIS) */ diff --git a/src/libmpeg2new/xine_mpeg2new_decoder.c b/src/libmpeg2new/xine_mpeg2new_decoder.c index c096ccfa7..8c16c441b 100644 --- a/src/libmpeg2new/xine_mpeg2new_decoder.c +++ b/src/libmpeg2new/xine_mpeg2new_decoder.c @@ -20,6 +20,10 @@ * stuff needed to turn libmpeg2 into a xine decoder plugin */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> @@ -35,13 +39,14 @@ #include "video_out.h" #include "buffer.h" - - +/* #define LOG #define LOG_FRAME_ALLOC_FREE #define LOG_ENTRY #define LOG_FRAME_COUNTER +*/ +#define _x_abort() do {} while (0) typedef struct { video_decoder_class_t decoder_class; @@ -66,7 +71,9 @@ typedef struct mpeg2_video_decoder_s { } mpeg2_video_decoder_t; - +#ifndef LOG_FRAME_ALLOC_FREE +inline static void mpeg2_video_print_bad_state(img_state_t * img_state) {} +#else static void mpeg2_video_print_bad_state(img_state_t * img_state) { int32_t n,m; m=0; @@ -79,6 +86,7 @@ static void mpeg2_video_print_bad_state(img_state_t * img_state) { if (m > 3) _x_abort(); if (m == 0) printf("NO FRAMES\n"); } +#endif static void mpeg2_video_free_all(img_state_t * img_state) { int32_t n,m; @@ -153,7 +161,7 @@ static void mpeg2_video_decode_data (video_decoder_t *this_gen, buf_element_t *b _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, info->sequence->picture_width); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, info->sequence->picture_height); _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, info->sequence->frame_period / 300); - if (this->force_aspect) info->sequence->pixel_width = this->force_aspect; + if (this->force_aspect) ((mpeg2_sequence_t *)info->sequence)->pixel_width = this->force_aspect; /* ugly... */ switch (info->sequence->pixel_width) { case 3: this->ratio = 16.0 / 9.0; @@ -503,14 +511,14 @@ static void *init_plugin (xine_t *xine, void *data) { * exported plugin catalog entry */ -static uint32_t supported_types[] = { BUF_VIDEO_MPEG, 0 }; +static const uint32_t supported_types[] = { BUF_VIDEO_MPEG, 0 }; -static decoder_info_t dec_info_mpeg2 = { +static const decoder_info_t dec_info_mpeg2 = { supported_types, /* supported types */ 6 /* priority */ }; -plugin_info_t xine_plugin_info[] = { +const plugin_info_t xine_plugin_info[] EXPORTED = { /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_DECODER, 18, "mpeg2new", XINE_VERSION_CODE, &dec_info_mpeg2, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } diff --git a/src/libmusepack/Makefile.am b/src/libmusepack/Makefile.am index 01875bdad..11344c3c2 100644 --- a/src/libmusepack/Makefile.am +++ b/src/libmusepack/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common SUBDIRS = musepack diff --git a/src/libmusepack/xine_musepack_decoder.c b/src/libmusepack/xine_musepack_decoder.c index 115532e86..5977abd63 100644 --- a/src/libmusepack/xine_musepack_decoder.c +++ b/src/libmusepack/xine_musepack_decoder.c @@ -24,6 +24,10 @@ * Seeking?? */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -43,6 +47,8 @@ #ifdef HAVE_MPCDEC_MPCDEC_H # include <mpcdec/mpcdec.h> +#elif defined(HAVE_MPC_MPCDEC_H) +# include <mpc/mpcdec.h> #else # include "musepack/musepack.h" #endif @@ -74,7 +80,11 @@ typedef struct mpc_decoder_s { mpc_reader reader; mpc_streaminfo streaminfo; +#ifndef HAVE_MPC_MPCDEC_H mpc_decoder decoder; +#else + mpc_demux *decoder; +#endif int decoder_ok; unsigned int current_frame; @@ -89,8 +99,13 @@ typedef struct mpc_decoder_s { *************************************************************************/ /* Reads size bytes of data into buffer at ptr. */ +#ifndef HAVE_MPC_MPCDEC_H static int32_t mpc_reader_read(void *data, void *ptr, int size) { mpc_decoder_t *this = (mpc_decoder_t *) data; +#else +static int32_t mpc_reader_read(mpc_reader *data, void *ptr, int size) { + mpc_decoder_t *this = (mpc_decoder_t *) data->data; +#endif lprintf("mpc_reader_read: size=%d\n", size); @@ -108,8 +123,13 @@ static int32_t mpc_reader_read(void *data, void *ptr, int size) { } /* Seeks to byte position offset. */ +#ifndef HAVE_MPC_MPCDEC_H static mpc_bool_t mpc_reader_seek(void *data, int32_t offset) { mpc_decoder_t *this = (mpc_decoder_t *) data; +#else +static mpc_bool_t mpc_reader_seek(mpc_reader *data, int32_t offset) { + mpc_decoder_t *this = (mpc_decoder_t *) data->data; +#endif lprintf("mpc_reader_seek: offset=%d\n", offset); @@ -117,11 +137,19 @@ static mpc_bool_t mpc_reader_seek(void *data, int32_t offset) { * that the buffer starts at the start of the file */ this->read = offset; +#ifndef HAVE_MPC_MPCDEC_H return TRUE; +#else + return MPC_TRUE; +#endif } /* Returns the current byte offset in the stream. */ +#ifndef HAVE_MPC_MPCDEC_H static int32_t mpc_reader_tell(void *data) { +#else +static int32_t mpc_reader_tell(mpc_reader *data) { +#endif lprintf("mpc_reader_tell\n"); /* Tell isn't used so just return 0 */ @@ -129,8 +157,13 @@ static int32_t mpc_reader_tell(void *data) { } /* Returns the total length of the source stream, in bytes. */ +#ifndef HAVE_MPC_MPCDEC_H static int32_t mpc_reader_get_size(void *data) { mpc_decoder_t *this = (mpc_decoder_t *) data; +#else +static int32_t mpc_reader_get_size(mpc_reader *data) { + mpc_decoder_t *this = (mpc_decoder_t *) data->data; +#endif lprintf("mpc_reader_get_size\n"); @@ -138,10 +171,17 @@ static int32_t mpc_reader_get_size(void *data) { } /* True if the stream is a seekable stream. */ +#ifndef HAVE_MPC_MPCDEC_H static mpc_bool_t mpc_reader_canseek(void *data) { lprintf("mpc_reader_canseek\n"); return TRUE; +#else +static mpc_bool_t mpc_reader_canseek(mpc_reader *data) { + + lprintf("mpc_reader_canseek\n"); + return MPC_TRUE; +#endif } /* Convert 32bit float samples into 16bit int samples */ @@ -161,10 +201,19 @@ static inline void float_to_int(float *_f, int16_t *s16, int samples) { static int mpc_decode_frame (mpc_decoder_t *this) { float buffer[MPC_DECODER_BUFFER_LENGTH]; uint32_t frames; +#ifdef HAVE_MPC_MPCDEC_H + mpc_frame_info frame; +#endif lprintf("mpd_decode_frame\n"); +#ifndef HAVE_MPC_MPCDEC_H frames = mpc_decoder_decode(&this->decoder, buffer, 0, 0); +#else + frame.buffer = buffer; + mpc_demux_decode(this->decoder, &frame); + frames = frame.samples; +#endif if (frames > 0) { audio_buffer_t *audio_buffer; @@ -231,6 +280,16 @@ static void mpc_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { xine_fast_memcpy(this->buf, buf->content, buf->size); this->size = buf->size; +#ifdef HAVE_MPC_MPCDEC_H + this->decoder = mpc_demux_init(&this->reader); + if (!this->decoder) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + _("libmusepack: mpc_demux_init failed.\n")); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0); + return; + } + mpc_demux_get_info(this->decoder, &this->streaminfo); +#else /* Initialise and read stream info */ mpc_streaminfo_init(&this->streaminfo); @@ -241,6 +300,7 @@ static void mpc_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0); return; } +#endif this->sample_rate = this->streaminfo.sample_freq; this->channels = this->streaminfo.channels; @@ -255,7 +315,9 @@ static void mpc_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { this->current_frame = 0; /* Setup the decoder */ +#ifndef HAVE_MPC_MPCDEC_H mpc_decoder_setup(&this->decoder, &this->reader); +#endif this->decoder_ok = 0; /* Take this opportunity to initialize stream/meta information */ @@ -308,7 +370,11 @@ static void mpc_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { /* Time to decode */ if (buf->decoder_flags & BUF_FLAG_FRAME_END) { /* Increment frame count */ +#ifndef HAVE_MPC_MPCDEC_H if (this->current_frame++ == this->streaminfo.frames) { +#else + if (this->current_frame++ == this->streaminfo.samples) { +#endif xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("libmusepack: data after last frame ignored\n")); return; @@ -319,7 +385,11 @@ static void mpc_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { if ((this->size - this->read) >= MPC_DECODER_MEMSIZE) { lprintf("initialise"); +#ifndef HAVE_MPC_MPCDEC_H if (!mpc_decoder_initialize(&this->decoder, &this->streaminfo)) { +#else + if (!this->decoder) { +#endif xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("libmusepack: mpc_decoder_initialise failed\n")); @@ -350,7 +420,11 @@ static void mpc_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { /* If we are at the end of the stream we decode the remaining frames as we * know we'll have enough data */ +#ifndef HAVE_MPC_MPCDEC_H if (this->current_frame == this->streaminfo.frames) { +#else + if (this->current_frame == this->streaminfo.samples) { +#endif lprintf("flushing buffers\n"); do { @@ -388,6 +462,10 @@ static void mpc_dispose (audio_decoder_t *this_gen) { /* free anything that was allocated during operation */ if (this->buf) free(this->buf); +#ifdef HAVE_MPC_MPCDEC_H + if (this->decoder) + mpc_demux_exit(this->decoder); +#endif free(this); } diff --git a/src/libreal/Makefile.am b/src/libreal/Makefile.am index 6e76d6279..90e47a63c 100644 --- a/src/libreal/Makefile.am +++ b/src/libreal/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common if ENABLE_REAL diff --git a/src/libreal/xine_real_audio_decoder.c b/src/libreal/xine_real_audio_decoder.c index 20f67a984..4187477e1 100644 --- a/src/libreal/xine_real_audio_decoder.c +++ b/src/libreal/xine_real_audio_decoder.c @@ -22,6 +22,10 @@ * code inspired by work from Florian Schneider for the MPlayer Project */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> diff --git a/src/libreal/xine_real_video_decoder.c b/src/libreal/xine_real_video_decoder.c index 3c575d0a8..314edc489 100644 --- a/src/libreal/xine_real_video_decoder.c +++ b/src/libreal/xine_real_video_decoder.c @@ -22,6 +22,10 @@ * code inspired by work from Florian Schneider for the MPlayer Project */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> diff --git a/src/libspucc/Makefile.am b/src/libspucc/Makefile.am index a8af8632e..1e170cdd5 100644 --- a/src/libspucc/Makefile.am +++ b/src/libspucc/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common xineplug_LTLIBRARIES = xineplug_decode_spucc.la diff --git a/src/libspucc/cc_decoder.c b/src/libspucc/cc_decoder.c index 67767c61a..98c7319b6 100644 --- a/src/libspucc/cc_decoder.c +++ b/src/libspucc/cc_decoder.c @@ -27,6 +27,10 @@ * available at http://sourceforge.net/projects/ccdecoder/. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/src/libspucc/xine_cc_decoder.c b/src/libspucc/xine_cc_decoder.c index 1d9c87366..12a5e7132 100644 --- a/src/libspucc/xine_cc_decoder.c +++ b/src/libspucc/xine_cc_decoder.c @@ -20,6 +20,10 @@ * closed caption spu decoder. receive data by events. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <stdio.h> #include <string.h> diff --git a/src/libspucmml/Makefile.am b/src/libspucmml/Makefile.am index 81e8d3623..53a980b57 100644 --- a/src/libspucmml/Makefile.am +++ b/src/libspucmml/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common xineplug_LTLIBRARIES = xineplug_decode_spucmml.la diff --git a/src/libspucmml/xine_cmml_decoder.c b/src/libspucmml/xine_cmml_decoder.c index c3da1b0fd..9cd446988 100644 --- a/src/libspucmml/xine_cmml_decoder.c +++ b/src/libspucmml/xine_cmml_decoder.c @@ -239,6 +239,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { spucmml_decoder_t *this = (spucmml_decoder_t *) this_gen; + xml_parser_t *xml_parser; xml_node_t *packet_xml_root; char * anchor_text = NULL; @@ -248,12 +249,15 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { /* parse the CMML */ - xml_parser_init (str, strlen (str), XML_PARSER_CASE_INSENSITIVE); - if (xml_parser_build_tree(&packet_xml_root) != XML_PARSER_OK) { + xml_parser = xml_parser_init_r (str, strlen (str), XML_PARSER_CASE_INSENSITIVE); + if (xml_parser_build_tree_r(xml_parser, &packet_xml_root) != XML_PARSER_OK) { lprintf ("warning: invalid XML packet detected in CMML track\n"); + xml_parser_finalize_r(xml_parser); return; } + xml_parser_finalize_r(xml_parser); + if (strcasecmp(packet_xml_root->name, "head") == 0) { /* found a <head>...</head> packet: need to parse the title */ diff --git a/src/libspudec/Makefile.am b/src/libspudec/Makefile.am index 208d994f5..061bd7731 100644 --- a/src/libspudec/Makefile.am +++ b/src/libspudec/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common xineplug_LTLIBRARIES = xineplug_decode_spu.la @@ -7,7 +8,7 @@ if HAVE_DVDNAV xineplug_decode_spu_la_SOURCES = \ spu.c \ xine_spu_decoder.c -xineplug_decode_spu_la_LIBADD = $(XINE_LIB) $(DVDNAV_LIBS) $(PTHREAD_LIBS) +xineplug_decode_spu_la_LIBADD = $(XINE_LIB) $(DVDNAV_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) else @@ -16,7 +17,7 @@ xineplug_decode_spu_la_SOURCES = \ spu.c \ xine_spu_decoder.c AM_CPPFLAGS = -I$(top_srcdir)/src/input/libdvdnav -xineplug_decode_spu_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS) +xineplug_decode_spu_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS) $(LTLIBINTL) endif diff --git a/src/libspudec/spu.c b/src/libspudec/spu.c index b41387dfb..e91cafbc1 100644 --- a/src/libspudec/spu.c +++ b/src/libspudec/spu.c @@ -37,6 +37,10 @@ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <errno.h> diff --git a/src/libspudec/spu.h b/src/libspudec/spu.h index 8d92146f0..464f77438 100644 --- a/src/libspudec/spu.h +++ b/src/libspudec/spu.h @@ -26,7 +26,7 @@ #define __SPU_H__ #ifdef HAVE_CONFIG_H -#include <config.h> +#include "config.h" #endif #include <inttypes.h> diff --git a/src/libspudec/xine_spu_decoder.c b/src/libspudec/xine_spu_decoder.c index 02bae6ac9..b6c06ca05 100644 --- a/src/libspudec/xine_spu_decoder.c +++ b/src/libspudec/xine_spu_decoder.c @@ -22,6 +22,10 @@ * stuff needed to turn libspu into a xine decoder plugin */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <unistd.h> #include <string.h> diff --git a/src/libspudvb/Makefile.am b/src/libspudvb/Makefile.am index 310c02f0b..8187346aa 100644 --- a/src/libspudvb/Makefile.am +++ b/src/libspudvb/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common xineplug_LTLIBRARIES = xineplug_decode_spudvb.la diff --git a/src/libspudvb/xine_spudvb_decoder.c b/src/libspudvb/xine_spudvb_decoder.c index 1e33c48af..62dced2d5 100644 --- a/src/libspudvb/xine_spudvb_decoder.c +++ b/src/libspudvb/xine_spudvb_decoder.c @@ -146,7 +146,6 @@ static void update_region (dvb_spu_decoder_t * this, int region_id, int region_w dvbsub_func_t *dvbsub = this->dvbsub; region_t *reg = &dvbsub->regions[region_id]; - page_t *page = &dvbsub->page; /* reject invalid sizes and set some limits ! */ if ( region_width<=0 || region_height<=0 || region_width>SPU_MAX_WIDTH || region_height>SPU_MAX_HEIGHT ) { @@ -325,22 +324,27 @@ static void set_clut(dvb_spu_decoder_t *this,int CLUT_id,int CLUT_entry_id,int Y static void process_CLUT_definition_segment(dvb_spu_decoder_t *this) { dvbsub_func_t *dvbsub = this->dvbsub; - const uint16_t page_id= _X_BE_16(&dvbsub->buf[dvbsub->i]); + /* + const uint16_t page_id= _X_BE_16(&dvbsub->buf[dvbsub->i]); + */ dvbsub->i+=2; const uint16_t segment_length= _X_BE_16(&dvbsub->buf[dvbsub->i]); dvbsub->i+=2; const int j=dvbsub->i+segment_length; const uint8_t CLUT_id=dvbsub->buf[dvbsub->i++]; - const uint8_t CLUT_version_number=(dvbsub->buf[dvbsub->i]&0xf0)>>4; + /* + const uint8_t CLUT_version_number=(dvbsub->buf[dvbsub->i]&0xf0)>>4; + */ dvbsub->i++; while (dvbsub->i < j) { const uint8_t CLUT_entry_id=dvbsub->buf[dvbsub->i++]; - - const uint8_t CLUT_flag_2_bit=(dvbsub->buf[dvbsub->i]&0x80)>>7; - const uint8_t CLUT_flag_4_bit=(dvbsub->buf[dvbsub->i]&0x40)>>6; - const uint8_t CLUT_flag_8_bit=(dvbsub->buf[dvbsub->i]&0x20)>>5; + /* + const uint8_t CLUT_flag_2_bit=(dvbsub->buf[dvbsub->i]&0x80)>>7; + const uint8_t CLUT_flag_4_bit=(dvbsub->buf[dvbsub->i]&0x40)>>6; + const uint8_t CLUT_flag_8_bit=(dvbsub->buf[dvbsub->i]&0x20)>>5; + */ const uint8_t full_range_flag=dvbsub->buf[dvbsub->i]&1; dvbsub->i++; @@ -453,13 +457,20 @@ static void process_region_composition_segment (dvb_spu_decoder_t * this) dvbsub->i += 2; const uint16_t region_height = _X_BE_16(&dvbsub->buf[dvbsub->i]); dvbsub->i += 2; - const uint8_t region_level_of_compatibility = (dvbsub->buf[dvbsub->i] & 0xe0) >> 5; - const uint8_t region_depth = (dvbsub->buf[dvbsub->i] & 0x1c) >> 2; + /* + const uint8_t region_level_of_compatibility = (dvbsub->buf[dvbsub->i] & 0xe0) >> 5; + const uint8_t region_depth = (dvbsub->buf[dvbsub->i] & 0x1c) >> 2; + */ dvbsub->i++; const uint8_t CLUT_id = dvbsub->buf[dvbsub->i++]; - const uint8_t region_8_bit_pixel_code = dvbsub->buf[dvbsub->i++]; + /* + const uint8_t region_8_bit_pixel_code = dvbsub->buf[dvbsub->i]; + */ + dvbsub->i++; const uint8_t region_4_bit_pixel_code = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; - const uint8_t region_2_bit_pixel_code = (dvbsub->buf[dvbsub->i] & 0x0c) >> 2; + /* + const uint8_t region_2_bit_pixel_code = (dvbsub->buf[dvbsub->i] & 0x0c) >> 2; + */ dvbsub->i++; if(region_id>=MAX_REGIONS) @@ -489,7 +500,9 @@ static void process_region_composition_segment (dvb_spu_decoder_t * this) const uint16_t object_id = _X_BE_16(&dvbsub->buf[dvbsub->i]); dvbsub->i += 2; const uint8_t object_type = (dvbsub->buf[dvbsub->i] & 0xc0) >> 6; - const uint8_t object_provider_flag = (dvbsub->buf[dvbsub->i] & 0x30) >> 4; + /* + const uint8_t object_provider_flag = (dvbsub->buf[dvbsub->i] & 0x30) >> 4; + */ const uint16_t object_x = ((dvbsub->buf[dvbsub->i] & 0x0f) << 8) | dvbsub->buf[dvbsub->i + 1]; dvbsub->i += 2; const uint16_t object_y = ((dvbsub->buf[dvbsub->i] & 0x0f) << 8) | dvbsub->buf[dvbsub->i + 1]; @@ -498,8 +511,11 @@ static void process_region_composition_segment (dvb_spu_decoder_t * this) dvbsub->regions[region_id].object_pos[object_id] = (object_x << 16) | object_y; if ((object_type == 0x01) || (object_type == 0x02)) { - const uint8_t foreground_pixel_code = dvbsub->buf[dvbsub->i++]; - const uint8_t background_pixel_code = dvbsub->buf[dvbsub->i++]; + /* + const uint8_t foreground_pixel_code = dvbsub->buf[dvbsub->i]; + const uint8_t background_pixel_code = dvbsub->buf[dvbsub->i+1]; + */ + dvbsub->i += 2; } } @@ -511,15 +527,19 @@ static void process_object_data_segment (dvb_spu_decoder_t * this) dvbsub->page.page_id = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; dvbsub->i += 2; - const uint16_t segment_length = _X_BE_16(&dvbsub->buf[dvbsub->i]); + /* + const uint16_t segment_length = _X_BE_16(&dvbsub->buf[dvbsub->i]); + */ dvbsub->i += 2; const uint16_t object_id = _X_BE_16(&dvbsub->buf[dvbsub->i]); dvbsub->i += 2; dvbsub->curr_obj = object_id; - const uint8_t object_version_number = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; const uint8_t object_coding_method = (dvbsub->buf[dvbsub->i] & 0x0c) >> 2; - const uint8_t non_modifying_colour_flag = (dvbsub->buf[dvbsub->i] & 0x02) >> 1; + /* + const uint8_t object_version_number = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; + const uint8_t non_modifying_colour_flag = (dvbsub->buf[dvbsub->i] & 0x02) >> 1; + */ dvbsub->i++; if ( object_coding_method != 0 ) @@ -765,8 +785,11 @@ static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf) this->dvbsub->i = 0; - const uint8_t data_identifier = this->dvbsub->buf[this->dvbsub->i++]; - const uint8_t subtitle_stream_id = this->dvbsub->buf[this->dvbsub->i++]; + /* + const uint8_t data_identifier = this->dvbsub->buf[this->dvbsub->i]; + const uint8_t subtitle_stream_id = this->dvbsub->buf[this->dvbsub->i+1]; + */ + this->dvbsub->i += 2; while (this->dvbsub->i <= (PES_packet_length)) { /* SUBTITLING SEGMENT */ diff --git a/src/libspuhdmv/Makefile.am b/src/libspuhdmv/Makefile.am new file mode 100644 index 000000000..15a029f8a --- /dev/null +++ b/src/libspuhdmv/Makefile.am @@ -0,0 +1,9 @@ +include $(top_builddir)/misc/Makefile.plugins +include $(top_srcdir)/misc/Makefile.common + +xineplug_LTLIBRARIES = xineplug_decode_spuhdmv.la + +xineplug_decode_spuhdmv_la_SOURCES = xine_hdmv_decoder.c +xineplug_decode_spuhdmv_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS) $(LTLIBINTL) +xineplug_decode_spuhdmv_la_CFLAGS = $(VISIBILITY_FLAG) +xineplug_decode_spuhdmv_la_LDFLAGS = $(xineplug_ldflags) diff --git a/src/libspuhdmv/xine_hdmv_decoder.c b/src/libspuhdmv/xine_hdmv_decoder.c new file mode 100644 index 000000000..ba4487bf6 --- /dev/null +++ b/src/libspuhdmv/xine_hdmv_decoder.c @@ -0,0 +1,1019 @@ +/* + * Copyright (C) 2000-2009 the xine project + * + * Copyright (C) 2009 Petri Hintukainen <phintuka@users.sourceforge.net> + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * Decoder for HDMV/BluRay bitmap subtitles + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <inttypes.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#ifdef HAVE_CONFIG_H +# include "xine_internal.h" +# include "buffer.h" +# include "xineutils.h" +# include "video_out.h" +# include "video_overlay.h" +#else +# include <xine/xine_internal.h> +# include <xine/buffer.h> +# include <xine/xineutils.h> +# include <xine/video_out.h> +# include <xine/video_overlay.h> +#endif + +#define TRACE(x...) printf(x) +/*#define TRACE(x...) */ +#define ERROR(x...) fprintf(stderr, "spuhdmv: " x) +/*#define ERROR(x...) lprintf(x) */ + +/* + * cached palette (xine-lib format) + */ +typedef struct subtitle_clut_s subtitle_clut_t; +struct subtitle_clut_s { + uint8_t id; + uint32_t color[256]; + uint8_t trans[256]; + subtitle_clut_t *next; + + int shown; +}; + +/* + * cached RLE image (xine-lib format) + */ +typedef struct subtitle_object_s subtitle_object_t; +struct subtitle_object_s { + uint16_t id; + uint16_t xpos, ypos; + uint16_t width, height; + + rle_elem_t *rle; + uint num_rle; + size_t data_size; + +#if 0 + uint8_t *raw_data; /* partial RLE data in HDMV format */ + size_t raw_data_len; + size_t raw_data_size; +#endif + + subtitle_object_t *next; + + int shown; +}; + +/* + * Window definition + */ +typedef struct window_def_s window_def_t; +struct window_def_s { + uint8_t id; + uint16_t xpos, ypos; + uint16_t width, height; + + window_def_t *next; + + int shown; +}; + + +/* + * decoded SPU + */ +typedef struct composition_object_s composition_object_t; +struct composition_object_s { + uint8_t window_id_ref; + uint8_t object_id_ref; + + uint16_t xpos, ypos; + + uint8_t forced_flag; + uint8_t cropped_flag; + uint16_t crop_horiz_pos, crop_vert_pos; + uint16_t crop_width, crop_height; + + composition_object_t *next; + + int shown; +}; + +typedef struct composition_descriptor_s composition_descriptor_t; +struct composition_descriptor_s { + uint16_t number; + uint8_t state; +}; + +typedef struct presentation_segment_s presentation_segment_t; +struct presentation_segment_s { + composition_descriptor_t comp_descr; + + uint8_t palette_update_flag; + uint8_t palette_id_ref; + uint8_t object_number; + + composition_object_t *comp_objs; + + presentation_segment_t *next; + + int64_t pts; + int shown; +}; + +/* + * list handling + */ + +#define LIST_REPLACE(list, obj, FREE_FUNC) \ + do { \ + uint id = obj->id; \ + \ + /* insert to list */ \ + obj->next = list; \ + list = obj; \ + \ + /* remove old */ \ + while (obj->next && obj->next->id != id) \ + obj = obj->next; \ + if (obj->next) { \ + void *tmp = (void*)obj->next; \ + obj->next = obj->next->next; \ + FREE_FUNC(tmp); \ + } \ + } while (0); + +#define LIST_DESTROY(list, FREE_FUNC) \ + while (list) { \ + void *tmp = (void*)list; \ + list = list->next; \ + FREE_FUNC(tmp); \ + } + +static void free_subtitle_object(void *ptr) +{ + if (ptr) { + free(((subtitle_object_t*)ptr)->rle); + free(ptr); + } +} +static void free_presentation_segment(void *ptr) +{ + if (ptr) { + presentation_segment_t *seg = (presentation_segment_t*)ptr; + LIST_DESTROY(seg->comp_objs, free); + free(ptr); + } +} + + +/* + * segment_buffer_t + * + * assemble and decode segments + */ + +typedef struct { + /* current segment */ + int segment_len; /* length of current segment (without 3-byte header) */ + uint8_t segment_type; /* current segment type */ + uint8_t *segment_data; /* pointer to current segment payload */ + uint8_t *segment_end; /* pointer to last byte + 1 of current segment */ + uint8_t error; /* boolean: buffer overflow etc. */ + + /* accumulated data */ + uint8_t *buf; /* */ + size_t len; /* count of unprocessed bytes */ + size_t data_size; /* allocated buffer size */ +} segment_buffer_t; + +/* + * mgmt + */ + +static segment_buffer_t *segbuf_init(void) +{ + segment_buffer_t *buf = calloc(1, sizeof(segment_buffer_t)); + return buf; +} + +static void segbuf_dispose(segment_buffer_t *buf) +{ + if (buf->buf) + free (buf->buf); + free (buf); +} + +static void segbuf_reset(segment_buffer_t *buf) +{ + buf->segment_end = buf->segment_data = buf->buf; + buf->len = 0; + buf->segment_len = -1; + buf->segment_type = 0; + buf->error = 0; +} + +/* + * assemble, parse + */ + +static void segbuf_parse_segment_header(segment_buffer_t *buf) +{ + if (buf->len > 2) { + buf->segment_type = buf->buf[0]; + buf->segment_len = (buf->buf[1] << 8) | buf->buf[2]; + buf->segment_data = buf->buf + 3; + buf->segment_end = buf->segment_data + buf->segment_len; + buf->error = 0; + + if ( buf->segment_type < 0x14 || + ( buf->segment_type > 0x18 && + buf->segment_type != 0x80)) { + ERROR("unknown segment type, resetting\n"); + segbuf_reset(buf); + } + } else { + buf->segment_len = -1; + buf->error = 1; + } +} + +static void segbuf_fill(segment_buffer_t *buf, uint8_t *data, size_t len) +{ + if (buf->len + len > buf->data_size) { + buf->data_size = buf->len + len; + if (buf->buf) + buf->buf = realloc(buf->buf, buf->data_size); + else + buf->buf = malloc(buf->data_size); + } + + memcpy(buf->buf + buf->len, data, len); + buf->len += len; + + segbuf_parse_segment_header(buf); +} + +static int segbuf_segment_complete(segment_buffer_t *buf) +{ + return (buf->segment_len >= 0) && (buf->len >= buf->segment_len + 3); +} + +static void segbuf_skip_segment(segment_buffer_t *buf) +{ + if (segbuf_segment_complete (buf)) { + buf->len -= buf->segment_len + 3; + if (buf->len > 0) + memmove(buf->buf, buf->buf + buf->segment_len + 3, buf->len); + + segbuf_parse_segment_header(buf); + + TRACE(" skip_segment: %d bytes left\n", (uint)buf->len); + } else { + ERROR(" skip_segment: ERROR - %d bytes queued, %d required\n", + (uint)buf->len, buf->segment_len); + segbuf_reset (buf); + } +} + +/* + * access segment data + */ + +static uint8_t segbuf_segment_type(segment_buffer_t *buf) +{ + return buf->segment_type; +} + +static size_t segbuf_data_length(segment_buffer_t *buf) +{ + ssize_t val = buf->segment_end - buf->segment_data; + if (val < 0) val = 0; + return (size_t)val; +} + +static uint8_t segbuf_get_u8(segment_buffer_t *buf) +{ + if (!(buf->error = ++buf->segment_data > buf->segment_end)) + return buf->segment_data[-1]; + ERROR("segbuf_get_u8: read failed (end of segment reached) !"); + return 0; +} + +static uint16_t segbuf_get_u16(segment_buffer_t *buf) +{ + return (segbuf_get_u8(buf) << 8) | segbuf_get_u8(buf); +} + +static uint32_t segbuf_get_u24(segment_buffer_t *buf) +{ + return (segbuf_get_u8(buf) << 16) | (segbuf_get_u8(buf) << 8) | segbuf_get_u8(buf); +} + +static uint8_t *segbuf_get_string(segment_buffer_t *buf, size_t len) +{ + if (len > 0) { + uint8_t *val = buf->segment_data; + buf->segment_data += len; + if (buf->segment_data <= buf->segment_end) + return val; + } + ERROR("segbuf_get_string(%d): read failed (end of segment reached) !", (int)len); + buf->error = 1; + return NULL; +} + +/* + * decode segments + */ + +static subtitle_clut_t *segbuf_decode_palette(segment_buffer_t *buf) +{ + uint8_t palette_id = segbuf_get_u8 (buf); + uint8_t palette_version_number = segbuf_get_u8 (buf); + + size_t len = segbuf_data_length(buf); + size_t entries = len / 5; + int i; + + if (buf->error) + return NULL; + + if (len % 5) { + ERROR(" decode_palette: segment size error (%d ; expected %d for %d entries)\n", + (uint)len, (uint)(5 * entries), (uint)entries); + return NULL; + } + TRACE("decode_palette: %d items (id %d, version %d)\n", + (uint)entries, palette_id, palette_version_number); + + /* convert to xine-lib clut */ + subtitle_clut_t *clut = calloc(1, sizeof(subtitle_clut_t)); + clut->id = palette_id; + + for (i = 0; i < entries; i++) { + uint8_t index = segbuf_get_u8 (buf); + uint8_t Y = segbuf_get_u8 (buf); + uint8_t Cr = segbuf_get_u8 (buf); + uint8_t Cb = segbuf_get_u8 (buf); + uint8_t alpha = segbuf_get_u8 (buf); + clut->color[index] = (Y << 16) | (Cr << 8) | Cb; + clut->trans[index] = alpha >> 4; + } + + return clut; +} + +static int segbuf_decode_rle(segment_buffer_t *buf, subtitle_object_t *obj) +{ + int x = 0, y = 0; + int rle_size = sizeof(rle_elem_t) * obj->width / 16 * obj->height + 1; + rle_elem_t *rlep = malloc(rle_size); + + free (obj->rle); + obj->rle = rlep; + obj->data_size = rle_size; + obj->num_rle = 0; + + /* convert to xine-lib rle format */ + while (y < obj->height && !buf->error) { + + /* decode RLE element */ + uint8_t byte = segbuf_get_u8 (buf); + if (byte != 0) { + rlep->color = byte; + rlep->len = 1; + } else { + byte = segbuf_get_u8 (buf); + if (!(byte & 0x80)) { + rlep->color = 0; + if (!(byte & 0x40)) + rlep->len = byte & 0x3f; + else + rlep->len = ((byte & 0x3f) << 8) | segbuf_get_u8 (buf); + } else { + if (!(byte & 0x40)) + rlep->len = byte & 0x3f; + else + rlep->len = ((byte & 0x3f) << 8) | segbuf_get_u8 (buf); + rlep->color = segbuf_get_u8 (buf); + } + } + + /* move to next element */ + if (rlep->len > 0) { + x += rlep->len; + rlep++; + obj->num_rle ++; + } else { + /* end of line marker (00 00) */ + if (x < obj->width) { + rlep->len = obj->width - x; + rlep->color = 0xff; + rlep++; + obj->num_rle ++; + } + x = 0; + y++; + } + + /* grow allocated RLE data size ? */ + if (obj->data_size <= (obj->num_rle + 1) * sizeof(rle_elem_t)) { + obj->data_size *= 2; + obj->rle = realloc(obj->rle, obj->data_size); + rlep = obj->rle + obj->num_rle; + } + } + + return buf->error; +} + +static subtitle_object_t *segbuf_decode_object(segment_buffer_t *buf) +{ + uint8_t object_id = segbuf_get_u16(buf); + uint8_t version = segbuf_get_u8 (buf); + uint8_t seq_desc = segbuf_get_u8 (buf); + + TRACE(" decode_object: object_id %d, version %d, seq 0x%x\n", + object_id, version, seq_desc); + + //LIST_FIND(); + subtitle_object_t *obj = calloc(1, sizeof(subtitle_object_t)); + obj->id = object_id; + + if (seq_desc & 0x80) { + + uint32_t data_len = segbuf_get_u24(buf); + obj->width = segbuf_get_u16(buf); + obj->height = segbuf_get_u16(buf); + + TRACE(" object length %d bytes, size %dx%d\n", data_len, obj->width, obj->height); + + segbuf_decode_rle (buf, obj); + + if (buf->error) { + free_subtitle_object(obj); + return NULL; + } + + } else { + ERROR(" TODO: APPEND RLE, length %d bytes\n", buf->segment_len - 4); + /* TODO */ + free_subtitle_object(obj); + return NULL; + } + + return obj; +} + +static window_def_t *segbuf_decode_window_definition(segment_buffer_t *buf) +{ + window_def_t *wnd = calloc(1, sizeof(window_def_t)); + + uint8_t a = segbuf_get_u8 (buf); + wnd->id = segbuf_get_u8 (buf); + wnd->xpos = segbuf_get_u16 (buf); + wnd->ypos = segbuf_get_u16 (buf); + wnd->width = segbuf_get_u16 (buf); + wnd->height = segbuf_get_u16 (buf); + + TRACE(" window: [%02x %d] %d,%d %dx%d\n", a, + wnd->id, wnd->xpos, wnd->ypos, wnd->width, wnd->height); + + if (buf->error) { + free(wnd); + return NULL; + } + + return wnd; +} + +static int segbuf_decode_video_descriptor(segment_buffer_t *buf) +{ + uint16_t width = segbuf_get_u16(buf); + uint16_t height = segbuf_get_u16(buf); + uint8_t frame_rate = segbuf_get_u8 (buf); + + TRACE(" video_descriptor: %dx%d fps %d\n", width, height, frame_rate); + return buf->error; +} + +static int segbuf_decode_composition_descriptor(segment_buffer_t *buf, composition_descriptor_t *descr) +{ + descr->number = segbuf_get_u16(buf); + descr->state = segbuf_get_u8 (buf); + + TRACE(" composition_descriptor: number %d, state %d\n", descr->number, descr->state); + return buf->error; +} + +static composition_object_t *segbuf_decode_composition_object(segment_buffer_t *buf) +{ + composition_object_t *cobj = calloc(1, sizeof(composition_object_t)); + + cobj->object_id_ref = segbuf_get_u16 (buf); + cobj->window_id_ref = segbuf_get_u8 (buf); + uint8_t tmp = segbuf_get_u8 (buf); + cobj->cropped_flag = !!(tmp & 0x80); + cobj->forced_flag = !!(tmp & 0x40); + cobj->xpos = segbuf_get_u16 (buf); + cobj->ypos = segbuf_get_u16 (buf); + if (cobj->cropped_flag) { + /* x,y where to take the image from */ + cobj->crop_horiz_pos = segbuf_get_u8 (buf); + cobj->crop_vert_pos = segbuf_get_u8 (buf); + /* size of the cropped image */ + cobj->crop_width = segbuf_get_u8 (buf); + cobj->crop_height = segbuf_get_u8 (buf); + } + + if (buf->error) { + free(cobj); + return NULL; + } + + TRACE(" composition_object: id: %d, win: %d, position %d,%d crop %d forced %d\n", + cobj->object_id_ref, cobj->window_id_ref, cobj->xpos, cobj->ypos, + cobj->cropped_flag, cobj->forced_flag); + + return cobj; +} + +static presentation_segment_t *segbuf_decode_presentation_segment(segment_buffer_t *buf) +{ + presentation_segment_t *seg = calloc(1, sizeof(presentation_segment_t)); + int index; + + segbuf_decode_video_descriptor (buf); + segbuf_decode_composition_descriptor (buf, &seg->comp_descr); + + seg->palette_update_flag = !!((segbuf_get_u8(buf)) & 0x80); + seg->palette_id_ref = segbuf_get_u8 (buf); + seg->object_number = segbuf_get_u8 (buf); + + TRACE(" presentation_segment: object_number %d, palette %d\n", + seg->object_number, seg->palette_id_ref); + + for (index = 0; index < seg->object_number; index++) { + composition_object_t *cobj = segbuf_decode_composition_object (buf); + cobj->next = seg->comp_objs; + seg->comp_objs = cobj; + } + + if (buf->error) { + free_presentation_segment(seg); + return NULL; + } + + return seg; +} + +static rle_elem_t *copy_crop_rle(subtitle_object_t *obj, composition_object_t *cobj) +{ + /* TODO: cropping (w,h sized image from pos x,y) */ + + rle_elem_t *rle = calloc (obj->num_rle, sizeof(rle_elem_t)); + memcpy (rle, obj->rle, obj->num_rle * sizeof(rle_elem_t)); + return rle; +} + + +/* + * xine plugin + */ + +typedef struct { + spu_decoder_class_t decoder_class; +} spuhdmv_class_t; + +typedef struct spuhdmv_decoder_s { + spu_decoder_t spu_decoder; + + spuhdmv_class_t *class; + xine_stream_t *stream; + + segment_buffer_t *buf; + + subtitle_clut_t *cluts; + subtitle_object_t *objects; + window_def_t *windows; + presentation_segment_t *segments; + + int overlay_handles[MAX_OBJECTS]; + + int64_t pts; + +} spuhdmv_decoder_t; + +static int decode_palette(spuhdmv_decoder_t *this) +{ + /* decode */ + subtitle_clut_t *clut = segbuf_decode_palette(this->buf); + if (!clut) + return 1; + + LIST_REPLACE (this->cluts, clut, free); + + return 0; +} + +static int decode_object(spuhdmv_decoder_t *this) +{ + /* decode */ + subtitle_object_t *obj = segbuf_decode_object(this->buf); + if (!obj) + return 1; + + LIST_REPLACE (this->objects, obj, free_subtitle_object); + + return 0; +} + +static int decode_window_definition(spuhdmv_decoder_t *this) +{ + /* decode */ + window_def_t *wnd = segbuf_decode_window_definition (this->buf); + if (!wnd) + return 1; + + LIST_REPLACE (this->windows, wnd, free); + + return 0; +} + +static int decode_presentation_segment(spuhdmv_decoder_t *this) +{ + /* decode */ + presentation_segment_t *seg = segbuf_decode_presentation_segment(this->buf); + if (!seg) + return 1; + + seg->pts = this->pts; + + /* replace */ + if (this->segments) + LIST_DESTROY(this->segments, free_presentation_segment); + this->segments = seg; + + return 0; +} + +static int show_overlay(spuhdmv_decoder_t *this, composition_object_t *cobj, uint palette_id_ref, + int overlay_index, int64_t pts, int force_update) +{ + video_overlay_manager_t *ovl_manager = this->stream->video_out->get_overlay_manager(this->stream->video_out); + metronom_t *metronom = this->stream->metronom; + video_overlay_event_t event = {0}; + vo_overlay_t overlay = {0}; + + /* find palette */ + subtitle_clut_t *clut = this->cluts; + while (clut && clut->id != palette_id_ref) + clut = clut->next; + if (!clut) { + TRACE(" show_overlay: clut %d not found !\n", palette_id_ref); + return -1; + } + + /* find RLE image */ + subtitle_object_t *obj = this->objects; + while (obj && obj->id != cobj->object_id_ref) + obj = obj->next; + if (!obj) { + TRACE(" show_overlay: object %d not found !\n", cobj->object_id_ref); + return -1; + } + + /* find window */ + window_def_t *wnd = this->windows; + while (wnd && wnd->id != cobj->window_id_ref) + wnd = wnd->next; + if (!wnd) { + TRACE(" show_overlay: window %d not found !\n", cobj->window_id_ref); + return -1; + } + + /* do not show again if all elements are unchanged */ + if (!force_update && clut->shown && obj->shown && wnd->shown && cobj->shown) + return 0; + clut->shown = obj->shown = wnd->shown = cobj->shown = 1; + + /* copy palette to xine overlay */ + overlay.rgb_clut = 0; + memcpy(overlay.color, clut->color, sizeof(uint32_t) * 256); + memcpy(overlay.trans, clut->trans, sizeof(uint8_t) * 256); + + /* copy and crop RLE image to xine overlay */ + overlay.width = obj->width; + overlay.height = obj->height; + + overlay.rle = copy_crop_rle (obj, cobj); + overlay.num_rle = obj->num_rle; + overlay.data_size = obj->num_rle * sizeof(rle_elem_t); + + /* */ + + overlay.x = /*wnd->xpos +*/ cobj->xpos; + overlay.y = /*wnd->ypos +*/ cobj->ypos; + + overlay.unscaled = 0; + overlay.hili_top = -1; + overlay.hili_bottom = -1; + overlay.hili_left = -1; + overlay.hili_right = -1; + + TRACE(" -> overlay: %d,%d %dx%d\n", + overlay.x, overlay.y, overlay.width, overlay.height); + + + /* set timings */ + + if (pts > 0) + event.vpts = metronom->got_spu_packet (metronom, pts); + else + event.vpts = 0; + + + /* generate SHOW event */ + + this->stream->video_out->enable_ovl(this->stream->video_out, 1); + + if (this->overlay_handles[overlay_index] < 0) + this->overlay_handles[overlay_index] = ovl_manager->get_handle(ovl_manager, 0); + + event.event_type = OVERLAY_EVENT_SHOW; + event.object.handle = this->overlay_handles[overlay_index]; + event.object.overlay = &overlay; + event.object.object_type = 0; /* subtitle */ + + ovl_manager->add_event (ovl_manager, (void *)&event); + + return 0; +} + +static void hide_overlays(spuhdmv_decoder_t *this, int64_t pts) +{ + video_overlay_event_t event = {0}; + int i = 0; + + while (this->overlay_handles[i] >= 0) { + TRACE(" -> HIDE %d\n", i); + + video_overlay_manager_t *ovl_manager = this->stream->video_out->get_overlay_manager(this->stream->video_out); + metronom_t *metronom = this->stream->metronom; + + event.object.handle = this->overlay_handles[i]; + if (this) + event.vpts = metronom->got_spu_packet (metronom, pts); + else + event.vpts = 0; + event.event_type = OVERLAY_EVENT_HIDE; + event.object.overlay = NULL; + ovl_manager->add_event (ovl_manager, (void *)&event); + + //this->overlay_handles[i] = -1; + i++; + } +} + +static void update_overlays(spuhdmv_decoder_t *this) +{ + presentation_segment_t *pseg = this->segments; + + while (pseg) { + + if (!pseg->comp_descr.state) { + + /* HIDE */ + if (!pseg->shown) + hide_overlays (this, pseg->pts); + + } else { + + /* SHOW */ + composition_object_t *cobj = pseg->comp_objs; + int i; + + for (i = 0; i < pseg->object_number; i++) { + if (!cobj) { + ERROR("show_overlays: composition object %d missing !\n", i); + } else { + show_overlay(this, cobj, pseg->palette_id_ref, i, pseg->pts, !pseg->shown); + cobj = cobj->next; + } + } + } + + pseg->shown = 1; + + pseg = pseg->next; + } +} + +static void free_objs(spuhdmv_decoder_t *this) +{ + LIST_DESTROY (this->cluts, free); + LIST_DESTROY (this->objects, free_subtitle_object); + LIST_DESTROY (this->windows, free); + LIST_DESTROY (this->segments, free_presentation_segment); +} + +static void decode_segment(spuhdmv_decoder_t *this) +{ + TRACE("*** new segment, pts %010ld: 0x%02x (%8d bytes)", + this->pts, (uint)this->buf->segment_type, (uint)this->buf->segment_len); + + switch (this->buf->segment_type) { + case 0x14: + TRACE(" segment: PALETTE\n"); + decode_palette(this); + break; + case 0x15: + TRACE(" segment: OBJECT\n"); + decode_object(this); + break; + case 0x16: + TRACE(" segment: PRESENTATION SEGMENT\n"); + decode_presentation_segment(this); + break; + case 0x17: + TRACE(" segment: WINDOW DEFINITION\n"); + decode_window_definition(this); + break; + case 0x18: + TRACE(" segment: INTERACTIVE\n"); + break; + case 0x80: + TRACE(" segment: END OF DISPLAY\n"); + /* drop all cached objects */ + free_objs(this); + break; + default: + ERROR(" segment type 0x%x unknown, skipping\n", this->buf->segment_type); + break; + } + if (this->buf->error) { + ERROR("*** DECODE ERROR ***\n"); + } + + update_overlays (this); +} + +static void close_osd(spuhdmv_decoder_t *this) +{ + video_overlay_manager_t *ovl_manager = this->stream->video_out->get_overlay_manager (this->stream->video_out); + + int i = 0; + while (this->overlay_handles[i] >= 0) { + ovl_manager->free_handle(ovl_manager, this->overlay_handles[i]); + this->overlay_handles[i] = -1; + i++; + } +} + +static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf) +{ + spuhdmv_decoder_t *this = (spuhdmv_decoder_t *) this_gen; + + if ((buf->type & 0xffff0000) != BUF_SPU_HDMV) + return; + + if (buf->size < 1) + return; + + if (buf->pts) + this->pts = buf->pts; + +#ifdef DUMP_SPU_DATA + int i; + for(i = 0; i < buf->size; i++) + printf(" %02x", buf->content[i]); + printf("\n"); +#endif + + segbuf_fill(this->buf, buf->content, buf->size); + + while (segbuf_segment_complete(this->buf)) { + decode_segment(this); + segbuf_skip_segment(this->buf); + } +} + +static void spudec_reset (spu_decoder_t * this_gen) +{ + spuhdmv_decoder_t *this = (spuhdmv_decoder_t *) this_gen; + + if (this->buf) + segbuf_reset(this->buf); + + free_objs(this); + + close_osd(this); +} + +static void spudec_discontinuity (spu_decoder_t *this_gen) +{ + spuhdmv_decoder_t *this = (spuhdmv_decoder_t *) this_gen; + + close_osd(this); +} + +static void spudec_dispose (spu_decoder_t *this_gen) +{ + spuhdmv_decoder_t *this = (spuhdmv_decoder_t *) this_gen; + + close_osd (this); + segbuf_dispose (this->buf); + + free_objs(this); + + free (this); +} + +static spu_decoder_t *open_plugin (spu_decoder_class_t *class_gen, xine_stream_t *stream) +{ + spuhdmv_decoder_t *this; + + this = (spuhdmv_decoder_t *) calloc(1, sizeof (spuhdmv_decoder_t)); + + this->spu_decoder.decode_data = spudec_decode_data; + this->spu_decoder.reset = spudec_reset; + this->spu_decoder.discontinuity = spudec_discontinuity; + this->spu_decoder.dispose = spudec_dispose; + this->spu_decoder.get_interact_info = NULL; + this->spu_decoder.set_button = NULL; + this->stream = stream; + this->class = (spuhdmv_class_t *) class_gen; + + this->buf = segbuf_init(); + + memset(this->overlay_handles, 0xff, sizeof(this->overlay_handles)); /* --> -1 */ + + return &this->spu_decoder; +} + +static char *get_identifier (spu_decoder_class_t *this) +{ + return "spuhdmv"; +} + +static char *get_description (spu_decoder_class_t *this) +{ + return "HDMV/BluRay bitmap SPU decoder plugin"; +} + +static void dispose_class (spu_decoder_class_t *this) +{ + free (this); +} + +static void *init_plugin (xine_t *xine, void *data) +{ + spuhdmv_class_t *this; + + this = calloc(1, sizeof (spuhdmv_class_t)); + + this->decoder_class.open_plugin = open_plugin; + this->decoder_class.get_identifier = get_identifier; + this->decoder_class.get_description = get_description; + this->decoder_class.dispose = dispose_class; + + return this; +} + +/* plugin catalog information */ +static uint32_t supported_types[] = { BUF_SPU_HDMV, 0 }; + +static const decoder_info_t dec_info_data = { + supported_types, /* supported types */ + 5 /* priority */ +}; + +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_SPU_DECODER, 16, "spuhdmv", XINE_VERSION_CODE, &dec_info_data, &init_plugin }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; diff --git a/src/libsputext/Makefile.am b/src/libsputext/Makefile.am index 4f03d7fa9..62258933d 100644 --- a/src/libsputext/Makefile.am +++ b/src/libsputext/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_LDFLAGS = $(xineplug_ldflags) diff --git a/src/libsputext/demux_sputext.c b/src/libsputext/demux_sputext.c index 3e9efb079..198c30498 100644 --- a/src/libsputext/demux_sputext.c +++ b/src/libsputext/demux_sputext.c @@ -147,7 +147,7 @@ static inline void trail_space(char *s) { static char *read_line_from_input(demux_sputext_t *this, char *line, off_t len) { off_t nread = 0; - if ((len - this->buflen) > 512) { + if ((len - this->buflen) > 512 && len < SUB_BUFSIZE) { if((nread = this->input->read(this->input, &this->buf[this->buflen], len - this->buflen)) < 0) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "read failed.\n"); diff --git a/src/libsputext/xine_sputext_decoder.c b/src/libsputext/xine_sputext_decoder.c index 5da948f4e..7d5e73ce9 100644 --- a/src/libsputext/xine_sputext_decoder.c +++ b/src/libsputext/xine_sputext_decoder.c @@ -18,6 +18,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <stdio.h> #include <unistd.h> diff --git a/src/libw32dll/Makefile.am b/src/libw32dll/Makefile.am index e7f655888..5036851a3 100644 --- a/src/libw32dll/Makefile.am +++ b/src/libw32dll/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_CFLAGS = -I$(srcdir)/wine -DWIN32_PATH=\"@w32_path@\" $(VISIBILITY_FLAG) diff --git a/src/libw32dll/w32codec.c b/src/libw32dll/w32codec.c index 64d29aeac..e61ebcb82 100644 --- a/src/libw32dll/w32codec.c +++ b/src/libw32dll/w32codec.c @@ -21,6 +21,10 @@ * DirectShow support by Miguel Freitas (Nov/2001) * DMO support (Dez/2002) */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include <stdlib.h> #include <stdio.h> diff --git a/src/libw32dll/wine/driver.c b/src/libw32dll/wine/driver.c index ef8761628..296fcd25a 100644 --- a/src/libw32dll/wine/driver.c +++ b/src/libw32dll/wine/driver.c @@ -1,4 +1,4 @@ -#include <config.h> +#include "config.h" #include <stdio.h> #ifdef HAVE_MALLOC_H #include <malloc.h> diff --git a/src/libw32dll/wine/elfdll.c b/src/libw32dll/wine/elfdll.c index 7853ffe71..e81467b5a 100644 --- a/src/libw32dll/wine/elfdll.c +++ b/src/libw32dll/wine/elfdll.c @@ -3,7 +3,7 @@ * * Copyright 1999 Bertho A. Stultiens */ -#include <config.h> +#include "config.h" #ifdef HAVE_LIBDL diff --git a/src/libw32dll/wine/pe_image.c b/src/libw32dll/wine/pe_image.c index c99bbaed0..1366cc396 100644 --- a/src/libw32dll/wine/pe_image.c +++ b/src/libw32dll/wine/pe_image.c @@ -900,7 +900,7 @@ void PE_UnloadLibrary(WINE_MODREF *wm) */ static void extend_stack_for_dll_alloca(void) { -#ifndef __FreeBSD__ +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) void* mem=alloca(0x20000); *(int*)mem=0x1234; #endif diff --git a/src/libw32dll/wine/pe_resource.c b/src/libw32dll/wine/pe_resource.c index 6acfef2f0..16dc85389 100644 --- a/src/libw32dll/wine/pe_resource.c +++ b/src/libw32dll/wine/pe_resource.c @@ -9,7 +9,7 @@ * Copyright 1995 Alexandre Julliard * Copyright 1997 Marcus Meissner */ -#include <config.h> +#include "config.h" #include <stdlib.h> #include <sys/types.h> diff --git a/src/libw32dll/wine/resource.c b/src/libw32dll/wine/resource.c index 9d4fa80bb..a38c1dd1e 100644 --- a/src/libw32dll/wine/resource.c +++ b/src/libw32dll/wine/resource.c @@ -4,7 +4,7 @@ * Copyright 1993 Robert J. Amstadt * Copyright 1995 Alexandre Julliard */ -#include <config.h> +#include "config.h" #include <assert.h> #include <stdio.h> diff --git a/src/libw32dll/wine/vfl.c b/src/libw32dll/wine/vfl.c index e8eb7969f..f509995de 100644 --- a/src/libw32dll/wine/vfl.c +++ b/src/libw32dll/wine/vfl.c @@ -1,7 +1,7 @@ /* * Copyright 1998 Marcus Meissner */ -#include <config.h> +#include "config.h" #include <stdio.h> #include <stdlib.h> diff --git a/src/libxineadec/Makefile.am b/src/libxineadec/Makefile.am index d502b7955..ae261e60c 100644 --- a/src/libxineadec/Makefile.am +++ b/src/libxineadec/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common EXTRA_DIST = fooaudio.c @@ -39,7 +40,7 @@ xineplug_decode_lpcm_la_CFLAGS = $(VISIBILITY_FLAG) xineplug_decode_lpcm_la_LIBADD = $(XINE_LIB) xineplug_decode_vorbis_la_SOURCES = xine_vorbis_decoder.c -xineplug_decode_vorbis_la_LIBADD = $(XINE_LIB) $(VORBIS_LIBS) $(OGG_LIBS) +xineplug_decode_vorbis_la_LIBADD = $(XINE_LIB) $(VORBIS_LIBS) $(OGG_LIBS) $(LTLIBINTL) xineplug_decode_vorbis_la_CFLAGS = $(VISIBILITY_FLAG) $(VORBIS_CFLAGS) xineplug_decode_speex_la_SOURCES = xine_speex_decoder.c diff --git a/src/libxineadec/fooaudio.c b/src/libxineadec/fooaudio.c index 319eefb0e..53fcef801 100644 --- a/src/libxineadec/fooaudio.c +++ b/src/libxineadec/fooaudio.c @@ -22,6 +22,10 @@ * place of the data it should actually send. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/src/libxineadec/gsm610/long_term.c b/src/libxineadec/gsm610/long_term.c index 625662e1f..d3ef1b63d 100644 --- a/src/libxineadec/gsm610/long_term.c +++ b/src/libxineadec/gsm610/long_term.c @@ -6,6 +6,10 @@ /* $Header: /nfshome/cvs/xine-lib/src/libxineadec/gsm610/long_term.c,v 1.3 2003/12/07 15:34:30 f1rmb Exp $ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include "xineutils.h" diff --git a/src/libxineadec/gsm610/lpc.c b/src/libxineadec/gsm610/lpc.c index 0f51fa55f..7a8a8e2bc 100644 --- a/src/libxineadec/gsm610/lpc.c +++ b/src/libxineadec/gsm610/lpc.c @@ -6,6 +6,10 @@ /* $Header: /nfshome/cvs/xine-lib/src/libxineadec/gsm610/lpc.c,v 1.3 2003/12/07 15:34:30 f1rmb Exp $ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include "xineutils.h" diff --git a/src/libxineadec/gsm610/rpe.c b/src/libxineadec/gsm610/rpe.c index 67d94d30e..be1b1529b 100644 --- a/src/libxineadec/gsm610/rpe.c +++ b/src/libxineadec/gsm610/rpe.c @@ -6,6 +6,10 @@ /* $Header: /nfshome/cvs/xine-lib/src/libxineadec/gsm610/rpe.c,v 1.3 2003/12/07 15:34:30 f1rmb Exp $ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include "xineutils.h" #include "private.h" diff --git a/src/libxineadec/gsm610/short_term.c b/src/libxineadec/gsm610/short_term.c index 8222b2caa..c2d64853b 100644 --- a/src/libxineadec/gsm610/short_term.c +++ b/src/libxineadec/gsm610/short_term.c @@ -6,6 +6,10 @@ /* $Header: /nfshome/cvs/xine-lib/src/libxineadec/gsm610/short_term.c,v 1.3 2003/12/07 15:34:30 f1rmb Exp $ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include "xineutils.h" #include "private.h" diff --git a/src/libxineadec/nsf.c b/src/libxineadec/nsf.c index 0c9cdbf55..d4841ec6e 100644 --- a/src/libxineadec/nsf.c +++ b/src/libxineadec/nsf.c @@ -21,6 +21,10 @@ * http://www.baisoku.org/ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/src/libxineadec/xine_lpcm_decoder.c b/src/libxineadec/xine_lpcm_decoder.c index e1d81a8bb..435545d56 100644 --- a/src/libxineadec/xine_lpcm_decoder.c +++ b/src/libxineadec/xine_lpcm_decoder.c @@ -20,6 +20,11 @@ * 31-8-2001 Added LPCM rate sensing. * (c) 2001 James Courtier-Dutton James@superbug.demon.co.uk */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #ifndef __sun #define _XOPEN_SOURCE 500 #endif diff --git a/src/libxinevdec/Makefile.am b/src/libxinevdec/Makefile.am index 9805eb09e..b7dbe1db1 100644 --- a/src/libxinevdec/Makefile.am +++ b/src/libxinevdec/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_CFLAGS = $(VISIBILITY_FLAG) @@ -43,4 +44,4 @@ xineplug_decode_gdk_pixbuf_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) $(GDK_PIXB xineplug_decode_theora_la_SOURCES = xine_theora_decoder.c xineplug_decode_theora_la_CFLAGS = $(AM_CFLAGS) $(OGG_CFLAGS) $(THEORA_CFLAGS) -xineplug_decode_theora_la_LIBADD = $(XINE_LIB) $(OGG_LIBS) $(THEORA_LIBS) +xineplug_decode_theora_la_LIBADD = $(XINE_LIB) $(OGG_LIBS) $(THEORA_LIBS) $(LTLIBINTL) diff --git a/src/libxinevdec/bitplane.c b/src/libxinevdec/bitplane.c index 057511c29..76b7c8a89 100644 --- a/src/libxinevdec/bitplane.c +++ b/src/libxinevdec/bitplane.c @@ -29,6 +29,10 @@ * - untested (found no testfiles) IFF-ANIM OPT 3, 4 and 6 */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/src/libxinevdec/foovideo.c b/src/libxinevdec/foovideo.c index e0e0883dc..7a80c7c66 100644 --- a/src/libxinevdec/foovideo.c +++ b/src/libxinevdec/foovideo.c @@ -24,6 +24,10 @@ * frame when the frames are played in succession. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/src/libxinevdec/gdkpixbuf.c b/src/libxinevdec/gdkpixbuf.c index d41a958d8..de4c2271e 100644 --- a/src/libxinevdec/gdkpixbuf.c +++ b/src/libxinevdec/gdkpixbuf.c @@ -20,6 +20,11 @@ * a gdk-pixbuf-based image video decoder */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + #include <stdlib.h> #include <string.h> diff --git a/src/libxinevdec/image.c b/src/libxinevdec/image.c index 51e5d0309..bd749be8e 100644 --- a/src/libxinevdec/image.c +++ b/src/libxinevdec/image.c @@ -20,6 +20,10 @@ * a image video decoder */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> @@ -88,7 +92,7 @@ static void image_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { if (buf->decoder_flags & BUF_FLAG_FRAME_END) { int width, height, i; - MagickBooleanType status; + int status; MagickWand *wand; uint8_t *img_buf, *img_buf_ptr; yuv_planes_t yuv_planes; @@ -101,7 +105,7 @@ static void image_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { status = MagickReadImageBlob(wand, this->image, this->index); this->index = 0; - if (status == MagickFalse) { + if (!status) { DestroyMagickWand(wand); lprintf("error loading image\n"); return; diff --git a/src/libxinevdec/rgb.c b/src/libxinevdec/rgb.c index c1e7f398b..fc206a0ce 100644 --- a/src/libxinevdec/rgb.c +++ b/src/libxinevdec/rgb.c @@ -31,6 +31,10 @@ * indicated by a negative height parameter. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/src/libxinevdec/yuv.c b/src/libxinevdec/yuv.c index 49b2363fb..b1a69cd65 100644 --- a/src/libxinevdec/yuv.c +++ b/src/libxinevdec/yuv.c @@ -22,6 +22,10 @@ * a way that xine can display them. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/src/post/audio/Makefile.am b/src/post/audio/Makefile.am index 41a364d0d..5e587ef2f 100644 --- a/src/post/audio/Makefile.am +++ b/src/post/audio/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common noinst_HEADERS = dsp.h filter.h window.h audio_filters.h diff --git a/src/post/audio/audio_filters.c b/src/post/audio/audio_filters.c index 8200db51b..12d48784c 100644 --- a/src/post/audio/audio_filters.c +++ b/src/post/audio/audio_filters.c @@ -20,6 +20,9 @@ * catalog for audio filter plugins */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include "xine_internal.h" #include "xineutils.h" diff --git a/src/post/audio/stretch.c b/src/post/audio/stretch.c index 6930fea3d..d4621a800 100644 --- a/src/post/audio/stretch.c +++ b/src/post/audio/stretch.c @@ -20,6 +20,10 @@ * Time stretch by a given factor, optionally preserving pitch */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include "xine_internal.h" diff --git a/src/post/audio/upmix.c b/src/post/audio/upmix.c index 725439c1f..e753f4a2a 100644 --- a/src/post/audio/upmix.c +++ b/src/post/audio/upmix.c @@ -24,6 +24,10 @@ * E.g. Converts Stereo into Surround 5.1 */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include "xine_internal.h" diff --git a/src/post/audio/upmix_mono.c b/src/post/audio/upmix_mono.c index 2d3429788..52b5f497b 100644 --- a/src/post/audio/upmix_mono.c +++ b/src/post/audio/upmix_mono.c @@ -23,6 +23,10 @@ * It simply converts Mono into Stereo. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #define LOG_MODULE "upmix_mono" diff --git a/src/post/audio/volnorm.c b/src/post/audio/volnorm.c index 792618322..158705ef7 100644 --- a/src/post/audio/volnorm.c +++ b/src/post/audio/volnorm.c @@ -22,6 +22,10 @@ * & Pierre Lombard. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <math.h> diff --git a/src/post/deinterlace/Makefile.am b/src/post/deinterlace/Makefile.am index c9e09ee23..bac6bac33 100644 --- a/src/post/deinterlace/Makefile.am +++ b/src/post/deinterlace/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common SUBDIRS = plugins diff --git a/src/post/deinterlace/tvtime.c b/src/post/deinterlace/tvtime.c index eff43d5e8..97da6543e 100644 --- a/src/post/deinterlace/tvtime.c +++ b/src/post/deinterlace/tvtime.c @@ -38,14 +38,6 @@ #include "tvtime.h" /** - * This is how many frames to wait until deciding if the pulldown phase - * has changed or if we've really found a pulldown sequence. This is - * currently set to about 1 second, that is, we won't go into film mode - * until we've seen a pulldown sequence successfully for 1 second. - */ -#define PULLDOWN_ERROR_WAIT 60 - -/** * This is how many predictions have to be incorrect before we fall back to * video mode. Right now, if we mess up, we jump to video mode immediately. */ @@ -192,13 +184,13 @@ int tvtime_build_deinterlaced_frame( tvtime_t *tvtime, uint8_t *output, if( !tvtime->pdoffset ) { /* No pulldown offset applies, drop out of pulldown immediately. */ tvtime->pdlastbusted = 0; - tvtime->pderror = PULLDOWN_ERROR_WAIT; + tvtime->pderror = tvtime->pulldown_error_wait; } else if( tvtime->pdoffset != predicted ) { if( tvtime->pdlastbusted ) { tvtime->pdlastbusted--; tvtime->pdoffset = predicted; } else { - tvtime->pderror = PULLDOWN_ERROR_WAIT; + tvtime->pderror = tvtime->pulldown_error_wait; } } else { if( tvtime->pderror ) { @@ -437,7 +429,7 @@ void tvtime_reset_context( tvtime_t *tvtime ) tvtime->last_botdiff = 0; tvtime->pdoffset = PULLDOWN_SEQ_AA; - tvtime->pderror = PULLDOWN_ERROR_WAIT; + tvtime->pderror = tvtime->pulldown_error_wait; tvtime->pdlastbusted = 0; tvtime->filmmode = 0; } diff --git a/src/post/deinterlace/tvtime.h b/src/post/deinterlace/tvtime.h index 8e4c5abc2..2253f264e 100644 --- a/src/post/deinterlace/tvtime.h +++ b/src/post/deinterlace/tvtime.h @@ -56,6 +56,11 @@ typedef struct { */ deinterlace_method_t *curmethod; + /** + * This is how many frames to wait until deciding if the pulldown phase + * has changed or if we've really found a pulldown sequence. + */ + unsigned int pulldown_error_wait; /* internal data */ int last_topdiff; diff --git a/src/post/deinterlace/xine_plugin.c b/src/post/deinterlace/xine_plugin.c index 8115198af..7149f2bdb 100644 --- a/src/post/deinterlace/xine_plugin.c +++ b/src/post/deinterlace/xine_plugin.c @@ -23,6 +23,10 @@ * heavily based on tvtime.sf.net by Billy Biggs */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /* #define LOG */ @@ -69,6 +73,7 @@ typedef struct deinterlace_parameters_s { int method; int enabled; int pulldown; + int pulldown_error_wait; int framerate_mode; int judder_correction; int use_progressive_frame_flag; @@ -87,6 +92,8 @@ PARAM_ITEM( POST_PARAM_TYPE_BOOL, enabled, NULL, 0, 1, 0, "enable/disable" ) PARAM_ITEM( POST_PARAM_TYPE_INT, pulldown, enum_pulldown, 0, 0, 0, "pulldown algorithm" ) +PARAM_ITEM( POST_PARAM_TYPE_INT, pulldown_error_wait, NULL, 0, 0, 0, + "number of frames of telecine pattern sync required before mode change" ) PARAM_ITEM( POST_PARAM_TYPE_INT, framerate_mode, enum_framerate, 0, 0, 0, "framerate output mode" ) PARAM_ITEM( POST_PARAM_TYPE_BOOL, judder_correction, NULL, 0, 1, 0, @@ -165,6 +172,7 @@ static int set_parameters (xine_post_t *this_gen, void *param_gen) { this->enabled = param->enabled; this->pulldown = param->pulldown; + this->tvtime->pulldown_error_wait = param->pulldown_error_wait; this->framerate_mode = param->framerate_mode; this->judder_correction = param->judder_correction; this->use_progressive_frame_flag = param->use_progressive_frame_flag; @@ -185,6 +193,7 @@ static int get_parameters (xine_post_t *this_gen, void *param_gen) { param->method = this->cur_method; param->enabled = this->enabled; param->pulldown = this->pulldown; + param->pulldown_error_wait = this->tvtime->pulldown_error_wait; param->framerate_mode = this->framerate_mode; param->judder_correction = this->judder_correction; param->use_progressive_frame_flag = this->use_progressive_frame_flag; @@ -212,6 +221,9 @@ static char * get_static_help (void) { "\n" " Enabled: Enable/disable the plugin.\n" "\n" + " Pulldown_error_wait: Ensures that the telecine pattern has been " + "locked for this many frames before changing to filmmode.\n" + "\n" " Pulldown: Choose the 2-3 pulldown detection algorithm. 24 FPS films " "that have being converted to NTSC can be detected and intelligently " "reconstructed to their original (non-interlaced) frames.\n" @@ -350,6 +362,7 @@ static void *deinterlace_init_plugin(xine_t *xine, void *data) class->init_param.method = 1; /* First (plugin) method available */ class->init_param.enabled = 1; class->init_param.pulldown = 1; /* vektor */ + class->init_param.pulldown_error_wait = 60; /* about one second */ class->init_param.framerate_mode = 0; /* full */ class->init_param.judder_correction = 1; class->init_param.use_progressive_frame_flag = 1; diff --git a/src/post/goom/Makefile.am b/src/post/goom/Makefile.am index c01482917..cd022c9b0 100644 --- a/src/post/goom/Makefile.am +++ b/src/post/goom/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common EXTRA_DIST = mmx.c xmmx.c ppc_drawings.s ppc_zoom_ultimate.s diff_against_release.patch \ diff --git a/src/post/goom/ppc_zoom_ultimate.h b/src/post/goom/ppc_zoom_ultimate.h index d6932e7e6..d070071c9 100644 --- a/src/post/goom/ppc_zoom_ultimate.h +++ b/src/post/goom/ppc_zoom_ultimate.h @@ -11,4 +11,4 @@ void ppc_zoom_generic (int sizeX, int sizeY, Pixel *src, Pixel *dest, int *brutS, int *brutD, int buffratio, int precalCoef[16][16]); /* G4 Specific PowerPC Code (Possible use of Altivec and Data Streams) */ -void ppc_zoom_G4 (int sizeX, int sizeY, Pixel *src, Pixel *dest, int *brutS, int *brutD, int buffratio, int precalCoef[16][16]);
\ No newline at end of file +void ppc_zoom_G4 (int sizeX, int sizeY, Pixel *src, Pixel *dest, int *brutS, int *brutD, int buffratio, int precalCoef[16][16]); diff --git a/src/post/goom/xine_goom.c b/src/post/goom/xine_goom.c index 5cd5406b2..db7079423 100644 --- a/src/post/goom/xine_goom.c +++ b/src/post/goom/xine_goom.c @@ -48,7 +48,7 @@ #define GOOM_HEIGHT 240 /* colorspace conversion methods */ -static const char const * goom_csc_methods[]={ +static const char* goom_csc_methods[]={ "Fast but not photorealistic", "Slow but looks better", NULL diff --git a/src/post/mosaico/Makefile.am b/src/post/mosaico/Makefile.am index af027b6e6..56426c711 100644 --- a/src/post/mosaico/Makefile.am +++ b/src/post/mosaico/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common xinepost_LTLIBRARIES = xineplug_post_mosaico.la xineplug_post_switch.la diff --git a/src/post/mosaico/mosaico.c b/src/post/mosaico/mosaico.c index d99bab43b..c9ac9ab4c 100644 --- a/src/post/mosaico/mosaico.c +++ b/src/post/mosaico/mosaico.c @@ -23,7 +23,7 @@ */ #ifdef HAVE_CONFIG_H -# include <config.h> +# include "config.h" #endif #define LOG_MODULE "mosaico" diff --git a/src/post/planar/Makefile.am b/src/post/planar/Makefile.am index c49243252..751ea390a 100644 --- a/src/post/planar/Makefile.am +++ b/src/post/planar/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common POSTPROC_INT_LIB = $(top_builddir)/src/libffmpeg/libavcodec/libpostproc/libpostprocess.la diff --git a/src/post/planar/boxblur.c b/src/post/planar/boxblur.c index edad304a6..517cec489 100644 --- a/src/post/planar/boxblur.c +++ b/src/post/planar/boxblur.c @@ -21,6 +21,10 @@ * Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at> */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "post.h" #include "xineutils.h" diff --git a/src/post/planar/denoise3d.c b/src/post/planar/denoise3d.c index 74ed02250..21b58dbf9 100644 --- a/src/post/planar/denoise3d.c +++ b/src/post/planar/denoise3d.c @@ -21,6 +21,10 @@ * Copyright (C) 2003 Daniel Moreno <comac@comac.darktech.org> */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "post.h" #include "xineutils.h" diff --git a/src/post/planar/eq.c b/src/post/planar/eq.c index 92dae8e36..45bc43463 100644 --- a/src/post/planar/eq.c +++ b/src/post/planar/eq.c @@ -21,6 +21,10 @@ * Copyright (C) Richard Felker */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "post.h" #include "xineutils.h" diff --git a/src/post/planar/eq2.c b/src/post/planar/eq2.c index a1c208919..1a301fdab 100644 --- a/src/post/planar/eq2.c +++ b/src/post/planar/eq2.c @@ -25,6 +25,10 @@ * Richard Felker (original MMX contrast/brightness code (vf_eq.c)) */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "post.h" #include "xineutils.h" diff --git a/src/post/planar/noise.c b/src/post/planar/noise.c index e15c6fb4d..f639fce76 100644 --- a/src/post/planar/noise.c +++ b/src/post/planar/noise.c @@ -21,6 +21,10 @@ * is copyright 2002 Michael Niedermayer <michaelni@gmx.at> */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "post.h" #include "xineutils.h" diff --git a/src/post/planar/planar.c b/src/post/planar/planar.c index 5907d58e5..e1c9681ab 100644 --- a/src/post/planar/planar.c +++ b/src/post/planar/planar.c @@ -20,6 +20,10 @@ * catalog for planar post plugins */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "post.h" #include "xineutils.h" diff --git a/src/post/planar/pp.c b/src/post/planar/pp.c index 51d28b33d..1ce45e381 100644 --- a/src/post/planar/pp.c +++ b/src/post/planar/pp.c @@ -21,7 +21,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include "config.h" #endif #include "xine_internal.h" diff --git a/src/post/planar/unsharp.c b/src/post/planar/unsharp.c index da41708d0..6fac727ce 100644 --- a/src/post/planar/unsharp.c +++ b/src/post/planar/unsharp.c @@ -21,6 +21,10 @@ * Copyright (C) 2002 Rémi Guyomarch <rguyom@pobox.com> */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "post.h" #include "xineutils.h" diff --git a/src/post/visualizations/Makefile.am b/src/post/visualizations/Makefile.am index f42598d9c..a766bc10a 100644 --- a/src/post/visualizations/Makefile.am +++ b/src/post/visualizations/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common EXTRA_DIST = fooviz.c diff --git a/src/post/visualizations/fftgraph.c b/src/post/visualizations/fftgraph.c index 0cf27faf8..8bd30ed5c 100644 --- a/src/post/visualizations/fftgraph.c +++ b/src/post/visualizations/fftgraph.c @@ -21,6 +21,10 @@ * by Thibaut Mattern (tmattern@noos.fr) */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <math.h> diff --git a/src/post/visualizations/fftscope.c b/src/post/visualizations/fftscope.c index 2c6297a44..ccff59634 100644 --- a/src/post/visualizations/fftscope.c +++ b/src/post/visualizations/fftscope.c @@ -23,6 +23,10 @@ * FFT code by Steve Haehnichen, originally licensed under GPL v1 */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <math.h> diff --git a/src/post/visualizations/fooviz.c b/src/post/visualizations/fooviz.c index 2219143be..c645601fc 100644 --- a/src/post/visualizations/fooviz.c +++ b/src/post/visualizations/fooviz.c @@ -24,6 +24,10 @@ * colors on each iteration. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include "xine_internal.h" diff --git a/src/post/visualizations/oscope.c b/src/post/visualizations/oscope.c index 099920b42..a2c9c6961 100644 --- a/src/post/visualizations/oscope.c +++ b/src/post/visualizations/oscope.c @@ -21,6 +21,10 @@ * by Mike Melanson (melanson@pcisys.net) */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include "xine_internal.h" diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am index 8d8753659..afa838ab7 100644 --- a/src/video_out/Makefile.am +++ b/src/video_out/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_CPPFLAGS = -DXINE_COMPILE @@ -193,7 +194,7 @@ xineplug_vo_out_stk_la_CFLAGS = $(VISIBILITY_FLAG) $(LIBSTK_CFLAGS) xineplug_vo_out_directx_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c video_out_directx.c xineplug_vo_out_directx_la_CPPFLAGS = $(AM_CPPFLAGS) $(DIRECTX_CPPFLAGS) -xineplug_vo_out_directx_la_LIBADD = $(XINE_LIB) $(DIRECTX_VIDEO_LIBS) $(PTHREAD_LIBS) +xineplug_vo_out_directx_la_LIBADD = $(XINE_LIB) $(DIRECTX_VIDEO_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_directx_la_CFLAGS = $(VISIBILITY_FLAG) xineplug_vo_out_none_la_SOURCES = video_out_none.c diff --git a/src/video_out/deinterlace.c b/src/video_out/deinterlace.c index 263160808..712e9a83e 100644 --- a/src/video_out/deinterlace.c +++ b/src/video_out/deinterlace.c @@ -30,6 +30,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <string.h> #include "xine_internal.h" diff --git a/src/video_out/video_out_directx.c b/src/video_out/video_out_directx.c index 529968bec..3c6f6e784 100644 --- a/src/video_out/video_out_directx.c +++ b/src/video_out/video_out_directx.c @@ -21,6 +21,10 @@ * by Matthew Grooms <elon@altavista.com> */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + typedef unsigned char boolean; #include <windows.h> @@ -55,21 +59,33 @@ typedef unsigned char boolean; * the linking stage. *****************************************************************************/ #if 1 -static const GUID IID_IDirectDraw = { +static const GUID xine_IID_IDirectDraw = { 0x6C14DB80,0xA733,0x11CE,{0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60} }; +#ifdef IID_IDirectDraw +# undef IID_IDirectDraw +#endif +#define IID_IDirectDraw xine_IID_IDirectDraw #endif #if 0 static const GUID IID_IDirectDraw2 = { 0xB3A6F3E0,0x2B43,0x11CF,{0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56} }; +#ifdef IID_IDirectDraw2 +# undef IID_IDirectDraw2 +#endif +#define IID_IDirectDraw2 xine_IID_IDirectDraw2 #endif #if 0 static const GUID IID_IDirectDraw4 = { 0x9C59509A,0x39BD,0x11D1,{0x8C,0x4A,0x00,0xC0,0x4F,0xD9,0x30,0xC5} }; +#ifdef IID_IDirectDraw4 +# undef IID_IDirectDraw4 +#endif +#define IID_IDirectDraw4 xine_IID_IDirectDraw4 #endif /* ----------------------------------------- @@ -118,6 +134,7 @@ typedef struct { int mode; /* rgb mode */ int bytespp; /* rgb bits per pixel */ DDPIXELFORMAT primary_pixel_format; + DDSURFACEDESC ddsd; /* set by Lock(), used during display_frame */ alphablend_t alphablend_extra_data; } win32_driver_t; @@ -487,6 +504,7 @@ static boolean CheckPixelFormat( win32_driver_t * win32_driver ) return TRUE; } +#if 0 /* Create a Direct draw surface from * a bitmap resource.. * @@ -552,6 +570,7 @@ static LPDIRECTDRAWSURFACE CreateBMP( win32_driver_t * win32_driver, int resourc return bmp_surf; } +#endif /* Merge overlay with the current primary * surface. This funtion is only used when @@ -761,23 +780,22 @@ static boolean DisplayFrame( win32_driver_t * win32_driver ) /* Lock our back buffer to update its contents. */ -static void * Lock( void * surface ) +static void * Lock( win32_driver_t * win32_driver, void * surface ) { LPDIRECTDRAWSURFACE lock_surface = ( LPDIRECTDRAWSURFACE ) surface; - DDSURFACEDESC ddsd; HRESULT result; if( !surface ) return 0; - memset( &ddsd, 0, sizeof( ddsd ) ); - ddsd.dwSize = sizeof( ddsd ); + memset( &win32_driver->ddsd, 0, sizeof( win32_driver->ddsd ) ); + win32_driver->ddsd.dwSize = sizeof( win32_driver->ddsd ); - result = IDirectDrawSurface_Lock( lock_surface, 0, &ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 ); + result = IDirectDrawSurface_Lock( lock_surface, 0, &win32_driver->ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 ); if( result == DDERR_SURFACELOST ) { IDirectDrawSurface_Restore( lock_surface ); - result = IDirectDrawSurface_Lock( lock_surface, 0, &ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 ); + result = IDirectDrawSurface_Lock( lock_surface, 0, &win32_driver->ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 ); if( result != DD_OK ) return 0; @@ -792,7 +810,7 @@ static void * Lock( void * surface ) } } - return ddsd.lpSurface; + return win32_driver->ddsd.lpSurface; } /* Unlock our back buffer to prepair for display. */ @@ -952,8 +970,6 @@ static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame { win32_driver_t *win32_driver = ( win32_driver_t * ) vo_driver; win32_frame_t *win32_frame = ( win32_frame_t * ) vo_frame; - int offset; - int size; /* if the required width, height or format has changed @@ -972,7 +988,7 @@ static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame /* lock our surface to update its contents */ - win32_driver->contents = Lock( win32_driver->secondary ); + win32_driver->contents = Lock( win32_driver, win32_driver->secondary ); /* surface unavailable, skip frame render */ @@ -1057,37 +1073,47 @@ static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame /* the actual format is identical to our * stream format. we just need to copy it */ - switch(win32_frame->format) + int line; + uint8_t * src; + vo_frame_t * frame = vo_frame; + uint8_t * dst = (uint8_t *)win32_driver->contents; + + switch(win32_frame->format) { - case XINE_IMGFMT_YV12: - { - vo_frame_t *frame; - uint8_t *img; - - frame = vo_frame; - img = (uint8_t *)win32_driver->contents; - - offset = 0; - size = frame->pitches[0] * frame->height; - xine_fast_memcpy( img+offset, frame->base[0], size); - - offset += size; - size = frame->pitches[2]* frame->height / 2; - xine_fast_memcpy( img+offset, frame->base[2], size); - - offset += size; - size = frame->pitches[1] * frame->height / 2; - xine_fast_memcpy( img+offset, frame->base[1], size); - } + case XINE_IMGFMT_YV12: + src = frame->base[0]; + for (line = 0; line < frame->height ; line++){ + xine_fast_memcpy( dst, src, frame->width); + src += vo_frame->pitches[0]; + dst += win32_driver->ddsd.lPitch; + } + + src = frame->base[2]; + for (line = 0; line < frame->height/2 ; line++){ + xine_fast_memcpy( dst, src, frame->width/2); + src += vo_frame->pitches[2]; + dst += win32_driver->ddsd.lPitch/2; + } + + src = frame->base[1]; + for (line = 0; line < frame->height/2 ; line++){ + xine_fast_memcpy( dst, src, frame->width/2); + src += vo_frame->pitches[1]; + dst += win32_driver->ddsd.lPitch/2; + } break; + case XINE_IMGFMT_YUY2: - xine_fast_memcpy( win32_driver->contents, win32_frame->vo_frame.base[0], win32_frame->vo_frame.pitches[0] * win32_frame->vo_frame.height * 2); - break; default: - xine_fast_memcpy( win32_driver->contents, win32_frame->vo_frame.base[0], win32_frame->vo_frame.pitches[0] * win32_frame->vo_frame.height * 2); + src = frame->base[0]; + for (line = 0; line < frame->height ; line++){ + xine_fast_memcpy( dst, src, frame->width*2); + src += vo_frame->pitches[0]; + dst += win32_driver->ddsd.lPitch; + } break; } - } + } /* unlock the surface */ @@ -1149,11 +1175,38 @@ static int win32_gui_data_exchange( vo_driver_t * vo_driver, int data_type, void switch( data_type ) { + case GUI_WIN32_MOVED_OR_RESIZED: UpdateRect( win32_driver->win32_visual ); DisplayFrame( win32_driver ); break; + case XINE_GUI_SEND_DRAWABLE_CHANGED: + { + HRESULT result; + HWND newWndHnd = (HWND) data; + + /* set cooperative level */ + result = IDirectDraw_SetCooperativeLevel( win32_driver->ddobj, newWndHnd, DDSCL_NORMAL ); + if( result != DD_OK ) + { + Error( 0, "SetCooperativeLevel : error 0x%lx", result ); + return 0; + } + /* associate our clipper with new window */ + result = IDirectDrawClipper_SetHWnd( win32_driver->ddclipper, 0, newWndHnd ); + if( result != DD_OK ) + { + Error( 0, "ddclipper->SetHWnd : error 0x%lx", result ); + return 0; + } + /* store our objects in our visual struct */ + win32_driver->win32_visual->WndHnd = newWndHnd; + /* update video area and redraw current frame */ + UpdateRect( win32_driver->win32_visual ); + DisplayFrame( win32_driver ); + break; } + } return 0; } diff --git a/src/video_out/video_out_xcbxv.c b/src/video_out/video_out_xcbxv.c index 807bb766d..1e6e2b663 100644 --- a/src/video_out/video_out_xcbxv.c +++ b/src/video_out/video_out_xcbxv.c @@ -138,6 +138,8 @@ struct xv_driver_s { int use_colorkey; uint32_t colorkey; + int sync_is_vsync; + /* hold initial port attributes values to restore on exit */ xine_list_t *port_attributes; @@ -156,7 +158,9 @@ typedef struct { xine_t *xine; } xv_class_t; -static const char *const prefer_types[] = VIDEO_DEVICE_XV_PREFER_TYPES; +VIDEO_DEVICE_XV_DECL_BICUBIC_TYPES; +VIDEO_DEVICE_XV_DECL_PREFER_TYPES; +VIDEO_DEVICE_XV_DECL_SYNC_ATOMS; static uint32_t xv_get_capabilities (vo_driver_t *this_gen) { xv_driver_t *this = (xv_driver_t *) this_gen; @@ -1212,66 +1216,43 @@ static void xv_update_deinterlace(void *this_gen, xine_cfg_entry_t *entry) { this->deinterlace_method = entry->num_value; } -static void xv_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { +static void xv_update_attr (void *this_gen, xine_cfg_entry_t *entry, + const char *atomstr, const char *debugstr) +{ xv_driver_t *this = (xv_driver_t *) this_gen; - int xv_filter; xcb_intern_atom_cookie_t atom_cookie; xcb_intern_atom_reply_t *atom_reply; - xv_filter = entry->num_value; - pthread_mutex_lock(&this->main_mutex); - atom_cookie = xcb_intern_atom(this->connection, 0, sizeof("XV_FILTER"), "XV_FILTER"); + atom_cookie = xcb_intern_atom(this->connection, 0, strlen (atomstr), atomstr); atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL); - xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, xv_filter); + xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, entry->num_value); free(atom_reply); pthread_mutex_unlock(&this->main_mutex); xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xcbxv: bilinear scaling mode (XV_FILTER) = %d\n",xv_filter); + LOG_MODULE ": %s = %d\n", debugstr, entry->num_value); } -static void xv_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { - xv_driver_t *this = (xv_driver_t *) this_gen; - int xv_double_buffer; - - xcb_intern_atom_cookie_t atom_cookie; - xcb_intern_atom_reply_t *atom_reply; - - xv_double_buffer = entry->num_value; - - pthread_mutex_lock(&this->main_mutex); - atom_cookie = xcb_intern_atom(this->connection, 0, sizeof("XV_DOUBLE_BUFFER"), "XV_DOUBLE_BUFFER"); - atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL); - xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, xv_double_buffer); - free(atom_reply); - pthread_mutex_unlock(&this->main_mutex); +static void xv_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { + xv_update_attr (this_gen, entry, "XV_FILTER", "bilinear scaling mode"); +} - xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xcbxv: double buffering mode = %d\n", xv_double_buffer); +static void xv_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { + xv_update_attr (this_gen, entry, "XV_DOUBLE_BUFFER", "double buffering mode"); } static void xv_update_XV_SYNC_TO_VBLANK(void *this_gen, xine_cfg_entry_t *entry) { - xv_driver_t *this = (xv_driver_t *) this_gen; - int xv_sync_to_vblank; - - xcb_intern_atom_cookie_t atom_cookie; - xcb_intern_atom_reply_t *atom_reply; - - xv_sync_to_vblank = entry->num_value; - - pthread_mutex_lock(&this->main_mutex); - atom_cookie = xcb_intern_atom(this->connection, 0, sizeof("XV_SYNC_TO_VBLANK"), "XV_SYNC_TO_VBLANK"); - atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL); - xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, xv_sync_to_vblank); - free(atom_reply); - pthread_mutex_unlock(&this->main_mutex); - - xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xcbxv: sync to vblank = %d\n", xv_sync_to_vblank); + xv_update_attr (this_gen, entry, + sync_atoms[((xv_driver_t *)this_gen)->sync_is_vsync], + "sync to vblank"); } +static void xv_update_XV_BICUBIC(void *this_gen, xine_cfg_entry_t *entry) +{ + xv_update_attr (this_gen, entry, "XV_BICUBIC", "bicubic filtering mode"); +} static void xv_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry) { xv_driver_t *this = (xv_driver_t *) this_gen; @@ -1314,12 +1295,10 @@ static xcb_xv_port_t xv_autodetect_port(xv_driver_t *this, xcb_xv_port_t base, xv_prefertype prefer_type) { - xcb_xv_adaptor_info_iterator_t *start = adaptor_it; - for (; adaptor_it->rem; xcb_xv_adaptor_info_next(adaptor_it)) if (adaptor_it->data->type & XCB_XV_TYPE_IMAGE_MASK && (prefer_type == xv_prefer_none || - strcasestr (xcb_xv_adaptor_info_name (adaptor_it->data), prefer_types[prefer_type]))) + strcasestr (xcb_xv_adaptor_info_name (adaptor_it->data), prefer_substrings[prefer_type]))) { int j; for (j = 0; j < adaptor_it->data->num_ports; ++j) @@ -1350,7 +1329,7 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis xcb_xv_list_image_formats_cookie_t list_formats_cookie; xcb_xv_list_image_formats_reply_t *list_formats_reply; - xcb_xv_adaptor_info_iterator_t adaptor_it; + xcb_xv_adaptor_info_iterator_t adaptor_it, adaptor_first; xcb_xv_image_format_info_iterator_t format_it; this = (xv_driver_t *) calloc(1, sizeof(xv_driver_t)); @@ -1388,12 +1367,12 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis return NULL; } - adaptor_it = xcb_xv_query_adaptors_info_iterator(query_adaptors_reply); + adaptor_first = xcb_xv_query_adaptors_info_iterator(query_adaptors_reply); xv_port = config->register_num (config, "video.device.xv_port", 0, VIDEO_DEVICE_XV_PORT_HELP, 20, NULL, NULL); prefer_type = config->register_enum (config, "video.device.xv_preferred_method", 0, - prefer_types, VIDEO_DEVICE_XV_PREFER_TYPE_HELP, + prefer_labels, VIDEO_DEVICE_XV_PREFER_TYPE_HELP, 10, NULL, NULL); if (xv_port != 0) { @@ -1401,14 +1380,25 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis xprintf(class->xine, XINE_VERBOSITY_NONE, _("%s: could not open Xv port %d - autodetecting\n"), LOG_MODULE, xv_port); + adaptor_it = adaptor_first; xv_port = xv_autodetect_port (this, &adaptor_it, xv_port, prefer_type); } else xv_find_adaptor_by_port (xv_port, &adaptor_it); } if (!xv_port) + { + adaptor_it = adaptor_first; xv_port = xv_autodetect_port (this, &adaptor_it, 0, prefer_type); + } if (!xv_port) + { + if (prefer_type) + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: no available ports of type \"%s\", defaulting...\n"), + LOG_MODULE, prefer_labels[prefer_type]); + adaptor_it = adaptor_first; xv_port = xv_autodetect_port (this, &adaptor_it, 0, xv_prefer_none); + } if (!xv_port) { xprintf(class->xine, XINE_VERBOSITY_LOG, @@ -1536,7 +1526,8 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis VIDEO_DEVICE_XV_DOUBLE_BUFFER_HELP, 20, xv_update_XV_DOUBLE_BUFFER, this); config->update_num(config,"video.device.xv_double_buffer",xv_double_buffer); - } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_SYNC_TO_VBLANK")) { + } else if(!strcmp(name, sync_atoms[this->sync_is_vsync = 0]) || + !strcmp(name, sync_atoms[this->sync_is_vsync = 1])) { int xv_sync_to_vblank; xv_sync_to_vblank = config->register_bool (config, "video.device.xv_sync_to_vblank", 1, @@ -1548,6 +1539,12 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis "sync to under the XVideo Settings tab"), 20, xv_update_XV_SYNC_TO_VBLANK, this); config->update_num(config,"video.device.xv_sync_to_vblank",xv_sync_to_vblank); + } else if(!strcmp(name, "XV_BICUBIC")) { + int xv_bicubic = + config->register_enum (config, "video.device.xv_bicubic", 2, + bicubic_types, VIDEO_DEVICE_XV_BICUBIC_HELP, + 20, xv_update_XV_BICUBIC, this); + config->update_num(config,"video.device.xv_bicubic",xv_bicubic); } } } diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c index d791e6dc5..3fb088d59 100644 --- a/src/video_out/video_out_xv.c +++ b/src/video_out/video_out_xv.c @@ -143,6 +143,8 @@ struct xv_driver_s { int use_colorkey; uint32_t colorkey; + int sync_is_vsync; + /* hold initial port attributes values to restore on exit */ xine_list_t *port_attributes; @@ -169,7 +171,9 @@ typedef struct { static int gX11Fail; -static const char *const prefer_types[] = VIDEO_DEVICE_XV_PREFER_TYPES; +VIDEO_DEVICE_XV_DECL_BICUBIC_TYPES; +VIDEO_DEVICE_XV_DECL_PREFER_TYPES; +VIDEO_DEVICE_XV_DECL_SYNC_ATOMS; static uint32_t xv_get_capabilities (vo_driver_t *this_gen) { xv_driver_t *this = (xv_driver_t *) this_gen; @@ -1271,52 +1275,38 @@ static void xv_update_deinterlace(void *this_gen, xine_cfg_entry_t *entry) { this->deinterlace_method = entry->num_value; } -static void xv_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { +static void xv_update_attr (void *this_gen, xine_cfg_entry_t *entry, + const char *atomstr, const char *debugstr) +{ xv_driver_t *this = (xv_driver_t *) this_gen; Atom atom; - int xv_filter; - - xv_filter = entry->num_value; LOCK_DISPLAY(this); - atom = XInternAtom (this->display, "XV_FILTER", False); - XvSetPortAttribute (this->display, this->xv_port, atom, xv_filter); + atom = XInternAtom (this->display, atomstr, False); + XvSetPortAttribute (this->display, this->xv_port, atom, entry->num_value); UNLOCK_DISPLAY(this); xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xv: bilinear scaling mode (XV_FILTER) = %d\n",xv_filter); + LOG_MODULE ": %s = %d\n", debugstr, entry->num_value); } -static void xv_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { - xv_driver_t *this = (xv_driver_t *) this_gen; - Atom atom; - int xv_double_buffer; - - xv_double_buffer = entry->num_value; - - LOCK_DISPLAY(this); - atom = XInternAtom (this->display, "XV_DOUBLE_BUFFER", False); - XvSetPortAttribute (this->display, this->xv_port, atom, xv_double_buffer); - UNLOCK_DISPLAY(this); +static void xv_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { + xv_update_attr (this_gen, entry, "XV_FILTER", "bilinear scaling mode"); +} - xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xv: double buffering mode = %d\n", xv_double_buffer); +static void xv_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { + xv_update_attr (this_gen, entry, "XV_DOUBLE_BUFFER", "double buffering mode"); } static void xv_update_XV_SYNC_TO_VBLANK(void *this_gen, xine_cfg_entry_t *entry) { - xv_driver_t *this = (xv_driver_t *) this_gen; - Atom atom; - int xv_sync_to_vblank; - - xv_sync_to_vblank = entry->num_value; - - LOCK_DISPLAY(this); - atom = XInternAtom (this->display, "XV_SYNC_TO_VBLANK", False); - XvSetPortAttribute (this->display, this->xv_port, atom, xv_sync_to_vblank); - UNLOCK_DISPLAY(this); + xv_update_attr (this_gen, entry, + sync_atoms[((xv_driver_t *)this_gen)->sync_is_vsync], + "sync to vblank"); +} - xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xv: sync to vblank = %d\n", xv_sync_to_vblank); +static void xv_update_XV_BICUBIC(void *this_gen, xine_cfg_entry_t *entry) +{ + xv_update_attr (this_gen, entry, "XV_BICUBIC", "bicubic filtering mode"); } static void xv_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry) { @@ -1359,7 +1349,7 @@ static XvPortID xv_autodetect_port(xv_driver_t *this, for (an = 0; an < adaptors; an++) if (adaptor_info[an].type & XvImageMask && (prefer_type == xv_prefer_none || - strcasestr (adaptor_info[an].name, prefer_types[prefer_type]))) + strcasestr (adaptor_info[an].name, prefer_substrings[prefer_type]))) for (j = 0; j < adaptor_info[an].num_ports; j++) { XvPortID port = adaptor_info[an].base_id + j; if (port >= base && xv_open_port(this, port)) { @@ -1431,13 +1421,13 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * VIDEO_DEVICE_XV_PORT_HELP, 20, NULL, NULL); prefer_type = config->register_enum (config, "video.device.xv_preferred_method", 0, - prefer_types, VIDEO_DEVICE_XV_PREFER_TYPE_HELP, + prefer_labels, VIDEO_DEVICE_XV_PREFER_TYPE_HELP, 10, NULL, NULL); if (xv_port != 0) { if (! xv_open_port(this, xv_port)) { xprintf(class->xine, XINE_VERBOSITY_NONE, - _("%s: could not open Xv port %d - autodetecting\n"), + _("%s: could not open Xv port %"PRId32" - autodetecting\n"), LOG_MODULE, xv_port); xv_port = xv_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, xv_port, prefer_type); } else @@ -1446,7 +1436,13 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * if (!xv_port) xv_port = xv_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, prefer_type); if (!xv_port) + { + if (prefer_type) + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: no available ports of type \"%s\", defaulting...\n"), + LOG_MODULE, prefer_labels[prefer_type]); xv_port = xv_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, xv_prefer_none); + } if (!xv_port) { xprintf(class->xine, XINE_VERBOSITY_LOG, @@ -1585,7 +1581,8 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * VIDEO_DEVICE_XV_DOUBLE_BUFFER_HELP, 20, xv_update_XV_DOUBLE_BUFFER, this); config->update_num(config,"video.device.xv_double_buffer",xv_double_buffer); - } else if(!strcmp(attr[k].name, "XV_SYNC_TO_VBLANK")) { + } else if(((this->sync_is_vsync = 0), !strcmp(name, sync_atoms[0])) || + ((this->sync_is_vsync = 1), !strcmp(name, sync_atoms[1]))) { int xv_sync_to_vblank; xv_sync_to_vblank = config->register_bool (config, "video.device.xv_sync_to_vblank", 1, @@ -1597,6 +1594,12 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * "sync to under the XVideo Settings tab"), 20, xv_update_XV_SYNC_TO_VBLANK, this); config->update_num(config,"video.device.xv_sync_to_vblank",xv_sync_to_vblank); + } else if(!strcmp(name, "XV_BICUBIC")) { + int xv_bicubic = + config->register_enum (config, "video.device.xv_bicubic", 2, + bicubic_types, VIDEO_DEVICE_XV_BICUBIC_HELP, + 20, xv_update_XV_BICUBIC, this); + config->update_num(config,"video.device.xv_bicubic",xv_bicubic); } } } diff --git a/src/video_out/video_out_xxmc.c b/src/video_out/video_out_xxmc.c index b3ac39697..61e0139e3 100644 --- a/src/video_out/video_out_xxmc.c +++ b/src/video_out/video_out_xxmc.c @@ -45,7 +45,8 @@ static void xxmc_frame_updates(xxmc_driver_t *driver, xxmc_frame_t *frame, static void dispose_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo, XvImage *myimage); -static const char *const prefer_types[] = VIDEO_DEVICE_XV_PREFER_TYPES; +VIDEO_DEVICE_XV_DECL_BICUBIC_TYPES; +VIDEO_DEVICE_XV_DECL_PREFER_TYPES; /* * Acceleration level priority. Static for now. It may well turn out that IDCT @@ -2129,36 +2130,32 @@ static void xxmc_check_capability (xxmc_driver_t *this, this->props[property].value = int_default; } -static void xxmc_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { +static void xxmc_update_attr (void *this_gen, xine_cfg_entry_t *entry, + const char *atomstr, const char *debugstr) +{ xxmc_driver_t *this = (xxmc_driver_t *) this_gen; Atom atom; - int xv_filter; - - xv_filter = entry->num_value; XLockDisplay(this->display); - atom = XInternAtom (this->display, "XV_FILTER", False); - XvSetPortAttribute (this->display, this->xv_port, atom, xv_filter); + atom = XInternAtom (this->display, atomstr, False); + XvSetPortAttribute (this->display, this->xv_port, atom, entry->num_value); XUnlockDisplay(this->display); xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xxmc: bilinear scaling mode (XV_FILTER) = %d\n",xv_filter); + LOG_MODULE ": %s = %d\n", debugstr, entry->num_value); } -static void xxmc_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { - xxmc_driver_t *this = (xxmc_driver_t *) this_gen; - Atom atom; - int xv_double_buffer; - - xv_double_buffer = entry->num_value; +static void xxmc_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { + xxmc_update_attr (this_gen, entry, "XV_FILTER", "bilinear scaling mode"); +} - XLockDisplay(this->display); - atom = XInternAtom (this->display, "XV_DOUBLE_BUFFER", False); - XvSetPortAttribute (this->display, this->xv_port, atom, xv_double_buffer); - XUnlockDisplay(this->display); +static void xxmc_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { + xxmc_update_attr (this_gen, entry, "XV_DOUBLE_BUFFER", "double buffering mode"); +} - xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xxmc: double buffering mode = %d\n", xv_double_buffer); +static void xxmc_update_XV_BICUBIC(void *this_gen, xine_cfg_entry_t *entry) +{ + xxmc_update_attr (this_gen, entry, "XV_BICUBIC", "bicubic filtering mode"); } static void xxmc_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry) { @@ -2231,7 +2228,7 @@ static XvPortID xxmc_autodetect_port(xxmc_driver_t *this, for (an = 0; an < adaptors; an++) if (adaptor_info[an].type & XvImageMask && (prefer_type == xv_prefer_none || - strcasestr (adaptor_info[an].name, prefer_types[prefer_type]))) + strcasestr (adaptor_info[an].name, prefer_substrings[prefer_type]))) for (j = 0; j < adaptor_info[an].num_ports; j++) { XvPortID port = adaptor_info[an].base_id + j; if (port >= base && xxmc_open_port(this, port)) { @@ -2451,7 +2448,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi VIDEO_DEVICE_XV_PORT_HELP, 20, NULL, NULL); prefer_type = config->register_enum (config, "video.device.xv_preferred_method", 0, - prefer_types, VIDEO_DEVICE_XV_PREFER_TYPE_HELP, + prefer_labels, VIDEO_DEVICE_XV_PREFER_TYPE_HELP, 10, NULL, NULL); if (xv_port != 0) { @@ -2466,7 +2463,13 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi if (!xv_port) xv_port = xxmc_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, prefer_type); if (!xv_port) + { + if (prefer_type) + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: no available ports of type \"%s\", defaulting...\n"), + LOG_MODULE, prefer_labels[prefer_type]); xv_port = xxmc_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, xv_prefer_none); + } if (!xv_port) { xprintf(class->xine, XINE_VERBOSITY_LOG, @@ -2602,6 +2605,12 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi VIDEO_DEVICE_XV_DOUBLE_BUFFER_HELP, 20, xxmc_update_XV_DOUBLE_BUFFER, this); config->update_num(config,"video.device.xv_double_buffer",xv_double_buffer); + } else if(!strcmp(name, "XV_BICUBIC")) { + int xv_bicubic = + config->register_enum (config, "video.device.xv_bicubic", 2, + bicubic_types, VIDEO_DEVICE_XV_BICUBIC_HELP, + 20, xxmc_update_XV_BICUBIC, this); + config->update_num(config,"video.device.xv_bicubic",xv_bicubic); } } } diff --git a/src/video_out/xv_common.h b/src/video_out/xv_common.h index 259afe616..ff49286f0 100644 --- a/src/video_out/xv_common.h +++ b/src/video_out/xv_common.h @@ -57,13 +57,27 @@ _("pitch alignment workaround"), \ _("Some buggy video drivers need a workaround to function properly.") -typedef enum { - xv_prefer_none, xv_prefer_overlay, xv_prefer_textured -} xv_prefertype; -#define VIDEO_DEVICE_XV_PREFER_TYPES \ - { "Any", "Overlay", "Textured Video", NULL } +#define VIDEO_DEVICE_XV_DECL_SYNC_ATOMS \ + static const char *const sync_atoms[] = \ + { "XV_SYNC_TO_VBLANK", "XV_VSYNC" }; + +#define VIDEO_DEVICE_XV_DECL_PREFER_TYPES \ + typedef enum { \ + xv_prefer_none, xv_prefer_overlay, xv_prefer_textured, xv_prefer_blitter, \ + } xv_prefertype; \ + static const char *const prefer_labels[] = \ + { "Any", "Overlay", "Textured Video", "Blitter", NULL }; \ + static const char prefer_substrings[][8] = \ + { "", "Overlay", "Texture", "Blitter" }; #define VIDEO_DEVICE_XV_PREFER_TYPE_HELP \ _("video display method preference"), \ _("Selects which video output method is preferred. " \ "Detection is done using the reported Xv adaptor names.\n" \ "(Only applies when auto-detecting which Xv port to use.)") + +#define VIDEO_DEVICE_XV_DECL_BICUBIC_TYPES \ + static const char *const bicubic_types[] = { "Off", "On", "Auto", NULL }; +#define VIDEO_DEVICE_XV_BICUBIC_HELP \ + _("bicubic filtering"), \ + _("This option controls bicubic filtering of the video image. " \ + "It may be used instead of, or as well as, xine's deinterlacers.") diff --git a/src/video_out/xxmc.h b/src/video_out/xxmc.h index 1c24991be..03b12c15b 100644 --- a/src/video_out/xxmc.h +++ b/src/video_out/xxmc.h @@ -37,6 +37,14 @@ #define XVMC_THREAD_SAFE +/* + * some implementations are not aware of the display having been locked + * already before calling the xvmc function and may therefore deadlock. + */ +/* +#define XVMC_LOCKDISPLAY_SAFE +*/ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -171,7 +179,7 @@ typedef struct context_lock_s { return; \ } -#ifdef XVMC_THREAD_SAFE +#if defined(XVMC_THREAD_SAFE) && defined(XVMC_LOCKDISPLAY_SAFE) #define XVMCLOCKDISPLAY(display) #define XVMCUNLOCKDISPLAY(display) #else diff --git a/src/xine-engine/alphablend.c b/src/xine-engine/alphablend.c index 6f3ac3ebe..1dcd47eb7 100644 --- a/src/xine-engine/alphablend.c +++ b/src/xine-engine/alphablend.c @@ -23,6 +23,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /* #define LOG_BLEND_YUV #define LOG_BLEND_RGB16 @@ -1104,7 +1108,7 @@ static void blend_yuv_exact(uint8_t *dst_cr, uint8_t *dst_cb, int src_width, static uint8_t *(*blend_yuv_grow_extra_data(alphablend_t *extra_data, int osd_width))[ 3 ][ 2 ] { - struct __attribute__((packed)) header_s { + struct XINE_PACKED header_s { int id; int max_width; uint8_t *data[ 3 ][ 2 ]; @@ -1546,7 +1550,7 @@ static void blend_yuy2_exact(uint8_t *dst_cr, uint8_t *dst_cb, int src_width, static uint8_t *(*blend_yuy2_grow_extra_data(alphablend_t *extra_data, int osd_width))[ 3 ] { - struct __attribute__((packed)) header_s { + struct XINE_PACKED header_s { int id; int max_width; uint8_t *data[ 3 ]; diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c index 5476262d9..855dee372 100644 --- a/src/xine-engine/audio_decoder.c +++ b/src/xine-engine/audio_decoder.c @@ -89,16 +89,18 @@ static void *audio_decoder_loop (void *stream_gen) { if (stream->audio_decoder_plugin) { lprintf ("close old decoder\n"); - + + stream->keep_ao_driver_open = !!(buf->decoder_flags & BUF_FLAG_GAPLESS_SW); _x_free_audio_decoder (stream, stream->audio_decoder_plugin); stream->audio_decoder_plugin = NULL; stream->audio_track_map_entries = 0; stream->audio_type = 0; + stream->keep_ao_driver_open = 0; } running_ticket->release(running_ticket, 0); - if( !stream->gapless_switch ) + if( !(buf->decoder_flags & BUF_FLAG_GAPLESS_SW) ) stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_STREAMSTART, 0); buftype_unknown = 0; diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index d28c45ea6..a6f83dc9d 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -215,6 +215,7 @@ typedef struct { int num_driver_actions; /* number of threads, that wish to call * functions needing driver_lock */ pthread_mutex_t driver_action_lock; /* protects num_driver_actions */ + pthread_cond_t driver_action_cond; /* informs about num_driver_actions-- */ metronom_clock_t *clock; xine_t *xine; @@ -243,6 +244,7 @@ typedef struct { audio_fifo_t *free_fifo; audio_fifo_t *out_fifo; int64_t last_audio_vpts; + pthread_mutex_t current_speed_lock; uint32_t current_speed; /* the current playback speed */ /* FIXME: replace all this->clock->speed with this->current_speed. we should make * sure nobody will change speed without going through xine.c:set_speed_internal */ @@ -1040,6 +1042,7 @@ static void *ao_loop (void *this_gen) { * we must process/free buffers otherwise the entire engine will stop. */ + pthread_mutex_lock(&this->current_speed_lock); if ( this->audio_loop_running && (this->clock->speed == XINE_SPEED_PAUSE || (this->clock->speed != XINE_FINE_SPEED_NORMAL && @@ -1055,6 +1058,7 @@ static void *ao_loop (void *this_gen) { _x_refcounter_dec(in_buf->stream->refcounter); fifo_append (this->free_fifo, in_buf); in_buf = NULL; + pthread_mutex_unlock(&this->current_speed_lock); continue; } @@ -1065,6 +1069,7 @@ static void *ao_loop (void *this_gen) { } lprintf ("loop:pause: I feel sleepy (%d buffers).\n", this->out_fifo->num_buffers); + pthread_mutex_unlock(&this->current_speed_lock); xine_usec_sleep (10000); lprintf ("loop:pause: I wake up.\n"); continue; @@ -1274,12 +1279,20 @@ static void *ao_loop (void *this_gen) { fifo_append (this->free_fifo, in_buf); in_buf = NULL; } + pthread_mutex_unlock(&this->current_speed_lock); /* Give other threads a chance to use functions which require this->driver_lock to * be available. This is needed when using NPTL on Linux (and probably PThreads * on Solaris as well). */ - if (this->num_driver_actions > 0) - sched_yield(); + if (this->num_driver_actions > 0) { + /* calling sched_yield() is not sufficient on multicore systems */ + /* sched_yield(); */ + /* instead wait for the other thread to acquire this->driver_lock */ + pthread_mutex_lock(&this->driver_action_lock); + if (this->num_driver_actions > 0) + pthread_cond_wait(&this->driver_action_cond, &this->driver_action_lock); + pthread_mutex_unlock(&this->driver_action_lock); + } } if (in_buf) { @@ -1470,6 +1483,8 @@ static inline void dec_num_driver_actions(aos_t *this) { pthread_mutex_lock(&this->driver_action_lock); this->num_driver_actions--; + /* indicate the change to ao_loop() */ + pthread_cond_broadcast(&this->driver_action_cond); pthread_mutex_unlock(&this->driver_action_lock); } @@ -1609,7 +1624,7 @@ static void ao_close(xine_audio_port_t *this_gen, xine_stream_t *stream) { pthread_mutex_unlock(&this->streams_lock); /* close driver if no streams left */ - if (!ite && !this->grab_only && !stream->gapless_switch) { + if (!ite && !this->grab_only && !stream->keep_ao_driver_open) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_out: no streams left, closing driver\n"); if (this->audio_loop_running) { @@ -1672,6 +1687,7 @@ static void ao_exit(xine_audio_port_t *this_gen) { } pthread_mutex_destroy(&this->driver_lock); + pthread_cond_destroy(&this->driver_action_cond); pthread_mutex_destroy(&this->driver_action_lock); pthread_mutex_destroy(&this->streams_lock); xine_list_delete(this->streams); @@ -1684,6 +1700,7 @@ static void ao_exit(xine_audio_port_t *this_gen) { free (this->frame_buf[1]); free (this->zero_space); + pthread_mutex_destroy(&this->current_speed_lock); pthread_mutex_destroy(&this->flush_audio_driver_lock); pthread_cond_destroy(&this->flush_audio_driver_reached); @@ -1910,8 +1927,15 @@ static int ao_set_property (xine_audio_port_t *this_gen, int property, int value if (value != XINE_FINE_SPEED_NORMAL && value != XINE_SPEED_PAUSE && !this->slow_fast_audio ) this->ao.control(&this->ao, AO_CTRL_FLUSH_BUFFERS, NULL); - this->ao.control(&this->ao, - (value == XINE_SPEED_PAUSE) ? AO_CTRL_PLAY_PAUSE : AO_CTRL_PLAY_RESUME, NULL); + if( value == XINE_SPEED_PAUSE ) { + /* current_speed_lock is here to make sure the ao_loop will pause in a safe place. + * that is, we cannot pause writing to device, filling gaps etc. */ + pthread_mutex_lock(&this->current_speed_lock); + this->ao.control(&this->ao, AO_CTRL_PLAY_PAUSE, NULL); + pthread_mutex_unlock(&this->current_speed_lock); + } else { + this->ao.control(&this->ao, AO_CTRL_PLAY_RESUME, NULL); + } this->current_speed = value; if( this->slow_fast_audio ) ao_update_resample_factor(this); @@ -2056,6 +2080,7 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, this->driver = driver; this->xine = xine; this->clock = xine->clock; + this->current_speed = xine->clock->speed; this->streams = xine_list_new(); /* warning: driver_lock is a recursive mutex. it must NOT be @@ -2067,6 +2092,7 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, pthread_mutex_init( &this->streams_lock, NULL ); pthread_mutex_init( &this->driver_lock, &attr ); pthread_mutex_init( &this->driver_action_lock, NULL ); + pthread_cond_init( &this->driver_action_cond, NULL ); this->ao.open = ao_open; this->ao.get_buffer = ao_get_buffer; @@ -2087,6 +2113,7 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, this->discard_buffers = 0; this->zero_space = calloc (1, ZERO_BUF_SIZE * 4 * 6); /* MAX as 32bit, 6 channels. */ + pthread_mutex_init( &this->current_speed_lock, NULL ); pthread_mutex_init( &this->flush_audio_driver_lock, NULL ); pthread_cond_init( &this->flush_audio_driver_reached, NULL ); diff --git a/src/xine-engine/broadcaster.c b/src/xine-engine/broadcaster.c index 5ce1619d1..81711de49 100644 --- a/src/xine-engine/broadcaster.c +++ b/src/xine-engine/broadcaster.c @@ -32,6 +32,10 @@ * 'xine -V none -A none' */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <unistd.h> diff --git a/src/xine-engine/broadcaster.h b/src/xine-engine/broadcaster.h index 0c6a291eb..b59d33349 100644 --- a/src/xine-engine/broadcaster.h +++ b/src/xine-engine/broadcaster.h @@ -27,10 +27,6 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - typedef struct broadcaster_s broadcaster_t; broadcaster_t *_x_init_broadcaster(xine_stream_t *stream, int port) XINE_MALLOC XINE_PROTECTED; diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h index 04fa030bf..e0866f549 100644 --- a/src/xine-engine/buffer.h +++ b/src/xine-engine/buffer.h @@ -35,10 +35,6 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <string.h> #include <stdio.h> #include <pthread.h> @@ -275,6 +271,7 @@ extern "C" { #define BUF_SPU_CVD 0x04050000 #define BUF_SPU_OGM 0x04060000 #define BUF_SPU_CMML 0x04070000 +#define BUF_SPU_HDMV 0x04080000 /* demuxer block types: */ @@ -378,6 +375,16 @@ struct buf_element_s { * decoder_info[2] carries denominator for display aspect ratio */ #define BUF_FLAG_ASPECT 0x0800 +/* represent the state of gapless_switch at the time buf was enqueued */ +#define BUF_FLAG_GAPLESS_SW 0x1000 + +/* Amount of audio padding added by encoder (mp3, aac). These empty + * audio frames are causing a gap when switching between mp3 files. + * decoder_info[1] carries amount of audio frames padded at the + * beginning of the buffer + * decoder_info[2] carries amount of audio frames padded at the end of + * the buffer */ +#define BUF_FLAG_AUDIO_PADDING 0x2000 /* Special buffer types: * Sometimes there is a need to relay special information from a demuxer diff --git a/src/xine-engine/demux.c b/src/xine-engine/demux.c index 257a72383..98b2e3fd3 100644 --- a/src/xine-engine/demux.c +++ b/src/xine-engine/demux.c @@ -21,6 +21,9 @@ * hide some xine engine details from demuxers and reduce code duplication */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include <stdio.h> #include <string.h> @@ -117,6 +120,34 @@ void _x_demux_flush_engine (xine_stream_t *stream) { } +static struct timespec _x_compute_interval(unsigned int millisecs) { + struct timespec ts; +#ifdef WIN32 + FILETIME ft; + ULARGE_INTEGER ui; + + GetSystemTimeAsFileTime(&ft); + ui.u.LowPart = ft.dwLowDateTime; + ui.u.HighPart = ft.dwHighDateTime; + ui.QuadPart += millisecs * 10000; + ts.tv_sec = ui.QuadPart / 10000000; + ts.tv_sec = (ui.QuadPart % 10000000)*100; +#elif _POSIX_TIMERS > 0 + clock_gettime(CLOCK_REALTIME, &ts); + uint64_t ttimer = (uint64_t)ts.tv_sec*1000 + ts.tv_nsec/1000000 + millisecs; + ts.tv_sec = ttimer/1000; + ts.tv_nsec = (ttimer%1000)*1000000; +#else + struct timeval tv; + gettimeofday(&tv, NULL); + uint64_t ttimer = (uint64_t)tv.tv_sec*1000 + tv.tv_usec/1000 + millisecs; + ts.tv_sec = ttimer/1000; + ts.tv_nsec = (ttimer%1000)*1000000; +#endif + return ts; +} + + void _x_demux_control_newpts( xine_stream_t *stream, int64_t pts, uint32_t flags ) { buf_element_t *buf; @@ -138,6 +169,29 @@ void _x_demux_control_newpts( xine_stream_t *stream, int64_t pts, uint32_t flags pthread_mutex_unlock(&stream->demux_mutex); } +/* avoid ao_loop being stuck in a pthread_cond_wait, waiting for data; + * return 1 if the stream is stopped + * (better fix wanted!) + */ +static int demux_unstick_ao_loop (xine_stream_t *stream) +{ +/* if (!stream->audio_thread_created) + return 0; +*/ + int status = xine_get_status (stream); + if (status != XINE_STATUS_QUIT && status != XINE_STATUS_STOP && stream->demux_plugin->get_status(stream->demux_plugin) != DEMUX_FINISHED) + return 0; +#if 0 + /* right, stream is stopped... */ + audio_buffer_t *buf = stream->audio_out->get_buffer (stream->audio_out); + buf->num_frames = 0; + buf->stream = NULL; + stream->audio_out->put_buffer (stream->audio_out, buf, stream); +#endif + lprintf("stuck\n"); + return 1; +} + /* sync with decoder fifos, making sure everything gets processed */ void _x_demux_control_headers_done (xine_stream_t *stream) { @@ -175,21 +229,27 @@ void _x_demux_control_headers_done (xine_stream_t *stream) { stream->audio_fifo->put (stream->audio_fifo, buf_audio); pthread_mutex_unlock(&stream->demux_mutex); + unsigned int max_iterations = 0; while ((stream->header_count_audio < header_count_audio) || (stream->header_count_video < header_count_video)) { - struct timeval tv; - struct timespec ts; lprintf ("waiting for headers. v:%d %d a:%d %d\n", stream->header_count_video, header_count_video, stream->header_count_audio, header_count_audio); + + struct timespec ts = _x_compute_interval(1000); + int ret_wait; - gettimeofday(&tv, NULL); - ts.tv_sec = tv.tv_sec + 1; - ts.tv_nsec = tv.tv_usec * 1000; /* use timedwait to workaround buggy pthread broadcast implementations */ - pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts); + ret_wait = pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts); + + if (ret_wait == ETIMEDOUT && demux_unstick_ao_loop (stream) && ++max_iterations > 4) { + xine_log(stream->xine, + XINE_LOG_MSG,_("Stuck in _x_demux_control_headers_done(). Taking the emergency exit\n")); + stream->emergency_brake = 1; + break; + } } stream->demux_action_pending = 0; @@ -203,15 +263,18 @@ void _x_demux_control_headers_done (xine_stream_t *stream) { void _x_demux_control_start( xine_stream_t *stream ) { buf_element_t *buf; + uint32_t flags = (stream->gapless_switch) ? BUF_FLAG_GAPLESS_SW : 0; pthread_mutex_lock(&stream->demux_mutex); buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); buf->type = BUF_CONTROL_START; + buf->decoder_flags = flags; stream->video_fifo->put (stream->video_fifo, buf); buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo); buf->type = BUF_CONTROL_START; + buf->decoder_flags = flags; stream->audio_fifo->put (stream->audio_fifo, buf); pthread_mutex_unlock(&stream->demux_mutex); @@ -343,10 +406,21 @@ static void *demux_loop (void *stream_gen) { pthread_mutex_unlock( &stream->demux_lock ); pthread_mutex_lock (&stream->counter_lock); + struct timespec ts; + unsigned int max_iterations = 0; + int ret_wait; while ((stream->finished_count_audio < finished_count_audio) || (stream->finished_count_video < finished_count_video)) { lprintf ("waiting for finisheds.\n"); - pthread_cond_wait (&stream->counter_changed, &stream->counter_lock); + ts = _x_compute_interval(1000); + ret_wait = pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts); + + if (ret_wait == ETIMEDOUT && demux_unstick_ao_loop (stream) && ++max_iterations > 4) { + xine_log(stream->xine, + XINE_LOG_MSG,_("Stuck in demux_loop(). Taking the emergency exit\n")); + stream->emergency_brake = 1; + break; + } } pthread_mutex_unlock (&stream->counter_lock); diff --git a/src/xine-engine/info_helper.c b/src/xine-engine/info_helper.c index 34d1bbdba..6ce9bcd38 100644 --- a/src/xine-engine/info_helper.c +++ b/src/xine-engine/info_helper.c @@ -251,7 +251,15 @@ static void meta_info_set_unlocked_encoding(xine_stream_t *stream, int info, con size_t inbytesleft, outbytesleft; inbuf = (ICONV_CONST char *)value; - inbytesleft = strlen(value); + if (!strncmp (enc, "UTF-16", 6) || !strncmp (enc, "UCS-2", 5)) + { + /* strlen() won't work with UTF-16* or UCS-2* */ + inbytesleft = 0; + while (value[inbytesleft] || value[inbytesleft + 1]) + inbytesleft += 2; + } /* ... do we need to handle UCS-4? Probably not. */ + else + inbytesleft = strlen(value); outbytesleft = 4 * inbytesleft; /* estimative (max) */ outbuf = utf8_value = malloc(outbytesleft+1); diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c index f0e33ceed..04e0b4461 100644 --- a/src/xine-engine/load_plugins.c +++ b/src/xine-engine/load_plugins.c @@ -485,7 +485,7 @@ static void _register_plugins_internal(xine_t *this, plugin_file_t *file, plugin while ( info && info->type != PLUGIN_NONE ) { - if (file) + if (file && file->filename) xine_log (this, XINE_LOG_PLUGIN, _("load_plugins: plugin %s found\n"), file->filename); else @@ -1062,20 +1062,21 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { static void save_catalog (xine_t *this) { FILE *fp; - char *cachefile, *dirfile; + char *cachefile, *cachefile_new, *dirfile; const char *relname = CACHE_CATALOG_FILE; const char *dirname = CACHE_CATALOG_DIR; const char *const homedir = xine_get_homedir(); asprintf(&cachefile, "%s/%s", homedir, relname); + asprintf(&cachefile_new, "%s.new", cachefile); /* make sure homedir (~/.xine) exists */ asprintf(&dirfile, "%s/%s", homedir, dirname); mkdir (dirfile, 0755); free (dirfile); - if( (fp = fopen(cachefile,"w")) != NULL ) { + if( (fp = fopen(cachefile_new,"w")) != NULL ) { int i; fprintf(fp, "# this file is automatically created by xine, do not edit.\n\n"); @@ -1084,9 +1085,29 @@ static void save_catalog (xine_t *this) { for (i = 0; i < PLUGIN_TYPE_MAX; i++) { save_plugin_list (fp, this->plugin_catalog->plugin_lists[i]); } - fclose(fp); + if (fclose(fp)) + { + const char *err = strerror (errno); + xine_log (this, XINE_LOG_MSG, + _("failed to save catalogue cache: %s\n"), err); + goto do_unlink; + } + else if (rename (cachefile_new, cachefile)) + { + const char *err = strerror (errno); + xine_log (this, XINE_LOG_MSG, + _("failed to replace catalogue cache: %s\n"), err); + do_unlink: + if (unlink (cachefile_new) && errno != ENOENT) + { + err = strerror (errno); + xine_log (this, XINE_LOG_MSG, + _("failed to remove new catalogue cache: %s\n"), err); + } + } } free(cachefile); + free(cachefile_new); } /* diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index 84b936941..eb9abb84a 100644 --- a/src/xine-engine/metronom.c +++ b/src/xine-engine/metronom.c @@ -304,6 +304,8 @@ static void metronom_handle_discontinuity (metronom_t *this, int type, /* video_vpts and audio_vpts adjustements */ cur_time = this->xine->clock->get_current_time(this->xine->clock); + xprintf(this->xine, XINE_VERBOSITY_DEBUG, + "current time : %" PRId64 "\n", cur_time); switch (type) { case DISC_STREAMSTART: @@ -320,33 +322,12 @@ static void metronom_handle_discontinuity (metronom_t *this, int type, case DISC_ABSOLUTE: case DISC_RELATIVE: - if (this->video_vpts < cur_time) { - /* still frame */ - if (this->audio_vpts > cur_time) { - /* still frame with audio */ - this->video_vpts = this->audio_vpts; - xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video vpts adjusted to audio vpts %" PRId64 "\n", this->video_vpts); - } else { - /* still frame, no audio */ - this->video_vpts = this->prebuffer + cur_time; - this->audio_vpts = this->video_vpts; - this->audio_vpts_rmndr = 0; - this->force_video_jump = 1; - this->force_audio_jump = 1; - this->video_drift = 0; - xprintf(this->xine, XINE_VERBOSITY_DEBUG, "vpts adjusted with prebuffer to %" PRId64 "\n", - this->video_vpts); - } + if (this->video_vpts < this->audio_vpts) { + this->video_vpts = this->audio_vpts; + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video vpts adjusted to audio vpts %" PRId64 "\n", this->video_vpts); } else { - /* video */ - if (this->audio_vpts < cur_time) { - /* video, no sound */ - this->audio_vpts = this->video_vpts; - this->audio_vpts_rmndr = 0; - xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio vpts adjusted to video vpts %" PRId64 "\n", this->video_vpts); - } else { - /* video + audio */ - } + this->audio_vpts = this->video_vpts; + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio vpts adjusted to video vpts %" PRId64 "\n", this->video_vpts); } break; } diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c index 73470be1f..0a66efaab 100644 --- a/src/xine-engine/osd.c +++ b/src/xine-engine/osd.c @@ -121,6 +121,20 @@ struct osd_ft2context_s { FT_Face face; int size; }; + +static void osd_free_ft2 (osd_object_t *osd) +{ + if( osd->ft2 ) { + if ( osd->ft2->face ) + FT_Done_Face (osd->ft2->face); + if ( osd->ft2->library ) + FT_Done_FreeType(osd->ft2->library); + free( osd->ft2 ); + osd->ft2 = NULL; + } +} +#else +static inline void osd_free_ft2 (osd_object_t *osd __attr_unused) {} #endif /* @@ -873,6 +887,11 @@ static int osd_set_font_freetype2( osd_object_t *osd, const char *fontname, int return 0; } } + + if (osd->ft2->face) { + FT_Done_Face (osd->ft2->face); + osd->ft2->face = NULL; + } #ifdef HAVE_FONTCONFIG do { @@ -931,16 +950,14 @@ static int osd_set_font_freetype2( osd_object_t *osd, const char *fontname, int _("osd: error loading font %s with ft2\n"), fontname); } - free(osd->ft2); - osd->ft2 = NULL; + osd_free_ft2 (osd); return 0; end: if (FT_Set_Pixel_Sizes(osd->ft2->face, 0, size)) { xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, _("osd: error setting font size (no scalable font?)\n")); - free(osd->ft2); - osd->ft2 = NULL; + osd_free_ft2 (osd); return 0; } @@ -1516,15 +1533,7 @@ static void osd_free_object (osd_object_t *osd_to_close) { if ( osd == osd_to_close ) { free( osd->area ); -#ifdef HAVE_FT2 - if( osd->ft2 ) { - if ( osd->ft2->library ) - FT_Done_FreeType(osd->ft2->library); - - free( osd->ft2 ); - } -#endif - + osd_free_ft2 (osd); osd_free_encoding(osd); if( last ) diff --git a/src/xine-engine/refcounter.c b/src/xine-engine/refcounter.c index 8e952952b..384bdf5ed 100644 --- a/src/xine-engine/refcounter.c +++ b/src/xine-engine/refcounter.c @@ -17,6 +17,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define LOG_MODULE "refcounter" #define LOG_VERBOSE /* diff --git a/src/xine-engine/refcounter.h b/src/xine-engine/refcounter.h index d51973675..b3ddd71fc 100644 --- a/src/xine-engine/refcounter.h +++ b/src/xine-engine/refcounter.h @@ -20,10 +20,6 @@ #ifndef HAVE_REFCOUNTER_H #define HAVE_REFCOUNTER_H -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <pthread.h> typedef struct { diff --git a/src/xine-engine/scratch.c b/src/xine-engine/scratch.c index 696e99ffb..980af2f71 100644 --- a/src/xine-engine/scratch.c +++ b/src/xine-engine/scratch.c @@ -37,7 +37,7 @@ #include "xineutils.h" #include "scratch.h" -static void __attribute__((__format__(__printf__, 2, 0))) +static void XINE_FORMAT_PRINTF(2, 0) scratch_printf (scratch_buffer_t *this, const char *format, va_list argp) { time_t t; diff --git a/src/xine-engine/scratch.h b/src/xine-engine/scratch.h index 1029276e3..c45af198f 100644 --- a/src/xine-engine/scratch.h +++ b/src/xine-engine/scratch.h @@ -32,10 +32,7 @@ typedef struct scratch_buffer_s scratch_buffer_t; struct scratch_buffer_s { - void -#if __GNUC__ >= 3 - __attribute__((__format__(__printf__, 2, 0))) -#endif + void XINE_FORMAT_PRINTF(2, 0) (*scratch_printf) (scratch_buffer_t *this, const char *format, va_list ap); char **(*get_content) (scratch_buffer_t *this); diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c index c88e01714..d3c9e0d34 100644 --- a/src/xine-engine/video_decoder.c +++ b/src/xine-engine/video_decoder.c @@ -160,7 +160,7 @@ static void *video_decoder_loop (void *stream_gen) { running_ticket->release(running_ticket, 0); - if( !stream->gapless_switch ) + if( !(buf->decoder_flags & BUF_FLAG_GAPLESS_SW) ) stream->metronom->handle_video_discontinuity (stream->metronom, DISC_STREAMSTART, 0); diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 480c1c8f2..ae0f61407 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -36,10 +36,6 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <pthread.h> #ifdef XINE_COMPILE diff --git a/src/xine-engine/video_overlay.c b/src/xine-engine/video_overlay.c index 945df3cb9..b88f10c11 100644 --- a/src/xine-engine/video_overlay.c +++ b/src/xine-engine/video_overlay.c @@ -18,6 +18,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <unistd.h> #include <string.h> diff --git a/src/xine-engine/vo_scale.c b/src/xine-engine/vo_scale.c index ff30c47a6..8d84c32da 100644 --- a/src/xine-engine/vo_scale.c +++ b/src/xine-engine/vo_scale.c @@ -22,6 +22,10 @@ * Takes into account aspect ratio correction and zooming. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <string.h> #include <math.h> diff --git a/src/xine-engine/vo_scale.h b/src/xine-engine/vo_scale.h index 829405162..eb2607024 100644 --- a/src/xine-engine/vo_scale.h +++ b/src/xine-engine/vo_scale.h @@ -29,10 +29,6 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #ifdef XINE_COMPILE # include "configfile.h" #else diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index e0c98c018..1154a4602 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -330,17 +330,20 @@ static xine_ticket_t *XINE_MALLOC ticket_init(void) { static void set_speed_internal (xine_stream_t *stream, int speed) { xine_t *xine = stream->xine; + int old_speed = xine->clock->speed; - if (xine->clock->speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE) + if (old_speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE) /* get all decoder and post threads in a state where they agree to be blocked */ xine->port_ticket->revoke(xine->port_ticket, 0); - if (xine->clock->speed == XINE_SPEED_PAUSE && speed != XINE_SPEED_PAUSE) + if (old_speed == XINE_SPEED_PAUSE && speed != XINE_SPEED_PAUSE) /* all decoder and post threads may continue now */ xine->port_ticket->issue(xine->port_ticket, 0); - stream->xine->clock->set_fine_speed (stream->xine->clock, speed); - + if (old_speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE) + /* set master clock so audio_out loop can pause in a safe place */ + stream->xine->clock->set_fine_speed (stream->xine->clock, speed); + /* see coment on audio_out loop about audio_paused */ if( stream->audio_out ) { xine->port_ticket->acquire(xine->port_ticket, 1); @@ -350,6 +353,10 @@ static void set_speed_internal (xine_stream_t *stream, int speed) { xine->port_ticket->release(xine->port_ticket, 1); } + + if (old_speed == XINE_SPEED_PAUSE || speed != XINE_SPEED_PAUSE) + /* master clock is set after resuming the audio device (audio_out loop may continue) */ + stream->xine->clock->set_fine_speed (stream->xine->clock, speed); } @@ -419,6 +426,7 @@ void xine_stop (xine_stream_t *stream) { static void close_internal (xine_stream_t *stream) { int i ; + int gapless_switch = stream->gapless_switch; if( stream->slave ) { xine_close( stream->slave ); @@ -429,7 +437,7 @@ static void close_internal (xine_stream_t *stream) { } } - if( !stream->gapless_switch ) { + if( !gapless_switch ) { /* make sure that other threads cannot change the speed, especially pauseing the stream */ pthread_mutex_lock(&stream->speed_change_lock); stream->ignore_speed_change = 1; @@ -445,7 +453,7 @@ static void close_internal (xine_stream_t *stream) { stop_internal( stream ); - if( !stream->gapless_switch ) { + if( !gapless_switch ) { if (stream->video_out) stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 0); if (stream->audio_out) @@ -596,6 +604,7 @@ xine_stream_t *xine_stream_new (xine_t *this, stream->early_finish_event = 0; stream->delay_finish_event = 0; stream->gapless_switch = 0; + stream->keep_ao_driver_open = 0; stream->video_out = vo; if (vo) diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c index 8301414cd..c9481ab94 100644 --- a/src/xine-engine/xine_interface.c +++ b/src/xine-engine/xine_interface.c @@ -529,6 +529,9 @@ void xine_set_param (xine_stream_t *stream, int param, int value) { case XINE_PARAM_GAPLESS_SWITCH: stream->gapless_switch = !!value; + if( stream->gapless_switch && !stream->early_finish_event ) { + xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "frontend possibly buggy: gapless_switch without early_finish_event\n"); + } break; default: diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h index f97ca0b24..945157fc2 100644 --- a/src/xine-engine/xine_internal.h +++ b/src/xine-engine/xine_internal.h @@ -361,6 +361,7 @@ struct xine_stream_s { int early_finish_event; /* do not wait fifos get empty before sending event */ int gapless_switch; /* next stream switch will be gapless */ int delay_finish_event; /* delay event in 1/10 sec units. 0=>no delay, -1=>forever */ + int keep_ao_driver_open; #endif }; diff --git a/src/xine-utils/Makefile.am b/src/xine-utils/Makefile.am index 8a3d88ddd..501f489fe 100644 --- a/src/xine-utils/Makefile.am +++ b/src/xine-utils/Makefile.am @@ -37,6 +37,7 @@ xineinclude_HEADERS = \ compat.h \ xine_buffer.h \ xineutils.h \ + xine_mmx.h \ xmllexer.h \ xmlparser.h \ list.h \ diff --git a/src/xine-utils/cpu_accel.c b/src/xine-utils/cpu_accel.c index c241dd7ef..d6c4bd9a8 100644 --- a/src/xine-utils/cpu_accel.c +++ b/src/xine-utils/cpu_accel.c @@ -40,6 +40,10 @@ #include "xineutils.h" +#if defined(PIC) && ! defined(__PIC__) +#define __PIC__ +#endif + #if defined(ARCH_X86) || defined(ARCH_X86_64) static jmp_buf sigill_return; diff --git a/src/xine-utils/mangle.h b/src/xine-utils/mangle.h index 7627ca2fc..746317fa5 100644 --- a/src/xine-utils/mangle.h +++ b/src/xine-utils/mangle.h @@ -29,6 +29,10 @@ #ifndef _XINE_MANGLE_H #define _XINE_MANGLE_H +#if defined(PIC) && ! defined(__PIC__) +#define __PIC__ +#endif + // Use rip-relative addressing if compiling PIC code on x86-64. #if defined(__MINGW32__) || defined(__CYGWIN__) || defined(__DJGPP__) || \ defined(__OS2__) || (defined (__OpenBSD__) && !defined(__ELF__)) diff --git a/src/xine-utils/monitor.c b/src/xine-utils/monitor.c index 650c10f99..77280ffc6 100644 --- a/src/xine-utils/monitor.c +++ b/src/xine-utils/monitor.c @@ -32,41 +32,42 @@ #ifndef NDEBUG -static long long int profiler_times[MAX_ID] ; -static long long int profiler_start[MAX_ID] ; -static long profiler_calls[MAX_ID] ; -static const char *profiler_label[MAX_ID] ; +typedef struct { + uint64_t p_times; + uint64_t p_start; + long p_calls; + const char *p_label; +} xine_profiler_t; + +static xine_profiler_t profiler[MAX_ID]; void xine_profiler_init () { - memset(profiler_times, 0, sizeof(profiler_times)); - memset(profiler_start, 0, sizeof(profiler_start)); - memset(profiler_calls, 0, sizeof(profiler_calls)); - memset(profiler_label, 0, sizeof(profiler_label)); + memset(profiler, 0, sizeof(profiler)); } int xine_profiler_allocate_slot (const char *label) { int id; - for (id = 0; id < MAX_ID && profiler_label[id] != NULL; id++) + for (id = 0; id < MAX_ID && profiler[id].p_label != NULL; id++) ; if (id >= MAX_ID) return -1; - profiler_label[id] = label; + profiler[id].p_label = label; return id; } #if defined(ARCH_X86_32) -static __inline__ unsigned long long int rdtsc(void) +static __inline__ uint64_t rdtsc(void) { unsigned long long int x; __asm__ volatile ("rdtsc\n\t" : "=A" (x)); return x; } #elif defined(ARCH_X86_64) -static __inline__ unsigned long long int rdtsc(void) +static __inline__ uint64_t rdtsc(void) { unsigned long long int a, d; __asm__ volatile ("rdtsc\n\t" : "=a" (a), "=d" (d)); @@ -78,7 +79,7 @@ void xine_profiler_start_count (int id) { if ( id >= MAX_ID || id < 0 ) return; #if defined(ARCH_X86) || defined(ARCH_X86_64) - profiler_start[id] = rdtsc(); + profiler[id].p_start = rdtsc(); #endif } @@ -86,18 +87,19 @@ void xine_profiler_stop_count (int id) { if ( id >= MAX_ID || id < 0 ) return; #if defined(ARCH_X86) || defined(ARCH_X86_64) - profiler_times[id] += rdtsc() - profiler_start[id]; + profiler[id].p_times += rdtsc() - profiler[id].p_start; #endif - profiler_calls[id]++; + profiler[id].p_calls++; } void xine_profiler_print_results (void) { int i; #if defined(ARCH_X86) || defined(ARCH_X86_64) - static long long int cpu_speed; /* cpu cyles/usec */ + static uint64_t cpu_speed; /* cpu cyles/usec */ + if (!cpu_speed) { - long long int tsc_start, tsc_end; + uint64_t tsc_start, tsc_end; struct timeval tv_start, tv_end; tsc_start = rdtsc(); @@ -119,13 +121,13 @@ void xine_profiler_print_results (void) { "----------------------------------------------------------------------------\n", "ID", "name", "cpu cycles", "calls", "cycles/call", "usec/call"); for (i=0; i<MAX_ID; i++) { - if (profiler_label[i]) { + if (profiler[i].p_label) { printf ("%2d: %-24.24s %12lld %9ld", - i, profiler_label[i], profiler_times[i], profiler_calls[i]); - if (profiler_calls[i]) { - printf(" %12lld", profiler_times[i] / profiler_calls[i]); + i, profiler[i].p_label, profiler[i].p_times, profiler[i].p_calls); + if (profiler[i].p_calls) { + printf(" %12lld", profiler[i].p_times / profiler[i].p_calls); #if defined(ARCH_X86) || defined(ARCH_X86_64) - printf(" %9lld", profiler_times[i] / (cpu_speed * profiler_calls[i])); + printf(" %9lld", profiler[i].p_times / (cpu_speed * profiler[i].p_calls)); #endif } printf ("\n"); diff --git a/src/xine-utils/utils.c b/src/xine-utils/utils.c index 689b68502..c3281f369 100644 --- a/src/xine-utils/utils.c +++ b/src/xine-utils/utils.c @@ -564,7 +564,7 @@ char *xine_get_system_encoding(void) { char *codeset = NULL; #ifdef HAVE_NL_LANGINFO - setlocale(LC_ALL, ""); + setlocale(LC_CTYPE, ""); codeset = nl_langinfo(CODESET); #endif /* diff --git a/src/xine-utils/xine_buffer.c b/src/xine-utils/xine_buffer.c index 097ca0f1f..44d0acbab 100644 --- a/src/xine-utils/xine_buffer.c +++ b/src/xine-utils/xine_buffer.c @@ -47,6 +47,10 @@ * (eg during reallocation). The user must respect that. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <stdio.h> #include <string.h> diff --git a/src/xine-utils/xine_mmx.h b/src/xine-utils/xine_mmx.h new file mode 100644 index 000000000..440d1efcc --- /dev/null +++ b/src/xine-utils/xine_mmx.h @@ -0,0 +1,490 @@ +/* + * 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 + */ +#ifndef XINE_MMX_H +#define XINE_MMX_H + +#if defined(ARCH_X86) || defined(ARCH_X86_64) + +typedef union { + int64_t q; /* Quadword (64-bit) value */ + uint64_t uq; /* Unsigned Quadword */ + int d[2]; /* 2 Doubleword (32-bit) values */ + unsigned int ud[2]; /* 2 Unsigned Doubleword */ + short w[4]; /* 4 Word (16-bit) values */ + unsigned short uw[4]; /* 4 Unsigned Word */ + char b[8]; /* 8 Byte (8-bit) values */ + unsigned char ub[8]; /* 8 Unsigned Byte */ + float s[2]; /* Single-precision (32-bit) value */ +} ATTR_ALIGN(8) mmx_t; /* On an 8-byte (64-bit) boundary */ + + + +#define mmx_i2r(op,imm,reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "i" (imm) ) + +#define mmx_m2r(op,mem,reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "m" (mem)) + +#define mmx_r2m(op,reg,mem) \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=m" (mem) \ + : /* nothing */ ) + +#define mmx_r2r(op,regs,regd) \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd) + + +#define emms() __asm__ __volatile__ ("emms") + +#define movd_m2r(var,reg) mmx_m2r (movd, var, reg) +#define movd_r2m(reg,var) mmx_r2m (movd, reg, var) +#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd) + +#define movq_m2r(var,reg) mmx_m2r (movq, var, reg) +#define movq_r2m(reg,var) mmx_r2m (movq, reg, var) +#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd) + +#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg) +#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd) +#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg) +#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd) + +#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg) +#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd) + +#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg) +#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd) +#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg) +#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd) +#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg) +#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd) + +#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg) +#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd) +#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg) +#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd) + +#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg) +#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd) +#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg) +#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd) + +#define pand_m2r(var,reg) mmx_m2r (pand, var, reg) +#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd) + +#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg) +#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd) + +#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg) +#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd) +#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg) +#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd) +#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg) +#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd) + +#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg) +#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd) +#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg) +#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd) +#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg) +#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd) + +#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg) +#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd) + +#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg) +#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd) + +#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg) +#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd) + +#define por_m2r(var,reg) mmx_m2r (por, var, reg) +#define por_r2r(regs,regd) mmx_r2r (por, regs, regd) + +#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg) +#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg) +#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd) +#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg) +#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg) +#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd) +#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg) +#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg) +#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd) + +#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg) +#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg) +#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd) +#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg) +#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg) +#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd) + +#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg) +#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg) +#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd) +#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg) +#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg) +#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd) +#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg) +#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg) +#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd) + +#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg) +#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd) +#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg) +#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd) +#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg) +#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd) + +#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg) +#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd) +#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg) +#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd) + +#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg) +#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd) +#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg) +#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd) + +#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg) +#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd) +#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg) +#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd) +#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg) +#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd) + +#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg) +#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd) +#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg) +#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd) +#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg) +#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd) + +#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg) +#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd) + + +/* 3DNOW extensions */ + +#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg) +#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd) + + +/* AMD MMX extensions - also available in intel SSE */ + + +#define mmx_m2ri(op,mem,reg,imm) \ + __asm__ __volatile__ (#op " %1, %0, %%" #reg \ + : /* nothing */ \ + : "X" (mem), "X" (imm)) +#define mmx_r2ri(op,regs,regd,imm) \ + __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ + : /* nothing */ \ + : "X" (imm) ) + +#define mmx_fetch(mem,hint) \ + __asm__ __volatile__ ("prefetch" #hint " %0" \ + : /* nothing */ \ + : "X" (mem)) + + +#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg) + +#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var) + +#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg) +#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd) +#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg) +#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd) + +#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm) + +#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm) + +#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg) +#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd) + +#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg) +#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd) + +#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg) +#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd) + +#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg) +#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd) + +#define pmovmskb(mmreg,reg) \ + __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg) + +#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg) +#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd) + +#define prefetcht0(mem) mmx_fetch (mem, t0) +#define prefetcht1(mem) mmx_fetch (mem, t1) +#define prefetcht2(mem) mmx_fetch (mem, t2) +#define prefetchnta(mem) mmx_fetch (mem, nta) + +#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg) +#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd) + +#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm) +#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm) + +#define sfence() __asm__ __volatile__ ("sfence\n\t") + +typedef union { + float sf[4]; /* Single-precision (32-bit) value */ +} ATTR_ALIGN(16) sse_t; /* On a 16 byte (128-bit) boundary */ + + +#define sse_i2r(op, imm, reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "X" (imm) ) + +#define sse_m2r(op, mem, reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "X" (mem)) + +#define sse_r2m(op, reg, mem) \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=X" (mem) \ + : /* nothing */ ) + +#define sse_r2r(op, regs, regd) \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd) + +#define sse_r2ri(op, regs, regd, imm) \ + __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ + : /* nothing */ \ + : "X" (imm) ) + +#define sse_m2ri(op, mem, reg, subop) \ + __asm__ __volatile__ (#op " %0, %%" #reg ", " #subop \ + : /* nothing */ \ + : "X" (mem)) + + +#define movaps_m2r(var, reg) sse_m2r(movaps, var, reg) +#define movaps_r2m(reg, var) sse_r2m(movaps, reg, var) +#define movaps_r2r(regs, regd) sse_r2r(movaps, regs, regd) + +#define movntps_r2m(xmmreg, var) sse_r2m(movntps, xmmreg, var) + +#define movups_m2r(var, reg) sse_m2r(movups, var, reg) +#define movups_r2m(reg, var) sse_r2m(movups, reg, var) +#define movups_r2r(regs, regd) sse_r2r(movups, regs, regd) + +#define movhlps_r2r(regs, regd) sse_r2r(movhlps, regs, regd) + +#define movlhps_r2r(regs, regd) sse_r2r(movlhps, regs, regd) + +#define movhps_m2r(var, reg) sse_m2r(movhps, var, reg) +#define movhps_r2m(reg, var) sse_r2m(movhps, reg, var) + +#define movlps_m2r(var, reg) sse_m2r(movlps, var, reg) +#define movlps_r2m(reg, var) sse_r2m(movlps, reg, var) + +#define movss_m2r(var, reg) sse_m2r(movss, var, reg) +#define movss_r2m(reg, var) sse_r2m(movss, reg, var) +#define movss_r2r(regs, regd) sse_r2r(movss, regs, regd) + +#define shufps_m2r(var, reg, index) sse_m2ri(shufps, var, reg, index) +#define shufps_r2r(regs, regd, index) sse_r2ri(shufps, regs, regd, index) + +#define cvtpi2ps_m2r(var, xmmreg) sse_m2r(cvtpi2ps, var, xmmreg) +#define cvtpi2ps_r2r(mmreg, xmmreg) sse_r2r(cvtpi2ps, mmreg, xmmreg) + +#define cvtps2pi_m2r(var, mmreg) sse_m2r(cvtps2pi, var, mmreg) +#define cvtps2pi_r2r(xmmreg, mmreg) sse_r2r(cvtps2pi, mmreg, xmmreg) + +#define cvttps2pi_m2r(var, mmreg) sse_m2r(cvttps2pi, var, mmreg) +#define cvttps2pi_r2r(xmmreg, mmreg) sse_r2r(cvttps2pi, mmreg, xmmreg) + +#define cvtsi2ss_m2r(var, xmmreg) sse_m2r(cvtsi2ss, var, xmmreg) +#define cvtsi2ss_r2r(reg, xmmreg) sse_r2r(cvtsi2ss, reg, xmmreg) + +#define cvtss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) +#define cvtss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) + +#define cvttss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) +#define cvttss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) + +#define movmskps(xmmreg, reg) \ + __asm__ __volatile__ ("movmskps %" #xmmreg ", %" #reg) + +#define addps_m2r(var, reg) sse_m2r(addps, var, reg) +#define addps_r2r(regs, regd) sse_r2r(addps, regs, regd) + +#define addss_m2r(var, reg) sse_m2r(addss, var, reg) +#define addss_r2r(regs, regd) sse_r2r(addss, regs, regd) + +#define subps_m2r(var, reg) sse_m2r(subps, var, reg) +#define subps_r2r(regs, regd) sse_r2r(subps, regs, regd) + +#define subss_m2r(var, reg) sse_m2r(subss, var, reg) +#define subss_r2r(regs, regd) sse_r2r(subss, regs, regd) + +#define mulps_m2r(var, reg) sse_m2r(mulps, var, reg) +#define mulps_r2r(regs, regd) sse_r2r(mulps, regs, regd) + +#define mulss_m2r(var, reg) sse_m2r(mulss, var, reg) +#define mulss_r2r(regs, regd) sse_r2r(mulss, regs, regd) + +#define divps_m2r(var, reg) sse_m2r(divps, var, reg) +#define divps_r2r(regs, regd) sse_r2r(divps, regs, regd) + +#define divss_m2r(var, reg) sse_m2r(divss, var, reg) +#define divss_r2r(regs, regd) sse_r2r(divss, regs, regd) + +#define rcpps_m2r(var, reg) sse_m2r(rcpps, var, reg) +#define rcpps_r2r(regs, regd) sse_r2r(rcpps, regs, regd) + +#define rcpss_m2r(var, reg) sse_m2r(rcpss, var, reg) +#define rcpss_r2r(regs, regd) sse_r2r(rcpss, regs, regd) + +#define rsqrtps_m2r(var, reg) sse_m2r(rsqrtps, var, reg) +#define rsqrtps_r2r(regs, regd) sse_r2r(rsqrtps, regs, regd) + +#define rsqrtss_m2r(var, reg) sse_m2r(rsqrtss, var, reg) +#define rsqrtss_r2r(regs, regd) sse_r2r(rsqrtss, regs, regd) + +#define sqrtps_m2r(var, reg) sse_m2r(sqrtps, var, reg) +#define sqrtps_r2r(regs, regd) sse_r2r(sqrtps, regs, regd) + +#define sqrtss_m2r(var, reg) sse_m2r(sqrtss, var, reg) +#define sqrtss_r2r(regs, regd) sse_r2r(sqrtss, regs, regd) + +#define andps_m2r(var, reg) sse_m2r(andps, var, reg) +#define andps_r2r(regs, regd) sse_r2r(andps, regs, regd) + +#define andnps_m2r(var, reg) sse_m2r(andnps, var, reg) +#define andnps_r2r(regs, regd) sse_r2r(andnps, regs, regd) + +#define orps_m2r(var, reg) sse_m2r(orps, var, reg) +#define orps_r2r(regs, regd) sse_r2r(orps, regs, regd) + +#define xorps_m2r(var, reg) sse_m2r(xorps, var, reg) +#define xorps_r2r(regs, regd) sse_r2r(xorps, regs, regd) + +#define maxps_m2r(var, reg) sse_m2r(maxps, var, reg) +#define maxps_r2r(regs, regd) sse_r2r(maxps, regs, regd) + +#define maxss_m2r(var, reg) sse_m2r(maxss, var, reg) +#define maxss_r2r(regs, regd) sse_r2r(maxss, regs, regd) + +#define minps_m2r(var, reg) sse_m2r(minps, var, reg) +#define minps_r2r(regs, regd) sse_r2r(minps, regs, regd) + +#define minss_m2r(var, reg) sse_m2r(minss, var, reg) +#define minss_r2r(regs, regd) sse_r2r(minss, regs, regd) + +#define cmpps_m2r(var, reg, op) sse_m2ri(cmpps, var, reg, op) +#define cmpps_r2r(regs, regd, op) sse_r2ri(cmpps, regs, regd, op) + +#define cmpeqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 0) +#define cmpeqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 0) + +#define cmpltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 1) +#define cmpltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 1) + +#define cmpleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 2) +#define cmpleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 2) + +#define cmpunordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 3) +#define cmpunordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 3) + +#define cmpneqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 4) +#define cmpneqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 4) + +#define cmpnltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 5) +#define cmpnltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 5) + +#define cmpnleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 6) +#define cmpnleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 6) + +#define cmpordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 7) +#define cmpordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 7) + +#define cmpss_m2r(var, reg, op) sse_m2ri(cmpss, var, reg, op) +#define cmpss_r2r(regs, regd, op) sse_r2ri(cmpss, regs, regd, op) + +#define cmpeqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 0) +#define cmpeqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 0) + +#define cmpltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 1) +#define cmpltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 1) + +#define cmpless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 2) +#define cmpless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 2) + +#define cmpunordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 3) +#define cmpunordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 3) + +#define cmpneqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 4) +#define cmpneqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 4) + +#define cmpnltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 5) +#define cmpnltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 5) + +#define cmpnless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 6) +#define cmpnless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 6) + +#define cmpordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 7) +#define cmpordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 7) + +#define comiss_m2r(var, reg) sse_m2r(comiss, var, reg) +#define comiss_r2r(regs, regd) sse_r2r(comiss, regs, regd) + +#define ucomiss_m2r(var, reg) sse_m2r(ucomiss, var, reg) +#define ucomiss_r2r(regs, regd) sse_r2r(ucomiss, regs, regd) + +#define unpcklps_m2r(var, reg) sse_m2r(unpcklps, var, reg) +#define unpcklps_r2r(regs, regd) sse_r2r(unpcklps, regs, regd) + +#define unpckhps_m2r(var, reg) sse_m2r(unpckhps, var, reg) +#define unpckhps_r2r(regs, regd) sse_r2r(unpckhps, regs, regd) + +#define fxrstor(mem) \ + __asm__ __volatile__ ("fxrstor %0" \ + : /* nothing */ \ + : "X" (mem)) + +#define fxsave(mem) \ + __asm__ __volatile__ ("fxsave %0" \ + : /* nothing */ \ + : "X" (mem)) + +#define stmxcsr(mem) \ + __asm__ __volatile__ ("stmxcsr %0" \ + : /* nothing */ \ + : "X" (mem)) + +#define ldmxcsr(mem) \ + __asm__ __volatile__ ("ldmxcsr %0" \ + : /* nothing */ \ + : "X" (mem)) +#endif /*ARCH_X86 */ + +#endif /*XINE_MMX_H*/ diff --git a/src/xine-utils/xineutils.h b/src/xine-utils/xineutils.h index 5476ef2ce..581932cee 100644 --- a/src/xine-utils/xineutils.h +++ b/src/xine-utils/xineutils.h @@ -24,10 +24,6 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdlib.h> #include <string.h> #include <stdarg.h> @@ -43,6 +39,7 @@ extern "C" { # include "list.h" # include "array.h" # include "sorted_array.h" +# include "xine_mmx.h" #else # ifdef WIN32 # include <winsock.h> @@ -58,6 +55,7 @@ extern "C" { # include <xine/list.h> # include <xine/array.h> # include <xine/sorted_array.h> +# include <xine/xine_mmx.h> #endif #include <stdio.h> @@ -127,472 +125,6 @@ extern "C" { uint32_t xine_mm_accel (void) XINE_CONST XINE_PROTECTED; -#if defined(ARCH_X86) || defined(ARCH_X86_64) - -typedef union { - int64_t q; /* Quadword (64-bit) value */ - uint64_t uq; /* Unsigned Quadword */ - int d[2]; /* 2 Doubleword (32-bit) values */ - unsigned int ud[2]; /* 2 Unsigned Doubleword */ - short w[4]; /* 4 Word (16-bit) values */ - unsigned short uw[4]; /* 4 Unsigned Word */ - char b[8]; /* 8 Byte (8-bit) values */ - unsigned char ub[8]; /* 8 Unsigned Byte */ - float s[2]; /* Single-precision (32-bit) value */ -} ATTR_ALIGN(8) mmx_t; /* On an 8-byte (64-bit) boundary */ - - - -#define mmx_i2r(op,imm,reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "i" (imm) ) - -#define mmx_m2r(op,mem,reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "m" (mem)) - -#define mmx_r2m(op,reg,mem) \ - __asm__ __volatile__ (#op " %%" #reg ", %0" \ - : "=m" (mem) \ - : /* nothing */ ) - -#define mmx_r2r(op,regs,regd) \ - __asm__ __volatile__ (#op " %" #regs ", %" #regd) - - -#define emms() __asm__ __volatile__ ("emms") - -#define movd_m2r(var,reg) mmx_m2r (movd, var, reg) -#define movd_r2m(reg,var) mmx_r2m (movd, reg, var) -#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd) - -#define movq_m2r(var,reg) mmx_m2r (movq, var, reg) -#define movq_r2m(reg,var) mmx_r2m (movq, reg, var) -#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd) - -#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg) -#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd) -#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg) -#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd) - -#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg) -#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd) - -#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg) -#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd) -#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg) -#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd) -#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg) -#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd) - -#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg) -#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd) -#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg) -#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd) - -#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg) -#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd) -#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg) -#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd) - -#define pand_m2r(var,reg) mmx_m2r (pand, var, reg) -#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd) - -#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg) -#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd) - -#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg) -#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd) -#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg) -#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd) -#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg) -#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd) - -#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg) -#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd) -#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg) -#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd) -#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg) -#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd) - -#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg) -#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd) - -#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg) -#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd) - -#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg) -#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd) - -#define por_m2r(var,reg) mmx_m2r (por, var, reg) -#define por_r2r(regs,regd) mmx_r2r (por, regs, regd) - -#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg) -#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg) -#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd) -#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg) -#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg) -#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd) -#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg) -#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg) -#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd) - -#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg) -#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg) -#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd) -#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg) -#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg) -#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd) - -#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg) -#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg) -#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd) -#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg) -#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg) -#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd) -#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg) -#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg) -#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd) - -#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg) -#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd) -#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg) -#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd) -#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg) -#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd) - -#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg) -#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd) -#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg) -#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd) - -#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg) -#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd) -#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg) -#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd) - -#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg) -#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd) -#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg) -#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd) -#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg) -#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd) - -#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg) -#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd) -#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg) -#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd) -#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg) -#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd) - -#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg) -#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd) - - -/* 3DNOW extensions */ - -#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg) -#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd) - - -/* AMD MMX extensions - also available in intel SSE */ - - -#define mmx_m2ri(op,mem,reg,imm) \ - __asm__ __volatile__ (#op " %1, %0, %%" #reg \ - : /* nothing */ \ - : "X" (mem), "X" (imm)) -#define mmx_r2ri(op,regs,regd,imm) \ - __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ - : /* nothing */ \ - : "X" (imm) ) - -#define mmx_fetch(mem,hint) \ - __asm__ __volatile__ ("prefetch" #hint " %0" \ - : /* nothing */ \ - : "X" (mem)) - - -#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg) - -#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var) - -#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg) -#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd) -#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg) -#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd) - -#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm) - -#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm) - -#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg) -#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd) - -#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg) -#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd) - -#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg) -#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd) - -#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg) -#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd) - -#define pmovmskb(mmreg,reg) \ - __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg) - -#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg) -#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd) - -#define prefetcht0(mem) mmx_fetch (mem, t0) -#define prefetcht1(mem) mmx_fetch (mem, t1) -#define prefetcht2(mem) mmx_fetch (mem, t2) -#define prefetchnta(mem) mmx_fetch (mem, nta) - -#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg) -#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd) - -#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm) -#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm) - -#define sfence() __asm__ __volatile__ ("sfence\n\t") - -typedef union { - float sf[4]; /* Single-precision (32-bit) value */ -} ATTR_ALIGN(16) sse_t; /* On a 16 byte (128-bit) boundary */ - - -#define sse_i2r(op, imm, reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "X" (imm) ) - -#define sse_m2r(op, mem, reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "X" (mem)) - -#define sse_r2m(op, reg, mem) \ - __asm__ __volatile__ (#op " %%" #reg ", %0" \ - : "=X" (mem) \ - : /* nothing */ ) - -#define sse_r2r(op, regs, regd) \ - __asm__ __volatile__ (#op " %" #regs ", %" #regd) - -#define sse_r2ri(op, regs, regd, imm) \ - __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ - : /* nothing */ \ - : "X" (imm) ) - -#define sse_m2ri(op, mem, reg, subop) \ - __asm__ __volatile__ (#op " %0, %%" #reg ", " #subop \ - : /* nothing */ \ - : "X" (mem)) - - -#define movaps_m2r(var, reg) sse_m2r(movaps, var, reg) -#define movaps_r2m(reg, var) sse_r2m(movaps, reg, var) -#define movaps_r2r(regs, regd) sse_r2r(movaps, regs, regd) - -#define movntps_r2m(xmmreg, var) sse_r2m(movntps, xmmreg, var) - -#define movups_m2r(var, reg) sse_m2r(movups, var, reg) -#define movups_r2m(reg, var) sse_r2m(movups, reg, var) -#define movups_r2r(regs, regd) sse_r2r(movups, regs, regd) - -#define movhlps_r2r(regs, regd) sse_r2r(movhlps, regs, regd) - -#define movlhps_r2r(regs, regd) sse_r2r(movlhps, regs, regd) - -#define movhps_m2r(var, reg) sse_m2r(movhps, var, reg) -#define movhps_r2m(reg, var) sse_r2m(movhps, reg, var) - -#define movlps_m2r(var, reg) sse_m2r(movlps, var, reg) -#define movlps_r2m(reg, var) sse_r2m(movlps, reg, var) - -#define movss_m2r(var, reg) sse_m2r(movss, var, reg) -#define movss_r2m(reg, var) sse_r2m(movss, reg, var) -#define movss_r2r(regs, regd) sse_r2r(movss, regs, regd) - -#define shufps_m2r(var, reg, index) sse_m2ri(shufps, var, reg, index) -#define shufps_r2r(regs, regd, index) sse_r2ri(shufps, regs, regd, index) - -#define cvtpi2ps_m2r(var, xmmreg) sse_m2r(cvtpi2ps, var, xmmreg) -#define cvtpi2ps_r2r(mmreg, xmmreg) sse_r2r(cvtpi2ps, mmreg, xmmreg) - -#define cvtps2pi_m2r(var, mmreg) sse_m2r(cvtps2pi, var, mmreg) -#define cvtps2pi_r2r(xmmreg, mmreg) sse_r2r(cvtps2pi, mmreg, xmmreg) - -#define cvttps2pi_m2r(var, mmreg) sse_m2r(cvttps2pi, var, mmreg) -#define cvttps2pi_r2r(xmmreg, mmreg) sse_r2r(cvttps2pi, mmreg, xmmreg) - -#define cvtsi2ss_m2r(var, xmmreg) sse_m2r(cvtsi2ss, var, xmmreg) -#define cvtsi2ss_r2r(reg, xmmreg) sse_r2r(cvtsi2ss, reg, xmmreg) - -#define cvtss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) -#define cvtss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) - -#define cvttss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) -#define cvttss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) - -#define movmskps(xmmreg, reg) \ - __asm__ __volatile__ ("movmskps %" #xmmreg ", %" #reg) - -#define addps_m2r(var, reg) sse_m2r(addps, var, reg) -#define addps_r2r(regs, regd) sse_r2r(addps, regs, regd) - -#define addss_m2r(var, reg) sse_m2r(addss, var, reg) -#define addss_r2r(regs, regd) sse_r2r(addss, regs, regd) - -#define subps_m2r(var, reg) sse_m2r(subps, var, reg) -#define subps_r2r(regs, regd) sse_r2r(subps, regs, regd) - -#define subss_m2r(var, reg) sse_m2r(subss, var, reg) -#define subss_r2r(regs, regd) sse_r2r(subss, regs, regd) - -#define mulps_m2r(var, reg) sse_m2r(mulps, var, reg) -#define mulps_r2r(regs, regd) sse_r2r(mulps, regs, regd) - -#define mulss_m2r(var, reg) sse_m2r(mulss, var, reg) -#define mulss_r2r(regs, regd) sse_r2r(mulss, regs, regd) - -#define divps_m2r(var, reg) sse_m2r(divps, var, reg) -#define divps_r2r(regs, regd) sse_r2r(divps, regs, regd) - -#define divss_m2r(var, reg) sse_m2r(divss, var, reg) -#define divss_r2r(regs, regd) sse_r2r(divss, regs, regd) - -#define rcpps_m2r(var, reg) sse_m2r(rcpps, var, reg) -#define rcpps_r2r(regs, regd) sse_r2r(rcpps, regs, regd) - -#define rcpss_m2r(var, reg) sse_m2r(rcpss, var, reg) -#define rcpss_r2r(regs, regd) sse_r2r(rcpss, regs, regd) - -#define rsqrtps_m2r(var, reg) sse_m2r(rsqrtps, var, reg) -#define rsqrtps_r2r(regs, regd) sse_r2r(rsqrtps, regs, regd) - -#define rsqrtss_m2r(var, reg) sse_m2r(rsqrtss, var, reg) -#define rsqrtss_r2r(regs, regd) sse_r2r(rsqrtss, regs, regd) - -#define sqrtps_m2r(var, reg) sse_m2r(sqrtps, var, reg) -#define sqrtps_r2r(regs, regd) sse_r2r(sqrtps, regs, regd) - -#define sqrtss_m2r(var, reg) sse_m2r(sqrtss, var, reg) -#define sqrtss_r2r(regs, regd) sse_r2r(sqrtss, regs, regd) - -#define andps_m2r(var, reg) sse_m2r(andps, var, reg) -#define andps_r2r(regs, regd) sse_r2r(andps, regs, regd) - -#define andnps_m2r(var, reg) sse_m2r(andnps, var, reg) -#define andnps_r2r(regs, regd) sse_r2r(andnps, regs, regd) - -#define orps_m2r(var, reg) sse_m2r(orps, var, reg) -#define orps_r2r(regs, regd) sse_r2r(orps, regs, regd) - -#define xorps_m2r(var, reg) sse_m2r(xorps, var, reg) -#define xorps_r2r(regs, regd) sse_r2r(xorps, regs, regd) - -#define maxps_m2r(var, reg) sse_m2r(maxps, var, reg) -#define maxps_r2r(regs, regd) sse_r2r(maxps, regs, regd) - -#define maxss_m2r(var, reg) sse_m2r(maxss, var, reg) -#define maxss_r2r(regs, regd) sse_r2r(maxss, regs, regd) - -#define minps_m2r(var, reg) sse_m2r(minps, var, reg) -#define minps_r2r(regs, regd) sse_r2r(minps, regs, regd) - -#define minss_m2r(var, reg) sse_m2r(minss, var, reg) -#define minss_r2r(regs, regd) sse_r2r(minss, regs, regd) - -#define cmpps_m2r(var, reg, op) sse_m2ri(cmpps, var, reg, op) -#define cmpps_r2r(regs, regd, op) sse_r2ri(cmpps, regs, regd, op) - -#define cmpeqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 0) -#define cmpeqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 0) - -#define cmpltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 1) -#define cmpltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 1) - -#define cmpleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 2) -#define cmpleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 2) - -#define cmpunordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 3) -#define cmpunordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 3) - -#define cmpneqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 4) -#define cmpneqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 4) - -#define cmpnltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 5) -#define cmpnltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 5) - -#define cmpnleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 6) -#define cmpnleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 6) - -#define cmpordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 7) -#define cmpordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 7) - -#define cmpss_m2r(var, reg, op) sse_m2ri(cmpss, var, reg, op) -#define cmpss_r2r(regs, regd, op) sse_r2ri(cmpss, regs, regd, op) - -#define cmpeqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 0) -#define cmpeqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 0) - -#define cmpltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 1) -#define cmpltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 1) - -#define cmpless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 2) -#define cmpless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 2) - -#define cmpunordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 3) -#define cmpunordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 3) - -#define cmpneqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 4) -#define cmpneqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 4) - -#define cmpnltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 5) -#define cmpnltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 5) - -#define cmpnless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 6) -#define cmpnless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 6) - -#define cmpordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 7) -#define cmpordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 7) - -#define comiss_m2r(var, reg) sse_m2r(comiss, var, reg) -#define comiss_r2r(regs, regd) sse_r2r(comiss, regs, regd) - -#define ucomiss_m2r(var, reg) sse_m2r(ucomiss, var, reg) -#define ucomiss_r2r(regs, regd) sse_r2r(ucomiss, regs, regd) - -#define unpcklps_m2r(var, reg) sse_m2r(unpcklps, var, reg) -#define unpcklps_r2r(regs, regd) sse_r2r(unpcklps, regs, regd) - -#define unpckhps_m2r(var, reg) sse_m2r(unpckhps, var, reg) -#define unpckhps_r2r(regs, regd) sse_r2r(unpckhps, regs, regd) - -#define fxrstor(mem) \ - __asm__ __volatile__ ("fxrstor %0" \ - : /* nothing */ \ - : "X" (mem)) - -#define fxsave(mem) \ - __asm__ __volatile__ ("fxsave %0" \ - : /* nothing */ \ - : "X" (mem)) - -#define stmxcsr(mem) \ - __asm__ __volatile__ ("stmxcsr %0" \ - : /* nothing */ \ - : "X" (mem)) - -#define ldmxcsr(mem) \ - __asm__ __volatile__ ("ldmxcsr %0" \ - : /* nothing */ \ - : "X" (mem)) -#endif /*ARCH_X86 */ /* Optimized/fast memcpy */ diff --git a/src/xine-utils/xmllexer.c b/src/xine-utils/xmllexer.c index 7da4cc59b..696c18011 100644 --- a/src/xine-utils/xmllexer.c +++ b/src/xine-utils/xmllexer.c @@ -25,6 +25,10 @@ #define LOG */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #ifdef XINE_COMPILE #include "xineutils.h" #else @@ -46,16 +50,11 @@ #define DATA 1 /* data lex mode */ /* private global variables */ -static const char * lexbuf; -static int lexbuf_size = 0; -static int lexbuf_pos = 0; -static int lex_mode = NORMAL; -static int in_comment = 0; -static char *lex_malloc = NULL; +struct lexer * static_lexer; enum utf { UTF32BE, UTF32LE, UTF16BE, UTF16LE }; -static void lex_convert (const char * buf, int size, enum utf utf) +static void lex_convert (struct lexer * lexer, const char * buf, int size, enum utf utf) { char *utf8 = malloc (size * (utf >= UTF16BE ? 3 : 6) + 1); char *bp = utf8; @@ -87,42 +86,60 @@ static void lex_convert (const char * buf, int size, enum utf utf) } } *bp = 0; - lexbuf_size = bp - utf8; - lexbuf = lex_malloc = realloc (utf8, lexbuf_size + 1); + lexer->lexbuf_size = bp - utf8; + lexer->lexbuf = lexer->lex_malloc = realloc (utf8, lexer->lexbuf_size + 1); } +/* for ABI compatibility */ void lexer_init(const char * buf, int size) { + if (static_lexer) { + lexer_finalize_r(static_lexer); + } + static_lexer = lexer_init_r(buf, size); +} + +struct lexer *lexer_init_r(const char * buf, int size) { static const char boms[] = { 0xFF, 0xFE, 0, 0, 0xFE, 0xFF }, bom_utf8[] = { 0xEF, 0xBB, 0xBF }; + struct lexer * lexer = calloc (1, sizeof (*lexer)); - free (lex_malloc); - lex_malloc = NULL; - - lexbuf = buf; - lexbuf_size = size; + lexer->lexbuf = buf; + lexer->lexbuf_size = size; if (size >= 4 && !memcmp (buf, boms + 2, 4)) - lex_convert (buf + 4, size - 4, UTF32BE); + lex_convert (lexer, buf + 4, size - 4, UTF32BE); else if (size >= 4 && !memcmp (buf, boms, 4)) - lex_convert (buf + 4, size - 4, UTF32LE); + lex_convert (lexer, buf + 4, size - 4, UTF32LE); else if (size >= 3 && !memcmp (buf, bom_utf8, 3)) { - lexbuf += 3; - lexbuf_size -= 3; + lexer->lexbuf += 3; + lexer->lexbuf_size -= 3; } else if (size >= 2 && !memcmp (buf, boms + 4, 2)) - lex_convert (buf + 2, size - 2, UTF16BE); + lex_convert (lexer, buf + 2, size - 2, UTF16BE); else if (size >= 2 && !memcmp (buf, boms, 2)) - lex_convert (buf + 2, size - 2, UTF16LE); + lex_convert (lexer, buf + 2, size - 2, UTF16LE); - lexbuf_pos = 0; - lex_mode = NORMAL; - in_comment = 0; + lexer->lexbuf_pos = 0; + lexer->lex_mode = NORMAL; + lexer->in_comment = 0; lprintf("buffer length %d\n", size); + return lexer; } +void lexer_finalize_r(struct lexer * lexer) +{ + free(lexer->lex_malloc); + free(lexer); +} + +/* for ABI compatibility */ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { + return lexer_get_token_d_r(static_lexer, _tok, _tok_size, fixed); +} + +int lexer_get_token_d_r(struct lexer * lexer, char ** _tok, int * _tok_size, int fixed) { char *tok = *_tok; int tok_size = *_tok_size; @@ -131,11 +148,11 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { char c; if (tok) { - while ((tok_pos < tok_size) && (lexbuf_pos < lexbuf_size)) { - c = lexbuf[lexbuf_pos]; - lprintf("c=%c, state=%d, in_comment=%d\n", c, state, in_comment); + while ((tok_pos < tok_size) && (lexer->lexbuf_pos < lexer->lexbuf_size)) { + c = lexer->lexbuf[lexer->lexbuf_pos]; + lprintf("c=%c, state=%d, in_comment=%d\n", c, state, lexer->in_comment); - if (lex_mode == NORMAL) { + if (lexer->lex_mode == NORMAL) { /* normal mode */ switch (state) { /* init state */ @@ -168,7 +185,7 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { break; case '/': - if (!in_comment) + if (!lexer->in_comment) state = 5; tok[tok_pos] = c; tok_pos++; @@ -206,14 +223,14 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { tok_pos++; break; } - lexbuf_pos++; + lexer->lexbuf_pos++; break; /* end of line */ case 1: if (c == '\n' || (c == '\r')) { tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; } else { tok[tok_pos] = '\0'; @@ -225,7 +242,7 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { case 2: if (c == ' ' || (c == '\t')) { tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; } else { tok[tok_pos] = '\0'; @@ -238,20 +255,20 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { switch (c) { case '/': tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; /* FIXME */ tok[tok_pos] = '\0'; return T_M_START_2; break; case '!': tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; state = 8; break; case '?': tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; /* FIXME */ tok[tok_pos] = '\0'; return T_TI_START; @@ -265,8 +282,8 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { /* T_M_STOP_1 */ case 4: tok[tok_pos] = '\0'; - if (!in_comment) - lex_mode = DATA; + if (!lexer->in_comment) + lexer->lex_mode = DATA; return T_M_STOP_1; break; @@ -274,11 +291,11 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { case 5: if (c == '>') { tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; /* FIXME */ tok[tok_pos] = '\0'; - if (!in_comment) - lex_mode = DATA; + if (!lexer->in_comment) + lexer->lex_mode = DATA; return T_M_STOP_2; } else { tok[tok_pos] = '\0'; @@ -295,7 +312,7 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { /* T_STRING */ case 7: tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; if (c == '\"') { /* " */ tok[tok_pos] = '\0'; /* FIXME */ return T_STRING; @@ -307,22 +324,22 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { case 8: switch (c) { case '-': - lexbuf_pos++; - if (lexbuf[lexbuf_pos] == '-') + lexer->lexbuf_pos++; + if (lexer->lexbuf[lexer->lexbuf_pos] == '-') { - lexbuf_pos++; + lexer->lexbuf_pos++; tok[tok_pos++] = '-'; /* FIXME */ tok[tok_pos++] = '-'; tok[tok_pos] = '\0'; - in_comment = 1; + lexer->in_comment = 1; return T_C_START; } break; case 'D': - lexbuf_pos++; - if (strncmp(lexbuf + lexbuf_pos, "OCTYPE", 6) == 0) { + lexer->lexbuf_pos++; + if (strncmp(lexer->lexbuf + lexer->lexbuf_pos, "OCTYPE", 6) == 0) { strncpy(tok + tok_pos, "DOCTYPE", 7); /* FIXME */ - lexbuf_pos += 6; + lexer->lexbuf_pos += 6; return T_DOCTYPE_START; } else { return T_ERROR; @@ -338,7 +355,7 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { case 9: if (c == '>') { tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; /* FIXME */ tok[tok_pos] = '\0'; return T_TI_STOP; @@ -354,13 +371,13 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { case '-': tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; state = 11; break; default: tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; state = 100; } break; @@ -371,21 +388,21 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { case '>': tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; tok[tok_pos] = '\0'; /* FIX ME */ if (strlen(tok) != 3) { tok[tok_pos - 3] = '\0'; - lexbuf_pos -= 3; + lexer->lexbuf_pos -= 3; return T_IDENT; } else { - in_comment = 0; + lexer->in_comment = 0; return T_C_STOP; } break; default: tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; state = 100; } break; @@ -393,7 +410,7 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { /* T_STRING (single quotes) */ case 12: tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; if (c == '\'') { /* " */ tok[tok_pos] = '\0'; /* FIXME */ return T_STRING; @@ -420,19 +437,19 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { case '?': tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; state = 9; break; case '-': tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; state = 10; break; default: tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; } break; default: @@ -445,17 +462,17 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { { case '<': tok[tok_pos] = '\0'; - lex_mode = NORMAL; + lexer->lex_mode = NORMAL; return T_DATA; default: tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; } } } lprintf ("loop done tok_pos = %d, tok_size=%d, lexbuf_pos=%d, lexbuf_size=%d\n", - tok_pos, tok_size, lexbuf_pos, lexbuf_size); + tok_pos, tok_size, lexer->lexbuf_pos, lexer->lexbuf_size); /* pb */ if (tok_pos >= tok_size) { @@ -466,12 +483,12 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { lprintf("token buffer is too small\n"); lprintf("increasing buffer size to %d bytes\n", *_tok_size); if (*_tok) { - return lexer_get_token_d (_tok, _tok_size, 0); + return lexer_get_token_d_r (lexer, _tok, _tok_size, 0); } else { return T_ERROR; } } else { - if (lexbuf_pos >= lexbuf_size) { + if (lexer->lexbuf_pos >= lexer->lexbuf_size) { /* Terminate the current token */ tok[tok_pos] = '\0'; switch (state) { diff --git a/src/xine-utils/xmllexer.h b/src/xine-utils/xmllexer.h index 425d0e70a..bcea7d6b4 100644 --- a/src/xine-utils/xmllexer.h +++ b/src/xine-utils/xmllexer.h @@ -23,6 +23,10 @@ #ifndef XML_LEXER_H #define XML_LEXER_H +#ifndef XINE_DEPRECATED +#define XINE_DEPRECATED +#endif + #ifndef XINE_PROTECTED #define XINE_PROTECTED #endif @@ -49,10 +53,25 @@ #define T_DOCTYPE_STOP 17 /* > */ +/* public structure */ +struct lexer +{ + const char * lexbuf; + int lexbuf_size; + int lexbuf_pos; + int lex_mode; + int in_comment; + char *lex_malloc; +}; + + /* public functions */ -void lexer_init(const char * buf, int size) XINE_PROTECTED; -int lexer_get_token_d(char ** tok, int * tok_size, int fixed) XINE_PROTECTED; -int lexer_get_token(char * tok, int tok_size) XINE_PROTECTED; +void lexer_init(const char * buf, int size) XINE_DEPRECATED XINE_PROTECTED; +struct lexer *lexer_init_r(const char * buf, int size) XINE_PROTECTED; +void lexer_finalize_r(struct lexer * lexer) XINE_PROTECTED; +int lexer_get_token_d_r(struct lexer * lexer, char ** tok, int * tok_size, int fixed) XINE_PROTECTED; +int lexer_get_token_d(char ** tok, int * tok_size, int fixed) XINE_DEPRECATED XINE_PROTECTED; +int lexer_get_token(char * tok, int tok_size) XINE_DEPRECATED XINE_PROTECTED; char *lexer_decode_entities (const char *tok) XINE_PROTECTED; #endif diff --git a/src/xine-utils/xmlparser.c b/src/xine-utils/xmlparser.c index a4917429b..2e93da4e9 100644 --- a/src/xine-utils/xmlparser.c +++ b/src/xine-utils/xmlparser.c @@ -19,6 +19,10 @@ * Floor, Boston, MA 02110, USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <unistd.h> #include <stdio.h> #include <stdlib.h> @@ -47,7 +51,7 @@ #define MAX_RECURSION 10 /* private global variables */ -static int xml_parser_mode; +xml_parser_t * static_xml_parser; /* private functions */ @@ -95,10 +99,24 @@ static void free_xml_property(xml_property_t * property) { free(property); } +/* for ABI compatibility */ void xml_parser_init(const char * buf, int size, int mode) { + if (static_xml_parser) { + xml_parser_finalize_r(static_xml_parser); + } + static_xml_parser = xml_parser_init_r(buf, size, mode); +} - lexer_init(buf, size); - xml_parser_mode = mode; +xml_parser_t *xml_parser_init_r(const char * buf, int size, int mode) { + xml_parser_t *xml_parser = malloc(sizeof(*xml_parser)); + xml_parser->lexer = lexer_init_r(buf, size); + xml_parser->mode = mode; + return xml_parser; +} + +void xml_parser_finalize_r(xml_parser_t *xml_parser) { + lexer_finalize_r(xml_parser->lexer); + free(xml_parser); } static void xml_parser_free_props(xml_property_t *current_property) { @@ -153,9 +171,9 @@ void xml_parser_free_tree(xml_node_t *current_node) { #define STATE_NODE 1 #define STATE_COMMENT 7 -static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int rec); +static int xml_parser_get_node (xml_parser_t *xml_parser, xml_node_t *current_node, char *root_name, int rec); -static int _xml_parser_get_node (char ** token_buffer, int * token_buffer_size, +static int _xml_parser_get_node (xml_parser_t *xml_parser, char ** token_buffer, int * token_buffer_size, char ** pname_buffer, int * pname_buffer_size, char ** nname_buffer, int * nname_buffer_size, xml_node_t *current_node, char *root_name, int rec) { @@ -175,7 +193,7 @@ static int _xml_parser_get_node (char ** token_buffer, int * token_buffer_size, memset (tok, 0, *token_buffer_size); - while ((bypass_get_token) || (res = lexer_get_token_d(token_buffer, token_buffer_size, 0)) != T_ERROR) { + while ((bypass_get_token) || (res = lexer_get_token_d_r(xml_parser->lexer, token_buffer, token_buffer_size, 0)) != T_ERROR) { tok = *token_buffer; bypass_get_token = 0; lprintf("info: %d - %d : '%s'\n", state, res, tok); @@ -228,7 +246,7 @@ static int _xml_parser_get_node (char ** token_buffer, int * token_buffer_size, current_property = NULL; /* save node name */ - if (xml_parser_mode == XML_PARSER_CASE_INSENSITIVE) { + if (xml_parser->mode == XML_PARSER_CASE_INSENSITIVE) { strtoupper(tok); } /* make sure the buffer for the node name is big enough */ @@ -263,7 +281,7 @@ static int _xml_parser_get_node (char ** token_buffer, int * token_buffer_size, /* set node propertys */ subtree->props = properties; lprintf("info: rec %d new subtree %s\n", rec, node_name); - parse_res = xml_parser_get_node(subtree, node_name, rec + 1); + parse_res = xml_parser_get_node(xml_parser, subtree, node_name, rec + 1); if (parse_res != 0) { return parse_res; } @@ -300,7 +318,7 @@ static int _xml_parser_get_node (char ** token_buffer, int * token_buffer_size, break; case (T_IDENT): /* save property name */ - if (xml_parser_mode == XML_PARSER_CASE_INSENSITIVE) { + if (xml_parser->mode == XML_PARSER_CASE_INSENSITIVE) { strtoupper(tok); } /* make sure the buffer for the property name is big enough */ @@ -324,7 +342,7 @@ static int _xml_parser_get_node (char ** token_buffer, int * token_buffer_size, switch (res) { case (T_IDENT): /* must be equal to root_name */ - if (xml_parser_mode == XML_PARSER_CASE_INSENSITIVE) { + if (xml_parser->mode == XML_PARSER_CASE_INSENSITIVE) { strtoupper(tok); } if (strcmp(tok, root_name) == 0) { @@ -470,7 +488,7 @@ static int _xml_parser_get_node (char ** token_buffer, int * token_buffer_size, } } -static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int rec) +static int xml_parser_get_node (xml_parser_t *xml_parser, xml_node_t *current_node, char *root_name, int rec) { int res = 0; int token_buffer_size = TOKEN_SIZE; @@ -480,7 +498,7 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r char *pname_buffer = calloc(1, pname_buffer_size); char *nname_buffer = calloc(1, nname_buffer_size); - res = _xml_parser_get_node(&token_buffer, &token_buffer_size, + res = _xml_parser_get_node(xml_parser, &token_buffer, &token_buffer_size, &pname_buffer, &pname_buffer_size, &nname_buffer, &nname_buffer_size, current_node, root_name, rec); @@ -492,12 +510,17 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r return res; } +/* for ABI compatibility */ int xml_parser_build_tree(xml_node_t **root_node) { + return xml_parser_build_tree_r(static_xml_parser, root_node); +} + +int xml_parser_build_tree_r(xml_parser_t *xml_parser, xml_node_t **root_node) { xml_node_t *tmp_node; int res; tmp_node = new_xml_node(); - res = xml_parser_get_node(tmp_node, "", 0); + res = xml_parser_get_node(xml_parser, tmp_node, "", 0); if ((tmp_node->child) && (!tmp_node->child->next)) { *root_node = tmp_node->child; free_xml_node(tmp_node); diff --git a/src/xine-utils/xmlparser.h b/src/xine-utils/xmlparser.h index 98695a756..fe94e4b76 100644 --- a/src/xine-utils/xmlparser.h +++ b/src/xine-utils/xmlparser.h @@ -22,6 +22,10 @@ #ifndef XML_PARSER_H #define XML_PARSER_H +#ifndef XINE_DEPRECATED +#define XINE_DEPRECATED +#endif + #ifndef XINE_PROTECTED #define XINE_PROTECTED #endif @@ -51,9 +55,18 @@ typedef struct xml_node_s { struct xml_node_s *next; } xml_node_t; -void xml_parser_init(const char * buf, int size, int mode) XINE_PROTECTED; +/* xml parser */ +typedef struct xml_parser_s { + struct lexer *lexer; + int mode; +} xml_parser_t; + +void xml_parser_init(const char * buf, int size, int mode) XINE_DEPRECATED XINE_PROTECTED; +xml_parser_t *xml_parser_init_r(const char * buf, int size, int mode) XINE_PROTECTED; +void xml_parser_finalize_r(xml_parser_t *xml_parser) XINE_PROTECTED; -int xml_parser_build_tree(xml_node_t **root_node) XINE_PROTECTED; +int xml_parser_build_tree(xml_node_t **root_node) XINE_DEPRECATED XINE_PROTECTED; +int xml_parser_build_tree_r(xml_parser_t *xml_parser, xml_node_t **root_node) XINE_PROTECTED; void xml_parser_free_tree(xml_node_t *root_node) XINE_PROTECTED; |