summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio_dec/xine_dts_decoder.c32
-rw-r--r--src/audio_dec/xine_lpcm_decoder.c26
-rw-r--r--src/audio_dec/xine_mad_decoder.c2
-rw-r--r--src/audio_out/audio_oss_out.c27
-rw-r--r--src/audio_out/audio_pulse_out.c742
-rw-r--r--src/combined/ffmpeg/ff_audio_decoder.c81
-rw-r--r--src/combined/ffmpeg/ff_video_decoder.c26
-rw-r--r--src/combined/ffmpeg/ffmpeg_decoder.h6
-rw-r--r--src/combined/wavpack_combined.c2
-rw-r--r--src/combined/wavpack_demuxer.c4
-rw-r--r--src/combined/xine_ogg_demuxer.c5
-rw-r--r--src/demuxers/Makefile.am2
-rw-r--r--src/demuxers/asfheader.c14
-rw-r--r--src/demuxers/demux_4xm.c2
-rw-r--r--src/demuxers/demux_aiff.c35
-rw-r--r--src/demuxers/demux_avi.c10
-rw-r--r--src/demuxers/demux_dts.c72
-rw-r--r--src/demuxers/demux_film.c5
-rw-r--r--src/demuxers/demux_flac.c2
-rw-r--r--src/demuxers/demux_flv.c16
-rw-r--r--src/demuxers/demux_iff.c10
-rw-r--r--src/demuxers/demux_ipmovie.c5
-rw-r--r--src/demuxers/demux_matroska.c21
-rw-r--r--src/demuxers/demux_qt.c53
-rw-r--r--src/demuxers/demux_real.c157
-rw-r--r--src/demuxers/demux_realaudio.c90
-rw-r--r--src/demuxers/demux_vmd.c2
-rw-r--r--src/demuxers/demux_wav.c89
-rw-r--r--src/demuxers/demux_wc3movie.c11
-rw-r--r--src/demuxers/ebml.c24
-rw-r--r--src/demuxers/ebml.h4
-rw-r--r--src/demuxers/real_common.h56
-rw-r--r--src/input/libdvdnav/dvd_reader.c24
-rw-r--r--src/input/libdvdnav/dvd_reader.h2
-rw-r--r--src/input/libdvdnav/ifo_read.c6
-rw-r--r--src/input/libreal/sdpplin.c23
-rw-r--r--src/input/libreal/sdpplin.h4
-rw-r--r--src/libreal/xine_real_audio_decoder.c166
-rw-r--r--src/libreal/xine_real_video_decoder.c46
-rw-r--r--src/vdr/input_vdr.c223
-rw-r--r--src/video_dec/libmpeg2/decode.c7
-rw-r--r--src/video_out/video_out_macosx.m12
-rw-r--r--src/video_out/video_out_xcbxv.c23
-rw-r--r--src/video_out/video_out_xv.c22
-rw-r--r--src/video_out/video_out_xxmc.c21
-rw-r--r--src/video_out/xv_common.h11
-rw-r--r--src/xine-engine/buffer_types.c8
-rw-r--r--src/xine-engine/configfile.c2
-rw-r--r--src/xine-engine/demux.c15
-rw-r--r--src/xine-engine/load_plugins.c19
-rw-r--r--src/xine-engine/xine.c141
-rw-r--r--src/xine-utils/Makefile.am4
-rw-r--r--src/xine-utils/xmllexer.c2
-rw-r--r--src/xine-utils/xmlparser.c70
54 files changed, 1795 insertions, 689 deletions
diff --git a/src/audio_dec/xine_dts_decoder.c b/src/audio_dec/xine_dts_decoder.c
index 2b8dabd10..4f9171d6e 100644
--- a/src/audio_dec/xine_dts_decoder.c
+++ b/src/audio_dec/xine_dts_decoder.c
@@ -199,19 +199,27 @@ static void dts_decode_frame (dts_decoder_t *this, const int64_t pts, const int
audio_buffer->num_frames = this->ac5_pcm_length;
- data_out[0] = 0x72; data_out[1] = 0xf8; /* spdif syncword */
- data_out[2] = 0x1f; data_out[3] = 0x4e; /* .............. */
- data_out[4] = ac5_spdif_type; /* DTS data */
- data_out[5] = 0; /* Unknown */
- data_out[6] = (this->ac5_length << 3) & 0xff; /* ac5_length * 8 */
- data_out[7] = ((this->ac5_length ) >> 5) & 0xff;
-
- if( this->ac5_pcm_length ) {
- if( this->ac5_pcm_length % 2) {
- swab(data_in, &data_out[8], this->ac5_length );
- } else {
- swab(data_in, &data_out[8], this->ac5_length + 1);
+ // Checking if AC5 data plus IEC958 header will fit into frames samples data
+ if ( this->ac5_length + 8 <= this->ac5_pcm_length * 2 * 2 ) {
+ data_out[0] = 0x72; data_out[1] = 0xf8; /* spdif syncword */
+ data_out[2] = 0x1f; data_out[3] = 0x4e; /* .............. */
+ data_out[4] = ac5_spdif_type; /* DTS data */
+ data_out[5] = 0; /* Unknown */
+ data_out[6] = (this->ac5_length << 3) & 0xff; /* ac5_length * 8 */
+ data_out[7] = ((this->ac5_length ) >> 5) & 0xff;
+
+ if( this->ac5_pcm_length ) {
+ if( this->ac5_pcm_length % 2) {
+ swab(data_in, &data_out[8], this->ac5_length );
+ } else {
+ swab(data_in, &data_out[8], this->ac5_length + 1);
+ }
}
+ // Transmit it without header otherwise, receivers will autodetect DTS
+ } else {
+ lprintf("AC5 data is too large (%i > %i), sending without IEC958 header\n",
+ this->ac5_length + 8, this->ac5_pcm_length * 2 * 2);
+ memcpy(data_out, data_in, this->ac5_length);
}
} else {
/* Software decode */
diff --git a/src/audio_dec/xine_lpcm_decoder.c b/src/audio_dec/xine_lpcm_decoder.c
index e84b112f4..83043cec9 100644
--- a/src/audio_dec/xine_lpcm_decoder.c
+++ b/src/audio_dec/xine_lpcm_decoder.c
@@ -192,18 +192,34 @@ static void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
uint8_t *d = (uint8_t *)audio_buffer->mem;
int n = buf->size;
- while (n >= 0) {
+ while (n >= 3) {
if ( stream_be ) {
- *d++ = s[0];
- *d++ = s[1];
+ if ( stream_be == this->cpu_be ) {
+ *d++ = s[0];
+ *d++ = s[1];
+ } else {
+ *d++ = s[1];
+ *d++ = s[0];
+ }
} else {
- *d++ = s[1];
- *d++ = s[2];
+ if ( stream_be == this->cpu_be ) {
+ *d++ = s[1];
+ *d++ = s[2];
+ }
+ else
+ {
+ *d++ = s[2];
+ *d++ = s[1];
+ }
}
s += 3;
n -= 3;
}
+
+ if ( (d - (uint8_t*)audio_buffer->mem)/2*3 < buf->size )
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "lpcm_decoder: lost %i bytes\n", (int)(buf->size - (d - (uint8_t*)audio_buffer->mem))/2*3);
+
} else {
memcpy (audio_buffer->mem, sample_buffer, buf->size);
}
diff --git a/src/audio_dec/xine_mad_decoder.c b/src/audio_dec/xine_mad_decoder.c
index 74c04924f..abad70f4f 100644
--- a/src/audio_dec/xine_mad_decoder.c
+++ b/src/audio_dec/xine_mad_decoder.c
@@ -393,7 +393,7 @@ static const uint32_t audio_types[] = {
static const decoder_info_t dec_info_audio = {
audio_types, /* supported types */
- 7 /* priority */
+ 8 /* priority */
};
const plugin_info_t xine_plugin_info[] EXPORTED = {
diff --git a/src/audio_out/audio_oss_out.c b/src/audio_out/audio_oss_out.c
index 7cae9b300..89d79fae9 100644
--- a/src/audio_out/audio_oss_out.c
+++ b/src/audio_out/audio_oss_out.c
@@ -405,6 +405,18 @@ static int ao_oss_delay(ao_driver_t *this_gen) {
if (bytes_left<=0) /* buffer ran dry */
bytes_left = 0;
break;
+ case OSS_SYNC_GETODELAY:
+#ifdef SNDCTL_DSP_GETODELAY
+ if (ioctl (this->audio_fd, SNDCTL_DSP_GETODELAY, &bytes_left)) {
+ perror ("audio_oss_out: DSP_GETODELAY ioctl():");
+ }
+ if (bytes_left<0)
+ bytes_left = 0;
+
+ lprintf ("%d bytes left\n", bytes_left);
+
+ break;
+#endif
case OSS_SYNC_GETOPTR:
if (ioctl (this->audio_fd, SNDCTL_DSP_GETOPTR, &info)) {
perror ("audio_oss_out: SNDCTL_DSP_GETOPTR failed:");
@@ -424,16 +436,6 @@ static int ao_oss_delay(ao_driver_t *this_gen) {
}
this->last_getoptr = info.bytes;
break;
- case OSS_SYNC_GETODELAY:
- if (ioctl (this->audio_fd, SNDCTL_DSP_GETODELAY, &bytes_left)) {
- perror ("audio_oss_out: DSP_GETODELAY ioctl():");
- }
- if (bytes_left<0)
- bytes_left = 0;
-
- lprintf ("%d bytes left\n", bytes_left);
-
- break;
}
return bytes_left / this->bytes_per_frame;
@@ -840,10 +842,13 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
* check if SNDCTL_DSP_GETODELAY works. if so, using it is preferred.
*/
+#ifdef SNDCTL_DSP_GETODELAY
if (ioctl(audio_fd, SNDCTL_DSP_GETODELAY, &info) != -1) {
xprintf(class->xine, XINE_VERBOSITY_DEBUG, "audio_oss_out: using SNDCTL_DSP_GETODELAY\n");
this->sync_method = OSS_SYNC_GETODELAY;
- } else if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &info) != -1) {
+ } else
+#endif
+ if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &info) != -1) {
xprintf(class->xine, XINE_VERBOSITY_DEBUG, "audio_oss_out: using SNDCTL_DSP_GETOPTR\n");
this->sync_method = OSS_SYNC_GETOPTR;
} else {
diff --git a/src/audio_out/audio_pulse_out.c b/src/audio_out/audio_pulse_out.c
index 0235a4321..9b811aaaf 100644
--- a/src/audio_out/audio_pulse_out.c
+++ b/src/audio_out/audio_pulse_out.c
@@ -1,28 +1,28 @@
-/*
- * Copyright (C) 2000-2007 the xine project
- *
+/* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+
+/*
+ * 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
*
- * ao plugin for pulseaudio (rename of polypaudio):
+ * ao plugin for PulseAudio:
* http://0pointer.de/lennart/projects/pulsaudio/
*
- * originally written for polypaudio simple api. Lennart then suggested
- * using the async api for better control (such as volume), therefore, a lot
- * of this code comes from Lennart's patch to mplayer.
+ * Diego Petteno, Lennart Poettering
*/
#ifdef HAVE_CONFIG_H
@@ -48,15 +48,9 @@
#define GAP_TOLERANCE AO_MAX_GAP
-/* CHECKME: should this be conditional on autotools? */
-extern const char *__progname;
-
typedef struct {
audio_driver_class_t driver_class;
xine_t *xine;
-
- struct pa_context *context; /*< Pulseaudio connection context */
- struct pa_threaded_mainloop *mainloop; /*< Main event loop object */
} pulse_class_t;
typedef struct pulse_driver_s {
@@ -67,11 +61,13 @@ typedef struct pulse_driver_s {
char *host; /*< The host to connect to */
char *sink; /*< The sink to connect to */
- struct pa_stream *stream; /*< Pulseaudio playback stream object */
- pthread_mutex_t info_mutex; /**< Mutex for info callback signaling */
+ pa_threaded_mainloop *mainloop; /*< Main event loop object */
+ pa_context *context; /*< Pulseaudio connection context */
+ pa_stream *stream; /*< Pulseaudio playback stream object */
pa_volume_t swvolume;
+ int muted;
pa_cvolume cvolume;
int capabilities;
@@ -82,67 +78,117 @@ typedef struct pulse_driver_s {
uint32_t bits_per_sample;
uint32_t bytes_per_frame;
- uint32_t frames_written;
-
} pulse_driver_t;
/**
- * @brief Callback function called when a stream operation succeed
- * @param stream Stream which operation has succeeded
- * @param success The success value for the operation (ignored)
- * @param this_Gen pulse_driver_t pointer for the PulseAudio output
- * instance.
+ * @brief Callback function called when the state of the context is changed
+ * @param c Context which changed status
+ * @param this_gen pulse_class_t pointer for the PulseAudio output class
*/
-static void __xine_pa_stream_success_callback(pa_stream *const stream, const int success,
- void *const mutex_gen)
+static void __xine_pa_context_state_callback(pa_context *c, void *this_gen)
{
- pthread_mutex_t *const completion_mutex = (pthread_mutex_t*)mutex_gen;
+ pulse_driver_t * this = (pulse_driver_t*) this_gen;
+
+ switch (pa_context_get_state(c)) {
+
+ case PA_CONTEXT_READY:
+ case PA_CONTEXT_TERMINATED:
+ case PA_CONTEXT_FAILED:
+ pa_threaded_mainloop_signal(this->mainloop, 0);
+ break;
- pthread_mutex_unlock(completion_mutex);
+ case PA_CONTEXT_CONNECTING:
+ case PA_CONTEXT_UNCONNECTED:
+ case PA_CONTEXT_AUTHORIZING:
+ case PA_CONTEXT_SETTING_NAME:
+ break;
+ }
}
/**
- * @brief Callback function called when the state of the context is changed
- * @param ctx Context which operation has succeeded
+ * @brief Callback function called when the state of the stream is changed
+ * @param s Stream that changed status
* @param this_gen pulse_driver_t pointer for the PulseAudio output
* instance.
*/
-static void __xine_pa_context_status_callback(pa_context *const ctx, void *const this_gen)
+static void __xine_pa_stream_state_callback(pa_stream *s, void *this_gen)
{
- pulse_driver_t *const this = (pulse_driver_t*)this_gen;
-
- switch (pa_context_get_state(ctx)) {
- case PA_CONTEXT_READY:
- case PA_CONTEXT_TERMINATED:
- case PA_CONTEXT_FAILED:
- pa_threaded_mainloop_signal(this->pa_class->mainloop, 0);
- break;
-
- case PA_CONTEXT_CONNECTING:
- case PA_CONTEXT_UNCONNECTED:
- case PA_CONTEXT_AUTHORIZING:
- case PA_CONTEXT_SETTING_NAME:
- break;
+ pulse_driver_t * this = (pulse_driver_t*) this_gen;
+
+ switch (pa_stream_get_state(s)) {
+
+ case PA_STREAM_READY:
+ case PA_STREAM_TERMINATED:
+ case PA_STREAM_FAILED:
+ pa_threaded_mainloop_signal(this->mainloop, 0);
+ break;
+
+ case PA_STREAM_UNCONNECTED:
+ case PA_STREAM_CREATING:
+ break;
}
}
/**
- * @brief Callback function called when a context operation succeed
+ * @brief Callback function called when PA asks for more audio data.
+ * @param s Stream on which data is requested
+ * @param nbytes the number of bytes PA requested
+ * @param this_gen pulse_driver_t pointer for the PulseAudio output
+ * instance.
+ */
+static void __xine_pa_stream_request_callback(pa_stream *s, size_t nbytes, void *this_gen)
+{
+ pulse_driver_t * this = (pulse_driver_t*) this_gen;
+
+ pa_threaded_mainloop_signal(this->mainloop, 0);
+}
+
+/**
+ * @brief Callback function called when PA notifies about something
+ * @param s Stream on which the notification happened
+ * @param this_gen pulse_driver_t pointer for the PulseAudio output
+ * instance.
+ */
+static void __xine_pa_stream_notify_callback(pa_stream *s, void *this_gen)
+{
+ pulse_driver_t * this = (pulse_driver_t*) this_gen;
+
+ pa_threaded_mainloop_signal(this->mainloop, 0);
+}
+
+/**
+ * @brief Callback function called when PA completed an operation
* @param ctx Context which operation has succeeded
- * @param success The success value for the operation (ignored)
+ * @param nbytes the number of bytes PA requested
* @param this_gen pulse_driver_t pointer for the PulseAudio output
* instance.
*/
-static void __xine_pa_context_success_callback(pa_context *const ctx, const int success,
- void *const this_gen)
+static void __xine_pa_stream_success_callback(pa_stream *s, int success, void *this_gen)
{
- pulse_driver_t *const this = (pulse_driver_t*)this_gen;
+ pulse_driver_t * this = (pulse_driver_t*) this_gen;
- _x_assert(ctx); _x_assert(this);
- _x_assert(ctx == this->pa_class->context);
+ if (!success)
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: stream operation failed: %s\n", pa_strerror(pa_context_errno(this->context)));
- pa_threaded_mainloop_signal(this->pa_class->mainloop, 0);
+ pa_threaded_mainloop_signal(this->mainloop, 0);
+}
+
+/**
+ * @brief Callback function called when PA completed an operation
+ * @param c Context on which operation has succeeded
+ * @param nbytes the number of bytes PA requested
+ * @param this_gen pulse_driver_t pointer for the PulseAudio output
+ * instance.
+ */
+static void __xine_pa_context_success_callback(pa_context *c, int success, void *this_gen)
+{
+ pulse_driver_t *this = (pulse_driver_t*) this_gen;
+
+ if (!success)
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: context operation failed: %s\n", pa_strerror(pa_context_errno(this->context)));
+
+ pa_threaded_mainloop_signal(this->mainloop, 0);
}
/**
@@ -156,14 +202,14 @@ static void __xine_pa_context_success_callback(pa_context *const ctx, const int
* This function saves the volume field of the passed structure to the
* @c cvolume variable of the output instance.
*/
-static void __xine_pa_sink_info_callback(pa_context *const ctx, const pa_sink_input_info *const info,
- const int is_last, void *const userdata) {
+static void __xine_pa_sink_info_callback(pa_context *c, const pa_sink_input_info *info,
+ int is_last, void *userdata) {
pulse_driver_t *const this = (pulse_driver_t *) userdata;
if (is_last < 0) {
xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: Failed to get sink input info: %s\n",
- pa_strerror(pa_context_errno(this->pa_class->context)));
+ pa_strerror(pa_context_errno(this->context)));
return;
}
@@ -171,36 +217,90 @@ static void __xine_pa_sink_info_callback(pa_context *const ctx, const pa_sink_in
return;
this->cvolume = info->volume;
+ this->swvolume = pa_sw_volume_to_linear(pa_cvolume_avg(&info->volume));
+ this->muted = info->mute;
+}
+
+static int connect_context(pulse_driver_t *this) {
+
+ if (this->context && (pa_context_get_state(this->context) == PA_CONTEXT_FAILED ||
+ pa_context_get_state(this->context) == PA_CONTEXT_TERMINATED)) {
+ pa_context_unref(this->context);
+ this->context = NULL;
+ }
+
+ if (!this->context) {
+ char fn[PATH_MAX], *p;
+
+ if (pa_get_binary_name(fn, sizeof(fn)))
+ p = pa_path_get_filename(fn);
+ else
+ p = "Xine";
+
+ this->context = pa_context_new(pa_threaded_mainloop_get_api(this->mainloop), p);
+ _x_assert(this->context);
+
+ pa_context_set_state_callback(this->context, __xine_pa_context_state_callback, this);
+ }
+
+ if (pa_context_get_state(this->context) == PA_CONTEXT_UNCONNECTED) {
+
+ if (pa_context_connect(this->context, this->host, 0, NULL) < 0) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to connect context object %s\n", pa_strerror(pa_context_errno(this->context)));
+ return -1;
+ }
+ }
+
+ for (;;) {
+ pa_context_state_t state = pa_context_get_state(this->context);
+
+ if (state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to connect context object: %s\n", pa_strerror(pa_context_errno(this->context)));
+ return -1;
+ }
+
+ if (state == PA_CONTEXT_READY)
+ break;
+
+ pa_threaded_mainloop_wait(this->mainloop);
+ }
- pthread_mutex_unlock(&this->info_mutex);
+ return 0;
}
/*
* open the audio device for writing to
*/
static int ao_pulse_open(ao_driver_t *this_gen,
- uint32_t bits, uint32_t rate, int mode)
+ uint32_t bits, uint32_t rate, int mode)
{
pulse_driver_t *this = (pulse_driver_t *) this_gen;
- struct pa_sample_spec ss;
- struct pa_buffer_attr a;
- pa_stream_state_t streamstate;
+ pa_sample_spec ss;
+ pa_channel_map cm;
+ int r;
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "audio_pulse_out: ao_open bits=%d rate=%d, mode=%d\n", bits, rate, mode);
+ "audio_pulse_out: ao_open bits=%d rate=%d, mode=%d\n", bits, rate, mode);
if ( (mode & this->capabilities) == 0 ) {
xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: unsupported mode %08x\n", mode);
return 0;
}
+ pa_threaded_mainloop_lock(this->mainloop);
+
if (this->stream) {
- if ( mode == this->mode && rate == this->sample_rate &&
- bits == this->bits_per_sample )
+ if (mode == this->mode && rate == this->sample_rate &&
+ bits == this->bits_per_sample) {
+
+ pa_threaded_mainloop_unlock(this->mainloop);
return this->sample_rate;
+ }
- this_gen->close(this_gen);
+ pa_stream_disconnect(this->stream);
+ pa_stream_unref(this->stream);
+ this->stream = NULL;
}
this->mode = mode;
@@ -221,6 +321,8 @@ static int ao_pulse_open(ao_driver_t *this_gen,
case 32:
ss.format = PA_SAMPLE_FLOAT32NE;
break;
+ default:
+ _x_assert(!"Should not be reached");
}
if (!pa_sample_spec_valid(&ss)) {
@@ -228,70 +330,86 @@ static int ao_pulse_open(ao_driver_t *this_gen,
goto fail;
}
- if ( this->pa_class->context && pa_context_get_state(this->pa_class->context) > PA_CONTEXT_READY ) {
- pa_context_unref(this->pa_class->context);
- this->pa_class->context = NULL;
- }
-
- if ( this->pa_class->context == NULL ) {
- this->pa_class->context = pa_context_new(pa_threaded_mainloop_get_api(this->pa_class->mainloop),
- __progname);
- }
+ cm.channels = ss.channels;
- pa_context_ref(this->pa_class->context);
-
- if ( pa_context_get_state(this->pa_class->context) == PA_CONTEXT_UNCONNECTED ) {
- int ret;
+ switch (mode) {
+ case AO_CAP_MODE_MONO:
+ cm.map[0] = PA_CHANNEL_POSITION_MONO;
+ _x_assert(cm.channels == 1);
+ break;
- pa_threaded_mainloop_lock(this->pa_class->mainloop);
- ret = pa_context_connect(this->pa_class->context, this->host, 1, NULL);
- if ( ret < 0 )
- goto fail_unlock;
+ case AO_CAP_MODE_STEREO:
+ cm.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
+ cm.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
+ _x_assert(cm.channels == 2);
+ break;
- pa_context_set_state_callback(this->pa_class->context, __xine_pa_context_status_callback, this);
+ case AO_CAP_MODE_4CHANNEL:
+ cm.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
+ cm.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
+ cm.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
+ cm.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
+ _x_assert(cm.channels == 4);
+ break;
- pa_threaded_mainloop_wait(this->pa_class->mainloop);
- pa_threaded_mainloop_unlock(this->pa_class->mainloop);
+ case AO_CAP_MODE_4_1CHANNEL:
+ case AO_CAP_MODE_5CHANNEL:
+ case AO_CAP_MODE_5_1CHANNEL:
+ cm.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
+ cm.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
+ cm.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
+ cm.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
+ cm.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
+ cm.map[5] = PA_CHANNEL_POSITION_LFE;
+ cm.channels = 6;
+ break;
+ default:
+ _x_assert(!"Should not be reached");
}
- if (pa_context_get_state(this->pa_class->context) != PA_CONTEXT_READY) {
- xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: Failed to connect to server: %s\n",
- pa_strerror(pa_context_errno(this->pa_class->context)));
+ if (!pa_channel_map_valid(&cm)) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: Invalid channel map\n");
goto fail;
}
- this->stream = pa_stream_new(this->pa_class->context, "audio stream", &ss, NULL);
+ if (connect_context(this) < 0)
+ goto fail;
+
+ _x_assert(!this->stream);
+ this->stream = pa_stream_new(this->context, "Audio Stream", &ss, &cm);
_x_assert(this->stream);
- a.maxlength = pa_bytes_per_second(&ss)*1;
- a.tlength = a.maxlength*9/10;
- a.prebuf = a.tlength/2;
- a.minreq = a.tlength/10;
+ pa_stream_set_state_callback(this->stream, __xine_pa_stream_state_callback, this);
+ pa_stream_set_write_callback(this->stream, __xine_pa_stream_request_callback, this);
+ pa_stream_set_latency_update_callback(this->stream, __xine_pa_stream_notify_callback, this);
- pa_stream_connect_playback(this->stream, this->sink, &a,
- PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE,
+ r = pa_stream_connect_playback(this->stream, this->sink, NULL,
+ PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE,
NULL, NULL);
- do {
- xine_usec_sleep (100);
+ for (;;) {
+ pa_context_state_t cstate = pa_context_get_state(this->context);
+ pa_stream_state_t sstate = pa_stream_get_state(this->stream);
- streamstate = pa_stream_get_state(this->stream);
- } while (streamstate < PA_STREAM_READY);
-
- if (streamstate != PA_STREAM_READY) {
- xprintf (this->xine, XINE_VERBOSITY_LOG, "audio_pulse_out: Failed to connect to server: %s\n",
- pa_strerror(pa_context_errno(this->pa_class->context)));
- goto fail;
+ if (cstate == PA_CONTEXT_FAILED || cstate == PA_CONTEXT_TERMINATED ||
+ sstate == PA_STREAM_FAILED || sstate == PA_STREAM_TERMINATED) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to connect context object: %s\n", pa_strerror(pa_context_errno(this->context)));
+ goto fail;
+ }
+
+ if (sstate == PA_STREAM_READY)
+ break;
+
+ pa_threaded_mainloop_wait(this->mainloop);
}
- this->frames_written = 0;
- this->ao_driver.set_property(this, AO_PROP_PCM_VOL, 100);
+ pa_threaded_mainloop_unlock(this->mainloop);
return this->sample_rate;
- fail_unlock:
- pa_threaded_mainloop_unlock(this->pa_class->mainloop);
fail:
+
+ pa_threaded_mainloop_unlock(this->mainloop);
this_gen->close(this_gen);
return 0;
}
@@ -319,217 +437,348 @@ static int ao_pulse_write(ao_driver_t *this_gen, int16_t *data,
{
pulse_driver_t *this = (pulse_driver_t *) this_gen;
size_t size = num_frames * this->bytes_per_frame;
- int ret = 0;
-
- if ( !this->stream || !this->pa_class->context)
- return -1;
+ int ret = -1;
+ size_t done = 0;
- switch( pa_stream_get_state(this->stream) ) {
- case PA_STREAM_READY:
- while (size > 0) {
- size_t l;
+ pa_threaded_mainloop_lock(this->mainloop);
- while (!(l = pa_stream_writable_size(this->stream))) {
- xine_usec_sleep (10000);
- }
+ while (size > 0) {
+ size_t l;
- if (l > size)
- l = size;
-
- pa_stream_write(this->stream, data, l, NULL, 0, PA_SEEK_RELATIVE);
- data = (int16_t *) ((uint8_t*) data + l);
- size -= l;
- }
+ for (;;) {
+
+ if (!this->stream ||
+ !this->context ||
+ pa_context_get_state(this->context) != PA_CONTEXT_READY ||
+ pa_stream_get_state(this->stream) != PA_STREAM_READY)
+ goto finish;
- this->frames_written += num_frames;
+ if ((l = pa_stream_writable_size(this->stream)) == (size_t) -1)
+ goto finish;
- if (pa_stream_get_state(this->stream) == PA_STREAM_READY)
- ret = 1;
+ if (l > 0)
+ break;
- break;
+ pa_threaded_mainloop_wait(this->mainloop);
+ }
+
+ if (l > size)
+ l = size;
+
+ pa_stream_write(this->stream, data, l, NULL, 0, PA_SEEK_RELATIVE);
+ data = (int16_t *) ((uint8_t*) data + l);
+ size -= l;
+ done += l;
}
+ ret = done;
+
+finish:
+
+ pa_threaded_mainloop_unlock(this->mainloop);
+
+/* fprintf(stderr, "write-out\n"); */
+
return ret;
-}
+}
static int ao_pulse_delay (ao_driver_t *this_gen)
{
pulse_driver_t *this = (pulse_driver_t *) this_gen;
- pa_usec_t latency = 0;
- unsigned int delay_frames;
+ int ret = 0;
- if ( ! this->stream ) return this->frames_written;
+/* fprintf(stderr, "delay-in\n"); */
- if (pa_stream_get_latency(this->stream, &latency, NULL) < 0) {
- pa_context_unref(this->pa_class->context);
- this->pa_class->context = NULL;
+ pa_threaded_mainloop_lock(this->mainloop);
- pa_stream_disconnect(this->stream);
- pa_stream_unref(this->stream);
- this->stream = NULL;
+ for (;;) {
+ pa_usec_t latency = 0;
- return 0;
+ if (!this->stream ||
+ !this->context ||
+ pa_context_get_state(this->context) != PA_CONTEXT_READY ||
+ pa_stream_get_state(this->stream) != PA_STREAM_READY)
+ goto finish;
+
+ if (pa_stream_get_latency(this->stream, &latency, NULL) >= 0) {
+ ret = (int) ((latency * this->sample_rate) / 1000000);
+ goto finish;
+ }
+
+ if (pa_context_errno(this->context) != PA_ERR_NODATA) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to query latency: %s\n", pa_strerror(pa_context_errno(this->context)));
+ goto finish;
+ }
+
+ pa_threaded_mainloop_wait(this->mainloop);
}
- /* convert latency (us) to frame units. */
- delay_frames = (int)(latency * this->sample_rate / 1000000);
+finish:
+
+ pa_threaded_mainloop_unlock(this->mainloop);
- if( delay_frames > this->frames_written )
- return this->frames_written;
- else
- return delay_frames;
+ return ret;
}
static void ao_pulse_close(ao_driver_t *this_gen)
{
pulse_driver_t *this = (pulse_driver_t *) this_gen;
-
- if (this->stream) {
- if (pa_stream_get_state(this->stream) == PA_STREAM_READY) {
- pthread_mutex_t completion_callback = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&completion_callback);
- pa_stream_drain(this->stream, __xine_pa_stream_success_callback, &completion_callback);
- pthread_mutex_lock(&completion_callback);
- pthread_mutex_destroy(&completion_callback);
- }
+ pa_threaded_mainloop_lock(this->mainloop);
+ if (this->stream) {
pa_stream_disconnect(this->stream);
pa_stream_unref(this->stream);
this->stream = NULL;
-
- pa_context_unref(this->pa_class->context);
}
+
+ pa_threaded_mainloop_unlock(this->mainloop);
}
static uint32_t ao_pulse_get_capabilities (ao_driver_t *this_gen) {
pulse_driver_t *this = (pulse_driver_t *) this_gen;
+
return this->capabilities;
}
-static void ao_pulse_exit(ao_driver_t *this_gen)
-{
+static void ao_pulse_exit(ao_driver_t *this_gen) {
pulse_driver_t *this = (pulse_driver_t *) this_gen;
- free (this);
+ ao_pulse_close(this_gen);
+
+ pa_threaded_mainloop_lock(this->mainloop);
+
+ if (this->context) {
+ pa_context_disconnect(this->context);
+ pa_context_unref(this->context);
+ }
+
+ pa_threaded_mainloop_unlock(this->mainloop);
+
+ pa_threaded_mainloop_free(this->mainloop);
+
+ free(this->host);
+ free(this->sink);
+ free(this);
+}
+
+static int wait_for_operation(pulse_driver_t *this, pa_operation *o) {
+
+ for (;;) {
+
+ if (!this->stream ||
+ !this->context ||
+ pa_context_get_state(this->context) != PA_CONTEXT_READY ||
+ pa_stream_get_state(this->stream) != PA_STREAM_READY)
+ return -1;
+
+ if (pa_operation_get_state(o) != PA_OPERATION_RUNNING)
+ return 0;
+
+ pa_threaded_mainloop_wait(this->mainloop);
+ }
}
static int ao_pulse_get_property (ao_driver_t *this_gen, int property) {
pulse_driver_t *this = (pulse_driver_t *) this_gen;
int result = 0;
+ pa_operation *o = NULL;
- if ( ! this->stream || ! this->pa_class->context )
+ pa_threaded_mainloop_lock(this->mainloop);
+
+ if (!this->stream ||
+ !this->context ||
+ pa_context_get_state(this->context) != PA_CONTEXT_READY ||
+ pa_stream_get_state(this->stream) != PA_STREAM_READY) {
+ pa_threaded_mainloop_unlock(this->mainloop);
return 0;
+ }
switch(property) {
- case AO_PROP_PCM_VOL:
- case AO_PROP_MIXER_VOL:
- {
- pthread_mutex_lock(&this->info_mutex);
- pa_operation *o = pa_context_get_sink_input_info(this->pa_class->context,
- pa_stream_get_index(this->stream),
- __xine_pa_sink_info_callback, this);
- if ( ! o ) return 0;
- pthread_mutex_lock(&this->info_mutex); pthread_mutex_unlock(&this->info_mutex);
-
- result = (pa_sw_volume_to_linear(this->swvolume)*100);
- }
- break;
- case AO_PROP_MUTE_VOL:
- result = pa_cvolume_is_muted(&this->cvolume);
- break;
+ case AO_PROP_MUTE_VOL:
+ case AO_PROP_PCM_VOL:
+ case AO_PROP_MIXER_VOL:
+
+ o = pa_context_get_sink_input_info(this->context, pa_stream_get_index(this->stream),
+ __xine_pa_sink_info_callback, this);
+
+ break;
+ }
+
+ if (o) {
+ wait_for_operation(this, o);
+ pa_operation_unref(o);
}
-
+
+ switch(property) {
+
+ case AO_PROP_MUTE_VOL:
+ result = this->muted;
+ break;
+
+ case AO_PROP_PCM_VOL:
+ case AO_PROP_MIXER_VOL:
+ result = (int) (pa_sw_volume_to_linear(this->swvolume)*100);
+ break;
+ }
+
+ pa_threaded_mainloop_unlock(this->mainloop);
+
return result;
}
static int ao_pulse_set_property (ao_driver_t *this_gen, int property, int value) {
pulse_driver_t *this = (pulse_driver_t *) this_gen;
int result = ~value;
+ pa_operation *o = NULL;
- if ( ! this->stream || ! this->pa_class->context )
- return result;
+ pa_threaded_mainloop_lock(this->mainloop);
+
+ if (!this->stream ||
+ !this->context ||
+ pa_context_get_state(this->context) != PA_CONTEXT_READY ||
+ pa_stream_get_state(this->stream) != PA_STREAM_READY) {
+ pa_threaded_mainloop_unlock(this->mainloop);
+ return 0;
+ }
switch(property) {
- case AO_PROP_PCM_VOL:
- case AO_PROP_MIXER_VOL:
- this->swvolume = pa_sw_volume_from_linear((double)value/100.0);
- pa_cvolume_set(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels, this->swvolume);
+ case AO_PROP_PCM_VOL:
+ case AO_PROP_MIXER_VOL:
- pa_context_set_sink_input_volume(this->pa_class->context, pa_stream_get_index(this->stream),
- &this->cvolume, __xine_pa_context_success_callback, this);
+ this->swvolume = pa_sw_volume_from_linear((double)value/100.0);
+ pa_cvolume_set(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels, this->swvolume);
- result = value;
- break;
+ o = pa_context_set_sink_input_volume(this->context, pa_stream_get_index(this->stream),
+ &this->cvolume, __xine_pa_context_success_callback, this);
- case AO_PROP_MUTE_VOL:
- if ( value )
- pa_cvolume_mute(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels);
- else
- pa_cvolume_set(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels, this->swvolume);
+ result = value;
+ break;
+
+ case AO_PROP_MUTE_VOL:
- pa_context_set_sink_input_volume(this->pa_class->context, pa_stream_get_index(this->stream),
- &this->cvolume, __xine_pa_context_success_callback, this);
-
- result = value;
- break;
+ this->muted = value;
+
+ o = pa_context_set_sink_input_mute(this->context, pa_stream_get_index(this->stream),
+ value, __xine_pa_context_success_callback, this);
+
+ result = value;
+ }
+
+ if (o) {
+ wait_for_operation(this, o);
+ pa_operation_unref(o);
}
-
+
+ pa_threaded_mainloop_unlock(this->mainloop);
+
return result;
}
static int ao_pulse_ctrl(ao_driver_t *this_gen, int cmd, ...) {
pulse_driver_t *this = (pulse_driver_t *) this_gen;
+ pa_operation *o = NULL;
+
+ pa_threaded_mainloop_lock(this->mainloop);
- if ( ! this->stream ) return 0;
+ if (!this->stream ||
+ !this->context ||
+ pa_context_get_state(this->context) != PA_CONTEXT_READY ||
+ pa_stream_get_state(this->stream) != PA_STREAM_READY) {
+ pa_threaded_mainloop_unlock(this->mainloop);
+ return 0;
+ }
switch (cmd) {
- case AO_CTRL_FLUSH_BUFFERS:
- _x_assert(this->stream && this->pa_class->context);
+ case AO_CTRL_FLUSH_BUFFERS:
- if(pa_stream_get_state(this->stream) == PA_STREAM_READY) {
- pthread_mutex_t completion_callback = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&completion_callback);
- pa_stream_flush(this->stream, __xine_pa_stream_success_callback, &completion_callback);
+ o = pa_stream_flush(this->stream, __xine_pa_stream_success_callback, this);
+ break;
- pthread_mutex_lock(&completion_callback);
- pthread_mutex_destroy(&completion_callback);
- }
+ case AO_CTRL_PLAY_RESUME:
+ case AO_CTRL_PLAY_PAUSE:
- this->frames_written = 0;
+ o = pa_stream_cork(this->stream, cmd == AO_CTRL_PLAY_PAUSE, __xine_pa_stream_success_callback, this);
+ break;
+ }
- break;
+ if (o) {
+ wait_for_operation(this, o);
+ pa_operation_unref(o);
}
+ pa_threaded_mainloop_unlock(this->mainloop);
+
return 0;
}
static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *data) {
pulse_class_t *class = (pulse_class_t *) class_gen;
pulse_driver_t *this;
- char *device;
+ const char* device;
+ int r;
lprintf ("audio_pulse_out: open_plugin called\n");
this = (pulse_driver_t *) xine_xmalloc (sizeof (pulse_driver_t));
if (!this)
return NULL;
+
this->xine = class->xine;
+ this->host = NULL;
+ this->sink = NULL;
+ this->context = NULL;
+ this->mainloop = NULL;
+
+ device = class->xine->config->register_string(class->xine->config,
+ "audio.pulseaudio_device",
+ "",
+ _("device used for pulseaudio"),
+ _("use 'server[:sink]' for setting the "
+ "pulseaudio sink device."),
+ 10, NULL,
+ NULL);
+
+ if (device && *device) {
+ char *sep = strrchr(device, ':');
+ if ( sep ) {
+ if (!(this->host = strndup(device, sep-device))) {
+ free(this);
+ return NULL;
+ }
+
+ if (!(this->sink = strdup(sep+1))) {
+ free(this->host);
+ free(this);
+ return NULL;
+ }
+ } else {
+
+ if (!(this->host = strdup(device))) {
+ free(this);
+ return NULL;
+ }
+ }
+ }
+
+ this->mainloop = pa_threaded_mainloop_new();
+ _x_assert(this->mainloop);
+ pa_threaded_mainloop_start(this->mainloop);
/*
* set capabilities
*/
- this->capabilities = AO_CAP_MODE_MONO | AO_CAP_MODE_STEREO | AO_CAP_MODE_4CHANNEL |
- AO_CAP_MODE_4_1CHANNEL | AO_CAP_MODE_5CHANNEL |
- AO_CAP_MODE_5_1CHANNEL | AO_CAP_MIXER_VOL |
- AO_CAP_PCM_VOL | AO_CAP_MUTE_VOL | AO_CAP_8BITS |
- AO_CAP_16BITS | AO_CAP_FLOAT32;
+ this->capabilities =
+ AO_CAP_MODE_MONO | AO_CAP_MODE_STEREO | AO_CAP_MODE_4CHANNEL |
+ AO_CAP_MODE_4_1CHANNEL | AO_CAP_MODE_5CHANNEL | AO_CAP_MODE_5_1CHANNEL |
+ AO_CAP_MIXER_VOL | AO_CAP_PCM_VOL | AO_CAP_MUTE_VOL |
+ AO_CAP_8BITS | AO_CAP_16BITS | AO_CAP_FLOAT32;
this->sample_rate = 0;
- this->host = NULL;
- this->sink = NULL;
-
+
this->ao_driver.get_capabilities = ao_pulse_get_capabilities;
this->ao_driver.get_property = ao_pulse_get_property;
this->ao_driver.set_property = ao_pulse_set_property;
@@ -541,33 +790,22 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
this->ao_driver.close = ao_pulse_close;
this->ao_driver.exit = ao_pulse_exit;
this->ao_driver.get_gap_tolerance = ao_pulse_get_gap_tolerance;
- this->ao_driver.control = ao_pulse_ctrl;
-
- device = this->xine->config->register_string(this->xine->config,
- "audio.pulseaudio_device",
- "",
- _("device used for pulseaudio"),
- _("use 'server[:sink]' for setting the "
- "pulseaudio sink device."),
- 10, NULL,
- NULL);
-
- if (device && *device) {
- char *sep = strchr(device, ':');
- if ( sep ) {
- this->host = strndup(device, sep-device);
- this->sink = strdup(&sep[1]);
- } else
- this->host = strdup(device);
- }
-
- pthread_mutex_init(&this->info_mutex, NULL);
+ this->ao_driver.control = ao_pulse_ctrl;
xprintf (class->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: host %s sink %s\n",
this->host ? this->host : "(null)", this->sink ? this->sink : "(null)");
this->pa_class = class;
+ pa_threaded_mainloop_lock(this->mainloop);
+ r = connect_context(this);
+ pa_threaded_mainloop_unlock(this->mainloop);
+
+ if (r < 0) {
+ ao_pulse_exit((ao_driver_t *) this);
+ return NULL;
+ }
+
return &this->ao_driver;
}
@@ -579,13 +817,7 @@ static void dispose_class (audio_driver_class_t *this_gen) {
pulse_class_t *this = (pulse_class_t *) this_gen;
- if ( this->context )
- pa_context_unref(this->context);
-
- pa_threaded_mainloop_stop(this->mainloop);
- pa_threaded_mainloop_free(this->mainloop);
-
- free (this);
+ free(this);
}
static void *init_class (xine_t *xine, void *data) {
@@ -598,25 +830,17 @@ static void *init_class (xine_t *xine, void *data) {
if (!this)
return NULL;
+ this->xine = xine;
this->driver_class.open_plugin = open_plugin;
this->driver_class.dispose = dispose_class;
this->driver_class.identifier = "pulseaudio";
this->driver_class.description = N_("xine audio output plugin using pulseaudio sound server");
- this->xine = xine;
-
- this->mainloop = pa_threaded_mainloop_new();
- _x_assert(this->mainloop);
-
- pa_threaded_mainloop_start(this->mainloop);
-
- this->context = NULL;
-
return this;
}
static const ao_info_t ao_info_pulse = {
- 6
+ 12
};
/*
@@ -628,5 +852,3 @@ const plugin_info_t xine_plugin_info[] EXPORTED = {
{ PLUGIN_AUDIO_OUT, 9, "pulseaudio", XINE_VERSION_CODE, &ao_info_pulse, init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
-
-
diff --git a/src/combined/ffmpeg/ff_audio_decoder.c b/src/combined/ffmpeg/ff_audio_decoder.c
index b7f966325..27fe18d9c 100644
--- a/src/combined/ffmpeg/ff_audio_decoder.c
+++ b/src/combined/ffmpeg/ff_audio_decoder.c
@@ -78,6 +78,7 @@ static const ff_codec_t ff_audio_lookup[] = {
{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)"},
@@ -198,8 +199,8 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf)
this->audio_channels = this->buf[0x37];
/* this->audio_bits = buf->content[0x35] */
- this->context->block_align = _X_BE_16(&this->buf[0x2A]);
-
+ this->context->block_align = _X_BE_32(&this->buf[0x18]);
+
this->context->extradata_size = 5*sizeof(short);
this->context->extradata = xine_xmalloc(this->context->extradata_size);
@@ -210,7 +211,49 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf)
ptr[2] = _X_BE_16(&this->buf[0x16]); /* subpacket flavour */
ptr[3] = _X_BE_32(&this->buf[0x18]); /* coded frame size */
ptr[4] = 0; /* codec's data length */
+
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "ffmpeg_audio_dec: 28_8 audio channels %d bits %d sample rate %d block align %d\n",
+ this->audio_channels, this->audio_bits, this->audio_sample_rate,
+ this->context->block_align);
break;
+ case BUF_AUDIO_COOK:
+ {
+ int version;
+ int data_len;
+ int extradata;
+
+ version = _X_BE_16 (this->buf+4);
+ if (version == 4) {
+ this->audio_sample_rate = _X_BE_16 (this->buf+48);
+ this->audio_bits = _X_BE_16 (this->buf+52);
+ this->audio_channels = _X_BE_16 (this->buf+54);
+ data_len = _X_BE_32 (this->buf+67);
+ extradata = 71;
+ } else {
+ this->audio_sample_rate = _X_BE_16 (this->buf+54);
+ this->audio_bits = _X_BE_16 (this->buf+58);
+ this->audio_channels = _X_BE_16 (this->buf+60);
+ data_len = _X_BE_32 (this->buf+74);
+ extradata = 78;
+ }
+ this->context->block_align = _X_BE_16 (this->buf+44);
+
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "ffmpeg_audio_dec: cook audio channels %d bits %d sample rate %d block align %d\n",
+ this->audio_channels, this->audio_bits, this->audio_sample_rate,
+ this->context->block_align);
+
+ if (extradata + data_len > this->size)
+ break; /* abort early - extradata length is bad */
+
+ this->context->extradata_size = data_len;
+ this->context->extradata = xine_xmalloc(this->context->extradata_size +
+ FF_INPUT_BUFFER_PADDING_SIZE);
+ xine_fast_memcpy (this->context->extradata, this->buf + extradata,
+ this->context->extradata_size);
+ break;
+ }
default:
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
"ffmpeg_audio_dec: unknown header with buf type 0x%X\n", codec_type);
@@ -227,6 +270,7 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf)
this->context->sample_rate = this->audio_sample_rate;
this->context->channels = this->audio_channels;
this->context->codec_id = this->codec->id;
+ this->context->codec_type = this->codec->type;
this->context->codec_tag = _x_stream_info_get(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC);
this->size = 0;
@@ -266,7 +310,26 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf)
this->decoder_ok = 1;
}
+ if( buf->decoder_flags & BUF_FLAG_PREVIEW )
+ return;
+
+ ff_audio_ensure_buffer_size(this, this->size + buf->size);
+ xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size);
+ this->size += buf->size;
+
if (!this->output_open) {
+ if (!this->audio_bits || !this->audio_sample_rate || !this->audio_channels) {
+ avcodec_decode_audio (this->context,
+ (int16_t *)this->decode_buffer,
+ &decode_buffer_size,
+ &this->buf[0],
+ this->size);
+ this->audio_bits = this->context->bits_per_sample;
+ this->audio_sample_rate = this->context->sample_rate;
+ this->audio_channels = this->context->channels;
+ if (!this->audio_bits || !this->audio_sample_rate || !this->audio_channels)
+ return;
+ }
this->output_open = (this->stream->audio_out->open) (this->stream->audio_out,
this->stream, this->audio_bits, this->audio_sample_rate,
_x_ao_channels2mode(this->audio_channels));
@@ -276,13 +339,6 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf)
if (!this->output_open)
return;
- if( buf->decoder_flags & BUF_FLAG_PREVIEW )
- return;
-
- ff_audio_ensure_buffer_size(this, this->size + buf->size);
- xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size);
- this->size += buf->size;
-
if (buf->decoder_flags & BUF_FLAG_FRAME_END) { /* time to decode a frame */
offset = 0;
@@ -323,7 +379,7 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf)
/* fill up this buffer */
xine_fast_memcpy(audio_buffer->mem, &this->decode_buffer[out],
- bytes_to_send);
+ bytes_to_send);
/* byte count / 2 (bytes / sample) / channels */
audio_buffer->num_frames = bytes_to_send / 2 / this->audio_channels;
@@ -354,7 +410,8 @@ static void ff_audio_reset (audio_decoder_t *this_gen) {
if( this->context && this->decoder_ok ) {
pthread_mutex_lock (&ffmpeg_lock);
avcodec_close (this->context);
- avcodec_open (this->context, this->codec);
+ if (avcodec_open (this->context, this->codec) < 0)
+ this->decoder_ok = 0;
pthread_mutex_unlock (&ffmpeg_lock);
}
}
@@ -468,5 +525,5 @@ static const uint32_t supported_audio_types[] = {
decoder_info_t dec_info_ffmpeg_audio = {
supported_audio_types, /* supported types */
- 6 /* priority */
+ 7 /* priority */
};
diff --git a/src/combined/ffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c
index fcc6b9283..951e12deb 100644
--- a/src/combined/ffmpeg/ff_video_decoder.c
+++ b/src/combined/ffmpeg/ff_video_decoder.c
@@ -44,11 +44,7 @@
#include "ffmpeg_decoder.h"
#include "ff_mpeg_parser.h"
-#ifdef HAVE_FFMPEG_AVCODEC_H
-# include <postprocess.h>
-#else
-# include <libpostproc/postprocess.h>
-#endif
+#include <postprocess.h>
#define VIDEOBUFSIZE (128*1024)
#define SLICE_BUFFER_SIZE (1194*1024)
@@ -943,6 +939,26 @@ static void ff_handle_header_buffer (ff_video_decoder_t *this, buf_element_t *bu
this->context->slice_offset = xine_xmalloc(sizeof(int)*SLICE_OFFSET_SIZE);
this->slice_offset_size = SLICE_OFFSET_SIZE;
+ this->context->extradata_size = this->size - 26;
+ if (this->context->extradata_size < 8) {
+ this->context->extradata_size= 8;
+ this->context->extradata = malloc(this->context->extradata_size +
+ FF_INPUT_BUFFER_PADDING_SIZE);
+ ((uint32_t *)this->context->extradata)[0] = 0;
+ if (codec_type == BUF_VIDEO_RV10)
+ ((uint32_t *)this->context->extradata)[1] = 0x10000000;
+ else
+ ((uint32_t *)this->context->extradata)[1] = 0x10003001;
+ } else {
+ this->context->extradata = malloc(this->context->extradata_size +
+ FF_INPUT_BUFFER_PADDING_SIZE);
+ memcpy(this->context->extradata, this->buf + 26,
+ this->context->extradata_size);
+ }
+
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "ffmpeg_video_dec: buf size %d\n", this->size);
+
lprintf("w=%d, h=%d\n", this->bih.biWidth, this->bih.biHeight);
break;
diff --git a/src/combined/ffmpeg/ffmpeg_decoder.h b/src/combined/ffmpeg/ffmpeg_decoder.h
index adf0908dd..bfe71a6b1 100644
--- a/src/combined/ffmpeg/ffmpeg_decoder.h
+++ b/src/combined/ffmpeg/ffmpeg_decoder.h
@@ -25,11 +25,7 @@
#include "config.h"
#endif
-#ifdef HAVE_FFMPEG_AVCODEC_H
-# include <avcodec.h>
-#else
-# include <libavcodec/avcodec.h>
-#endif
+#include <avcodec.h>
typedef struct ff_codec_s {
uint32_t type;
diff --git a/src/combined/wavpack_combined.c b/src/combined/wavpack_combined.c
index 8a4b488ae..ca54635e7 100644
--- a/src/combined/wavpack_combined.c
+++ b/src/combined/wavpack_combined.c
@@ -33,7 +33,7 @@ static const uint32_t audio_types[] = {
static const decoder_info_t decoder_info_wv = {
audio_types, /* supported types */
- 7 /* priority */
+ 8 /* priority */
};
const plugin_info_t xine_plugin_info[] EXPORTED = {
diff --git a/src/combined/wavpack_demuxer.c b/src/combined/wavpack_demuxer.c
index 403d136d1..e32c17e4e 100644
--- a/src/combined/wavpack_demuxer.c
+++ b/src/combined/wavpack_demuxer.c
@@ -368,8 +368,8 @@ void *demux_wv_init_plugin (xine_t *const xine, void *const data) {
this->demux_class.open_plugin = open_plugin;
this->demux_class.description = N_("Wavpack demux plugin");
this->demux_class.identifier = "Wavpack";
- this->demux_class.mimetypes = "audio/x-wavpack";
- this->demux_class.extensions = "wv";
+ this->demux_class.mimetypes = "audio/x-wavpack: wv,wvp: WavPack audio;";
+ this->demux_class.extensions = "wv wvp";
this->demux_class.dispose = default_demux_class_dispose;
return this;
diff --git a/src/combined/xine_ogg_demuxer.c b/src/combined/xine_ogg_demuxer.c
index 88fcea08a..52788612f 100644
--- a/src/combined/xine_ogg_demuxer.c
+++ b/src/combined/xine_ogg_demuxer.c
@@ -1208,7 +1208,7 @@ static void decode_theora_header (demux_ogg_t *this, const int stream_num, ogg_p
static void decode_flac_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) {
xine_flac_metadata_header header;
- xine_flac_streaminfo_block streaminfo;
+ xine_flac_streaminfo_block streaminfo = {};
buf_element_t *buf;
xine_waveformatex wave;
@@ -2110,6 +2110,9 @@ static void *ogg_init_class (xine_t *xine, void *data) {
this->demux_class.identifier = "OGG";
this->demux_class.mimetypes =
"application/ogg: ogx: Ogg Stream;"
+ "application/x-ogm: ogx: Ogg Stream;"
+ "application/x-ogm-audio: oga: Ogg Audio;"
+ "application/x-ogm-video: ogv: Ogg Video;"
"application/x-ogg: ogx: Ogg Stream;"
"audio/ogg: oga: Ogg Audio;"
"audio/x-ogg: oga: Ogg Audio;"
diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am
index 596d7dbd0..e2ee826ec 100644
--- a/src/demuxers/Makefile.am
+++ b/src/demuxers/Makefile.am
@@ -8,7 +8,7 @@ AM_LDFLAGS = $(xineplug_ldflags)
# ---------
# All of xine demuxer plugins should be named like the scheme "xineplug_dmx_"
-noinst_HEADERS = asfheader.h qtpalette.h group_games.h group_audio.h id3.h ebml.h matroska.h iff.h flacutils.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
if ENABLE_ASF
asf_module = xineplug_dmx_asf.la
diff --git a/src/demuxers/asfheader.c b/src/demuxers/asfheader.c
index 75ad11c75..d602445a0 100644
--- a/src/demuxers/asfheader.c
+++ b/src/demuxers/asfheader.c
@@ -394,7 +394,7 @@ static int asf_header_parse_stream_extended_properties(asf_header_t *header, uin
if (asf_stream_extension->stream_name_count) {
asf_stream_extension->stream_names = malloc (asf_stream_extension->stream_name_count * sizeof(void*));
for (i = 0; i < asf_stream_extension->stream_name_count; i++) {
- uint16_t lang_index, length;
+ uint16_t lang_index, length = 0;
asf_reader_get_16(&reader, &lang_index);
asf_reader_get_16(&reader, &length);
asf_stream_extension->stream_names[i] = (char*)asf_reader_get_bytes(&reader, length); /* store them */
@@ -406,7 +406,7 @@ static int asf_header_parse_stream_extended_properties(asf_header_t *header, uin
for (i = 0; i < asf_stream_extension->payload_extension_system_count; i++) {
GUID guid;
uint16_t data_size;
- uint32_t length;
+ uint32_t length = 0;
asf_reader_get_guid(&reader, &guid);
asf_reader_get_16(&reader, &data_size);
asf_reader_get_32(&reader, &length);
@@ -422,7 +422,7 @@ static int asf_header_parse_stream_extended_properties(asf_header_t *header, uin
/* embeded stream properties */
if (asf_reader_get_size(&reader) >= 24) {
GUID guid;
- uint64_t object_length;
+ uint64_t object_length = 0;
asf_reader_get_guid(&reader, &guid);
asf_reader_get_64(&reader, &object_length);
@@ -485,8 +485,8 @@ static int asf_header_parse_stream_bitrate_properties(asf_header_t *header_pub,
lprintf (" bitrate count: %d\n", bitrate_count);
for(i = 0; i < bitrate_count; i++) {
- uint16_t flags;
- uint32_t bitrate;
+ uint16_t flags = 0;
+ uint32_t bitrate = 0;
int stream_number;
uint8_t *bitrate_pointer;
@@ -528,7 +528,7 @@ static int asf_header_parse_header_extension(asf_header_t *header, uint8_t *buff
GUID guid;
int object_id;
- uint64_t object_length, object_data_length;
+ uint64_t object_length = 0, object_data_length;
if (asf_reader_get_size(&reader) < 24) {
printf("invalid buffer size\n");
@@ -633,7 +633,7 @@ asf_header_t *asf_header_new (uint8_t *buffer, int buffer_len) {
GUID guid;
int object_id;
- uint64_t object_length, object_data_length;
+ uint64_t object_length = 0, object_data_length;
if (asf_reader_get_size(&reader) < 24) {
printf("invalid buffer size\n");
diff --git a/src/demuxers/demux_4xm.c b/src/demuxers/demux_4xm.c
index 6256cb042..264806421 100644
--- a/src/demuxers/demux_4xm.c
+++ b/src/demuxers/demux_4xm.c
@@ -159,7 +159,7 @@ static int open_fourxm_file(demux_fourxm_t *fourxm) {
/* read the whole header */
header_size = _X_LE_32(&preview[4]) - 4;
header = xine_xmalloc(header_size);
- if (fourxm->input->read(fourxm->input, header, header_size) != header_size) {
+ if (!header || fourxm->input->read(fourxm->input, header, header_size) != header_size) {
free(header);
return 0;
}
diff --git a/src/demuxers/demux_aiff.c b/src/demuxers/demux_aiff.c
index 51bc624e3..06ff65680 100644
--- a/src/demuxers/demux_aiff.c
+++ b/src/demuxers/demux_aiff.c
@@ -46,6 +46,10 @@
#define COMM_TAG FOURCC_TAG('C', 'O', 'M', 'M')
#define SSND_TAG FOURCC_TAG('S', 'S', 'N', 'D')
#define APCM_TAG FOURCC_TAG('A', 'P', 'C', 'M')
+#define NAME_TAG FOURCC_TAG('N', 'A', 'M', 'E')
+#define AUTH_TAG FOURCC_TAG('A', 'U', 'T', 'H')
+#define COPY_TAG FOURCC_TAG('(', 'c', ')', ' ')
+#define ANNO_TAG FOURCC_TAG('A', 'N', 'N', 'O')
#define PREAMBLE_SIZE 8
#define AIFF_SIGNATURE_SIZE 12
@@ -80,6 +84,24 @@ typedef struct {
demux_class_t demux_class;
} demux_aiff_class_t;
+/* converts IEEE 80bit extended into int, based on FFMPEG code */
+int extended_to_int(const unsigned char p[10])
+{
+ uint64_t m = 0;
+ int e, i;
+
+ for (i = 0; i < 8; i++)
+ m = (m<<8) + p[2+i];;
+ e = (((int)p[0]&0x7f)<<8) | p[1];
+ if (e == 0x7fff && m)
+ return 0.0/0.0;
+ e -= 16383 + 63;
+
+ if (p[0]&0x80)
+ m= -m;
+ return (int) ldexp(m, e);
+}
+
/* returns 1 if the AIFF file was opened successfully, 0 otherwise */
static int open_aiff_file(demux_aiff_t *this) {
@@ -87,6 +109,7 @@ static int open_aiff_file(demux_aiff_t *this) {
unsigned char preamble[PREAMBLE_SIZE];
unsigned int chunk_type;
unsigned int chunk_size;
+ unsigned char extended_sample_rate[10];
if (_x_demux_read_header(this->input, signature, AIFF_SIGNATURE_SIZE) != AIFF_SIGNATURE_SIZE)
return 0;
@@ -135,7 +158,8 @@ static int open_aiff_file(demux_aiff_t *this) {
this->audio_channels = _X_BE_16(&buffer[0]);
this->audio_frames = _X_BE_32(&buffer[2]);
this->audio_bits = _X_BE_16(&buffer[6]);
- this->audio_sample_rate = _X_BE_16(&buffer[0x0A]);
+ memcpy(&extended_sample_rate, &buffer[8], sizeof(extended_sample_rate));
+ this->audio_sample_rate = extended_to_int(extended_sample_rate);
this->audio_bytes_per_second = this->audio_channels *
(this->audio_bits / 8) * this->audio_sample_rate;
@@ -150,11 +174,18 @@ static int open_aiff_file(demux_aiff_t *this) {
(this->audio_bits / 8);
this->running_time = (this->audio_frames / this->audio_sample_rate) * 1000;
- this->audio_block_align = PCM_BLOCK_ALIGN;
+ /* we should send only complete frames to decoder, as it
+ * doesn't handle underconsumption yet */
+ this->audio_block_align = PCM_BLOCK_ALIGN - PCM_BLOCK_ALIGN % (this->audio_bits / 8 * this->audio_channels);
break;
} else {
+ /* if chunk contains metadata, it will be word-aligned (as seen at sox and ffmpeg) */
+ if ( ((chunk_type == NAME_TAG) || (chunk_type==AUTH_TAG) ||
+ (chunk_type == COPY_TAG) || (chunk_type==ANNO_TAG)) && (chunk_size&1))
+ chunk_size++;
+
/* unrecognized; skip it */
this->input->seek(this->input, chunk_size, SEEK_CUR);
}
diff --git a/src/demuxers/demux_avi.c b/src/demuxers/demux_avi.c
index 27dfce443..e06caf94f 100644
--- a/src/demuxers/demux_avi.c
+++ b/src/demuxers/demux_avi.c
@@ -973,6 +973,10 @@ static avi_t *AVI_init(demux_avi_t *this) {
xine_waveformatex *wavex;
wavex = (xine_waveformatex *)malloc(n);
+ if (!wavex) {
+ this->AVI_errno = AVI_ERR_NO_MEM;
+ return 0;
+ }
memcpy((void *)wavex, hdrl_data+i, n);
_x_waveformatex_le2me( wavex );
@@ -1237,6 +1241,9 @@ static avi_t *AVI_init(demux_avi_t *this) {
/* read from file */
chunk_start = en = malloc (AVI->video_superindex->aIndex[j].dwSize+hdrl_len);
+ if (!chunk_start)
+ ERR_EXIT(AVI_ERR_NO_MEM);
+
if (this->input->seek(this->input, AVI->video_superindex->aIndex[j].qwOffset, SEEK_SET) == (off_t)-1) {
lprintf("cannot seek to 0x%" PRIx64 "\n", AVI->video_superindex->aIndex[j].qwOffset);
free(chunk_start);
@@ -1308,6 +1315,9 @@ static avi_t *AVI_init(demux_avi_t *this) {
/* read from file */
chunk_start = en = malloc (audio->audio_superindex->aIndex[j].dwSize+hdrl_len);
+ if (!chunk_start)
+ ERR_EXIT(AVI_ERR_NO_MEM);
+
if (this->input->seek(this->input, audio->audio_superindex->aIndex[j].qwOffset, SEEK_SET) == (off_t)-1) {
lprintf("cannot seek to 0x%" PRIx64 "\n", audio->audio_superindex->aIndex[j].qwOffset);
free(chunk_start);
diff --git a/src/demuxers/demux_dts.c b/src/demuxers/demux_dts.c
index 9d3313a72..750d212f5 100644
--- a/src/demuxers/demux_dts.c
+++ b/src/demuxers/demux_dts.c
@@ -140,29 +140,63 @@ static int open_dts_file(demux_dts_t *this) {
}
}
+ /* DTS bitstream encoding version
+ * -1 - not detected
+ * 0 - 16 bits and big endian
+ * 1 - 16 bits and low endian (detection not implemented)
+ * 2 - 14 bits and big endian (detection not implemented)
+ * 3 - 14 bits and low endian
+ */
+ int dts_version = -1;
+
/* Look for a valid DTS syncword */
for (i=offset; i<peak_size-1; i++) {
+ /* 16 bits and big endian bitstream */
+ if (syncword == 0x7ffe8001) {
+ dts_version = 0;
+ break;
+ }
/* 14 bits and little endian bitstream */
- if ((syncword == 0xff1f00e8) &&
- ((peak[i] & 0xf0) == 0xf0) && (peak[i+1] == 0x07)) {
- this->data_start = i-4;
- lprintf("found DTS syncword at offset %d\n", i-4);
- break;
+ else if ((syncword == 0xff1f00e8) &&
+ ((peak[i] & 0xf0) == 0xf0) && (peak[i+1] == 0x07)) {
+ dts_version = 3;
+ break;
}
syncword = (syncword << 8) | peak[i];
}
+ if (dts_version == -1) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ LOG_MODULE ": unsupported DTS stream type, or not a DTS stream\n");
+ return 0;
+ }
+
+ this->data_start = i-4;
+ lprintf("found DTS syncword at offset %d\n", i-4);
+
if (i < peak_size-9) {
unsigned int nblks, fsize, sfreq;
+ switch (dts_version)
+ {
+ case 0: /* BE16 */
+ nblks = ((peak[this->data_start+4] & 0x01) << 6) |
+ ((peak[this->data_start+5] & 0xfc) >> 2);
+ fsize = (((peak[this->data_start+5] & 0x03) << 12) |(peak[this->data_start+6] << 4) |
+ ((peak[this->data_start+7] & 0xf0) >> 4)) + 1;
+ sfreq = (peak[this->data_start+8] & 0x3c) >> 2;
+ break;
- /* 14 bits and little endian bitstream */
- nblks = ((peak[this->data_start+4] & 0x07) << 4) |
- ((peak[this->data_start+7] & 0x3c) >> 2);
- fsize = (((peak[this->data_start+7] & 0x03) << 12) |
- (peak[this->data_start+6] << 4) |
- ((peak[this->data_start+9] & 0x3c) >> 2)) + 1;
- sfreq = peak[this->data_start+8] & 0x0f;
+ case 3: /* LE14 */
+ nblks = ((peak[this->data_start+4] & 0x07) << 4) |
+ ((peak[this->data_start+7] & 0x3c) >> 2);
+ fsize = (((peak[this->data_start+7] & 0x03) << 12) |
+ (peak[this->data_start+6] << 4) |
+ ((peak[this->data_start+9] & 0x3c) >> 2)) + 1;
+ sfreq = peak[this->data_start+8] & 0x0f;
+ break;
+
+ }
if ((sfreq > sizeof(dts_sample_rates)/sizeof(int)) ||
(dts_sample_rates[sfreq] == 0))
@@ -170,7 +204,19 @@ static int open_dts_file(demux_dts_t *this) {
/* Big assumption - this is CBR data */
this->samples_per_frame = (nblks + 1) * 32;
- this->frame_size = fsize * 8 / 14 * 2;
+
+ switch (dts_version)
+ {
+ case 0: /* BE16 */
+ case 1: /* LE16 */
+ this->frame_size = fsize * 8 / 16 * 2;
+ break;
+ case 2: /* BE14 */
+ case 3: /* LE14 */
+ this->frame_size = fsize * 8 / 14 * 2;
+ break;
+ }
+
this->sample_rate = dts_sample_rates[sfreq];
lprintf("samples per frame: %d\n", this->samples_per_frame);
diff --git a/src/demuxers/demux_film.c b/src/demuxers/demux_film.c
index 193d8850b..f7b514e4b 100644
--- a/src/demuxers/demux_film.c
+++ b/src/demuxers/demux_film.c
@@ -260,6 +260,8 @@ static int open_film_file(demux_film_t *film) {
film->sample_count = _X_BE_32(&film_header[i + 12]);
film->sample_table =
xine_xcalloc(film->sample_count, sizeof(film_sample_t));
+ if (!film->sample_table)
+ goto film_abort;
for (j = 0; j < film->sample_count; j++) {
film->sample_table[j].sample_offset =
@@ -335,11 +337,14 @@ static int open_film_file(demux_film_t *film) {
free(film->interleave_buffer);
film->interleave_buffer =
xine_xmalloc(film->sample_table[0].sample_size);
+ if (!film->interleave_buffer)
+ goto film_abort;
}
break;
default:
xine_log(film->stream->xine, XINE_LOG_MSG, _("unrecognized FILM chunk\n"));
+ film_abort:
free (film->interleave_buffer);
free (film->sample_table);
free (film_header);
diff --git a/src/demuxers/demux_flac.c b/src/demuxers/demux_flac.c
index ed974a69c..94c599562 100644
--- a/src/demuxers/demux_flac.c
+++ b/src/demuxers/demux_flac.c
@@ -166,6 +166,8 @@ static int open_flac_file(demux_flac_t *flac) {
flac->seekpoint_count = block_length / FLAC_SEEKPOINT_SIZE;
flac->seekpoints = xine_xcalloc(flac->seekpoint_count,
sizeof(flac_seekpoint_t));
+ if (flac->seekpoint_count && !flac->seekpoints)
+ return 0;
for (i = 0; i < flac->seekpoint_count; i++) {
if (flac->input->read(flac->input, buffer, FLAC_SEEKPOINT_SIZE) != FLAC_SEEKPOINT_SIZE)
return 0;
diff --git a/src/demuxers/demux_flv.c b/src/demuxers/demux_flv.c
index 38855c027..e111468aa 100644
--- a/src/demuxers/demux_flv.c
+++ b/src/demuxers/demux_flv.c
@@ -85,7 +85,7 @@ typedef struct {
off_t filesize;
flv_index_entry_t *index;
- int num_indices;
+ unsigned int num_indices;
unsigned int cur_pts;
@@ -209,7 +209,7 @@ static int parse_flv_var(demux_flv_t *this,
unsigned char *end = buf + size;
char *str;
unsigned char type;
- int len, num;
+ unsigned int len, num;
if (size < 1)
return 0;
@@ -283,6 +283,8 @@ static int parse_flv_var(demux_flv_t *this,
str = tmp + 2;
tmp += len + 2;
len = parse_flv_var(this, tmp, end-tmp, str, len);
+ if (!len)
+ return 0;
tmp += len;
}
if (*tmp++ != FLV_DATA_TYPE_ENDOBJECT)
@@ -298,6 +300,8 @@ static int parse_flv_var(demux_flv_t *this,
str = tmp + 2;
tmp += len + 2;
len = parse_flv_var(this, tmp, end-tmp, str, len);
+ if (!len)
+ return 0;
tmp += len;
}
break;
@@ -310,6 +314,8 @@ static int parse_flv_var(demux_flv_t *this,
if (this->index)
free(this->index);
this->index = xine_xcalloc(num, sizeof(flv_index_entry_t));
+ if (!this->index)
+ return 0;
this->num_indices = num;
}
for (num = 0; num < this->num_indices && tmp < end; num++) {
@@ -326,6 +332,8 @@ static int parse_flv_var(demux_flv_t *this,
if (this->index)
free(this->index);
this->index = xine_xcalloc(num, sizeof(flv_index_entry_t));
+ if (!this->index)
+ return 0;
this->num_indices = num;
}
for (num = 0; num < this->num_indices && tmp < end; num++) {
@@ -339,6 +347,8 @@ static int parse_flv_var(demux_flv_t *this,
}
while (num-- && tmp < end) {
len = parse_flv_var(this, tmp, end-tmp, NULL, 0);
+ if (!len)
+ return 0;
tmp += len;
}
break;
@@ -360,7 +370,7 @@ static void parse_flv_script(demux_flv_t *this, int size) {
unsigned char *end = buf + size;
int len;
- if (this->input->read(this->input, buf, size ) != size) {
+ if (!buf || this->input->read(this->input, buf, size ) != size) {
this->status = DEMUX_FINISHED;
free(buf);
return;
diff --git a/src/demuxers/demux_iff.c b/src/demuxers/demux_iff.c
index 665d29cd2..dcef148b4 100644
--- a/src/demuxers/demux_iff.c
+++ b/src/demuxers/demux_iff.c
@@ -401,7 +401,7 @@ static int read_iff_chunk(demux_iff_t *this) {
this->cmap_num = junk_size / PIC_SIZE_OF_COLOR_REGISTER;
this->cmap = (ColorRegister *)xine_xmalloc(junk_size);
this->video_send_palette = 1;
- if (this->input->read(this->input, (char *)this->cmap, junk_size) != junk_size)
+ if (!this->cmap || this->input->read(this->input, (char *)this->cmap, junk_size) != junk_size)
return 0;
break;
case IFF_GRAB_CHUNK:
@@ -709,11 +709,19 @@ static int demux_iff_send_chunk(demux_plugin_t *this_gen) {
/* load the whole chunk into the buffer */
if (this->audio_buffer_filled == 0) {
if (this->audio_interleave_buffer_size > 0)
+ {
this->audio_interleave_buffer =
xine_xmalloc(this->audio_interleave_buffer_size);
+ if (!this->audio_interleave_buffer)
+ return this->status = DEMUX_FINISHED;
+ }
if (this->audio_read_buffer_size > 0)
+ {
this->audio_read_buffer =
xine_xmalloc(this->audio_read_buffer_size);
+ if (!this->audio_read_buffer)
+ return this->status = DEMUX_FINISHED;
+ }
if (this->audio_read_buffer) {
if (this->input->read(this->input, this->audio_read_buffer,
this->data_size) != this->data_size) {
diff --git a/src/demuxers/demux_ipmovie.c b/src/demuxers/demux_ipmovie.c
index 4d08af6fa..88fd70811 100644
--- a/src/demuxers/demux_ipmovie.c
+++ b/src/demuxers/demux_ipmovie.c
@@ -283,9 +283,10 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) {
this->bih.biWidth = _X_LE_16(&scratch[0]) * 8;
this->bih.biHeight = _X_LE_16(&scratch[2]) * 8;
/* set up staging area for decode map */
- this->decode_map_size = (this->bih.biWidth * this->bih.biHeight) /
- (8 * 8) / 2;
+ this->decode_map_size = (this->bih.biWidth / 8) * (this->bih.biHeight / 8) / 2;
this->decode_map = xine_xmalloc(this->decode_map_size);
+ if (!this->decode_map)
+ this->status = DEMUX_FINISHED;
lprintf("video resolution: %d x %d\n",
this->bih.biWidth, this->bih.biHeight);
break;
diff --git a/src/demuxers/demux_matroska.c b/src/demuxers/demux_matroska.c
index ec932aacb..713995e97 100644
--- a/src/demuxers/demux_matroska.c
+++ b/src/demuxers/demux_matroska.c
@@ -635,9 +635,7 @@ static void init_codec_xiph(demux_matroska_t *this, matroska_track_t *track) {
}
buf->size = frame[i];
- buf->decoder_flags = BUF_FLAG_HEADER;
- if (i == 2)
- buf->decoder_flags |= BUF_FLAG_FRAME_END;
+ buf->decoder_flags = BUF_FLAG_HEADER | BUF_FLAG_FRAME_START | BUF_FLAG_FRAME_END;
buf->type = track->buf_type;
buf->pts = 0;
@@ -1179,13 +1177,10 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) {
break;
case MATROSKA_ID_TR_CODECID: {
- char *codec_id = malloc (elem.len + 1);
+ char *codec_id = ebml_alloc_read_ascii (ebml, &elem);
lprintf("CodecID\n");
- if (!ebml_read_ascii(ebml, &elem, codec_id)) {
- free(codec_id);
+ if (!codec_id)
return 0;
- }
- codec_id[elem.len] = '\0';
track->codec_id = codec_id;
}
break;
@@ -1203,13 +1198,10 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) {
break;
case MATROSKA_ID_TR_LANGUAGE: {
- char *language = malloc (elem.len + 1);
+ char *language = ebml_alloc_read_ascii (ebml, &elem);
lprintf("Language\n");
- if (!ebml_read_ascii(ebml, &elem, language)) {
- free(language);
+ if (!language)
return 0;
- }
- language[elem.len] = '\0';
track->language = language;
}
break;
@@ -2893,7 +2885,8 @@ static void *init_class (xine_t *xine, void *data) {
this->demux_class.open_plugin = open_plugin;
this->demux_class.description = N_("matroska demux plugin");
this->demux_class.identifier = "matroska";
- this->demux_class.mimetypes = "video/mkv: mkv: matroska;";
+ this->demux_class.mimetypes = "video/mkv: mkv: matroska;"
+ "video/x-matroska: mkv: matroska;";
this->demux_class.extensions = "mkv";
this->demux_class.dispose = default_demux_class_dispose;
diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c
index ecd2c319a..b8e0acb12 100644
--- a/src/demuxers/demux_qt.c
+++ b/src/demuxers/demux_qt.c
@@ -746,8 +746,10 @@ static char *parse_data_atom(const uint8_t *data_atom) {
}
alloc_str = xine_xmalloc(alloc_size);
- xine_fast_memcpy(alloc_str, &data_atom[16], alloc_size-1);
- alloc_str[alloc_size-1] = '\0';
+ if (alloc_str) {
+ xine_fast_memcpy(alloc_str, &data_atom[16], alloc_size-1);
+ alloc_str[alloc_size-1] = '\0';
+ }
debug_meta_load("demux_qt: got a string of size %zd (%s)\n", alloc_size, alloc_str);
@@ -954,8 +956,8 @@ static qt_error parse_trak_atom (qt_trak *trak,
debug_atom_load(" qt elst atom (edit list atom): %d entries\n",
trak->edit_list_count);
- trak->edit_list_table = (edit_list_table_t *)xine_xmalloc(
- trak->edit_list_count * sizeof(edit_list_table_t));
+ trak->edit_list_table = (edit_list_table_t *)calloc(
+ trak->edit_list_count, sizeof(edit_list_table_t));
if (!trak->edit_list_table) {
last_error = QT_NO_MEMORY;
goto free_trak;
@@ -1023,6 +1025,10 @@ static qt_error parse_trak_atom (qt_trak *trak,
trak->stsd_atoms[k].video.properties_atom_size = current_stsd_atom_size - 4;
trak->stsd_atoms[k].video.properties_atom =
xine_xmalloc(trak->stsd_atoms[k].video.properties_atom_size);
+ if (!trak->stsd_atoms[k].video.properties_atom) {
+ last_error = QT_NO_MEMORY;
+ goto free_trak;
+ }
memcpy(trak->stsd_atoms[k].video.properties_atom, &trak_atom[atom_pos],
trak->stsd_atoms[k].video.properties_atom_size);
@@ -1162,6 +1168,10 @@ static qt_error parse_trak_atom (qt_trak *trak,
trak->stsd_atoms[k].audio.properties_atom_size = current_stsd_atom_size - 4;
trak->stsd_atoms[k].audio.properties_atom =
xine_xmalloc(trak->stsd_atoms[k].audio.properties_atom_size);
+ if (!trak->stsd_atoms[k].audio.properties_atom) {
+ last_error = QT_NO_MEMORY;
+ goto free_trak;
+ }
memcpy(trak->stsd_atoms[k].audio.properties_atom, &trak_atom[atom_pos],
trak->stsd_atoms[k].audio.properties_atom_size);
@@ -1278,6 +1288,10 @@ static qt_error parse_trak_atom (qt_trak *trak,
trak->stsd_atoms[k].audio.properties_atom_size = 36;
trak->stsd_atoms[k].audio.properties_atom =
xine_xmalloc(trak->stsd_atoms[k].audio.properties_atom_size);
+ if (!trak->stsd_atoms[k].audio.properties_atom) {
+ last_error = QT_NO_MEMORY;
+ goto free_trak;
+ }
memcpy(trak->stsd_atoms[k].audio.properties_atom,
&trak_atom[atom_pos + 0x20],
trak->stsd_atoms[k].audio.properties_atom_size);
@@ -1299,6 +1313,10 @@ static qt_error parse_trak_atom (qt_trak *trak,
(current_atom_size >= (0x4C + wave_size))) {
trak->stsd_atoms[k].audio.wave_size = wave_size;
trak->stsd_atoms[k].audio.wave = xine_xmalloc(wave_size);
+ if (!trak->stsd_atoms[k].audio.wave) {
+ last_error = QT_NO_MEMORY;
+ goto free_trak;
+ }
memcpy(trak->stsd_atoms[k].audio.wave, &trak_atom[atom_pos + 0x4C],
wave_size);
_x_waveformatex_le2me(trak->stsd_atoms[k].audio.wave);
@@ -1368,8 +1386,16 @@ static qt_error parse_trak_atom (qt_trak *trak,
j += mp4_read_descr_len( &trak_atom[j], &len );
debug_atom_load(" decoder config is %d (0x%X) bytes long\n",
len, len);
+ if (len > current_atom_size - (j - i)) {
+ last_error = QT_NOT_A_VALID_FILE;
+ goto free_trak;
+ }
trak->decoder_config = realloc(trak->decoder_config, len);
trak->decoder_config_len = len;
+ if (!trak->decoder_config) {
+ last_error = QT_NO_MEMORY;
+ goto free_trak;
+ }
memcpy(trak->decoder_config,&trak_atom[j],len);
}
}
@@ -1399,8 +1425,8 @@ static qt_error parse_trak_atom (qt_trak *trak,
/* allocate space and load table only if sample size is 0 */
if (trak->sample_size == 0) {
- trak->sample_size_table = (unsigned int *)malloc(
- trak->sample_size_count * sizeof(unsigned int));
+ trak->sample_size_table = (unsigned int *)calloc(
+ trak->sample_size_count, sizeof(unsigned int));
if (!trak->sample_size_table) {
last_error = QT_NO_MEMORY;
goto free_trak;
@@ -1430,8 +1456,8 @@ static qt_error parse_trak_atom (qt_trak *trak,
debug_atom_load(" qt stss atom (sample sync atom): %d sync samples\n",
trak->sync_sample_count);
- trak->sync_sample_table = (unsigned int *)malloc(
- trak->sync_sample_count * sizeof(unsigned int));
+ trak->sync_sample_table = (unsigned int *)calloc(
+ trak->sync_sample_count, sizeof(unsigned int));
if (!trak->sync_sample_table) {
last_error = QT_NO_MEMORY;
goto free_trak;
@@ -1614,6 +1640,9 @@ static qt_error parse_reference_atom (reference_t *ref,
size_t string_size = _X_BE_32(&ref_atom[i + 12]);
size_t url_offset = 0;
+ if (string_size >= current_atom_size || i + string_size >= ref_atom_size)
+ 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) &&
@@ -2054,8 +2083,12 @@ static void parse_moov_atom(qt_info *info, unsigned char *moov_atom,
info->references = (reference_t *)realloc(info->references,
info->reference_count * sizeof(reference_t));
- parse_reference_atom(&info->references[info->reference_count - 1],
- &moov_atom[i - 4], info->base_mrl);
+ error = parse_reference_atom(&info->references[info->reference_count - 1],
+ &moov_atom[i - 4], info->base_mrl);
+ if (error != QT_OK) {
+ info->last_error = error;
+ return;
+ }
break;
default:
diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c
index 41c6fb4a2..cc6a214e0 100644
--- a/src/demuxers/demux_real.c
+++ b/src/demuxers/demux_real.c
@@ -55,6 +55,8 @@
#include <xine/demux.h>
#include "bswap.h"
+#include "real_common.h"
+
#define FOURCC_TAG BE_FOURCC
#define RMF_TAG FOURCC_TAG('.', 'R', 'M', 'F')
#define PROP_TAG FOURCC_TAG('P', 'R', 'O', 'P')
@@ -113,6 +115,12 @@ typedef struct {
int index_entries;
mdpr_t *mdpr;
+ int sps, cfs, w, h;
+ int block_align;
+ int frame_size;
+ uint8_t *frame_buffer;
+ uint32_t frame_num_bytes;
+ uint32_t sub_packet_cnt;
} real_stream_t;
typedef struct {
@@ -168,14 +176,14 @@ typedef struct {
demux_class_t demux_class;
} demux_real_class_t;
-
static void real_parse_index(demux_real_t *this) {
off_t next_index_chunk = this->index_start;
off_t original_pos = this->input->get_current_pos(this->input);
unsigned char index_chunk_header[INDEX_CHUNK_HEADER_SIZE];
unsigned char index_record[INDEX_RECORD_SIZE];
- int i, entries, stream_num;
+ int i;
+ unsigned int entries, stream_num;
real_index_entry_t **index;
while(next_index_chunk) {
@@ -230,10 +238,11 @@ static void real_parse_index(demux_real_t *this) {
}
}
- if(index && entries) {
+ if(index && entries)
/* Allocate memory for index */
*index = xine_xcalloc(entries, sizeof(real_index_entry_t));
+ if(index && entries && *index) {
/* Read index */
for(i = 0; i < entries; i++) {
if(this->input->read(this->input, index_record, INDEX_RECORD_SIZE)
@@ -308,6 +317,64 @@ static void real_free_mdpr (mdpr_t *mdpr) {
free (mdpr);
}
+static void real_parse_audio_specific_data (demux_real_t *this,
+ real_stream_t * stream,
+ uint8_t * data, int len)
+{
+ int coded_frame_size;
+ int codec_data_length;
+ int coded_frame_size2;
+ int subpacket_size;
+
+ coded_frame_size = _X_BE_32 (data+24);
+ codec_data_length = _X_BE_16 (data+40);
+ coded_frame_size2 = _X_BE_16 (data+42);
+ subpacket_size = _X_BE_16 (data+44);
+
+ stream->sps = subpacket_size;
+ stream->w = coded_frame_size2;
+ stream->h = codec_data_length;
+ stream->block_align = coded_frame_size2;
+ stream->cfs = coded_frame_size;
+
+ switch (stream->buf_type) {
+ case BUF_AUDIO_COOK:
+ case BUF_AUDIO_ATRK:
+ stream->block_align = subpacket_size;
+ break;
+
+ case BUF_AUDIO_14_4:
+ break;
+
+ case BUF_AUDIO_28_8:
+ stream->block_align = stream->cfs;
+ break;
+
+ case BUF_AUDIO_SIPRO:
+ /* this->block_align = 19; */
+ break;
+
+ default:
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: error, i don't handle buf type 0x%08x\n", stream->buf_type);
+ }
+
+ if (stream->sps) {
+ stream->frame_size = stream->w / stream->sps * stream->h * stream->sps;
+ stream->frame_buffer = xine_xmalloc (stream->frame_size);
+ stream->frame_num_bytes = 0;
+ } else {
+ stream->frame_size = stream->w * stream->h;
+ stream->frame_buffer = xine_xmalloc (stream->frame_size);
+ stream->frame_num_bytes = 0;
+ }
+ stream->sub_packet_cnt = 0;
+
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ "demux_real: buf type 0x%08x frame size %dblock align %d\n", stream->buf_type,
+ stream->frame_size, stream->block_align);
+
+}
static void real_parse_headers (demux_real_t *this) {
@@ -418,8 +485,16 @@ static void real_parse_headers (demux_real_t *this) {
mdpr = real_parse_mdpr (chunk_buffer);
lprintf ("parsing type specific data...\n");
+ if(!strcmp(mdpr->mime_type, "audio/X-MP3-draft-00")) {
+ lprintf ("mpeg layer 3 audio detected...\n");
- if(_X_BE_32(mdpr->type_specific_data) == RA_TAG) {
+ fourcc = ME_FOURCC('a', 'd', 'u', 0x55);
+ this->audio_streams[this->num_audio_streams].fourcc = fourcc;
+ this->audio_streams[this->num_audio_streams].buf_type = _x_formattag_to_buf_audio(fourcc);
+ 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) {
int version, len;
if(this->num_audio_streams == MAX_AUDIO_STREAMS) {
@@ -457,6 +532,10 @@ 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;
+ real_parse_audio_specific_data (this,
+ &this->audio_streams[this->num_audio_streams],
+ mdpr->type_specific_data,
+ mdpr->type_specific_len);
this->num_audio_streams++;
if (!this->audio_streams[this->num_audio_streams].buf_type)
@@ -745,6 +824,13 @@ unknown:
memcpy(buf->content, mdpr->type_specific_data + 79,
buf->decoder_info[2]);
+ } else if(buf->type == BUF_AUDIO_MP3ADU) {
+ buf->decoder_flags |= BUF_FLAG_STDHEADER | BUF_FLAG_FRAME_END;
+ buf->size = 0;
+ buf->decoder_info[0] = 0;
+ buf->decoder_info[1] = 0;
+ buf->decoder_info[2] = 0;
+ buf->decoder_info[3] = 0;
} else {
memcpy(buf->content, mdpr->type_specific_data,
mdpr->type_specific_len);
@@ -983,6 +1069,7 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) {
off_t offset, input_length = 0;
int normpos = 0;
+ read_next_packet:
if(this->reference_mode)
return demux_real_parse_references(this);
@@ -1320,6 +1407,64 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) {
}
free(sizes);
+ } else if (this->audio_stream->buf_type == BUF_AUDIO_COOK ||
+ this->audio_stream->buf_type == BUF_AUDIO_ATRK ||
+ this->audio_stream->buf_type == BUF_AUDIO_28_8 ||
+ this->audio_stream->buf_type == BUF_AUDIO_SIPRO) {
+ /* reorder */
+ uint8_t * buffer = this->audio_stream->frame_buffer;
+ int sps = this->audio_stream->sps;
+ int sph = this->audio_stream->h;
+ int cfs = this->audio_stream->cfs;
+ int w = this->audio_stream->w;
+ int spc = this->audio_stream->sub_packet_cnt;
+ int x, pos;
+
+ switch (this->audio_stream->buf_type) {
+ case BUF_AUDIO_28_8:
+ for (x = 0; x < sph / 2; x++) {
+ pos = x * 2 * w + spc * cfs;
+ if(this->input->read(this->input, buffer + pos, cfs) < cfs) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: failed to read audio chunk\n");
+
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+ }
+ break;
+ case BUF_AUDIO_COOK:
+ case BUF_AUDIO_ATRK:
+ for (x = 0; x < w / sps; x++) {
+ pos = sps * (sph * x + ((sph + 1) / 2) * (spc & 1) + (spc >> 1));
+ if(this->input->read(this->input, buffer + pos, sps) < sps) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: failed to read audio chunk\n");
+
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+ }
+ break;
+ case BUF_AUDIO_SIPRO:
+ pos = spc * w;
+ if(this->input->read(this->input, buffer + pos, w) < w) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: failed to read audio chunk\n");
+
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+ if (spc == sph - 1)
+ demux_real_sipro_swap (buffer, sph * w * 2 / 96);
+ break;
+ }
+ if(++this->audio_stream->sub_packet_cnt == sph) {
+ this->audio_stream->sub_packet_cnt = 0;
+ _x_demux_send_data(this->audio_fifo, buffer, this->audio_stream->frame_size,
+ pts, this->audio_stream->buf_type, 0, normpos, input_time,
+ this->duration, 0);
+ }
} else {
if(_x_demux_read_send_data(this->audio_fifo, this->input, size, pts,
this->audio_stream->buf_type, 0, normpos,
@@ -1469,6 +1614,9 @@ static int demux_real_seek (demux_plugin_t *this_gen,
this->input->seek(this->input, index[i].offset, SEEK_SET);
if(playing) {
+ if(this->audio_stream)
+ this->audio_stream->sub_packet_cnt = 0;
+
this->buf_flag_seek = 1;
_x_demux_flush_engine(this->stream);
}
@@ -1505,6 +1653,7 @@ static void demux_real_dispose (demux_plugin_t *this_gen) {
for(i = 0; i < this->num_audio_streams; i++) {
real_free_mdpr(this->audio_streams[i].mdpr);
free(this->audio_streams[i].index);
+ free(this->audio_streams[i].frame_buffer);
}
free(this->fragment_tab);
diff --git a/src/demuxers/demux_realaudio.c b/src/demuxers/demux_realaudio.c
index 732ddfcc4..2873a522e 100644
--- a/src/demuxers/demux_realaudio.c
+++ b/src/demuxers/demux_realaudio.c
@@ -41,6 +41,8 @@
#include "bswap.h"
#include "group_audio.h"
+#include "real_common.h"
+
#define RA_FILE_HEADER_PREV_SIZE 22
typedef struct {
@@ -62,6 +64,10 @@ typedef struct {
off_t data_start;
off_t data_size;
+ int sps, cfs, w, h;
+ int frame_size;
+ uint8_t *frame_buffer;
+
unsigned char *header;
unsigned int header_size;
} demux_ra_t;
@@ -70,6 +76,9 @@ typedef struct {
demux_class_t demux_class;
} demux_ra_class_t;
+/* Map flavour to bytes per second */
+static int sipr_fl2bps[4] = {813, 1062, 625, 2000}; // 6.5, 8.5, 5, 16 kbit per second
+
/* returns 1 if the RealAudio file was opened successfully, 0 otherwise */
static int open_ra_file(demux_ra_t *this) {
unsigned char file_header[RA_FILE_HEADER_PREV_SIZE], len;
@@ -103,7 +112,7 @@ static int open_ra_file(demux_ra_t *this) {
/* allocate for and read header data */
this->header = xine_xmalloc(this->header_size);
- if (_x_demux_read_header(this->input, this->header, this->header_size) != this->header_size) {
+ if (!this->header || _x_demux_read_header(this->input, this->header, this->header_size) != this->header_size) {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: unable to read header\n");
free(this->header);
return 0;
@@ -165,20 +174,41 @@ static int open_ra_file(demux_ra_t *this) {
offset++;
/* Fourcc for version 3 comes after meta info */
- if((version == 3) && ((offset+7) <= this->header_size)) {
- if(this->header[offset+2] == 4)
- this->fourcc = _X_ME_32(&this->header[offset+3]);
- else {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_realaudio: invalid fourcc size %d\n", this->header[offset+2]);
- free(this->header);
- return 0;
+ if(version == 3) {
+ if (((offset+7) <= this->header_size)) {
+ if(this->header[offset+2] == 4)
+ this->fourcc = _X_ME_32(&this->header[offset+3]);
+ else {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_realaudio: invalid fourcc size %d\n", this->header[offset+2]);
+ free(this->header);
+ return 0;
+ }
+ } else {
+ this->fourcc = ME_FOURCC('l', 'p', 'c', 'J');
}
}
_x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, this->fourcc);
this->audio_type = _x_formattag_to_buf_audio(this->fourcc);
+ if (version == 4) {
+ this->sps = _X_BE_16 (this->header+44);
+ this->w = _X_BE_16 (this->header+42);
+ this->h = _X_BE_16 (this->header+40);
+ this->cfs = _X_BE_32 (this->header+24);
+ if (this->sps) {
+ this->frame_size = this->sps * this->h * this->sps;
+ this->frame_buffer = xine_xmalloc (this->frame_size);
+ } else {
+ this->frame_size = this->w * this->h;
+ this->frame_buffer = xine_xmalloc (this->frame_size);
+ }
+
+ if (this->audio_type == BUF_AUDIO_28_8 || this->audio_type == BUF_AUDIO_SIPRO)
+ this->block_align = this->cfs;
+ }
+
/* seek to start of data */
this->data_start = this->header_size;
if (this->input->seek(this->input, this->data_start, SEEK_SET) !=
@@ -212,7 +242,45 @@ static int demux_ra_send_chunk(demux_plugin_t *this_gen) {
this->seek_flag = 0;
}
- if(_x_demux_read_send_data(this->audio_fifo, this->input, this->block_align,
+ if (this->audio_type == BUF_AUDIO_28_8 || this->audio_type == BUF_AUDIO_SIPRO) {
+ int x;
+ uint8_t * buffer;
+
+ buffer = this->frame_buffer;
+ if (this->audio_type == BUF_AUDIO_SIPRO) {
+ int n;
+ int len = this->h * this->w;
+ if(this->input->read(this->input, this->frame_buffer, len) < len) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_realaudio: failed to read audio chunk\n");
+
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+ demux_real_sipro_swap (this->frame_buffer, len * 2 / 96);
+ } else {
+ int x, y;
+ int pos;
+
+ for (y = 0; y < this->h; y++)
+ for (x = 0; x < this->h / 2; x++) {
+ pos = x * 2 * this->w + y * this->cfs;
+ if(this->input->read(this->input, this->frame_buffer + pos,
+ this->cfs) < this->cfs) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_realaudio: failed to read audio chunk\n");
+
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+ }
+ }
+
+ _x_demux_send_data(this->audio_fifo,
+ buffer, this->frame_size,
+ current_pts, this->audio_type, 0,
+ current_normpos, current_pts / 90, 0, 0);
+ } else if(_x_demux_read_send_data(this->audio_fifo, this->input, this->block_align,
current_pts, this->audio_type, 0, current_normpos,
current_pts / 90, 0, 0) < 0) {
this->status = DEMUX_FINISHED;
@@ -298,6 +366,7 @@ static void demux_ra_dispose (demux_plugin_t *this_gen) {
demux_ra_t *this = (demux_ra_t *) this_gen;
free(this->header);
+ free(this->frame_buffer);
free(this);
}
@@ -329,6 +398,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
this = xine_xmalloc (sizeof (demux_ra_t));
this->stream = stream;
this->input = input;
+ this->frame_buffer = NULL;
this->demux_plugin.send_headers = demux_ra_send_headers;
this->demux_plugin.send_chunk = demux_ra_send_chunk;
diff --git a/src/demuxers/demux_vmd.c b/src/demuxers/demux_vmd.c
index c2902eac1..d1d98f534 100644
--- a/src/demuxers/demux_vmd.c
+++ b/src/demuxers/demux_vmd.c
@@ -168,7 +168,7 @@ static int open_vmd_file(demux_vmd_t *this) {
return 0;
}
- this->frame_table = xine_xmalloc(this->frame_count * sizeof(vmd_frame_t));
+ this->frame_table = calloc(this->frame_count, sizeof(vmd_frame_t));
current_offset = this->data_start = _X_LE_32(&vmd_header[20]);
this->data_size = toc_offset - this->data_start;
diff --git a/src/demuxers/demux_wav.c b/src/demuxers/demux_wav.c
index b8f0d0194..2beb43291 100644
--- a/src/demuxers/demux_wav.c
+++ b/src/demuxers/demux_wav.c
@@ -41,9 +41,11 @@
#include "bswap.h"
#include "group_audio.h"
-#define WAV_SIGNATURE_SIZE 16
+#define WAV_SIGNATURE_SIZE 12
/* this is the hex value for 'data' */
#define data_TAG 0x61746164
+/* this is the hex value for 'fmt ' */
+#define fmt_TAG 0x20746D66
#define PCM_BLOCK_ALIGN 1024
#define PREFERED_BLOCK_SIZE 4096
@@ -73,31 +75,63 @@ typedef struct {
static int demux_wav_get_stream_length (demux_plugin_t *this_gen);
+/* searches for the chunk with the given tag from the beginning of WAV file
+ * returns 1 if chunk was found, 0 otherwise,
+ * fills chunk_size and chunk_pos if chunk was found
+ * NOTE: chunk_pos is set to the position of the first byte of chunk data */
+static int find_chunk_by_tag(demux_wav_t *this, const uint32_t given_chunk_tag,
+ uint32_t *found_chunk_size, off_t *found_chunk_pos) {
+ uint32_t chunk_tag;
+ uint32_t chunk_size;
+ uint8_t chunk_preamble[8];
+
+ /* search for the chunks from the start of the WAV file */
+ this->input->seek(this->input, WAV_SIGNATURE_SIZE, SEEK_SET);
+
+ while (1) {
+ if (this->input->read(this->input, chunk_preamble, 8) != 8) {
+ return 0;
+ }
+
+ chunk_tag = _X_LE_32(&chunk_preamble[0]);
+ chunk_size = _X_LE_32(&chunk_preamble[4]);
+
+ if (chunk_tag == given_chunk_tag) {
+ if (found_chunk_size)
+ *found_chunk_size = _X_LE_32(&chunk_preamble[4]);
+ if (found_chunk_pos)
+ *found_chunk_pos = this->input->get_current_pos(this->input);
+ return 1;
+ } else {
+ this->input->seek(this->input, chunk_size, SEEK_CUR);
+ }
+ }
+}
+
/* returns 1 if the WAV file was opened successfully, 0 otherwise */
static int open_wav_file(demux_wav_t *this) {
uint8_t signature[WAV_SIGNATURE_SIZE];
uint32_t chunk_tag;
uint32_t chunk_size;
uint8_t chunk_preamble[8];
+ off_t wave_pos;
/* check the signature */
if (_x_demux_read_header(this->input, signature, WAV_SIGNATURE_SIZE) != WAV_SIGNATURE_SIZE)
return 0;
- if (memcmp(signature, "RIFF", 4) || memcmp(&signature[8], "WAVEfmt ", 8) )
+ if (memcmp(signature, "RIFF", 4) || memcmp(&signature[8], "WAVE", 4) )
return 0;
- /* file is qualified; skip over the header bytes in the stream */
- this->input->seek(this->input, WAV_SIGNATURE_SIZE, SEEK_SET);
-
- /* go after the format structure */
- if (this->input->read(this->input,
- (unsigned char *)&this->wave_size, 4) != 4)
+ /* search for the 'fmt ' chunk first */
+ wave_pos = 0;
+ if (find_chunk_by_tag(this, fmt_TAG, &this->wave_size, &wave_pos)==0)
return 0;
- this->wave_size = le2me_32(this->wave_size);
+
+ this->input->seek(this->input, wave_pos, SEEK_SET);
this->wave = xine_xmalloc( this->wave_size );
-
- if (this->input->read(this->input, (void *)this->wave, this->wave_size) !=
+
+ if (!this->wave || this->input->read(this->input, (void *)this->wave, this->wave_size) !=
this->wave_size) {
free (this->wave);
return 0;
@@ -113,28 +147,21 @@ static int open_wav_file(demux_wav_t *this) {
return 0;
}
- /* traverse through the chunks to find the 'data' chunk */
+ /* search for the 'data' chunk */
this->data_start = this->data_size = 0;
- while (this->data_start == 0) {
-
- if (this->input->read(this->input, chunk_preamble, 8) != 8) {
- free (this->wave);
- return 0;
- }
- chunk_tag = _X_LE_32(&chunk_preamble[0]);
- chunk_size = _X_LE_32(&chunk_preamble[4]);
-
- if (chunk_tag == data_TAG) {
- this->data_start = this->input->get_current_pos(this->input);
- /* Get the data length from the file itself, instead of the data
- * TAG, for broken files */
- this->data_size = this->input->get_length(this->input);
- } else {
- this->input->seek(this->input, chunk_size, SEEK_CUR);
- }
+ if (find_chunk_by_tag(this, data_TAG, &this->data_size, &this->data_start)==0)
+ {
+ free (this->wave);
+ return 0;
+ }
+ else
+ {
+ /* Get the data length from the file itself, instead of the data
+ * TAG, for broken files */
+ this->input->seek(this->input, this->data_start, SEEK_SET);
+ this->data_size = this->input->get_length(this->input);
+ return 1;
}
-
- return 1;
}
static int demux_wav_send_chunk(demux_plugin_t *this_gen) {
diff --git a/src/demuxers/demux_wc3movie.c b/src/demuxers/demux_wc3movie.c
index bb9a40306..5be59b12b 100644
--- a/src/demuxers/demux_wc3movie.c
+++ b/src/demuxers/demux_wc3movie.c
@@ -387,6 +387,12 @@ static int open_mve_file(demux_mve_t *this) {
/* load the palette chunks */
this->palettes = xine_xcalloc(this->number_of_shots, PALETTE_SIZE *
sizeof(palette_entry_t));
+
+ if (!this->shot_offsets || !this->palettes) {
+ free (this->shot_offsets);
+ return 0;
+ }
+
for (i = 0; i < this->number_of_shots; i++) {
/* make sure there was a valid palette chunk preamble */
if (this->input->read(this->input, preamble, PREAMBLE_SIZE) !=
@@ -458,8 +464,9 @@ static int open_mve_file(demux_mve_t *this) {
case BNAM_TAG:
/* load the name into the stream attributes */
- title = realloc (title, chunk_size);
- if (this->input->read(this->input, title, chunk_size) != chunk_size) {
+ free (title);
+ title = malloc (chunk_size);
+ if (!title || this->input->read(this->input, title, chunk_size) != chunk_size) {
free (title);
free (this->palettes);
free (this->shot_offsets);
diff --git a/src/demuxers/ebml.c b/src/demuxers/ebml.c
index 41a91371e..1e9a456d2 100644
--- a/src/demuxers/ebml.c
+++ b/src/demuxers/ebml.c
@@ -310,7 +310,25 @@ int ebml_read_ascii(ebml_parser_t *ebml, ebml_elem_t *elem, char *str) {
int ebml_read_utf8 (ebml_parser_t *ebml, ebml_elem_t *elem, char *str) {
return ebml_read_ascii (ebml, elem, str);
}
+#endif
+
+char *ebml_alloc_read_ascii (ebml_parser_t *ebml, ebml_elem_t *elem)
+{
+ char *text;
+ if (elem->len >= 4096)
+ return NULL;
+ text = malloc(elem->len + 1);
+ if (text)
+ {
+ text[elem->len] = '\0';
+ if (ebml_read_ascii (ebml, elem, text))
+ return text;
+ free (text);
+ }
+ return NULL;
+}
+#if 0
int ebml_read_date (ebml_parser_t *ebml, ebml_elem_t *elem, int64_t *date) {
return ebml_read_sint (ebml, elem, date);
}
@@ -414,10 +432,8 @@ int ebml_check_header(ebml_parser_t *ebml) {
}
case EBML_ID_DOCTYPE: {
- char *text = malloc(elem.len + 1);
-
- text[elem.len] = '\0';
- if (!ebml_read_ascii (ebml, &elem, text))
+ char *text = ebml_alloc_read_ascii (ebml, &elem);
+ if (!text)
return 0;
lprintf("doctype: %s\n", text);
diff --git a/src/demuxers/ebml.h b/src/demuxers/ebml.h
index 31d825e35..a090bb130 100644
--- a/src/demuxers/ebml.h
+++ b/src/demuxers/ebml.h
@@ -93,7 +93,11 @@ int ebml_read_ascii(ebml_parser_t *ebml, ebml_elem_t *elem, char *str);
#if 0
int ebml_read_utf8(ebml_parser_t *ebml, ebml_elem_t *elem, char *str);
+#endif
+
+char *ebml_alloc_read_ascii(ebml_parser_t *ebml, ebml_elem_t *elem);
+#if 0
int ebml_read_date(ebml_parser_t *ebml, ebml_elem_t *elem, int64_t *date);
#endif
diff --git a/src/demuxers/real_common.h b/src/demuxers/real_common.h
new file mode 100644
index 000000000..4945a65ff
--- /dev/null
+++ b/src/demuxers/real_common.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 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
+ */
+
+static inline void demux_real_sipro_swap (char buffer[], int bs)
+{
+ /* bs = nybbles per subpacket */
+ static const unsigned char sipr_swaps[38][2] = {
+ {0, 63}, {1, 22}, {2, 44}, {3, 90}, {5, 81}, {7, 31}, {8, 86}, {9, 58},
+ {10, 36}, {12, 68}, {13, 39}, {14, 73}, {15, 53}, {16, 69}, {17, 57},
+ {19, 88}, {20, 34}, {21, 71}, {24, 46}, {25, 94}, {26, 54}, {28, 75},
+ {29, 50}, {32, 70}, {33, 92}, {35, 74}, {38, 85}, {40, 56}, {42, 87},
+ {43, 65}, {45, 59}, {48, 79}, {49, 93}, {51, 89}, {55, 95}, {61, 76},
+ {67, 83}, {77, 80}
+ };
+ int n;
+
+ for (n = 0; n < 38; ++n)
+ {
+ int j;
+ int i = bs * sipr_swaps[n][0];
+ int o = bs * sipr_swaps[n][1];
+ /* swap nibbles of block 'i' with 'o' TODO: optimize */
+ for (j = 0; j < bs; ++j)
+ {
+ int x = (i & 1) ? (buffer[i >> 1] >> 4) : (buffer[i >> 1] & 0x0F);
+ int y = (o & 1) ? (buffer[o >> 1] >> 4) : (buffer[o >> 1] & 0x0F);
+ if (o & 1)
+ buffer[o >> 1] = (buffer[o >> 1] & 0x0F) | (x << 4);
+ else
+ buffer[o >> 1] = (buffer[o >> 1] & 0xF0) | x;
+ if (i & 1)
+ buffer[i >> 1] = (buffer[i >> 1] & 0x0F) | (y << 4);
+ else
+ buffer[i >> 1] = (buffer[i >> 1] & 0xF0) | y;
+ ++i;
+ ++o;
+ }
+ }
+}
diff --git a/src/input/libdvdnav/dvd_reader.c b/src/input/libdvdnav/dvd_reader.c
index c15a5c3f5..4144b9133 100644
--- a/src/input/libdvdnav/dvd_reader.c
+++ b/src/input/libdvdnav/dvd_reader.c
@@ -1037,6 +1037,28 @@ int32_t DVDFileSeek( dvd_file_t *dvd_file, int32_t offset )
return offset;
}
+int32_t DVDFileSeekForce( dvd_file_t *dvd_file, int offset, int force_size )
+{
+ /* Check arguments. */
+ if( dvd_file == NULL || offset < 0 )
+ return -1;
+
+ if( dvd_file->dvd->isImageFile ) {
+ if( force_size < 0 )
+ force_size = (offset - 1) / DVD_VIDEO_LB_LEN + 1;
+ if( dvd_file->filesize < force_size) {
+ dvd_file->filesize = force_size;
+ fprintf(stderr, "libdvdread: Ignored UDF provided size of file.\n");
+ }
+ }
+
+ if( offset > dvd_file->filesize * DVD_VIDEO_LB_LEN ) {
+ return -1;
+ }
+ dvd_file->seek_pos = (uint32_t) offset;
+ return offset;
+}
+
ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
{
unsigned char *secbuf_base, *secbuf;
@@ -1077,7 +1099,7 @@ ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
memcpy( data, &(secbuf[ seek_byte ]), byte_size );
free( secbuf_base );
- dvd_file->seek_pos += byte_size;
+ DVDFileSeekForce(dvd_file, dvd_file->seek_pos + byte_size, -1);
return byte_size;
}
diff --git a/src/input/libdvdnav/dvd_reader.h b/src/input/libdvdnav/dvd_reader.h
index bb3f5053b..e1b051c00 100644
--- a/src/input/libdvdnav/dvd_reader.h
+++ b/src/input/libdvdnav/dvd_reader.h
@@ -171,6 +171,8 @@ ssize_t DVDReadBlocks( dvd_file_t *, int, size_t, unsigned char * );
*/
int32_t DVDFileSeek( dvd_file_t *, int32_t );
+int32_t DVDFileSeekForce( dvd_file_t *, int, int );
+
/**
* Reads the given number of bytes from the file. This call can only be used
* on the information files, and may not be used for reading from a VOB. This
diff --git a/src/input/libdvdnav/ifo_read.c b/src/input/libdvdnav/ifo_read.c
index 8f47d2a54..bc1ba580b 100644
--- a/src/input/libdvdnav/ifo_read.c
+++ b/src/input/libdvdnav/ifo_read.c
@@ -93,6 +93,10 @@ static inline int DVDFileSeek_( dvd_file_t *dvd_file, uint32_t offset ) {
return (DVDFileSeek(dvd_file, (int)offset) == (int)offset);
}
+static inline int32_t DVDFileSeekForce_( dvd_file_t *dvd_file, uint32_t offset, int force_size ) {
+ return (DVDFileSeekForce(dvd_file, (int)offset, force_size) == (int)offset);
+}
+
ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title) {
ifo_handle_t *ifofile;
@@ -1507,7 +1511,7 @@ static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile,
unsigned int i;
int info_length;
- if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN))
+ if(!DVDFileSeekForce_(ifofile->file, sector * DVD_BLOCK_LEN, sector))
return 0;
if(!(DVDReadBytes(ifofile->file, vobu_admap, VOBU_ADMAP_SIZE)))
diff --git a/src/input/libreal/sdpplin.c b/src/input/libreal/sdpplin.c
index fbc64957b..4ef8f5f03 100644
--- a/src/input/libreal/sdpplin.c
+++ b/src/input/libreal/sdpplin.c
@@ -84,7 +84,14 @@ static sdpplin_stream_t *sdpplin_parse_stream(char **data) {
handled=0;
if(filter(*data,"a=control:streamid=",&buf)) {
- desc->stream_id=atoi(buf);
+ /* This way negative values are mapped to unfeasibly high
+ * values, and will be discarded afterward
+ */
+ unsigned long tmp = strtoul(buf, NULL, 10);
+ if ( tmp > UINT16_MAX )
+ lprintf("stream id out of bound: %lu\n", tmp);
+ else
+ desc->stream_id=tmp;
handled=1;
*data=nl(*data);
}
@@ -192,7 +199,10 @@ sdpplin_t *sdpplin_parse(char *data) {
}
stream=sdpplin_parse_stream(&data);
lprintf("got data for stream id %u\n", stream->stream_id);
- desc->stream[stream->stream_id]=stream;
+ if ( stream->stream_id >= desc->stream_count )
+ lprintf("stream id %u is greater than stream count %u\n", stream->stream_id, desc->stream_count);
+ else
+ desc->stream[stream->stream_id]=stream;
continue;
}
@@ -233,7 +243,14 @@ sdpplin_t *sdpplin_parse(char *data) {
}
if(filter(data,"a=StreamCount:integer;",&buf)) {
- desc->stream_count=atoi(buf);
+ /* This way negative values are mapped to unfeasibly high
+ * values, and will be discarded afterward
+ */
+ unsigned long tmp = strtoul(buf, NULL, 10);
+ if ( tmp > UINT16_MAX )
+ lprintf("stream count out of bound: %lu\n", tmp);
+ else
+ desc->stream_count = tmp;
desc->stream = calloc(desc->stream_count, sizeof(sdpplin_stream_t*));
handled=1;
data=nl(data);
diff --git a/src/input/libreal/sdpplin.h b/src/input/libreal/sdpplin.h
index cb3b434d4..72cbaf731 100644
--- a/src/input/libreal/sdpplin.h
+++ b/src/input/libreal/sdpplin.h
@@ -37,7 +37,7 @@ typedef struct {
char *id;
char *bandwidth;
- int stream_id;
+ uint16_t stream_id;
char *range;
char *length;
char *rtpmap;
@@ -81,7 +81,7 @@ typedef struct {
int flags;
int is_real_data_type;
- int stream_count;
+ uint16_t stream_count;
char *title;
char *author;
char *copyright;
diff --git a/src/libreal/xine_real_audio_decoder.c b/src/libreal/xine_real_audio_decoder.c
index b9231a2b7..a12518c1e 100644
--- a/src/libreal/xine_real_audio_decoder.c
+++ b/src/libreal/xine_real_audio_decoder.c
@@ -51,6 +51,8 @@ typedef struct {
/* empty so far */
} real_class_t;
+typedef void * ra_codec_t;
+
typedef struct realdec_decoder_s {
audio_decoder_t audio_decoder;
@@ -60,18 +62,18 @@ typedef struct realdec_decoder_s {
void *ra_handle;
- unsigned long (*raCloseCodec)(void*);
- unsigned long (*raDecode)(void*, char*,unsigned long,char*,unsigned int*,long);
- unsigned long (*raFlush)(unsigned long,unsigned long,unsigned long);
- unsigned long (*raFreeDecoder)(void*);
- void* (*raGetFlavorProperty)(void*,unsigned long,unsigned long,int*);
- unsigned long (*raInitDecoder)(void*, void*);
- unsigned long (*raOpenCodec2)(void*);
- unsigned long (*raSetFlavor)(void*,unsigned long);
- void (*raSetDLLAccessPath)(char*);
- void (*raSetPwd)(char*,char*);
+ uint32_t (*raCloseCodec)(ra_codec_t);
+ uint32_t (*raDecode)(ra_codec_t, char *, uint32_t, char *, uint32_t *, uint32_t);
+ uint32_t (*raFlush)(ra_codec_t, char *, uint32_t *);
+ uint32_t (*raFreeDecoder)(ra_codec_t);
+ void * (*raGetFlavorProperty)(ra_codec_t, uint16_t, uint16_t, uint16_t *);
+ uint32_t (*raInitDecoder)(ra_codec_t, void *);
+ uint32_t (*raOpenCodec2)(ra_codec_t *, const char *);
+ uint32_t (*raSetFlavor)(ra_codec_t, uint16_t);
+ void (*raSetDLLAccessPath)(char *);
+ void (*raSetPwd)(ra_codec_t, char *);
- void *context;
+ ra_codec_t context;
int sps, w, h;
int block_align;
@@ -92,14 +94,14 @@ typedef struct realdec_decoder_s {
} realdec_decoder_t;
typedef struct {
- int samplerate;
- short bits;
- short channels;
- int unk1;
- int subpacket_size;
- int coded_frame_size;
- int codec_data_length;
- void *extras;
+ uint32_t samplerate;
+ uint16_t bits;
+ uint16_t channels;
+ uint16_t quality;
+ uint32_t subpacket_size;
+ uint32_t coded_frame_size;
+ uint32_t codec_data_length;
+ void *extras;
} ra_init_t;
static int load_syms_linux (realdec_decoder_t *this, const char *const codec_name, const char *const codec_alternate) {
@@ -216,13 +218,14 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) {
_x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Cook");
if (!load_syms_linux (this, "cook.so", "cook.so.6.0"))
return 0;
+ this->block_align = subpacket_size;
break;
case BUF_AUDIO_ATRK:
_x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Atrac");
if (!load_syms_linux (this, "atrc.so", "atrc.so.6.0"))
return 0;
- this->block_align = 384;
+ this->block_align = subpacket_size;
break;
case BUF_AUDIO_14_4:
@@ -254,7 +257,7 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) {
* init codec
*/
- result = this->raOpenCodec2 (&this->context);
+ result = this->raOpenCodec2 (&this->context, NULL);
if (result) {
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "libareal: error in raOpenCodec2: %d\n", result);
return 0;
@@ -266,7 +269,7 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) {
init_data.samplerate = samples_per_sec;
init_data.bits = bits_per_sample;
init_data.channels = num_channels;
- init_data.unk1 = 100; /* ??? */
+ init_data.quality = 100; /* ??? */
init_data.subpacket_size = subpacket_size; /* subpacket size */
init_data.coded_frame_size = coded_frame_size; /* coded frame size */
init_data.codec_data_length = data_len; /* codec data length */
@@ -350,13 +353,6 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) {
return 1;
}
-static const unsigned char sipr_swaps[38][2]={
- {0,63},{1,22},{2,44},{3,90},{5,81},{7,31},{8,86},{9,58},{10,36},{12,68},
- {13,39},{14,73},{15,53},{16,69},{17,57},{19,88},{20,34},{21,71},{24,46},
- {25,94},{26,54},{28,75},{29,50},{32,70},{33,92},{35,74},{38,85},{40,56},
- {42,87},{43,65},{45,59},{48,79},{49,93},{51,89},{55,95},{61,76},{67,83},
- {77,80} };
-
static void realdec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
realdec_decoder_t *this = (realdec_decoder_t *) this_gen;
@@ -383,116 +379,32 @@ static void realdec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf)
this->pts = buf->pts;
size = buf->size;
-
while (size) {
+ int need;
- int needed;
-
- needed = this->frame_size - this->frame_num_bytes;
-
- if (needed>size) {
-
- memcpy (this->frame_buffer+this->frame_num_bytes, buf->content, size);
+ need = this->frame_size - this->frame_num_bytes;
+ if (size < need) {
+ memcpy (this->frame_buffer + this->frame_num_bytes,
+ buf->content + buf->size - size, size);
this->frame_num_bytes += size;
-
- lprintf ("buffering %d/%d bytes\n", this->frame_num_bytes, this->frame_size);
-
size = 0;
-
} else {
-
- int result;
- int len =-1;
- int n;
- int sps = this->sps;
- int w = this->w;
- int h = this->h;
audio_buffer_t *audio_buffer;
+ int n, len;
+ int result;
- lprintf ("buffering %d bytes\n", needed);
-
- memcpy (this->frame_buffer+this->frame_num_bytes, buf->content, needed);
-
- size -= needed;
+ memcpy (this->frame_buffer + this->frame_num_bytes,
+ buf->content + buf->size - size, need);
+ size -= need;
this->frame_num_bytes = 0;
- lprintf ("frame completed. reordering...\n");
- lprintf ("bs=%d sps=%d w=%d h=%d \n",/*sh->wf->nBlockAlign*/-1,sps,w,h);
-
- if (!sps) {
-
- int j,n;
- int bs=h*w*2/96; /* nibbles per subpacket */
- unsigned char *p=this->frame_buffer;
-
- /* 'sipr' way */
- /* demux_read_data(sh->ds, p, h*w); */
- for (n=0;n<38;n++){
- int i=bs*sipr_swaps[n][0];
- int o=bs*sipr_swaps[n][1];
- /* swap nibbles of block 'i' with 'o' TODO: optimize */
- for (j=0;j<bs;j++) {
- int x=(i&1) ? (p[(i>>1)]>>4) : (p[(i>>1)]&15);
- int y=(o&1) ? (p[(o>>1)]>>4) : (p[(o>>1)]&15);
- if (o&1)
- p[(o>>1)]=(p[(o>>1)]&0x0F)|(x<<4);
- else
- p[(o>>1)]=(p[(o>>1)]&0xF0)|x;
-
- if (i&1)
- p[(i>>1)]=(p[(i>>1)]&0x0F)|(y<<4);
- else
- p[(i>>1)]=(p[(i>>1)]&0xF0)|y;
-
- ++i;
- ++o;
- }
- }
- /*
- sh->a_in_buffer_size=
- sh->a_in_buffer_len=w*h;
- */
-
- } else {
- int x, y;
- uint8_t *s;
-
- /* 'cook' way */
-
- w /= sps; s = this->frame_buffer;
-
- for (y=0; y<h; y++)
-
- for (x=0; x<w; x++) {
-
- lprintf ("x=%d, y=%d, off %d\n",
- x, y, sps*(h*x+((h+1)/2)*(y&1)+(y>>1)));
-
- memcpy (this->frame_reordered+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)),
- s, sps);
- s+=sps;
-
- /* demux_read_data(sh->ds, sh->a_in_buffer+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)),
- sps); */
-
- }
- /*
- sh->a_in_buffer_size=
- sh->a_in_buffer_len=w*h*sps;
- */
- }
-
-#ifdef LOG
- xine_hexdump (this->frame_reordered, buf->size);
-#endif
-
n = 0;
- while (n<this->frame_size) {
+ while (n < this->frame_size) {
audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out);
result = this->raDecode (this->context,
- this->frame_reordered+n,
+ this->frame_buffer + n,
this->block_align,
(char *) audio_buffer->mem, &len, -1);
@@ -506,7 +418,7 @@ static void realdec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf)
this->stream->audio_out->put_buffer (this->stream->audio_out,
audio_buffer, this->stream);
- n+=this->block_align;
+ n += this->block_align;
}
}
}
@@ -609,5 +521,5 @@ static const uint32_t audio_types[] = {
const decoder_info_t dec_info_realaudio = {
audio_types, /* supported types */
- 7 /* priority */
+ 6 /* priority */
};
diff --git a/src/libreal/xine_real_video_decoder.c b/src/libreal/xine_real_video_decoder.c
index 28fddafda..2b5eafa16 100644
--- a/src/libreal/xine_real_video_decoder.c
+++ b/src/libreal/xine_real_video_decoder.c
@@ -63,9 +63,9 @@ typedef struct realdec_decoder_s {
uint32_t (*rvyuv_custom_message)(void*, void*);
uint32_t (*rvyuv_free)(void*);
- uint32_t (*rvyuv_hive_message)(uint32_t, uint32_t);
+ uint32_t (*rvyuv_hive_message)(uint32_t, void*);
uint32_t (*rvyuv_init)(void*, void*); /* initdata,context */
- uint32_t (*rvyuv_transform)(char*, char*, void*, uint32_t*,void*);
+ uint32_t (*rvyuv_transform)(char*, char*, void*, void*, void*);
void *context;
@@ -113,13 +113,21 @@ typedef struct cmsg_data_s {
typedef struct transform_in_s {
uint32_t len;
- uint32_t unknown1;
- uint32_t chunks;
- uint32_t* extra;
- uint32_t unknown2;
+ uint32_t interpolate;
+ uint32_t nsegments;
+ void *segments;
+ uint32_t flags;
uint32_t timestamp;
} transform_in_t;
+typedef struct {
+ uint32_t frames;
+ uint32_t notes;
+ uint32_t timestamp;
+ uint32_t width;
+ uint32_t height;
+} transform_out_t;
+
/*
* real codec loader
*/
@@ -169,7 +177,6 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) {
int result;
rv_init_t init_data = {11, 0, 0, 0, 0, 0, 1, 0}; /* rv30 */
-
switch (buf->type) {
case BUF_VIDEO_RV20:
_x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "Real Video 2.0");
@@ -258,7 +265,7 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) {
#ifdef LOG
printf ("libreal: CustomMessage cmsg_data:\n");
- xine_hexdump ((uint8_t *) cmsg_data, sizeof (cmsg_data));
+ xine_hexdump ((uint8_t *) &cmsg_data, sizeof (cmsg_data));
printf ("libreal: cmsg24:\n");
xine_hexdump ((uint8_t *) cmsg24, (buf->size - 34 + 2) * sizeof(uint32_t));
#endif
@@ -342,7 +349,7 @@ static void realdec_decode_data (video_decoder_t *this_gen, buf_element_t *buf)
int result;
vo_frame_t *img;
- uint32_t transform_out[5];
+ transform_out_t transform_out;
transform_in_t transform_in = {
this->chunk_buffer_size,
/* length of the packet (sub-packets appended) */
@@ -369,7 +376,7 @@ static void realdec_decode_data (video_decoder_t *this_gen, buf_element_t *buf)
xine_hexdump (this->chunk_buffer, this->chunk_buffer_size);
printf ("libreal: transform_in:\n");
- xine_hexdump ((uint8_t *) transform_in, 6 * 4);
+ xine_hexdump ((uint8_t *) &transform_in, sizeof(rv_xform_in_t));
printf ("libreal: chunk_table:\n");
xine_hexdump ((uint8_t *) buf->decoder_info_ptr[2],
@@ -379,21 +386,21 @@ static void realdec_decode_data (video_decoder_t *this_gen, buf_element_t *buf)
result = this->rvyuv_transform (this->chunk_buffer,
this->frame_buffer,
&transform_in,
- transform_out,
+ &transform_out,
this->context);
lprintf ("transform result: %08x\n", result);
lprintf ("transform_out:\n");
- #ifdef LOG
- xine_hexdump ((uint8_t *) transform_out, 5 * 4);
- #endif
+#ifdef LOG
+ xine_hexdump ((uint8_t *) &transform_out, 5 * 4);
+#endif
/* Sometimes the stream contains video of a different size
* to that specified in the realmedia header */
- if(transform_out[0] && ((transform_out[3] != this->width) ||
- (transform_out[4] != this->height))) {
- this->width = transform_out[3];
- this->height = transform_out[4];
+ if(transform_out.frames && ((transform_out.width != this->width) ||
+ (transform_out.height != this->height))) {
+ this->width = transform_out.width;
+ this->height = transform_out.height;
this->frame_size = this->width * this->height;
@@ -531,8 +538,7 @@ void *init_realvdec (xine_t *xine, void *data) {
* exported plugin catalog entry
*/
-static const uint32_t supported_types[] = { BUF_VIDEO_RV20,
- BUF_VIDEO_RV30,
+static const uint32_t supported_types[] = { BUF_VIDEO_RV30,
BUF_VIDEO_RV40,
0 };
diff --git a/src/vdr/input_vdr.c b/src/vdr/input_vdr.c
index 154bb9b56..ade2ecfa1 100644
--- a/src/vdr/input_vdr.c
+++ b/src/vdr/input_vdr.c
@@ -61,8 +61,19 @@
*/
+typedef struct vdr_input_plugin_s vdr_input_plugin_t;
+
typedef struct
{
+ metronom_t metronom;
+ metronom_t *stream_metronom;
+ vdr_input_plugin_t *input;
+}
+vdr_metronom_t;
+
+
+struct vdr_input_plugin_s
+{
input_plugin_t input_plugin;
xine_stream_t *stream;
@@ -111,9 +122,12 @@ typedef struct
uint16_t image16_9_zoom_x;
uint16_t image16_9_zoom_y;
-}
-vdr_input_plugin_t;
+ uint8_t find_sync_point;
+ pthread_mutex_t find_sync_point_lock;
+ vdr_metronom_t metronom;
+ int last_disc_type;
+};
typedef struct
@@ -581,7 +595,13 @@ static off_t vdr_execute_rpc_command(vdr_input_plugin_t *this)
int orig_speed = xine_get_param(this->stream, XINE_PARAM_FINE_SPEED);
if (orig_speed <= 0)
xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, XINE_FINE_SPEED_NORMAL);
-fprintf(stderr, "+++ CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a');
+fprintf(stderr, "+++ CLEAR(%d%c): sync point: %02x\n", data->n, data->s ? 'b' : 'a', data->i);
+ if (!data->s)
+ {
+ pthread_mutex_lock(&this->find_sync_point_lock);
+ this->find_sync_point = data->i;
+ pthread_mutex_unlock(&this->find_sync_point_lock);
+ }
/*
if (!this->dont_change_xine_volume)
xine_set_param(this->stream, XINE_PARAM_AUDIO_VOLUME, 0);
@@ -952,33 +972,9 @@ fprintf(stderr, "ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß\n");
int height = 0;
int ratio_code = 0;
int format = 0;
-
- int orig_speed = xine_get_param(this->stream, XINE_PARAM_FINE_SPEED);
- if (XINE_SPEED_PAUSE != orig_speed)
- xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, XINE_SPEED_PAUSE);
-
- if (xine_get_current_frame(this->stream, &width, &height, &ratio_code, &format, 0))
+
+ if (xine_get_current_frame_alloc(this->stream, &width, &height, &ratio_code, &format, &img, &frame_size))
{
- switch (format)
- {
- case XINE_IMGFMT_YV12:
- frame_size = width * height
- + ((width + 1) / 2) * ((height + 1) / 2)
- + ((width + 1) / 2) * ((height + 1) / 2);
- break;
-
- case XINE_IMGFMT_YUY2:
- frame_size = width * height
- + ((width + 1) / 2) * height
- + ((width + 1) / 2) * height;
- break;
- }
-
- img = xine_xmalloc(frame_size);
-
- if (!xine_get_current_frame(this->stream, &width, &height, &ratio_code, &format, img))
- frame_size = 0;
-
if (ratio_code == XINE_VO_ASPECT_SQUARE)
ratio_code = 10000;
else if (ratio_code == XINE_VO_ASPECT_4_3)
@@ -987,17 +983,15 @@ fprintf(stderr, "ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß\n");
ratio_code = 17778;
else if (ratio_code == XINE_VO_ASPECT_DVB)
ratio_code = 21100;
-
- if (0 == frame_size)
- {
- width = 0;
- height = 0;
- ratio_code = 0;
- }
}
-
- if (XINE_SPEED_PAUSE != orig_speed)
- xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, orig_speed);
+
+ if (!img)
+ {
+ frame_size = 0,
+ width = 0;
+ height = 0;
+ ratio_code = 0;
+ }
{
result_grab_image_t result_grab_image;
@@ -1011,13 +1005,12 @@ fprintf(stderr, "ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß\n");
if (sizeof (result_grab_image) == vdr_write(this->fh_result, &result_grab_image, sizeof (result_grab_image)))
{
- if (frame_size == vdr_write(this->fh_result, img, frame_size))
+ if (!frame_size || (frame_size == vdr_write(this->fh_result, img, frame_size)))
ret_val = 0;
}
}
- if (img)
- free(img);
+ free(img);
if (ret_val != 0)
return ret_val;
@@ -1034,8 +1027,7 @@ fprintf(stderr, "ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß\n");
result_get_pts.header.func = data->header.func;
result_get_pts.header.len = sizeof (result_get_pts);
- result_get_pts.pts = xine_get_current_vpts(this->stream) - this->stream->metronom->get_option(this->stream->metronom, METRONOM_VPTS_OFFSET);
-
+ result_get_pts.pts = (this->last_disc_type == DISC_STREAMSTART) ? -2 : (xine_get_current_vpts(this->stream) - this->stream->metronom->get_option(this->stream->metronom, METRONOM_VPTS_OFFSET));
if (sizeof (result_get_pts) != vdr_write(this->fh_result, &result_get_pts, sizeof (result_get_pts)))
return -1;
}
@@ -1311,7 +1303,7 @@ static off_t vdr_plugin_read(input_plugin_t *this_gen,
void *buf_gen, off_t len)
{
vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen;
- char *buf = (char *)buf_gen;
+ uint8_t *buf = (uint8_t *)buf_gen;
off_t n, total;
#ifdef LOG_READ
lprintf ("reading %lld bytes...\n", len);
@@ -1336,7 +1328,7 @@ static off_t vdr_plugin_read(input_plugin_t *this_gen,
int retries = 0;
do
{
- n = vdr_read_abort (this->stream, this->fh, &buf[total], len-total);
+ n = vdr_read_abort (this->stream, this->fh, (char *)&buf[total], len-total);
if (0 == n)
lprintf("read 0, retries: %d\n", retries);
}
@@ -1357,6 +1349,53 @@ static off_t vdr_plugin_read(input_plugin_t *this_gen,
this->curpos += n;
total += n;
}
+
+ if (this->find_sync_point
+ && total == 6)
+ {
+ pthread_mutex_lock(&this->find_sync_point_lock);
+
+ while (this->find_sync_point
+ && total == 6
+ && buf[0] == 0x00
+ && buf[1] == 0x00
+ && buf[2] == 0x01)
+ {
+ int l, sp;
+
+ if (buf[3] == 0xbe
+ && buf[4] == 0xff)
+ {
+//fprintf(stderr, "------- seen sync point: %02x, waiting for: %02x\n", buf[5], this->find_sync_point);
+ if (buf[5] == this->find_sync_point)
+ {
+ this->find_sync_point = 0;
+ break;
+ }
+ }
+
+ if ((buf[3] & 0xf0) != 0xe0
+ && (buf[3] & 0xe0) != 0xc0
+ && buf[3] != 0xbd
+ && buf[3] != 0xbe)
+ {
+ break;
+ }
+
+ l = buf[4] * 256 + buf[5];
+ if (l <= 0)
+ break;
+
+ sp = this->find_sync_point;
+ this->find_sync_point = 0;
+ this_gen->seek(this_gen, l, SEEK_CUR);
+ total = this_gen->read(this_gen, buf, 6);
+ this->find_sync_point = sp;
+ }
+
+ pthread_mutex_unlock(&this->find_sync_point_lock);
+ }
+
return total;
}
@@ -1512,6 +1551,7 @@ static void vdr_plugin_dispose(input_plugin_t *this_gen)
pthread_cond_destroy(&this->rpc_thread_shutdown_cond);
pthread_mutex_destroy(&this->rpc_thread_shutdown_lock);
+ pthread_mutex_destroy(&this->find_sync_point_lock);
pthread_mutex_destroy(&this->adjust_zoom_lock);
if (this->fh_result != -1)
@@ -1539,6 +1579,10 @@ static void vdr_plugin_dispose(input_plugin_t *this_gen)
close(this->fh);
free(this->mrl);
+
+ this->stream->metronom = this->metronom.stream_metronom;
+ this->metronom.stream_metronom = 0;
+
free(this);
}
@@ -1608,6 +1652,12 @@ static int vdr_plugin_open_fifo_mrl(input_plugin_t *this_gen)
fcntl(this->fh, F_SETFL, ~O_NONBLOCK & fcntl(this->fh, F_GETFL, 0));
+ /* eat initial handshake byte */
+ {
+ char b;
+ read(this->fh, &b, 1);
+ }
+
{
char *filename_control = 0;
asprintf(&filename_control, "%s.control", filename);
@@ -1946,6 +1996,69 @@ static void event_handler(void *user_data, const xine_event_t *event)
_("%s: input event write: %s.\n"), LOG_MODULE, strerror(errno));
}
+
+static void vdr_metronom_set_audio_rate(metronom_t *self, int64_t pts_per_smpls)
+{
+ vdr_metronom_t *this = (vdr_metronom_t *)self;
+ this->stream_metronom->set_audio_rate(this->stream_metronom, pts_per_smpls);
+}
+
+static void vdr_metronom_got_video_frame(metronom_t *self, vo_frame_t *frame)
+{
+ vdr_metronom_t *this = (vdr_metronom_t *)self;
+ this->stream_metronom->got_video_frame(this->stream_metronom, frame);
+}
+
+static int64_t vdr_metronom_got_audio_samples(metronom_t *self, int64_t pts, int nsamples)
+{
+ vdr_metronom_t *this = (vdr_metronom_t *)self;
+ return this->stream_metronom->got_audio_samples(this->stream_metronom, pts, nsamples);
+}
+
+static int64_t vdr_metronom_got_spu_packet(metronom_t *self, int64_t pts)
+{
+ vdr_metronom_t *this = (vdr_metronom_t *)self;
+ return this->stream_metronom->got_spu_packet(this->stream_metronom, pts);
+}
+
+static void vdr_metronom_handle_audio_discontinuity(metronom_t *self, int type, int64_t disc_off)
+{
+ vdr_metronom_t *this = (vdr_metronom_t *)self;
+ this->stream_metronom->handle_audio_discontinuity(this->stream_metronom, type, disc_off);
+ this->input->last_disc_type = type;
+}
+
+static void vdr_metronom_handle_video_discontinuity(metronom_t *self, int type, int64_t disc_off)
+{
+ vdr_metronom_t *this = (vdr_metronom_t *)self;
+ this->stream_metronom->handle_video_discontinuity(this->stream_metronom, type, disc_off);
+ this->input->last_disc_type = type;
+}
+
+static void vdr_metronom_set_option(metronom_t *self, int option, int64_t value)
+{
+ vdr_metronom_t *this = (vdr_metronom_t *)self;
+ this->stream_metronom->set_option(this->stream_metronom, option, value);
+}
+
+static int64_t vdr_metronom_get_option(metronom_t *self, int option)
+{
+ vdr_metronom_t *this = (vdr_metronom_t *)self;
+ return this->stream_metronom->get_option(this->stream_metronom, option);
+}
+
+static void vdr_metronom_set_master(metronom_t *self, metronom_t *master)
+{
+ vdr_metronom_t *this = (vdr_metronom_t *)self;
+ this->stream_metronom->set_master(this->stream_metronom, master);
+}
+
+static void vdr_metronom_exit(metronom_t *self)
+{
+ _x_abort();
+}
+
+
static input_plugin_t *vdr_class_get_instance(input_class_t *cls_gen, xine_stream_t *stream,
const char *data)
{
@@ -2017,6 +2130,7 @@ static input_plugin_t *vdr_class_get_instance(input_class_t *cls_gen, xine_strea
pthread_mutex_init(&this->rpc_thread_shutdown_lock, 0);
pthread_cond_init(&this->rpc_thread_shutdown_cond, 0);
+ pthread_mutex_init(&this->find_sync_point_lock, 0);
pthread_mutex_init(&this->adjust_zoom_lock, 0);
this->image4_3_zoom_x = 0;
this->image4_3_zoom_y = 0;
@@ -2027,6 +2141,21 @@ static input_plugin_t *vdr_class_get_instance(input_class_t *cls_gen, xine_strea
if (this->event_queue)
xine_event_create_listener_thread(this->event_queue, event_handler, this);
+ this->metronom.input = this;
+ this->metronom.metronom.set_audio_rate = vdr_metronom_set_audio_rate;
+ this->metronom.metronom.got_video_frame = vdr_metronom_got_video_frame;
+ this->metronom.metronom.got_audio_samples = vdr_metronom_got_audio_samples;
+ this->metronom.metronom.got_spu_packet = vdr_metronom_got_spu_packet;
+ this->metronom.metronom.handle_audio_discontinuity = vdr_metronom_handle_audio_discontinuity;
+ this->metronom.metronom.handle_video_discontinuity = vdr_metronom_handle_video_discontinuity;
+ this->metronom.metronom.set_option = vdr_metronom_set_option;
+ this->metronom.metronom.get_option = vdr_metronom_get_option;
+ this->metronom.metronom.set_master = vdr_metronom_set_master;
+ this->metronom.metronom.exit = vdr_metronom_exit;
+
+ this->metronom.stream_metronom = stream->metronom;
+ stream->metronom = &this->metronom.metronom;
+
return &this->input_plugin;
}
@@ -2039,7 +2168,7 @@ static char **vdr_class_get_autoplay_list(input_class_t *this_gen,
vdr_input_class_t *class = (vdr_input_class_t *)this_gen;
*num_files = 1;
- return class->mrls;
+ return (char **)class->mrls;
}
void *vdr_input_init_plugin(xine_t *xine, void *data)
diff --git a/src/video_dec/libmpeg2/decode.c b/src/video_dec/libmpeg2/decode.c
index 33d8b7ca9..e9700d95f 100644
--- a/src/video_dec/libmpeg2/decode.c
+++ b/src/video_dec/libmpeg2/decode.c
@@ -460,9 +460,10 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
break;
case 0xb7: /* sequence end code */
-#ifdef LOG_PAN_SCAN
- printf ("libmpeg2: sequence end code not handled\n");
-#endif
+ mpeg2_flush(mpeg2dec);
+ mpeg2dec->is_sequence_needed = 1;
+ break;
+
case 0xb8: /* group of pictures start code */
if (mpeg2_header_group_of_pictures (picture, buffer)) {
printf ("libmpeg2: bad group of pictures\n");
diff --git a/src/video_out/video_out_macosx.m b/src/video_out/video_out_macosx.m
index 9c65d579d..085387a44 100644
--- a/src/video_out/video_out_macosx.m
+++ b/src/video_out/video_out_macosx.m
@@ -36,11 +36,11 @@
#define LOG
*/
-#include "video_out.h"
-#include "vo_scale.h"
#include "xine.h"
-#include "xine_internal.h"
-#include "xineutils.h"
+#include "xine/video_out.h"
+#include "xine/vo_scale.h"
+#include "xine/xine_internal.h"
+#include "xine/xineutils.h"
#include "macosx/video_window.h"
@@ -207,7 +207,7 @@ static void macosx_display_frame(vo_driver_t *vo_driver, vo_frame_t *vo_frame) {
break;
case XINE_IMGFMT_YUY2:
xine_fast_memcpy (texture_buffer, vo_frame->base[0],
- vo_frame->pitches[0] * vo_frame->height * 2);
+ vo_frame->pitches[0] * vo_frame->height);
[driver->view updateTexture];
break;
default:
@@ -358,7 +358,7 @@ static void *init_class (xine_t *xine, void *visual) {
this->driver_class.open_plugin = open_plugin;
this->driver_class.identifier = "MacOSX";
this->driver_class.description = N_("xine video output plugin for Mac OS X");
- this->driver_class.dispose = default_video_driver_class;
+ this->driver_class.dispose = default_video_driver_class_dispose;
this->config = xine->config;
this->xine = xine;
diff --git a/src/video_out/video_out_xcbxv.c b/src/video_out/video_out_xcbxv.c
index d77917a70..e267f98fb 100644
--- a/src/video_out/video_out_xcbxv.c
+++ b/src/video_out/video_out_xcbxv.c
@@ -151,6 +151,8 @@ typedef struct {
xine_t *xine;
} xv_class_t;
+static const char *const prefer_types[] = VIDEO_DEVICE_XV_PREFER_TYPES;
+
static uint32_t xv_get_capabilities (vo_driver_t *this_gen) {
xv_driver_t *this = (xv_driver_t *) this_gen;
@@ -1145,10 +1147,15 @@ xv_find_adaptor_by_port (int port, xcb_xv_adaptor_info_iterator_t *adaptor_it)
static xcb_xv_port_t xv_autodetect_port(xv_driver_t *this,
xcb_xv_adaptor_info_iterator_t *adaptor_it,
- xcb_xv_port_t base)
+ 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)
+ 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])))
{
int j;
for (j = 0; j < adaptor_it->data->num_ports; ++j)
@@ -1168,6 +1175,7 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis
int i;
xcb_visual_t *visual = (xcb_visual_t *) visual_gen;
xcb_xv_port_t xv_port;
+ xv_prefertype prefer_type;
const xcb_query_extension_reply_t *query_extension_reply;
@@ -1219,19 +1227,24 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis
adaptor_it = 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,
- 10, NULL, NULL);
+ 20, NULL, NULL);
+ prefer_type = config->register_enum (config, "video.device.xv_preferred_method", 0,
+ prefer_types, 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"),
LOG_MODULE, xv_port);
- xv_port = xv_autodetect_port (this, &adaptor_it, xv_port);
+ 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)
- xv_port = xv_autodetect_port (this, &adaptor_it, 0);
+ xv_port = xv_autodetect_port (this, &adaptor_it, 0, prefer_type);
+ if (!xv_port)
+ xv_port = xv_autodetect_port (this, &adaptor_it, 0, xv_prefer_none);
if (!xv_port) {
xprintf(class->xine, XINE_VERBOSITY_LOG,
diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c
index a874e4cdf..0026bd8af 100644
--- a/src/video_out/video_out_xv.c
+++ b/src/video_out/video_out_xv.c
@@ -164,6 +164,8 @@ typedef struct {
static int gX11Fail;
+static const char *const prefer_types[] = VIDEO_DEVICE_XV_PREFER_TYPES;
+
static uint32_t xv_get_capabilities (vo_driver_t *this_gen) {
xv_driver_t *this = (xv_driver_t *) this_gen;
@@ -1178,11 +1180,15 @@ static XvPortID xv_autodetect_port(xv_driver_t *this,
unsigned int adaptors,
XvAdaptorInfo *adaptor_info,
unsigned int *adaptor_num,
- XvPortID base) {
+ XvPortID base,
+ xv_prefertype prefer_type)
+{
unsigned int an, j;
for (an = 0; an < adaptors; an++)
- if (adaptor_info[an].type & XvImageMask)
+ if (adaptor_info[an].type & XvImageMask &&
+ (prefer_type == xv_prefer_none ||
+ strcasestr (adaptor_info[an].name, prefer_types[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)) {
@@ -1212,6 +1218,7 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void *
XvPortID xv_port;
XvAdaptorInfo *adaptor_info;
unsigned int adaptor_num;
+ xv_prefertype prefer_type;
this = (xv_driver_t *) xine_xmalloc (sizeof (xv_driver_t));
if (!this)
@@ -1251,19 +1258,24 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void *
xv_port = config->register_num (config, "video.device.xv_port", 0,
VIDEO_DEVICE_XV_PORT_HELP,
- 10, NULL, NULL);
+ 20, NULL, NULL);
+ prefer_type = config->register_enum (config, "video.device.xv_preferred_method", 0,
+ prefer_types, 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"),
LOG_MODULE, xv_port);
- xv_port = xv_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, xv_port);
+ xv_port = xv_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, xv_port, prefer_type);
} else
adaptor_num = xv_find_adaptor_by_port (xv_port, adaptors, adaptor_info);
}
if (!xv_port)
- xv_port = xv_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0);
+ xv_port = xv_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, prefer_type);
+ if (!xv_port)
+ xv_port = xv_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, xv_prefer_none);
if (!xv_port) {
xprintf(class->xine, XINE_VERBOSITY_LOG,
diff --git a/src/video_out/video_out_xxmc.c b/src/video_out/video_out_xxmc.c
index 1ef3652a9..bd8a76046 100644
--- a/src/video_out/video_out_xxmc.c
+++ b/src/video_out/video_out_xxmc.c
@@ -45,6 +45,7 @@ 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;
/*
* Acceleration level priority. Static for now. It may well turn out that IDCT
@@ -2263,11 +2264,15 @@ static XvPortID xxmc_autodetect_port(xxmc_driver_t *this,
unsigned int adaptors,
XvAdaptorInfo *adaptor_info,
unsigned int *adaptor_num,
- XvPortID base) {
+ XvPortID base,
+ xv_prefertype prefer_type)
+{
unsigned int an, j;
for (an = 0; an < adaptors; an++)
- if (adaptor_info[an].type & XvImageMask)
+ if (adaptor_info[an].type & XvImageMask &&
+ (prefer_type == xv_prefer_none ||
+ strcasestr (adaptor_info[an].name, prefer_types[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)) {
@@ -2443,6 +2448,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi
XvPortID xv_port;
XvAdaptorInfo *adaptor_info;
unsigned int adaptor_num;
+ xv_prefertype prefer_type;
cfg_entry_t *entry;
int use_more_frames;
int use_unscaled;
@@ -2480,19 +2486,24 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi
xv_port = config->register_num (config, "video.device.xv_port", 0,
VIDEO_DEVICE_XV_PORT_HELP,
- 10, NULL, NULL);
+ 20, NULL, NULL);
+ prefer_type = config->register_enum (config, "video.device.xv_preferred_method", 0,
+ prefer_types, VIDEO_DEVICE_XV_PREFER_TYPE_HELP,
+ 10, NULL, NULL);
if (xv_port != 0) {
if (! xxmc_open_port(this, xv_port)) {
xprintf(class->xine, XINE_VERBOSITY_NONE,
_("%s: could not open Xv port %d - autodetecting\n"),
LOG_MODULE, xv_port);
- xv_port = xxmc_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, xv_port);
+ xv_port = xxmc_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, xv_port, prefer_type);
} else
adaptor_num = xxmc_find_adaptor_by_port (xv_port, adaptors, adaptor_info);
}
if (!xv_port)
- xv_port = xxmc_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0);
+ xv_port = xxmc_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, prefer_type);
+ if (!xv_port)
+ xv_port = xxmc_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, xv_prefer_none);
if (!xv_port) {
xprintf(class->xine, XINE_VERBOSITY_LOG,
diff --git a/src/video_out/xv_common.h b/src/video_out/xv_common.h
index ee2ab9a10..259afe616 100644
--- a/src/video_out/xv_common.h
+++ b/src/video_out/xv_common.h
@@ -56,3 +56,14 @@
#define VIDEO_DEVICE_XV_PITCH_ALIGNMENT_HELP \
_("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_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.)")
diff --git a/src/xine-engine/buffer_types.c b/src/xine-engine/buffer_types.c
index b0e01db31..15b5ff952 100644
--- a/src/xine-engine/buffer_types.c
+++ b/src/xine-engine/buffer_types.c
@@ -808,6 +808,14 @@ static const audio_db_t audio_db[] = {
},
{
{
+ ME_FOURCC('a', 'd', 'u', 0x55),
+ 0
+ },
+ BUF_AUDIO_MP3ADU,
+ "MPEG layer-3 adu"
+},
+{
+ {
ME_FOURCC('t','w','o','s'),
ME_FOURCC('i','n','2','4'),
0
diff --git a/src/xine-engine/configfile.c b/src/xine-engine/configfile.c
index a41abf193..9f67b7503 100644
--- a/src/xine-engine/configfile.c
+++ b/src/xine-engine/configfile.c
@@ -1458,7 +1458,7 @@ static char* config_register_serialized_entry (config_values_t *this, const char
if (!bytes) goto exit;
if ((value_count < 0) || (value_count > 256)) goto exit;
- enum_values = malloc (sizeof(void*) * value_count + 1);
+ enum_values = calloc (value_count + 1, sizeof(void*));
for (i = 0; i < value_count; i++) {
pos += bytes = get_string(output, output_len, pos, &enum_values[i]);
if (!bytes) goto exit;
diff --git a/src/xine-engine/demux.c b/src/xine-engine/demux.c
index 232e0342e..e641bbf77 100644
--- a/src/xine-engine/demux.c
+++ b/src/xine-engine/demux.c
@@ -198,6 +198,7 @@ void _x_demux_control_headers_done (xine_stream_t *stream) {
}
stream->demux_action_pending = 0;
+ pthread_cond_signal(&stream->demux_resume);
lprintf ("headers processed.\n");
@@ -284,12 +285,14 @@ static void *demux_loop (void *stream_gen) {
/* someone may want to interrupt us */
if( stream->demux_action_pending ) {
- pthread_mutex_unlock( &stream->demux_lock );
+ struct timeval tv;
+ struct timespec ts;
- lprintf ("sched_yield\n");
-
- sched_yield();
- pthread_mutex_lock( &stream->demux_lock );
+ gettimeofday(&tv, NULL);
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = (tv.tv_usec + 100000) * 1000;
+
+ pthread_cond_timedwait (&stream->demux_resume, &stream->demux_lock, &ts);
}
}
@@ -365,6 +368,7 @@ int _x_demux_start_thread (xine_stream_t *stream) {
stream->demux_action_pending = 1;
pthread_mutex_lock( &stream->demux_lock );
stream->demux_action_pending = 0;
+ pthread_cond_signal(&stream->demux_resume);
if( !stream->demux_thread_running ) {
@@ -396,6 +400,7 @@ int _x_demux_stop_thread (xine_stream_t *stream) {
pthread_mutex_lock( &stream->demux_lock );
stream->demux_thread_running = 0;
stream->demux_action_pending = 0;
+ pthread_cond_signal(&stream->demux_resume);
/* At that point, the demuxer has sent the last audio/video buffer,
* so it's a safe place to flush the engine.
diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c
index 8e4a10a60..710e6dfbf 100644
--- a/src/xine-engine/load_plugins.c
+++ b/src/xine-engine/load_plugins.c
@@ -1339,11 +1339,13 @@ input_plugin_t *_x_find_input_plugin (xine_stream_t *stream, const char *mrl) {
void _x_free_input_plugin (xine_stream_t *stream, input_plugin_t *input) {
plugin_catalog_t *catalog = stream->xine->plugin_catalog;
+ plugin_node_t *node = input->node;
input->dispose(input);
- if (input->node) {
+
+ if (node) {
pthread_mutex_lock(&catalog->lock);
- dec_node_ref(input->node);
+ dec_node_ref(node);
pthread_mutex_unlock(&catalog->lock);
}
}
@@ -1560,11 +1562,13 @@ demux_plugin_t *_x_find_demux_plugin_last_probe(xine_stream_t *stream, const cha
void _x_free_demux_plugin (xine_stream_t *stream, demux_plugin_t *demux) {
plugin_catalog_t *catalog = stream->xine->plugin_catalog;
+ plugin_node_t *node = demux->node;
demux->dispose(demux);
- if (demux->node) {
+
+ if (node) {
pthread_mutex_lock(&catalog->lock);
- dec_node_ref(demux->node);
+ dec_node_ref(node);
pthread_mutex_unlock(&catalog->lock);
}
}
@@ -2054,12 +2058,13 @@ video_decoder_t *_x_get_video_decoder (xine_stream_t *stream, uint8_t stream_typ
void _x_free_video_decoder (xine_stream_t *stream, video_decoder_t *vd) {
plugin_catalog_t *catalog = stream->xine->plugin_catalog;
+ plugin_node_t *node = vd->node;
vd->dispose (vd);
- if (vd->node) {
+ if (node) {
pthread_mutex_lock (&catalog->lock);
- dec_node_ref(vd->node);
+ dec_node_ref(node);
pthread_mutex_unlock (&catalog->lock);
}
}
@@ -2403,7 +2408,7 @@ const char *const *xine_list_post_plugins_typed(xine_t *xine, uint32_t type) {
else \
return NULL; \
} \
- return dgettext(ic->textdomain ? : XINE_TEXTDOMAIN, ic->description); \
+ return dgettext(ic->text_domain ? : XINE_TEXTDOMAIN, ic->description); \
} \
} \
return NULL; \
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index c6dc8a2ce..5c8d0be9d 100644
--- a/src/xine-engine/xine.c
+++ b/src/xine-engine/xine.c
@@ -36,6 +36,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>
+#include <unistd.h>
#if defined (__linux__) || defined (__GLIBC__)
#include <endian.h>
#elif defined (__FreeBSD__)
@@ -138,7 +139,7 @@ static int acquire_allowed_to_block(xine_ticket_t *this) {
unsigned new_size;
for(entry = 0; entry < this->holder_thread_count; ++entry) {
- if(this->holder_threads[entry].holder == own_id) {
+ if(pthread_equal(this->holder_threads[entry].holder, own_id)) {
/* This thread may already hold this ticket */
this->holder_threads[entry].count++;
return (this->holder_threads[entry].count == 1);
@@ -209,7 +210,7 @@ static int release_allowed_to_block(xine_ticket_t *this) {
unsigned entry;
for(entry = 0; entry < this->holder_thread_count; ++entry) {
- if(this->holder_threads[entry].holder == own_id) {
+ if(pthread_equal(this->holder_threads[entry].holder, own_id)) {
this->holder_threads[entry].count--;
return this->holder_threads[entry].count == 0;
}
@@ -670,6 +671,7 @@ xine_stream_t *xine_stream_new (xine_t *this,
pthread_mutex_init (&stream->meta_mutex, NULL);
pthread_mutex_init (&stream->demux_lock, NULL);
pthread_mutex_init (&stream->demux_mutex, NULL);
+ pthread_cond_init (&stream->demux_resume, NULL);
pthread_mutex_init (&stream->event_queues_lock, NULL);
pthread_mutex_init (&stream->counter_lock, NULL);
pthread_cond_init (&stream->counter_changed, NULL);
@@ -839,6 +841,7 @@ static inline int _x_path_looks_like_mrl (const char *path)
static int open_internal (xine_stream_t *stream, const char *mrl) {
const char *stream_setup = NULL;
+ const char *mrl_proto = NULL;
int no_cache = 0;
if (!mrl) {
@@ -862,16 +865,31 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
/*
* look for a stream_setup in MRL and try finding an input plugin
*/
+ stream_setup = strchr (mrl, '#');
if (isalpha (*mrl))
{
- stream_setup = mrl + 1;
- while (isalnum (*stream_setup) || *stream_setup == '+' || *stream_setup == '-' || *stream_setup == '.')
- ++stream_setup;
- if (stream_setup[0] == ':' && stream_setup[1] == '/')
- stream_setup = strchr (mrl, '#');
- else
- stream_setup = NULL;
+ mrl_proto = mrl + 1;
+ while (isalnum (*mrl_proto) || *mrl_proto == '+' || *mrl_proto == '-' || *mrl_proto == '.')
+ ++mrl_proto;
+ if (!mrl_proto[0] || mrl_proto[0] != ':' || mrl_proto[1] != '/')
+ mrl_proto = NULL;
+ }
+
+ /* for raw filenames we must try every '#' checking if it is part of the filename */
+ if( !mrl_proto && stream_setup) {
+ struct stat stat_buf;
+ int res;
+
+ while( stream_setup ) {
+ char *raw_filename = strndup (mrl, stream_setup - mrl);
+
+ res = stat(raw_filename, &stat_buf);
+ free(raw_filename);
+ if( !res )
+ break;
+ stream_setup = strchr(stream_setup + 1, '#');
+ }
}
{
@@ -880,12 +898,14 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
/*
* find an input plugin
*/
-
- if ((stream->input_plugin = _x_find_input_plugin (stream, input_source))) {
+ stream->input_plugin = _x_find_input_plugin (stream, input_source);
+ free(input_source);
+
+ if ( stream->input_plugin ) {
int res;
xine_log (stream->xine, XINE_LOG_MSG, _("xine: found input plugin : %s\n"),
- dgettext(stream->input_plugin->input_class->textdomain ? : XINE_TEXTDOMAIN,
+ dgettext(stream->input_plugin->input_class->text_domain ? : XINE_TEXTDOMAIN,
stream->input_plugin->input_class->description));
if (stream->input_plugin->input_class->eject_media)
stream->eject_class = stream->input_plugin->input_class;
@@ -897,7 +917,6 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
case 1: /* Open successfull */
break;
case -1: /* Open unsuccessfull, but correct plugin */
- free(input_source);
stream->err = XINE_ERROR_INPUT_FAILED;
_x_flush_events_queues (stream);
return 0;
@@ -908,8 +927,6 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
stream->err = XINE_ERROR_INPUT_FAILED;
}
}
-
- free(input_source);
}
if (!stream->input_plugin) {
@@ -1235,7 +1252,7 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
}
xine_log (stream->xine, XINE_LOG_MSG, _("xine: found demuxer plugin: %s\n"),
- dgettext(stream->demux_plugin->demux_class->textdomain ? : XINE_TEXTDOMAIN,
+ dgettext(stream->demux_plugin->demux_class->text_domain ? : XINE_TEXTDOMAIN,
stream->demux_plugin->demux_class->description));
_x_extra_info_reset( stream->current_extra_info );
@@ -1351,6 +1368,7 @@ static int play_internal (xine_stream_t *stream, int start_pos, int start_time)
pthread_mutex_lock( &stream->demux_lock );
/* demux_lock taken. now demuxer is suspended */
stream->demux_action_pending = 0;
+ pthread_cond_signal(&stream->demux_resume);
/* set normal speed again (now that demuxer/input pair is suspended)
* some input plugin may have changed speed by itself, we must ensure
@@ -1477,6 +1495,7 @@ static void xine_dispose_internal (xine_stream_t *stream) {
pthread_mutex_destroy (&stream->current_extra_info_lock);
pthread_cond_destroy (&stream->counter_changed);
pthread_mutex_destroy (&stream->demux_mutex);
+ pthread_cond_destroy (&stream->demux_resume);
pthread_mutex_destroy (&stream->demux_lock);
pthread_mutex_destroy (&stream->first_frame_lock);
pthread_cond_destroy (&stream->first_frame_reached);
@@ -1691,6 +1710,12 @@ void xine_init (xine_t *this) {
/* First of all, initialise libxdg-basedir as it's used by plugins. */
this->basedir_handle = xdgAllocHandle();
+ /*
+ * locks
+ */
+ pthread_mutex_init (&this->streams_lock, NULL);
+ pthread_mutex_init (&this->log_lock, NULL);
+
/* initialize color conversion tables and functions */
init_yuv_conversion();
@@ -1772,12 +1797,6 @@ void xine_init (xine_t *this) {
this->streams = xine_list_new();
/*
- * locks
- */
- pthread_mutex_init (&this->streams_lock, NULL);
- pthread_mutex_init (&this->log_lock, NULL);
-
- /*
* start metronom clock
*/
@@ -1963,11 +1982,12 @@ int xine_get_pos_length (xine_stream_t *stream, int *pos_stream,
return 1;
}
-int xine_get_current_frame (xine_stream_t *stream, int *width, int *height,
- int *ratio_code, int *format,
- uint8_t *img) {
+static int _x_get_current_frame_impl (xine_stream_t *stream, int *width, int *height,
+ int *ratio_code, int *format,
+ uint8_t **img, int *size, int alloc_img) {
vo_frame_t *frame;
+ int required_size;
stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
frame = stream->video_out->get_last_frame (stream->video_out);
@@ -1993,20 +2013,62 @@ int xine_get_current_frame (xine_stream_t *stream, int *width, int *height,
*format = frame->format;
- if (img){
+ switch (*format) {
+
+ case XINE_IMGFMT_YV12:
+ required_size = *width * *height
+ + ((*width + 1) / 2) * ((*height + 1) / 2)
+ + ((*width + 1) / 2) * ((*height + 1) / 2);
+ break;
+
+ case XINE_IMGFMT_YUY2:
+ required_size = *width * *height
+ + ((*width + 1) / 2) * *height
+ + ((*width + 1) / 2) * *height;
+ break;
+
+ default:
+ if (*img || alloc_img) {
+ xprintf (stream->xine, XINE_VERBOSITY_DEBUG,
+ "xine: error, snapshot function not implemented for format 0x%x\n", frame->format);
+ _x_abort ();
+ }
+
+ required_size = 0;
+ }
+
+ if (alloc_img) {
+ /* return size if requested */
+ if (size)
+ *size = required_size;
+ /* allocate img or fail */
+ if (!(*img = xine_xmalloc (required_size)))
+ return 0;
+ } else {
+ /* fail if supplied buffer is to small */
+ if (*img && size && *size < required_size) {
+ *size = required_size;
+ return 0;
+ }
+ /* return size if requested */
+ if (size)
+ *size = required_size;
+ }
+
+ if (*img) {
switch (frame->format) {
case XINE_IMGFMT_YV12:
yv12_to_yv12(
/* Y */
frame->base[0], frame->pitches[0],
- img, frame->width,
+ *img, frame->width,
/* U */
frame->base[1], frame->pitches[1],
- img+frame->width*frame->height, frame->width/2,
+ *img+frame->width*frame->height, frame->width/2,
/* V */
frame->base[2], frame->pitches[2],
- img+frame->width*frame->height+frame->width*frame->height/4, frame->width/2,
+ *img+frame->width*frame->height+frame->width*frame->height/4, frame->width/2,
/* width x height */
frame->width, frame->height);
break;
@@ -2016,7 +2078,7 @@ int xine_get_current_frame (xine_stream_t *stream, int *width, int *height,
/* src */
frame->base[0], frame->pitches[0],
/* dst */
- img, frame->width*2,
+ *img, frame->width*2,
/* width x height */
frame->width, frame->height);
break;
@@ -2030,6 +2092,25 @@ int xine_get_current_frame (xine_stream_t *stream, int *width, int *height,
return 1;
}
+int xine_get_current_frame_alloc (xine_stream_t *stream, int *width, int *height,
+ int *ratio_code, int *format,
+ uint8_t **img, int *size) {
+ uint8_t *no_img = NULL;
+ return _x_get_current_frame_impl(stream, width, height, ratio_code, format, img ? img : &no_img, size, img != NULL);
+}
+
+int xine_get_current_frame_s (xine_stream_t *stream, int *width, int *height,
+ int *ratio_code, int *format,
+ uint8_t *img, int *size) {
+ return (!img || size) && _x_get_current_frame_impl(stream, width, height, ratio_code, format, &img, size, 0);
+}
+
+int xine_get_current_frame (xine_stream_t *stream, int *width, int *height,
+ int *ratio_code, int *format,
+ uint8_t *img) {
+ return _x_get_current_frame_impl(stream, width, height, ratio_code, format, &img, NULL, 0);
+}
+
int xine_get_video_frame (xine_stream_t *stream,
int timestamp, /* msec */
int *width, int *height,
diff --git a/src/xine-utils/Makefile.am b/src/xine-utils/Makefile.am
index 75cab2131..0c664b0be 100644
--- a/src/xine-utils/Makefile.am
+++ b/src/xine-utils/Makefile.am
@@ -32,3 +32,7 @@ libxineutils_la_SOURCES = $(pppc_files) \
sorted_array.c \
pool.c \
ring_buffer.c
+
+noinst_PROGRAMS = xmltest
+xmltest_SOURCES = xmllexer.c xmlparser.c
+xmltest_CFLAGS = -DLOG -DXINE_XML_PARSER_TEST $(AM_CFLAGS)
diff --git a/src/xine-utils/xmllexer.c b/src/xine-utils/xmllexer.c
index 75a1aafec..394ca397f 100644
--- a/src/xine-utils/xmllexer.c
+++ b/src/xine-utils/xmllexer.c
@@ -445,6 +445,8 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) {
case '\"': /* " */
case ' ':
case '\t':
+ case '\n':
+ case '\r':
case '=':
case '/':
tok[tok_pos] = '\0';
diff --git a/src/xine-utils/xmlparser.c b/src/xine-utils/xmlparser.c
index 8ef828105..0c3d12f59 100644
--- a/src/xine-utils/xmlparser.c
+++ b/src/xine-utils/xmlparser.c
@@ -837,3 +837,73 @@ void xml_parser_dump_tree (const xml_node_t *node) {
node = node->next;
} while (node);
}
+
+#ifdef XINE_XML_PARSER_TEST
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+void *xine_xmalloc (size_t size)
+{
+ return malloc (size);
+}
+
+int main (int argc, char **argv)
+{
+ int i, ret = 0;
+ for (i = 1; argv[i]; ++i)
+ {
+ xml_node_t *tree;
+ int fd;
+ void *buf;
+ struct stat st;
+
+ if (stat (argv[i], &st))
+ {
+ perror (argv[i]);
+ ret = 1;
+ continue;
+ }
+ if (!S_ISREG (st.st_mode))
+ {
+ printf ("%s: not a file\n", argv[i]);
+ ret = 1;
+ continue;
+ }
+ fd = open (argv[i], O_RDONLY);
+ if (!fd)
+ {
+ perror (argv[i]);
+ ret = 1;
+ continue;
+ }
+ buf = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (!buf)
+ {
+ perror (argv[i]);
+ if (close (fd))
+ perror (argv[i]);
+ ret = 1;
+ continue;
+ }
+
+ xml_parser_init (buf, st.st_size, 0);
+ if (!xml_parser_build_tree (&tree))
+ {
+ puts (argv[i]);
+ xml_parser_dump_tree (tree);
+ xml_parser_free_tree (tree);
+ }
+ else
+ printf ("%s: parser failure\n", argv[i]);
+
+ if (close (fd))
+ {
+ perror (argv[i]);
+ ret = 1;
+ }
+ }
+ return ret;
+}
+#endif