diff options
| -rw-r--r-- | ChangeLog | 5 | ||||
| -rw-r--r-- | configure.ac | 18 | ||||
| -rw-r--r-- | include/xine.h.in | 1 | ||||
| -rw-r--r-- | src/audio_out/audio_directx2_out.c | 460 | ||||
| -rw-r--r-- | src/audio_out/audio_pulse_out.c | 6 | ||||
| -rw-r--r-- | src/demuxers/demux_flac.c | 3 | ||||
| -rw-r--r-- | src/demuxers/demux_ts.c | 9 | ||||
| -rw-r--r-- | src/demuxers/id3.c | 1 | ||||
| -rw-r--r-- | src/libfaad/xine_faad_decoder.c | 27 | ||||
| -rw-r--r-- | src/libspudvb/xine_spudvb_decoder.c | 46 | ||||
| -rw-r--r-- | src/video_out/video_out_directx.c | 10 | ||||
| -rw-r--r-- | src/video_out/video_out_raw.c | 2 | ||||
| -rw-r--r-- | src/video_out/video_out_sdl.c | 16 | ||||
| -rw-r--r-- | src/xine-utils/utils.c | 20 | 
14 files changed, 313 insertions, 311 deletions
| @@ -3,6 +3,11 @@ xine-lib (1.1.16) 2008-??-??    * Fix CDDB access in 64-bit builds.    * Fix seeking FLV clips that don't specify the movie length in the headers.    * Support H.264 and AAC streams within FLV. +  * Fix timing issues (broken audio) on mingw. +  * Add ID3 tag TDRC to replace/complement the deprecated tag TYER. +  * Add a new meta-tag, "Composer", and use it in the FLAC demuxer. +  * Correct AAC channel ordering for multi-channel audio, at least for FLAC +    when using ALSA or PulseAudio. (Needs a proper fix.)  xine-lib (1.1.15) 2008-08-14    * Security fixes: diff --git a/configure.ac b/configure.ac index 52f31ecb4..552a696a1 100644 --- a/configure.ac +++ b/configure.ac @@ -1081,18 +1081,11 @@ AC_ARG_WITH([pulseaudio],  if test "x$with_pulseaudio" != "xno"; then     PKG_CHECK_MODULES([PULSEAUDIO], [libpulse], [have_pulseaudio="yes"], [have_pulseaudio="no"]) -   if test x"$have_pulseaudio" = xyes; then -      AC_MSG_CHECKING([for pulseaudio >= 0.9.7]) -      PKG_CHECK_EXISTS([libpulse >= 0.9.7], -        [have_pulseaudio_0_9_7="yes"], -        [have_pulseaudio_0_9_7="no"]) -      AC_MSG_RESULT([$have_pulseaudio_0_9_7]) -      if test x"$have_pulseaudio_0_9_7" = xyes; then -         AC_DEFINE([HAVE_PULSEAUDIO_0_9_7], 1, [define this if you have pulseaudio >= 0.9.7]) -      fi -   fi  fi +  AM_CONDITIONAL(HAVE_PULSEAUDIO, [test "x$have_pulseaudio" = x"yes"]) +AC_SUBST([PULSEAUDIO_CFLAGS]) +AC_SUBST([PULSEAUDIO_LIBS])  dnl ---------------------------------------------  dnl check for DirectX @@ -2449,11 +2442,6 @@ XINE_REL_FONTDIR="`makeexpand "$XINE_FONTDIR" | sed -e "s,^${prefix}/,,"`"  XINE_REL_LOCALEDIR="`makeexpand "$XINE_LOCALEDIR" | sed -e "s,^${prefix}/,,"`"  XINE_PKGCONFIG_DIR="`makeexpand "$pkgconfigdir"`"  if test "x$SYS" = "xmingw32" -o "x$SYS" = "xcygwin"; then -  dnl polish paths (MinGW runtime accepts both \ and / anyway) -  XINE_REL_PLUGINROOT="`echo "$XINE_REL_PLUGINROOT" | sed -e 's/\\//\\\\\\\\/g'`" -  XINE_REL_PLUGINDIR="$XINE_REL_PLUGINROOT.$XINE_LT_AGE" -  XINE_REL_FONTDIR="`echo "$XINE_REL_FONTDIR" | sed -e 's/\\//\\\\\\\\/g'`" -  XINE_REL_LOCALEDIR="`echo "$XINE_REL_LOCALEDIR" | sed -e 's/\\//\\\\\\\\/g'`"    dnl prefix in xine-config    XINE_CONFIG_PREFIX="\$(cd \$(dirname \$0)/..; pwd)"    dnl installation directories (in xine-config) diff --git a/include/xine.h.in b/include/xine.h.in index 62cfa8747..33844a0e2 100644 --- a/include/xine.h.in +++ b/include/xine.h.in @@ -993,6 +993,7 @@ const char *xine_get_meta_info   (xine_stream_t *stream, int info) XINE_PROTECTE  #define XINE_META_INFO_INPUT_PLUGIN        9  #define XINE_META_INFO_CDINDEX_DISCID      10  #define XINE_META_INFO_TRACK_NUMBER        11 +#define XINE_META_INFO_COMPOSER            12  /********************************************************************* diff --git a/src/audio_out/audio_directx2_out.c b/src/audio_out/audio_directx2_out.c index 5fffd1e2d..e91e919fc 100644 --- a/src/audio_out/audio_directx2_out.c +++ b/src/audio_out/audio_directx2_out.c @@ -31,6 +31,9 @@   *   * Authors:   *   - Frantisek Dvorak <valtri@atlas.cz> + *     - Original version with slotted ring buffer + *   - Matthias Ringald <mringwal@inf.ethz.ch> + *     - non-slotted simpler version for ring buffer handling   *   * Inspiration:   *   - mplayer for workarounding -lguid idea @@ -55,8 +58,8 @@  #define LOG_MODULE "audio_directx2_out"  #define LOG_VERBOSE  /* -#define LOG -*/ + #define LOG + */  #include "xine_internal.h"  #include "audio_out.h" @@ -64,29 +67,33 @@  #define AO_OUT_DIRECTX2_IFACE_VERSION 8 + +/* + * If GAP_TOLERANCE is lower than AO_MAX_GAP, xine will + * try to smooth playback without skipping frames or  + * inserting silence. + */ +#define GAP_TOLERANCE        (AO_MAX_GAP/3) +  /*    * buffer size in miliseconds    * (one second takes 11-192 KB)    */  #define BUFFER_MS 1000 -/*  - * number of parts in the buffer, - * one is always locked for playing +/* + * buffer below this threshold is considered a buffer underrun   */ -#define PARTS 3 +#define BUFFER_MIN_MS 200  /*    * base power factor for volume remapping   */  #define FACTOR 60.0 - -/* experiments */ -/*#define EXACT_WAIT*/ -/*#define EXACT_SLEEP*/ -/*#define PANIC_OVERRUN*/ - +/* + * buffer handler status + */  #define STATUS_START 0  #define STATUS_WAIT 1  #define STATUS_RUNNING 2 @@ -108,12 +115,14 @@ typedef struct {    LPDIRECTSOUND ds;                /* DirectSound device */    LPDIRECTSOUNDBUFFER dsbuffer;    /* DirectSound buffer */ -  DSBPOSITIONNOTIFY events[PARTS]; /* position events */ -  LPDIRECTSOUNDNOTIFY notify;      /* notify interface */    size_t buffer_size;              /* size of the buffer */ -  size_t part_size;                /* second half of buffer */ -  size_t read_size;                /* size of prepared data */ +  size_t write_pos;                /* positition in ring buffer for writing*/  +	 +  int status;                      /* current status of the driver */ +  int paused;                      /* paused mode */ +  int finished;                    /* driver finished */ +  int failed;                      /* don't open modal dialog again */    uint32_t bits;    uint32_t rate; @@ -123,12 +132,6 @@ typedef struct {    int volume;    int muted; -  int status;                      /* current status of the driver */ -  int paused;                      /* paused mode */ -  int finished;                    /* driver finished */ -  int failed;                      /* don't open modal dialog again */ -  int count;                       /* current free part number */ -    pthread_t buffer_service;        /* service thread for operating with DSB */    pthread_cond_t data_cond;        /* signals on data */    pthread_mutex_t data_mutex;      /* data lock */ @@ -141,16 +144,14 @@ typedef struct {   * the linking stage.   *****************************************************************************/  static const GUID IID_IDirectSoundNotify = { -  0xB0210783, 0x89CD, 0x11D0, {0xAF, 0x08, 0x00, 0xA0, 0xC9, 0x25, 0xCD, 0x16} +0xB0210783, 0x89CD, 0x11D0, {0xAF, 0x08, 0x00, 0xA0, 0xC9, 0x25, 0xCD, 0x16}  }; -static int buffer_ready(dx2_driver_t *this); -  /* popup a dialog with error */  static void XINE_FORMAT_PRINTF(1, 2) -	    error_message(const char *fmt, ...) { +error_message(const char *fmt, ...) {    char message[256];    va_list ap; @@ -214,7 +215,7 @@ static LPDIRECTSOUND dsound_create() {  /* destroy direct sound object */  static void dsound_destroy(LPDIRECTSOUND ds) { -  IDirectSound_Release(ds);   +  IDirectSound_Release(ds);  } @@ -266,12 +267,10 @@ static int audio_create_buffers(dx2_driver_t *this) {    HRESULT err;    size_t buffer_size; -  buffer_size = this->rate * this->frame_size * BUFFER_MS / 1000; +  buffer_size = this->rate * BUFFER_MS / 1000 * this->frame_size;    if (buffer_size > DSBSIZE_MAX) buffer_size = DSBSIZE_MAX;    if (buffer_size < DSBSIZE_MIN) buffer_size = DSBSIZE_MIN; -  this->part_size = (buffer_size / PARTS / this->frame_size) * this->frame_size; -  if (!this->part_size) this->part_size = this->frame_size; -  this->buffer_size = this->part_size * PARTS; +  this->buffer_size = buffer_size;    flags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;    dsound_fill_wfx(&wfx, this->bits, this->rate, this->channels, this->frame_size); @@ -282,7 +281,7 @@ static int audio_create_buffers(dx2_driver_t *this) {      return 0;    } -  lprintf("created direct sound buffer, size = %u, part = %u\n", this->buffer_size, this->part_size); +  lprintf("created direct sound buffer, size = %u\n", this->buffer_size);    return 1;  } @@ -293,43 +292,6 @@ static void audio_destroy_buffers(dx2_driver_t *this) {  } -/* create position events */ -static int audio_create_events(dx2_driver_t *this) { -  HANDLE handle[PARTS]; -  HRESULT err; -  int i; - -  for (i = 0; i < PARTS; i++) { -    handle[i] = CreateEvent(NULL, FALSE, FALSE, NULL); -    if (!handle[i]) { -      error_message(_("Unable to create buffer position events.")); -      return 0; -    } -    this->events[i].dwOffset = i * this->part_size; -    this->events[i].hEventNotify = handle[i]; -  } - -  if ((err = IDirectSoundBuffer_QueryInterface(this->dsbuffer, &IID_IDirectSoundNotify, (void **)&this->notify)) != DS_OK) { -    audio_error(this, err, _("Unable to get notification interface")); -    return 0; -  } - -  if ((err = IDirectSoundNotify_SetNotificationPositions(this->notify, PARTS, this->events)) != DS_OK) { -    audio_error(this, err, _("Unable to set notification positions")); -    IDirectSoundNotify_Release(this->notify); -    return 0; -  } - -  return 1; -} - - -/* destroy notification interface */ -static void audio_destroy_events(dx2_driver_t *this) { -  IDirectSoundNotify_Release(this->notify); -} - -  /* start playback */  static int audio_play(dx2_driver_t *this) {    HRESULT err; @@ -385,8 +347,7 @@ static int audio_seek(dx2_driver_t *this, size_t pos) {  /* flush audio buffers */  static int audio_flush(dx2_driver_t *this) {    this->status = STATUS_WAIT; -  this->count = 0; -  this->read_size = 0; +  this->write_pos = 0;    return audio_seek(this, 0);  } @@ -421,12 +382,12 @@ static int audio_fill(dx2_driver_t *this, char *data, size_t size) {    HRESULT err;    /* lock a part of the buffer, begin position on free space */ -  err = IDirectSoundBuffer_Lock(this->dsbuffer, (this->count * this->part_size + this->read_size) % this->buffer_size, size, &ptr1, &size1, &ptr2, &size2, 0); +  err = IDirectSoundBuffer_Lock(this->dsbuffer, this->write_pos, size, &ptr1, &size1, &ptr2, &size2, 0);    /* try to restore the buffer, if necessary */    if (err == DSERR_BUFFERLOST) {      xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": buffer lost, tryig to restore\n"));      IDirectSoundBuffer_Restore(this->dsbuffer); -    err = IDirectSoundBuffer_Lock(this->dsbuffer, (this->count * this->part_size + this->read_size) % this->buffer_size, size, &ptr1, &size1, &ptr2, &size2, 0);  } +  err = IDirectSoundBuffer_Lock(this->dsbuffer, this->write_pos, size, &ptr1, &size1, &ptr2, &size2, 0);  }    if (err != DS_OK) {      audio_error(this, err, _("Couldn't lock direct sound buffer"));      return 0; @@ -436,19 +397,15 @@ static int audio_fill(dx2_driver_t *this, char *data, size_t size) {    if (ptr1 && size1) xine_fast_memcpy(ptr1, data, size1);    if (ptr2 && size2) xine_fast_memcpy(ptr2, data + size1, size2); -  this->read_size += size; +  // this->read_size += size; +  this->write_pos = (this->write_pos + size ) % this->buffer_size; +  lprintf("size %u, write_pos %u\n", size, this->write_pos);	    if ((err = IDirectSoundBuffer_Unlock(this->dsbuffer, ptr1, size1, ptr2, size2)) != DS_OK) {      audio_error(this, err, _("Couldn't unlock direct sound buffer"));      return 0;    } -  /* signal, if are waiting and need wake up */ -  if ((this->status == STATUS_WAIT) && buffer_ready(this)) { -    lprintf("buffer ready, waking up\n"); -    pthread_cond_signal(&this->data_cond); -  } -    return 1;  } @@ -458,28 +415,28 @@ static int mode2channels(uint32_t mode) {    int channels;    switch(mode) { -  case AO_CAP_MODE_MONO: -    channels = 1; -    break; - -  case AO_CAP_MODE_STEREO: -    channels = 2; -    break; - -  case AO_CAP_MODE_4CHANNEL: -    channels = 4; -    break; -   -  case AO_CAP_MODE_5CHANNEL: -    channels = 5; -    break; - -  case AO_CAP_MODE_5_1CHANNEL: -    channels = 6; -    break; - -  default: -    return 0; +    case AO_CAP_MODE_MONO: +      channels = 1; +      break; + +    case AO_CAP_MODE_STEREO: +      channels = 2; +      break; + +    case AO_CAP_MODE_4CHANNEL: +      channels = 4; +      break; + +    case AO_CAP_MODE_5CHANNEL: +      channels = 5; +      break; + +    case AO_CAP_MODE_5_1CHANNEL: +      channels = 6; +      break; + +    default: +      return 0;    }    return channels; @@ -556,109 +513,96 @@ static int test_capabilities(dx2_driver_t *this) {  /* size of free space in the ring buffer */  static size_t buffer_free_size(dx2_driver_t *this) { -  size_t used_full_size; +	 +  int ret; +  size_t play_pos; +	size_t free_space; -  used_full_size = this->read_size + ((this->status != STATUS_WAIT) ? this->part_size : 0); -  _x_assert(used_full_size <= this->buffer_size); -  return this->buffer_size - used_full_size; +  // get current play pos +	ret = audio_tell(this, &play_pos); +	if (!ret) +		return 0; +	 +	// calc free space (-1) +	free_space = (this->buffer_size + play_pos - this->write_pos - 1) % this->buffer_size; +	 +	return free_space;  } -/* enough data in the ring buffer for playing next part? */ -static int buffer_ready(dx2_driver_t *this) { -  return this->read_size >= this->part_size; +/* size of occupied space in the ring buffer */ +static size_t buffer_occupied_size(dx2_driver_t *this) { +  int ret; +  size_t play_pos; +	size_t used_space; + +  // get current play pos +	ret = audio_tell(this, &play_pos); +	if (!ret) return 0; +	 +	// calc used space +	used_space = (this->buffer_size + this->write_pos - play_pos) % this->buffer_size; +	 +	return used_space;  }  /* service thread working with direct sound buffer */  static void *buffer_service(void *data) {    dx2_driver_t *this = (dx2_driver_t *)data; -  HANDLE handles[PARTS];    DWORD ret; -  int i; -#if defined(EXACT_SLEEP) || defined(EXACT_WAIT) -  size_t play_pos, req_delay; -#endif +  size_t play_pos; +  size_t buffer_min; +  size_t data_in_buffer;    /* prepare empty buffer */    audio_flush(this); -  for (i = 0; i < PARTS; i++) handles[i] = this->events[i].hEventNotify; -   +  /* prepare min buffer fill */ +  buffer_min = BUFFER_MIN_MS * this->rate / 1000 * this->frame_size; +    /* we live! */    pthread_mutex_lock(&this->data_mutex);    pthread_cond_signal(&this->data_cond);    pthread_mutex_unlock(&this->data_mutex);    while (!this->finished) { +      pthread_mutex_lock(&this->data_mutex); -    if (!buffer_ready(this)) { -      if (!audio_stop(this)) goto fail; -      lprintf("no data (count=%d,free=%" PRIsizet ",avail=%" PRIsizet "), sleeping...\n", this->count, buffer_free_size(this), this->read_size); -      this->status = STATUS_WAIT; -      pthread_cond_wait(&this->data_cond, &this->data_mutex); -      lprintf("wake up (count=%d,free=%" PRIsizet "--,avail=%" PRIsizet ")\n", this->count, buffer_free_size(this), this->read_size); -      if (this->finished) goto finished; -      if (!audio_seek(this, this->count * this->part_size)) goto fail; -      if (!this->paused) { -        if (!audio_play(this)) goto fail; -      } -      this->status = STATUS_RUNNING; -      this->count = (this->count + 1) % PARTS; -      this->read_size -= this->part_size; -      pthread_mutex_unlock(&this->data_mutex); -      lprintf("wait for playback (newcount=%d,free=%" PRIsizet ",avail=%" PRIsizet ")\n", this->count, buffer_free_size(this), this->read_size); -      do { -        ret = WaitForMultipleObjects(PARTS, handles, FALSE, 250) - WAIT_OBJECT_0; +    switch( this->status){ + +			case STATUS_WAIT: + +        // pre: stop/buffer flushed +        lprintf("no data, sleeping...\n"); +        pthread_cond_wait(&this->data_cond, &this->data_mutex); +        lprintf("woke up (write_pos=%d,free=%" PRIsizet")\n", this->write_pos, buffer_free_size(this));          if (this->finished) goto finished; -      } while (ret > PARTS); -      lprintf("playback started (newcount=%d,ev=%d,free=%" PRIsizet ",avail=%" PRIsizet ")\n", this->count, ret, buffer_free_size(this), this->read_size); -      _x_assert(ret == ((PARTS + this->count - 1) % PARTS)); -    } else { -      this->count = (this->count + 1) % PARTS; -      this->read_size -= this->part_size; -      pthread_mutex_unlock(&this->data_mutex); -    } -    lprintf("waiting for sound event(count=%d,free=%" PRIsizet ",avail=%" PRIsizet ")...\n", this->count, buffer_free_size(this), this->read_size); -    do { -      ret = WaitForMultipleObjects(PARTS, handles, FALSE, 250) - WAIT_OBJECT_0; -      if (this->finished) goto finished; -    } while (ret > PARTS); -    lprintf("end wait(ev=%" PRIdword ",count=%d,free=%" PRIsizet ",avail=%" PRIsizet ")\n", ret, this->count, buffer_free_size(this), this->read_size); -#ifdef PANIC_OVERRUN -    _x_abort(ret == this->count); -#else -    if (ret != this->count) { -      xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": play cursor overran, flushing buffers\n")); -      pthread_mutex_lock(&this->data_mutex); -      if (!audio_stop(this)) goto fail; -      if (!audio_flush(this)) goto fail; -      pthread_mutex_unlock(&this->data_mutex); -    } -#endif -     -#if defined(EXACT_SLEEP) || defined(EXACT_WAIT) -    /* ugly hack: wait for right time, + little over for sure */ -    pthread_mutex_lock(&this->data_mutex); -    if (!audio_tell(this, &play_pos)) goto fail; -    req_delay = (this->buffer_size + play_pos - this->count * this->part_size) % this->buffer_size; -    pthread_mutex_unlock(&this->data_mutex); -    if (req_delay > (this->buffer_size >> 1)) { -      long delay; - -      delay = 1000 * (this->buffer_size - req_delay) / (this->frame_size * this->rate) + 1 + BUFFER_MS / PARTS / 4; -      xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": delayed by %ld msec\n"), delay); -      printf("should be delayed %ld msec\n", delay); -#ifdef EXACT_SLEEP -      xine_usec_sleep(delay * 1000); -#endif -#ifdef EXACT_WAIT -      WaitForMultipleObjects(PARTS, handles, FALSE, delay); -#endif +        if (!audio_seek(this, 0)) goto fail; +        if (!this->paused) { +					if (!audio_play(this)) goto fail; +        } +        this->status = STATUS_RUNNING; +        pthread_mutex_unlock(&this->data_mutex); +				break; + +      case STATUS_RUNNING: + +        // check for buffer underrun +        data_in_buffer =  buffer_occupied_size(this); +        if ( data_in_buffer < buffer_min){ +          xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": play cursor overran (data %u, min %u), flushing buffers\n"), +                   data_in_buffer, buffer_min); +          if (!audio_stop(this)) goto fail; +          if (!audio_flush(this)) goto fail; +        } +        pthread_mutex_unlock(&this->data_mutex); + +        // just wait BUFFER_MIN_MS before next check +        xine_usec_sleep(BUFFER_MIN_MS * 1000); +				break;      } -#endif    } -    return NULL;  fail: @@ -683,15 +627,15 @@ static int ao_dx2_get_property(ao_driver_t *this_gen, int property) {    switch(property) { -  case AO_PROP_MIXER_VOL: -  case AO_PROP_PCM_VOL: -    return this->volume; +    case AO_PROP_MIXER_VOL: +    case AO_PROP_PCM_VOL: +      return this->volume; -  case AO_PROP_MUTE_VOL: -    return this->muted; +    case AO_PROP_MUTE_VOL: +      return this->muted; -  default: -    return 0; +    default: +      return 0;    }  } @@ -702,26 +646,26 @@ static int ao_dx2_set_property(ao_driver_t *this_gen, int property, int value) {    switch(property) { -  case AO_PROP_MIXER_VOL: -  case AO_PROP_PCM_VOL: -    lprintf("set volume to %d\n", value); -    pthread_mutex_lock(&this->data_mutex); -    if (!this->muted) { -      if (this->dsbuffer && !audio_set_volume(this, value)) return ~value; -    } -    this->volume = value; -    pthread_mutex_unlock(&this->data_mutex); -    break; +    case AO_PROP_MIXER_VOL: +    case AO_PROP_PCM_VOL: +      lprintf("set volume to %d\n", value); +      pthread_mutex_lock(&this->data_mutex); +      if (!this->muted) { +        if (this->dsbuffer && !audio_set_volume(this, value)) return ~value; +      } +      this->volume = value; +      pthread_mutex_unlock(&this->data_mutex); +      break; -  case AO_PROP_MUTE_VOL: -    pthread_mutex_lock(&this->data_mutex); -    if (this->dsbuffer && !audio_set_volume(this, value ? 0 : this->volume)) return ~value; -    this->muted = value; -    pthread_mutex_unlock(&this->data_mutex); -    break; +    case AO_PROP_MUTE_VOL: +      pthread_mutex_lock(&this->data_mutex); +      if (this->dsbuffer && !audio_set_volume(this, value ? 0 : this->volume)) return ~value; +      this->muted = value; +      pthread_mutex_unlock(&this->data_mutex); +      break; -  default: -    return ~value; +    default: +      return ~value;    } @@ -747,18 +691,17 @@ static int ao_dx2_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int    this->status = STATUS_START;    if (!audio_create_buffers(this)) return 0; -  if (!audio_create_events(this)) goto fail_buffers; -  if (!audio_set_volume(this, this->volume)) goto fail_events; +  if (!audio_set_volume(this, this->volume)) goto fail_buffers;    if (pthread_cond_init(&this->data_cond, NULL) != 0) {      xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": can't create pthread condition: %s\n"), strerror(errno)); -    goto fail_events; +    goto fail_buffers;    }    if (pthread_mutex_init(&this->data_mutex, NULL) != 0) {      xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": can't create pthread mutex: %s\n"), strerror(errno));      goto fail_cond;    } -   +    /* creating the service thread and waiting for its signal */    pthread_mutex_lock(&this->data_mutex);    if (pthread_create(&this->buffer_service, NULL, buffer_service, this) != 0) { @@ -775,8 +718,6 @@ fail_mutex:    pthread_mutex_destroy(&this->data_mutex);  fail_cond:    pthread_cond_destroy(&this->data_cond); -fail_events: -  audio_destroy_events(this);  fail_buffers:    audio_destroy_buffers(this);    return 0; @@ -803,22 +744,26 @@ static int ao_dx2_bytes_per_frame(ao_driver_t *this_gen) {  static int ao_dx2_delay(ao_driver_t *this_gen) {    dx2_driver_t *this = (dx2_driver_t *)this_gen; -  int frames; -  size_t final_pos, play_pos; - -  if (this->status != STATUS_RUNNING) return this->read_size / this->frame_size; +  int frames = 0; +  int ret; +  size_t play_pos;    pthread_mutex_lock(&this->data_mutex); -  if (!audio_tell(this, &play_pos)) { -    pthread_mutex_unlock(&this->data_mutex); -    return 0; -  } -  final_pos = this->read_size + (((PARTS + this->count - 1) % PARTS) + 1) * this->part_size - 1; -  frames = (this->buffer_size + final_pos - play_pos) % this->buffer_size / this->frame_size; + +  if (this->status != STATUS_RUNNING){ +    frames = this->write_pos / this->frame_size; +  } else { +    ret = audio_tell(this, &play_pos); +    if (ret){ +      frames = buffer_occupied_size(this) / this->frame_size; +    } +  }	 +    pthread_mutex_unlock(&this->data_mutex);  #ifdef LOG -  if ((rand() % 10) == 0) lprintf("frames=%d, play_pos=%" PRIdword ", block=%" PRIsizet "..%" PRIsizet "\n", frames, play_pos, final_pos - this->part_size + 1, final_pos); +  if ((rand() % 10) == 0) +    lprintf("frames=%d, play_pos=%" PRIdword ", write_pos=%u\n", frames, play_pos, this->write_pos);  #endif    return frames; @@ -840,7 +785,7 @@ static int ao_dx2_write(ao_driver_t *this_gen, int16_t* audio_data, uint32_t num      while (((free_size = buffer_free_size(this)) == 0) && !this->finished) {        lprintf("buffer full, waiting\n");        pthread_mutex_unlock(&this->data_mutex); -      xine_usec_sleep(1000 * BUFFER_MS / PARTS / 5); +      xine_usec_sleep(1000 * BUFFER_MS / 10);        pthread_mutex_lock(&this->data_mutex);      }      if (free_size >= input_size) size = input_size; @@ -856,6 +801,12 @@ static int ao_dx2_write(ao_driver_t *this_gen, int16_t* audio_data, uint32_t num      input_size -= size;    } +  /* signal, if are waiting and need wake up */ +  if ((this->status == STATUS_WAIT) && (buffer_occupied_size(this) > BUFFER_MIN_MS * this->rate / 1000 * this->frame_size)) { +    lprintf("buffer ready, waking up\n"); +    pthread_cond_signal(&this->data_cond); +  } +    return 1;  } @@ -881,7 +832,6 @@ static void ao_dx2_close(ao_driver_t *this_gen) {    if (pthread_mutex_destroy(&this->data_mutex) != 0) {      xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": can't destroy pthread mutex: %s\n"), strerror(errno));    } -  audio_destroy_events(this);    audio_destroy_buffers(this);  } @@ -896,12 +846,8 @@ static void ao_dx2_exit(ao_driver_t *this_gen) {  } -/*  - * TODO: check - */  static int ao_dx2_get_gap_tolerance(ao_driver_t *this_gen) { -  /* half of part of the buffer in pts (1 msec = 90 pts) */ -  return (90 * (BUFFER_MS / PARTS)) >> 1; +  return GAP_TOLERANCE;  } @@ -910,36 +856,36 @@ static int ao_dx2_control(ao_driver_t *this_gen, int cmd, ...) {    switch(cmd) { -  case AO_CTRL_PLAY_PAUSE: -    lprintf("control pause\n"); -    pthread_mutex_lock(&this->data_mutex); -    if (!this->paused) { -      audio_stop(this); -      this->paused = 1; -    } -    pthread_mutex_unlock(&this->data_mutex); -    break; +    case AO_CTRL_PLAY_PAUSE: +      lprintf("control pause\n"); +      pthread_mutex_lock(&this->data_mutex); +      if (!this->paused) { +        audio_stop(this); +        this->paused = 1; +      } +      pthread_mutex_unlock(&this->data_mutex); +      break; -  case AO_CTRL_PLAY_RESUME: -    lprintf("control resume\n"); -    pthread_mutex_lock(&this->data_mutex); -    if (this->paused) { -      if (this->status != STATUS_WAIT) audio_play(this); -      this->paused = 0; -    } -    pthread_mutex_unlock(&this->data_mutex); -    break; -     -  case AO_CTRL_FLUSH_BUFFERS: -    lprintf("control flush\n"); -    pthread_mutex_lock(&this->data_mutex); -    audio_stop(this); -    audio_flush(this); -    pthread_mutex_unlock(&this->data_mutex); -    break; +    case AO_CTRL_PLAY_RESUME: +      lprintf("control resume\n"); +      pthread_mutex_lock(&this->data_mutex); +      if (this->paused) { +        if (this->status != STATUS_WAIT) audio_play(this); +        this->paused = 0; +      } +      pthread_mutex_unlock(&this->data_mutex); +      break; + +    case AO_CTRL_FLUSH_BUFFERS: +      lprintf("control flush\n"); +      pthread_mutex_lock(&this->data_mutex); +      audio_stop(this); +      audio_flush(this); +      pthread_mutex_unlock(&this->data_mutex); +      break; -  default: -    xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": unknown control command %d\n"), cmd); +    default: +      xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": unknown control command %d\n"), cmd);    } diff --git a/src/audio_out/audio_pulse_out.c b/src/audio_out/audio_pulse_out.c index dfae98c31..4b66fbaed 100644 --- a/src/audio_out/audio_pulse_out.c +++ b/src/audio_out/audio_pulse_out.c @@ -218,7 +218,8 @@ static void __xine_pa_sink_info_callback(pa_context *c, const pa_sink_input_info    this->cvolume = info->volume;    this->swvolume = pa_cvolume_avg(&info->volume); -#ifdef HAVE_PULSEAUDIO_0_9_7 +#if PA_PROTOCOL_VERSION >= 11 +  /* PulseAudio 0.9.7 and newer */    this->muted = info->mute;  #else    this->muted = pa_cvolume_is_muted (&this->cvolume); @@ -665,7 +666,8 @@ static int ao_pulse_set_property (ao_driver_t *this_gen, int property, int value        this->muted = value; -#ifdef HAVE_PULSEAUDIO_0_9_7 +#if PA_PROTOCOL_VERSION >= 11 +      /* PulseAudio 0.9.7 and newer */        o = pa_context_set_sink_input_mute(this->context, pa_stream_get_index(this->stream),                                             value, __xine_pa_context_success_callback, this);  #else diff --git a/src/demuxers/demux_flac.c b/src/demuxers/demux_flac.c index e6d6f6376..0cc2fc6b6 100644 --- a/src/demuxers/demux_flac.c +++ b/src/demuxers/demux_flac.c @@ -232,6 +232,9 @@ static int open_flac_file(demux_flac_t *flac) {              } else if ((strncasecmp ("ARTIST=", comment, 7) == 0)                  && (length - 7 > 0)) {                _x_meta_info_set_utf8 (flac->stream, XINE_META_INFO_ARTIST, comment + 7); +            } else if ((strncasecmp ("COMPOSER=", comment, 9) == 0) +                && (length - 9 > 0)) { +              _x_meta_info_set_utf8 (flac->stream, XINE_META_INFO_COMPOSER, comment + 9);              } else if ((strncasecmp ("ALBUM=", comment, 6) == 0)                  && (length - 6 > 0)) {                _x_meta_info_set_utf8 (flac->stream, XINE_META_INFO_ALBUM, comment + 6); diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c index 6c2adc67f..55e06c033 100644 --- a/src/demuxers/demux_ts.c +++ b/src/demuxers/demux_ts.c @@ -249,6 +249,7 @@ typedef struct {    int64_t          packet_count;    int              corrupted_pes;    uint32_t         buffered_bytes; +  int              autodetected;  } demux_ts_media; @@ -932,9 +933,11 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts,        m->buf->free_buffer(m->buf);        m->buf = NULL; -      if (m->corrupted_pes > CORRUPT_PES_THRESHOLD) { -        if (this->videoPid == m->pid) +      if (m->corrupted_pes > CORRUPT_PES_THRESHOLD && m->autodetected) { +        if (this->videoPid == m->pid) {            this->videoPid = INVALID_PID; +          this->last_pmt_crc = 0; +        }        } else {          m->corrupted_pes++;          xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,  @@ -1855,6 +1858,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) {          } else if (!found) {  	  this->videoPid = pid;  	  this->videoMedia = this->media_num; +	  this->media[this->videoMedia].autodetected = 1;  	  demux_ts_pes_new(this, this->media_num++, pid, this->video_fifo, 0x100 + pes_stream_id);          } @@ -2269,6 +2273,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,    for (i = 0; i < MAX_PIDS; i++) {      this->media[i].pid = INVALID_PID;      this->media[i].buf = NULL; +    this->media[i].autodetected = 0;    }    for (i = 0; i < MAX_PMTS; i++) { diff --git a/src/demuxers/id3.c b/src/demuxers/id3.c index 3c03fdc68..ba8f50676 100644 --- a/src/demuxers/id3.c +++ b/src/demuxers/id3.c @@ -767,6 +767,7 @@ static int id3v24_interp_frame(input_plugin_t *input,          break;        case ( FOURCC_TAG('T', 'Y', 'E', 'R') ): +      case ( FOURCC_TAG('T', 'D', 'R', 'C') ):          _x_meta_info_set_generic(stream, XINE_META_INFO_YEAR, buf + 1, id3_encoding[enc]);          break; diff --git a/src/libfaad/xine_faad_decoder.c b/src/libfaad/xine_faad_decoder.c index ae71af155..9c657610e 100644 --- a/src/libfaad/xine_faad_decoder.c +++ b/src/libfaad/xine_faad_decoder.c @@ -275,7 +275,32 @@ static void faad_decode_audio ( faad_decoder_t *this, int end_frame ) {        lprintf("decoded %d/%d output %ld\n",                used, this->size, this->faac_finfo.samples ); -       + +      /* Performing necessary channel reordering because aac uses a different +       * layout than alsa: +       * +       *  aac 5.1 channel layout: c l r ls rs lfe +       * alsa 5.1 channel layout: l r ls rs c lfe +       * +       * Reordering is only necessary for 5.0 and above. Currently only 5.0 +       * and 5.1 is being taken care of, the rest will stay in the wrong order +       * for now. +       * +       * WARNING: the following needs a output format of 16 bits per sample. +       *    TODO: - reorder while copying (in the while() loop) and optimizing +       */ +      if(this->num_channels == 5 || this->num_channels == 6) +      { +        int i         = 0; +        uint16_t* buf = (uint16_t*)(sample_buffer); + +        for(; i < this->faac_finfo.samples; i += this->num_channels) { +          uint16_t center         = buf[i]; +          *((uint64_t*)(buf + i)) = *((uint64_t*)(buf + i + 1)); +          buf[i + 4]              = center; +        } +      } +        while( decoded ) {          audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); diff --git a/src/libspudvb/xine_spudvb_decoder.c b/src/libspudvb/xine_spudvb_decoder.c index 957374799..8a4fe6926 100644 --- a/src/libspudvb/xine_spudvb_decoder.c +++ b/src/libspudvb/xine_spudvb_decoder.c @@ -48,6 +48,7 @@ typedef struct {  } page_t;  typedef struct { +  int                   version_number;    int 			width, height;    int                   empty;    int 			depth; @@ -166,20 +167,18 @@ static void update_region (dvb_spu_decoder_t * this, int region_id, int region_w        lprintf( "can't allocate mem for region %d\n", region_id );        return;      } -    fill_color = 15;      fill = 1;    } - +      if ( fill ) {      memset( reg->img, fill_color, region_width*region_height );      reg->empty = 1;  #ifdef LOG -  printf("SPUDVB : FILL REGION %d\n", region_id); +    printf("SPUDVB : FILL REGION %d\n", region_id);  #endif    }    reg->width = region_width;    reg->height = region_height; -  page->regions[region_id].is_visible = 1;  } @@ -409,17 +408,18 @@ static void process_page_composition_segment (dvb_spu_decoder_t * this)    const int j = dvbsub->i + segment_length;    dvbsub->page.page_time_out = dvbsub->buf[dvbsub->i++]; +  if ( dvbsub->page.page_time_out>6 ) /* some timeout are insane, e.g. 65s ! */ +    dvbsub->page.page_time_out = 6; -  dvbsub->page.page_version_number = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; +  int version = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; +  if ( version == dvbsub->page.page_version_number ) +    return; +  dvbsub->page.page_version_number = version;    dvbsub->page.page_state = (dvbsub->buf[dvbsub->i] & 0x0c) >> 2;    dvbsub->i++; -  if (dvbsub->page.page_state==2) { -    int r; -    for (r=0; r<MAX_REGIONS; r++) -      dvbsub->page.regions[r].is_visible = 0; -  } -  else if ( dvbsub->page.page_state!=0 && dvbsub->page.page_state!=1 ) { -    return; +  int r; +  for (r=0; r<MAX_REGIONS; r++) { /* reset */ +    dvbsub->page.regions[r].is_visible = 0;    }    while (dvbsub->i < j) { @@ -432,6 +432,7 @@ static void process_page_composition_segment (dvb_spu_decoder_t * this)      dvbsub->page.regions[region_id].x = region_x;      dvbsub->page.regions[region_id].y = region_y; +    dvbsub->page.regions[region_id].is_visible = 1;    }  } @@ -465,6 +466,11 @@ static void process_region_composition_segment (dvb_spu_decoder_t * this)    if(region_id>=MAX_REGIONS)      return; + +  if ( dvbsub->regions[region_id].version_number == region_version_number ) +    return; + +  dvbsub->regions[region_id].version_number = region_version_number;    /* Check if region size has changed and fill background. */    update_region (this, region_id, region_width, region_height, region_fill_flag, region_4_bit_pixel_code); @@ -673,6 +679,9 @@ static void draw_subtitles (dvb_spu_decoder_t * this)    printf("SPUDVB: this->vpts=%llu\n",this->vpts);  #endif    for ( r=0; r<MAX_REGIONS; r++ ) { +#ifdef LOG +    printf("SPUDVB : region=%d, visible=%d, osd=%d, empty=%d\n", r, this->dvbsub->page.regions[r].is_visible, this->dvbsub->regions[r].osd?1:0, this->dvbsub->regions[r].empty ); +#endif      if ( this->dvbsub->page.regions[r].is_visible && this->dvbsub->regions[r].osd && !this->dvbsub->regions[r].empty ) {        this->stream->osd_renderer->set_position( this->dvbsub->regions[r].osd, this->dvbsub->page.regions[r].x, this->dvbsub->page.regions[r].y );        this->stream->osd_renderer->show( this->dvbsub->regions[r].osd, this->vpts ); @@ -761,6 +770,9 @@ static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf)        this->vpts = vpts;    } +  /* completely ignore pts since it makes a lot of problems with various providers */ +  this->vpts = 0; +    /* process the pes section */    const int PES_packet_length = this->pes_pkt_size; @@ -791,10 +803,10 @@ static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf)        /* SEGMENT_DATA_FIELD */        switch (segment_type) {        case 0x10: -	process_page_composition_segment (this); +	process_page_composition_segment(this);  	break;        case 0x11: -	process_region_composition_segment (this); +	process_region_composition_segment(this);  	break;        case 0x12:   	process_CLUT_definition_segment(this); @@ -802,8 +814,8 @@ static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf)        case 0x13:  	process_object_data_segment (this);  	break; -      case 0x80:		/* Page is now completely rendered */ -	draw_subtitles( this ); +      case 0x80:		 +	draw_subtitles( this ); /* Page is now completely rendered */  	break;        default:  	return;   @@ -824,7 +836,9 @@ static void spudec_reset (spu_decoder_t * this_gen)    for ( i=0; i<MAX_REGIONS; i++ ) {      if ( this->dvbsub->regions[i].osd )        this->stream->osd_renderer->hide(this->dvbsub->regions[i].osd, 0); +    this->dvbsub->regions[i].version_number = -1;    } +  this->dvbsub->page.page_version_number = -1;    pthread_mutex_unlock(&this->dvbsub_osd_mutex);  } diff --git a/src/video_out/video_out_directx.c b/src/video_out/video_out_directx.c index f1136eab0..529968bec 100644 --- a/src/video_out/video_out_directx.c +++ b/src/video_out/video_out_directx.c @@ -117,7 +117,7 @@ typedef struct {    yuv2rgb_t               *yuv2rgb;         /* used for format conversion */    int			   mode;	    /* rgb mode */    int		           bytespp;	    /* rgb bits per pixel */ - +  DDPIXELFORMAT primary_pixel_format;    alphablend_t             alphablend_extra_data;  } win32_driver_t; @@ -367,8 +367,9 @@ static boolean CreateSecondary( win32_driver_t * win32_driver, int width, int he    lprintf("CreateSecondary() - Falling back to back buffer same as primary\n");    lprintf("CreateSecondary() - act_format = (NATIVE) %d\n", IMGFMT_NATIVE); -  ddsd.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; +  ddsd.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; +  ddsd.ddpfPixelFormat = win32_driver->primary_pixel_format;    win32_driver->act_format = IMGFMT_NATIVE;    if( IDirectDraw_CreateSurface( win32_driver->ddobj, &ddsd, &win32_driver->secondary, 0 ) == DD_OK ) @@ -429,6 +430,10 @@ static boolean CheckPixelFormat( win32_driver_t * win32_driver )        Error( 0, "IDirectDrawSurface_GetPixelFormat ( CheckPixelFormat ) : error 0x%lx", result );        return 0;      } +	 +  /* store pixel format for CreateSecondary */ + +  win32_driver->primary_pixel_format = ddpf;    /* TODO : support paletized video modes */ @@ -478,6 +483,7 @@ static boolean CheckPixelFormat( win32_driver_t * win32_driver )  	win32_driver->mode = MODE_15_BGR;      } +	lprintf("win32 mode: %u\n", win32_driver->mode);    return TRUE;  } diff --git a/src/video_out/video_out_raw.c b/src/video_out/video_out_raw.c index 45cfc1eda..0d4bf445a 100644 --- a/src/video_out/video_out_raw.c +++ b/src/video_out/video_out_raw.c @@ -473,7 +473,7 @@ static int raw_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *da  static uint32_t raw_get_capabilities (vo_driver_t *this_gen)  { -  uint32_t capabilities = VO_CAP_YV12 | VO_CAP_YUY2; +  uint32_t capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP;    return capabilities;  } diff --git a/src/video_out/video_out_sdl.c b/src/video_out/video_out_sdl.c index b53d1d31c..89150f5d0 100644 --- a/src/video_out/video_out_sdl.c +++ b/src/video_out/video_out_sdl.c @@ -469,9 +469,11 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi    sdl_driver_t         *this;    const SDL_VideoInfo  *vidInfo; -#ifdef HAVE_X11 +#if defined(HAVE_X11) || defined(WIN32)    static char           SDL_windowhack[32];    x11_visual_t         *visual = (x11_visual_t *) visual_gen; +#endif +#ifdef HAVE_X11    XWindowAttributes     window_attributes;  #endif @@ -502,14 +504,18 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi    _x_vo_scale_init( &this->sc, 0, 0, config);    this->sc.frame_output_cb   = visual->frame_output_cb;    this->sc.user_data         = visual->user_data; - -  /* set SDL to use our existing X11 window */ -  sprintf(SDL_windowhack,"SDL_WINDOWID=0x%x", (uint32_t) this->drawable ); -  putenv(SDL_windowhack);  #else    _x_vo_scale_init( &this->sc, 0, 0, config );  #endif +#if defined(HAVE_X11) || defined(WIN32) +  /* set SDL to use our existing X11/win32 window */ +  if (visual->d){ +    sprintf(SDL_windowhack,"SDL_WINDOWID=0x%x", (uint32_t) visual->d); +    putenv(SDL_windowhack); +  } +#endif +    if ((SDL_Init (SDL_INIT_VIDEO)) < 0) {      xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_sdl: open_plugin - sdl video initialization failed.\n");      return NULL; diff --git a/src/xine-utils/utils.c b/src/xine-utils/utils.c index 57a92623c..689b68502 100644 --- a/src/xine-utils/utils.c +++ b/src/xine-utils/utils.c @@ -456,23 +456,22 @@ char *xine_chomp(char *str) {   * a thread-safe usecond sleep   */  void xine_usec_sleep(unsigned usec) { -#if 0 -#if HAVE_NANOSLEEP +#ifdef WIN32 +  /* select does not work on win32 */ +  Sleep(usec / 1000); +#else +#  if 0 +#    if HAVE_NANOSLEEP    /* nanosleep is prefered on solaris, because it's mt-safe */    struct timespec ts, remaining; -    ts.tv_sec =   usec / 1000000;    ts.tv_nsec = (usec % 1000000) * 1000;    while (nanosleep (&ts, &remaining) == -1 && errno == EINTR)      ts = remaining; -#else -#  if WIN32 -  Sleep(usec / 1000); -#  else +#    else    usleep(usec); -#  endif -#endif -#else +#    endif +#  else    if (usec < 10000) {        usec = 10000;    } @@ -480,6 +479,7 @@ void xine_usec_sleep(unsigned usec) {    tm.tv_sec  = usec / 1000000;    tm.tv_usec = usec % 1000000;    select(0, 0, 0, 0, &tm); +#  endif  #endif  } | 
