summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/audio_out/Makefile.am17
-rw-r--r--src/audio_out/audio_directx2_out.c8
-rw-r--r--src/audio_out/audio_directx_out.c6
-rw-r--r--src/audio_out/audio_jack_out.c41
-rw-r--r--src/audio_out/audio_pulse_out.c2
-rw-r--r--src/audio_out/audio_sndio_out.c414
-rw-r--r--src/combined/Makefile.am1
-rw-r--r--src/combined/demux_flac.c10
-rw-r--r--src/combined/ffmpeg/Makefile.am38
-rw-r--r--src/combined/ffmpeg/ff_audio_decoder.c158
-rw-r--r--src/combined/ffmpeg/ff_video_decoder.c560
-rwxr-xr-xsrc/combined/ffmpeg/mkcodeclist.pl95
-rw-r--r--src/combined/ffmpeg/xine_audio.list55
-rw-r--r--src/combined/ffmpeg/xine_video.list109
-rw-r--r--src/demuxers/Makefile.am11
-rw-r--r--src/demuxers/demux_4xm.c6
-rw-r--r--src/demuxers/demux_aac.c2
-rw-r--r--src/demuxers/demux_ac3.c8
-rw-r--r--src/demuxers/demux_asf.c19
-rw-r--r--src/demuxers/demux_cdda.c16
-rw-r--r--src/demuxers/demux_dts.c2
-rw-r--r--src/demuxers/demux_flac.c3
-rw-r--r--src/demuxers/demux_matroska-chapters.c433
-rw-r--r--src/demuxers/demux_matroska.c575
-rw-r--r--src/demuxers/demux_matroska.h150
-rw-r--r--src/demuxers/demux_mng.c10
-rw-r--r--src/demuxers/demux_mod.c25
-rw-r--r--src/demuxers/demux_mpc.c2
-rw-r--r--src/demuxers/demux_mpeg.c24
-rw-r--r--src/demuxers/demux_mpeg_block.c37
-rw-r--r--src/demuxers/demux_mpeg_pes.c8
-rw-r--r--src/demuxers/demux_mpgaudio.c50
-rw-r--r--src/demuxers/demux_nsf.c2
-rw-r--r--src/demuxers/demux_ogg.c2
-rw-r--r--src/demuxers/demux_qt.c50
-rw-r--r--src/demuxers/demux_rawdv.c3
-rw-r--r--src/demuxers/demux_real.c88
-rw-r--r--src/demuxers/demux_realaudio.c18
-rw-r--r--src/demuxers/demux_shn.c2
-rw-r--r--src/demuxers/demux_slave.c5
-rw-r--r--src/demuxers/demux_ts.c190
-rw-r--r--src/demuxers/demux_tta.c10
-rw-r--r--src/demuxers/demux_vox.c2
-rw-r--r--src/demuxers/demux_wav.c27
-rw-r--r--src/demuxers/demux_yuv_frames.c10
-rw-r--r--src/demuxers/id3.c46
-rw-r--r--src/demuxers/matroska.h54
-rw-r--r--src/dxr3/Makefile.am1
-rw-r--r--src/dxr3/dxr3_decode_spu.c4
-rw-r--r--src/dxr3/dxr3_decode_video.c4
-rw-r--r--src/dxr3/video_out_dxr3.c2
-rw-r--r--src/input/Makefile.am4
-rw-r--r--src/input/http_helper.c18
-rw-r--r--src/input/http_helper.h13
-rw-r--r--src/input/input_cdda.c283
-rw-r--r--src/input/input_dvb.c12
-rw-r--r--src/input/input_dvd.c8
-rw-r--r--src/input/input_file.c10
-rw-r--r--src/input/input_gnome_vfs.c7
-rw-r--r--src/input/input_http.c29
-rw-r--r--src/input/input_mms.c7
-rw-r--r--src/input/input_net.c14
-rw-r--r--src/input/input_pnm.c20
-rw-r--r--src/input/input_pvr.c12
-rw-r--r--src/input/input_rtp.c14
-rw-r--r--src/input/input_rtsp.c20
-rw-r--r--src/input/input_smb.c9
-rw-r--r--src/input/input_stdin_fifo.c15
-rw-r--r--src/input/input_vcd.c18
-rw-r--r--src/input/libdvdnav/bswap.h2
-rw-r--r--src/input/libdvdnav/diff_against_cvs.patch2
-rw-r--r--src/input/libdvdnav/dvd_reader.c2
-rw-r--r--src/input/libdvdnav/dvd_reader.h2
-rw-r--r--src/input/libdvdnav/md5.c2
-rw-r--r--src/input/libdvdnav/remap.c1
-rw-r--r--src/input/libreal/asmrp.c4
-rw-r--r--src/input/libreal/real.c4
-rw-r--r--src/input/libreal/rmff.c38
-rw-r--r--src/input/libreal/sdpplin.c4
-rw-r--r--src/input/librtsp/rtsp.c4
-rw-r--r--src/input/librtsp/rtsp_session.c4
-rw-r--r--src/input/mms.c16
-rw-r--r--src/input/mmsh.c2
-rw-r--r--src/input/pnm.c2
-rw-r--r--src/input/vcd/Makefile.am1
-rw-r--r--src/input/vcd/libcdio/MSWindows/aspi32.c4
-rw-r--r--src/input/vcd/xineplug_inp_vcd.c2
-rw-r--r--src/liba52/Makefile.am1
-rw-r--r--src/liba52/xine_a52_decoder.c2
-rw-r--r--src/libdts/Makefile.am1
-rw-r--r--src/libdts/xine_dts_decoder.c4
-rw-r--r--src/libfaad/Makefile.am1
-rw-r--r--src/libfaad/common.h2
-rw-r--r--src/libfaad/xine_faad_decoder.c4
-rw-r--r--src/libmad/Makefile.am1
-rw-r--r--src/libmad/xine_mad_decoder.c57
-rw-r--r--src/libmpeg2/Makefile.am3
-rw-r--r--src/libmpeg2/motion_comp.c2
-rw-r--r--src/libmpeg2/slice_xvmc_vld.c4
-rw-r--r--src/libmpeg2/xine_mpeg2_decoder.c4
-rw-r--r--src/libmpeg2new/Makefile.am19
-rw-r--r--src/libmpeg2new/include/Makefile.am5
-rw-r--r--src/libmpeg2new/include/attributes.h6
-rw-r--r--src/libmpeg2new/libmpeg2/Makefile.am9
-rw-r--r--src/libmpeg2new/libmpeg2/motion_comp_alpha.c6
-rw-r--r--src/libmpeg2new/libmpeg2/motion_comp_altivec.c4
-rw-r--r--src/libmpeg2new/libmpeg2/motion_comp_vis.c10
-rw-r--r--src/libmpeg2new/xine_mpeg2new_decoder.c22
-rw-r--r--src/libmusepack/Makefile.am1
-rw-r--r--src/libmusepack/xine_musepack_decoder.c78
-rw-r--r--src/libreal/Makefile.am1
-rw-r--r--src/libreal/xine_real_audio_decoder.c4
-rw-r--r--src/libreal/xine_real_video_decoder.c4
-rw-r--r--src/libspucc/Makefile.am1
-rw-r--r--src/libspucc/cc_decoder.c4
-rw-r--r--src/libspucc/xine_cc_decoder.c4
-rw-r--r--src/libspucmml/Makefile.am1
-rw-r--r--src/libspucmml/xine_cmml_decoder.c8
-rw-r--r--src/libspudec/Makefile.am5
-rw-r--r--src/libspudec/spu.c4
-rw-r--r--src/libspudec/spu.h2
-rw-r--r--src/libspudec/xine_spu_decoder.c4
-rw-r--r--src/libspudvb/Makefile.am1
-rw-r--r--src/libspudvb/xine_spudvb_decoder.c61
-rw-r--r--src/libspuhdmv/Makefile.am9
-rw-r--r--src/libspuhdmv/xine_hdmv_decoder.c1019
-rw-r--r--src/libsputext/Makefile.am1
-rw-r--r--src/libsputext/demux_sputext.c2
-rw-r--r--src/libsputext/xine_sputext_decoder.c4
-rw-r--r--src/libw32dll/Makefile.am1
-rw-r--r--src/libw32dll/w32codec.c4
-rw-r--r--src/libw32dll/wine/driver.c2
-rw-r--r--src/libw32dll/wine/elfdll.c2
-rw-r--r--src/libw32dll/wine/pe_image.c2
-rw-r--r--src/libw32dll/wine/pe_resource.c2
-rw-r--r--src/libw32dll/wine/resource.c2
-rw-r--r--src/libw32dll/wine/vfl.c2
-rw-r--r--src/libxineadec/Makefile.am3
-rw-r--r--src/libxineadec/fooaudio.c4
-rw-r--r--src/libxineadec/gsm610/long_term.c4
-rw-r--r--src/libxineadec/gsm610/lpc.c4
-rw-r--r--src/libxineadec/gsm610/rpe.c4
-rw-r--r--src/libxineadec/gsm610/short_term.c4
-rw-r--r--src/libxineadec/nsf.c4
-rw-r--r--src/libxineadec/xine_lpcm_decoder.c5
-rw-r--r--src/libxinevdec/Makefile.am3
-rw-r--r--src/libxinevdec/bitplane.c4
-rw-r--r--src/libxinevdec/foovideo.c4
-rw-r--r--src/libxinevdec/gdkpixbuf.c5
-rw-r--r--src/libxinevdec/image.c8
-rw-r--r--src/libxinevdec/rgb.c4
-rw-r--r--src/libxinevdec/yuv.c4
-rw-r--r--src/post/audio/Makefile.am1
-rw-r--r--src/post/audio/audio_filters.c3
-rw-r--r--src/post/audio/stretch.c4
-rw-r--r--src/post/audio/upmix.c4
-rw-r--r--src/post/audio/upmix_mono.c4
-rw-r--r--src/post/audio/volnorm.c4
-rw-r--r--src/post/deinterlace/Makefile.am1
-rw-r--r--src/post/deinterlace/tvtime.c14
-rw-r--r--src/post/deinterlace/tvtime.h5
-rw-r--r--src/post/deinterlace/xine_plugin.c13
-rw-r--r--src/post/goom/Makefile.am1
-rw-r--r--src/post/goom/ppc_zoom_ultimate.h2
-rw-r--r--src/post/goom/xine_goom.c2
-rw-r--r--src/post/mosaico/Makefile.am1
-rw-r--r--src/post/mosaico/mosaico.c2
-rw-r--r--src/post/planar/Makefile.am1
-rw-r--r--src/post/planar/boxblur.c4
-rw-r--r--src/post/planar/denoise3d.c4
-rw-r--r--src/post/planar/eq.c4
-rw-r--r--src/post/planar/eq2.c4
-rw-r--r--src/post/planar/noise.c4
-rw-r--r--src/post/planar/planar.c4
-rw-r--r--src/post/planar/pp.c2
-rw-r--r--src/post/planar/unsharp.c4
-rw-r--r--src/post/visualizations/Makefile.am1
-rw-r--r--src/post/visualizations/fftgraph.c4
-rw-r--r--src/post/visualizations/fftscope.c4
-rw-r--r--src/post/visualizations/fooviz.c4
-rw-r--r--src/post/visualizations/oscope.c4
-rw-r--r--src/video_out/Makefile.am3
-rw-r--r--src/video_out/deinterlace.c4
-rw-r--r--src/video_out/video_out_directx.c125
-rw-r--r--src/video_out/video_out_xcbxv.c95
-rw-r--r--src/video_out/video_out_xv.c77
-rw-r--r--src/video_out/video_out_xxmc.c53
-rw-r--r--src/video_out/xv_common.h24
-rw-r--r--src/video_out/xxmc.h10
-rw-r--r--src/xine-engine/alphablend.c8
-rw-r--r--src/xine-engine/audio_decoder.c6
-rw-r--r--src/xine-engine/audio_out.c37
-rw-r--r--src/xine-engine/broadcaster.c4
-rw-r--r--src/xine-engine/broadcaster.h4
-rw-r--r--src/xine-engine/buffer.h15
-rw-r--r--src/xine-engine/demux.c88
-rw-r--r--src/xine-engine/info_helper.c10
-rw-r--r--src/xine-engine/load_plugins.c29
-rw-r--r--src/xine-engine/metronom.c33
-rw-r--r--src/xine-engine/osd.c35
-rw-r--r--src/xine-engine/refcounter.c5
-rw-r--r--src/xine-engine/refcounter.h4
-rw-r--r--src/xine-engine/scratch.c2
-rw-r--r--src/xine-engine/scratch.h5
-rw-r--r--src/xine-engine/video_decoder.c2
-rw-r--r--src/xine-engine/video_out.h4
-rw-r--r--src/xine-engine/video_overlay.c4
-rw-r--r--src/xine-engine/vo_scale.c4
-rw-r--r--src/xine-engine/vo_scale.h4
-rw-r--r--src/xine-engine/xine.c21
-rw-r--r--src/xine-engine/xine_interface.c3
-rw-r--r--src/xine-engine/xine_internal.h1
-rw-r--r--src/xine-utils/Makefile.am1
-rw-r--r--src/xine-utils/cpu_accel.c4
-rw-r--r--src/xine-utils/mangle.h4
-rw-r--r--src/xine-utils/monitor.c46
-rw-r--r--src/xine-utils/utils.c2
-rw-r--r--src/xine-utils/xine_buffer.c4
-rw-r--r--src/xine-utils/xine_mmx.h490
-rw-r--r--src/xine-utils/xineutils.h472
-rw-r--r--src/xine-utils/xmllexer.c143
-rw-r--r--src/xine-utils/xmllexer.h25
-rw-r--r--src/xine-utils/xmlparser.c49
-rw-r--r--src/xine-utils/xmlparser.h17
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;