* modules/demux/mpeg: Added DVB stream type for A/52 streams (0x6),
authorChristophe Massiot <massiot@videolan.org>
Sun, 20 Oct 2002 12:23:48 +0000 (12:23 +0000)
committerChristophe Massiot <massiot@videolan.org>
Sun, 20 Oct 2002 12:23:48 +0000 (12:23 +0000)
* include/vlc_threads.h: Avoid locking the interface,
* ALL: reworked all audio output plug-ins to correctly take into account
  i_channels. At present this is known to break OSS, probably others.

22 files changed:
include/aout_internal.h
include/audio_output.h
include/vlc_threads.h
modules/audio_filter/converter/a52tofloat32.c
modules/audio_output/alsa.c
modules/audio_output/arts.c
modules/audio_output/directx.c
modules/audio_output/esd.c
modules/audio_output/file.c
modules/audio_output/oss.c
modules/audio_output/waveout.c
modules/codec/mpeg_video/idct/idctaltivec.c
modules/codec/mpeg_video/synchro.c
modules/demux/mpeg/system.c
modules/demux/mpeg/system.h
modules/demux/mpeg/ts.c
src/audio_output/common.c
src/audio_output/filters.c
src/audio_output/input.c
src/audio_output/intf.c
src/audio_output/mixer.c
src/audio_output/output.c

index a1210fb..4dbb532 100644 (file)
@@ -2,7 +2,7 @@
  * aout_internal.h : internal defines for audio output
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: aout_internal.h,v 1.22 2002/09/27 23:38:04 massiot Exp $
+ * $Id: aout_internal.h,v 1.23 2002/10/20 12:23:47 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -260,6 +260,8 @@ VLC_EXPORT( aout_buffer_t *, aout_OutputNextBuffer, ( aout_instance_t *, mtime_t
 /* From common.c : */
 VLC_EXPORT( int, aout_FormatNbChannels, ( audio_sample_format_t * p_format ) );
 void aout_FormatPrepare( audio_sample_format_t * p_format );
+VLC_EXPORT( void, aout_FormatPrint, ( aout_instance_t * p_aout, const char * psz_text, audio_sample_format_t * p_format ) );
+VLC_EXPORT( void, aout_FormatsPrint, ( aout_instance_t * p_aout, const char * psz_text, audio_sample_format_t * p_format1, audio_sample_format_t * p_format2 ) );
 void aout_FifoInit( aout_instance_t *, aout_fifo_t *, u32 );
 mtime_t aout_FifoNextStart( aout_instance_t *, aout_fifo_t * );
 void aout_FifoPush( aout_instance_t *, aout_fifo_t *, aout_buffer_t * );
index 1f413c4..716245c 100644 (file)
@@ -2,7 +2,7 @@
  * audio_output.h : audio output interface
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: audio_output.h,v 1.68 2002/09/30 21:32:31 massiot Exp $
+ * $Id: audio_output.h,v 1.69 2002/10/20 12:23:47 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -178,4 +178,5 @@ VLC_EXPORT( int, aout_VolumeInfos, ( aout_instance_t *, audio_volume_t * ) );
 VLC_EXPORT( int, aout_VolumeUp, ( aout_instance_t *, int, audio_volume_t * ) );
 VLC_EXPORT( int, aout_VolumeDown, ( aout_instance_t *, int, audio_volume_t * ) );
 VLC_EXPORT( int, aout_Restart, ( aout_instance_t * p_aout ) );
+VLC_EXPORT( void, aout_FindAndRestart, ( vlc_object_t * p_this ) );
 
index 7efab72..88f89ce 100644 (file)
@@ -3,7 +3,7 @@
  * This header provides portable declarations for mutexes & conditions
  *****************************************************************************
  * Copyright (C) 1999, 2002 VideoLAN
- * $Id: vlc_threads.h,v 1.14 2002/10/08 22:48:25 massiot Exp $
+ * $Id: vlc_threads.h,v 1.15 2002/10/20 12:23:47 massiot Exp $
  *
  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
  *          Samuel Hocevar <sam@via.ecp.fr>
@@ -72,7 +72,7 @@
 #   define VLC_THREAD_PRIORITY_INPUT 37
 #   define VLC_THREAD_PRIORITY_AUDIO 38
 #   define VLC_THREAD_PRIORITY_VIDEO 31
-#   define VLC_THREAD_PRIORITY_OUTPUT 38
+#   define VLC_THREAD_PRIORITY_OUTPUT 31
 
 #elif defined(WIN32)
 #   define VLC_THREAD_PRIORITY_LOW 0
index 7b09682..dbdacde 100644 (file)
@@ -4,7 +4,7 @@
  *   (http://liba52.sf.net/).
  *****************************************************************************
  * Copyright (C) 2001, 2002 VideoLAN
- * $Id: a52tofloat32.c,v 1.3 2002/09/30 21:32:32 massiot Exp $
+ * $Id: a52tofloat32.c,v 1.4 2002/10/20 12:23:47 massiot Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *          Christophe Massiot <massiot@via.ecp.fr>
@@ -194,7 +194,8 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
     {
         msg_Err( p_filter,
                  "liba52 couldn't do the requested downmix 0x%x->0x%x",
-                 p_sys->i_flags, i_flags );
+                 p_sys->i_flags  & A52_CHANNEL_MASK,
+                 i_flags & A52_CHANNEL_MASK );
         memset( p_out_buf->p_buffer, 0, i_bytes_per_block * 6 );
         return;
     }
index 4cf8200..c5d1b0e 100644 (file)
@@ -2,7 +2,7 @@
  * alsa.c : alsa plugin for vlc
  *****************************************************************************
  * Copyright (C) 2000-2001 VideoLAN
- * $Id: alsa.c,v 1.13 2002/10/05 03:44:50 bozo Exp $
+ * $Id: alsa.c,v 1.14 2002/10/20 12:23:47 massiot Exp $
  *
  * Authors: Henri Fallon <henri@videolan.org> - Original Author
  *          Jeffrey Baker <jwbaker@acm.org> - Port to ALSA 1.0 API
 struct aout_sys_t
 {
     snd_pcm_t         * p_snd_pcm;
-    snd_pcm_sframes_t   i_buffer_size;
     int                 i_period_time;
 
-    volatile vlc_bool_t b_can_sleek;
-
 #ifdef DEBUG
     snd_output_t      * p_snd_stderr;
 #endif
@@ -69,6 +66,7 @@ struct aout_sys_t
 #define ALSA_DEFAULT_BUFFER_SIZE        ( ALSA_DEFAULT_PERIOD_SIZE << 4 )
 #define ALSA_SPDIF_PERIOD_SIZE          A52_FRAME_NB
 #define ALSA_SPDIF_BUFFER_SIZE          ( ALSA_SPDIF_PERIOD_SIZE << 4 )
+/* Why << 4 ? --Meuuh */
 
 /*****************************************************************************
  * Local prototypes
@@ -84,7 +82,8 @@ static void ALSAFill     ( aout_instance_t * );
  *****************************************************************************/
 vlc_module_begin();
     add_category_hint( N_("ALSA"), NULL );
-    add_string( "alsa-device", NULL, NULL, N_("device name"), NULL );
+    add_string( "alsa-device", "default", aout_FindAndRestart,
+                N_("device name"), NULL );
     set_description( _("ALSA audio module") );
     set_capability( "audio output", 50 );
     set_callbacks( Open, Close );
@@ -99,21 +98,16 @@ static int Open( vlc_object_t *p_this )
 {
     aout_instance_t * p_aout = (aout_instance_t *)p_this;
     struct aout_sys_t * p_sys;
+    char * psz_device;
+    int i_buffer_size;
 
-    int i_snd_rc = -1;
-
-    char * psz_device = NULL;
-    char psz_alsadev[128];
-    char * psz_userdev;
+    snd_pcm_hw_params_t *p_hw;
+    snd_pcm_sw_params_t *p_sw;
 
-    int i_format_tries[2];
-    int i_tries_count, i;
+    int i_snd_rc = -1;
 
     int i_format;
-    int i_channels;
 
-    snd_pcm_hw_params_t *p_hw;
-    snd_pcm_sw_params_t *p_sw;
 
     /* Allocate structures */
     p_aout->output.p_sys = p_sys = malloc( sizeof( aout_sys_t ) );
@@ -123,179 +117,180 @@ static int Open( vlc_object_t *p_this )
         return -1;
     }
 
-    p_aout->output.pf_play = Play;
+    /* Get device name */
+    if( (psz_device = config_GetPsz( p_aout, "dspdev" )) == NULL )
+    {
+        msg_Err( p_aout, "no audio device given (maybe \"default\" ?)" );
+        free( p_sys );
+        return VLC_EGENERIC;
+    }
 
 #ifdef DEBUG
     snd_output_stdio_attach( &p_sys->p_snd_stderr, stderr, 0 );
 #endif
 
-    i_tries_count = 0;
-    i_format_tries[i_tries_count++] = p_aout->output.output.i_format;
-    if( i_format_tries[0] == VLC_FOURCC('s','p','d','i') )
+    /* Open the device */
+    if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output )
+          && !strcmp( "default", psz_device ) )
     {
-        /* Try S/PDIF, and then FLOAT32 */
-        i_format_tries[i_tries_count++] = VLC_FOURCC('f','l','3','2');
-    }
+        /* ALSA doesn't understand "default" for S/PDIF. Cheat a little. */
+        char psz_iecdev[128];
 
-    /* Read in ALSA device preferences from configuration */
-    psz_userdev = config_GetPsz( p_aout, "alsa-device" );
-
-    for( i = 0 ; ( i_snd_rc < 0 ) && ( i < i_tries_count ) ; ++i )
-    {
-        if( i_format_tries[i] == VLC_FOURCC('s','p','d','i') )
+        if ( !strcmp( "default", psz_device ) )
         {
-            if( psz_userdev )
-            {
-                psz_device = psz_userdev;
-            }
-            else
-            {
-                /* Will probably need some little modification in the case
-                   we want to send some data at a different rate
-                   (32000, 44100 and 48000 are the possibilities) -- bozo */
-                unsigned char s[4];
-                s[0] = IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO;
-                s[1] = IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER;
-                s[2] = 0;
-                s[3] = IEC958_AES3_CON_FS_48000;
-                sprintf( psz_alsadev,
-                         "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
-                         s[0], s[1], s[2], s[3] );
-                psz_device = psz_alsadev;
-            }
+            snprintf( psz_iecdev, sizeof(psz_iecdev),
+                 "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
+                 IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
+                 IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
+                 0,
+                 (p_aout->output.output.i_rate == 48000 ?
+                  IEC958_AES3_CON_FS_48000 :
+                  (p_aout->output.output.i_rate == 44100 ?
+                   IEC958_AES3_CON_FS_44100 : IEC958_AES3_CON_FS_32000)) );
         }
         else
         {
-            if( psz_userdev )
-                psz_device = psz_userdev;
-            else
-                psz_device = "default";
+            strncat( psz_iecdev, psz_device, sizeof(psz_iecdev) );
         }
 
-        /* Open device */
-        i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_device,
-                                 SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
-    }
+        if ( (i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_iecdev,
+                           SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0 )
+        {
+            /* No S/PDIF. */
+            msg_Warn( p_aout, "cannot open S/PDIF ALSA device `%s' (%s)",
+                      psz_device, snd_strerror(i_snd_rc) );
+            p_aout->output.output.i_format = VLC_FOURCC('f','l','3','2');
+        }
+        else
+        {
+            i_buffer_size = ALSA_SPDIF_BUFFER_SIZE;
+            i_format = SND_PCM_FORMAT_S16_NE;
 
-    if( i_snd_rc < 0 )
-    {
-        msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",
-                         psz_device, snd_strerror(i_snd_rc) );
-        if( psz_userdev )
-            free( psz_userdev );
-        p_sys->p_snd_pcm = NULL;
-        return -1;
+            p_aout->output.i_nb_samples = ALSA_SPDIF_PERIOD_SIZE;
+            p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i');
+            p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
+            p_aout->output.output.i_frame_length = A52_FRAME_NB;
+
+            aout_VolumeNoneInit( p_aout );
+        }
     }
 
-    if( psz_userdev )
-        free( psz_userdev );
+    if ( !AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
+    {
+        if ( (i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_device,
+                           SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0 )
+        {
+            msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",
+                             psz_device, snd_strerror(i_snd_rc) );
+            free( p_sys );
+            free( psz_device );
+            return VLC_EGENERIC;
+        }
 
-    p_aout->output.output.i_format = i_format_tries[i - 1];
+        if ( p_aout->p_libvlc->i_cpu & CPU_CAPABILITY_FPU )
+        {
+            p_aout->output.output.i_format = VLC_FOURCC('f','l','3','2');
+            i_format = SND_PCM_FORMAT_FLOAT;
+        }
+        else
+        {
+            p_aout->output.output.i_format = AOUT_FMT_S16_NE;
+            i_format = SND_PCM_FORMAT_S16_NE;
+        }
 
-    /* Default settings */
-    p_sys->b_can_sleek = VLC_FALSE;
-    i_channels = p_aout->output.output.i_channels;
-    if ( p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i') )
-    {
-        p_sys->i_buffer_size = ALSA_SPDIF_BUFFER_SIZE;
-        p_aout->output.i_nb_samples = ALSA_SPDIF_PERIOD_SIZE;
-        aout_VolumeNoneInit( p_aout );
-    }
-    else
-    {
-        p_sys->i_buffer_size = ALSA_DEFAULT_BUFFER_SIZE;
+        i_buffer_size = ALSA_DEFAULT_BUFFER_SIZE;
         p_aout->output.i_nb_samples = ALSA_DEFAULT_PERIOD_SIZE;
+
         aout_VolumeSoftInit( p_aout );
     }
 
-    /* Compute the settings */
-    switch (p_aout->output.output.i_format)
-    {
-        case VLC_FOURCC('f','l','3','2'):
-            i_format = SND_PCM_FORMAT_FLOAT;
-            break;
-
-        case VLC_FOURCC('s','p','d','i'):
-            /* Override some settings to make S/PDIF work */
-            p_sys->b_can_sleek = VLC_TRUE;
-            i_format = SND_PCM_FORMAT_S16_LE;
-            i_channels = 2;
-            p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
-            p_aout->output.output.i_frame_length = ALSA_SPDIF_PERIOD_SIZE;
-            break;
-        default:
-            msg_Err( p_aout, "audio output format '%.4s' not supported",
-                     &p_aout->output.output.i_format );
-            return -1;
-            break;
-    }
+    free( psz_device );
+    p_aout->output.pf_play = Play;
 
     snd_pcm_hw_params_alloca(&p_hw);
     snd_pcm_sw_params_alloca(&p_sw);
 
-    i_snd_rc = snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw );
-    if( i_snd_rc < 0 )
+    if ( snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw ) < 0 )
     {
         msg_Err( p_aout, "unable to retrieve initial hardware parameters" );
-        return -1;
+        goto error;
     }
 
-    i_snd_rc = snd_pcm_hw_params_set_access( p_sys->p_snd_pcm, p_hw,
-                                             SND_PCM_ACCESS_RW_INTERLEAVED );
-    if( i_snd_rc < 0 )
-    {
-        msg_Err( p_aout, "unable to set interleaved stream format" );
-        return -1;
-    }
-
-    i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw, i_format );
-    if( i_snd_rc < 0 )
+    /* Set format. */
+    if ( snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw, i_format ) < 0 )
     {
         msg_Err( p_aout, "unable to set stream sample size and word order" );
-        return -1;
+        goto error;
     }
 
-    i_snd_rc = snd_pcm_hw_params_set_channels( p_sys->p_snd_pcm, p_hw,
-                                               i_channels );
-    if( i_snd_rc < 0 )
+    if ( !AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
     {
-        msg_Err( p_aout, "unable to set number of output channels" );
-        return -1;
-    }
+        int i_nb_channels;
 
-    i_snd_rc = snd_pcm_hw_params_set_rate_near( p_sys->p_snd_pcm, p_hw,
-                                                p_aout->output.output.i_rate,
-                                                NULL );
-    if( i_snd_rc < 0 )
-    {
-        msg_Err( p_aout, "unable to set sample rate" );
-        return -1;
+        if ( snd_pcm_hw_params_set_access( p_sys->p_snd_pcm, p_hw,
+                                       SND_PCM_ACCESS_RW_INTERLEAVED ) < 0 )
+        {
+            msg_Err( p_aout, "unable to set interleaved stream format" );
+            goto error;
+        }
+
+        /* Set channels. */
+        i_nb_channels = aout_FormatNbChannels( &p_aout->output.output );
+
+        if ( (i_snd_rc = snd_pcm_hw_params_set_channels( p_sys->p_snd_pcm,
+                                 p_hw, i_nb_channels )) < 0 )
+        {
+            msg_Err( p_aout, "unable to set number of output channels" );
+            goto error;
+        }
+        if ( i_snd_rc != i_nb_channels )
+        {
+            switch ( i_snd_rc )
+            {
+            case 1: p_aout->output.output.i_channels = AOUT_CHAN_MONO; break;
+            case 2: p_aout->output.output.i_channels = AOUT_CHAN_STEREO; break;
+            case 4: p_aout->output.output.i_channels = AOUT_CHAN_2F2R; break;
+            default:
+                msg_Err( p_aout, "Unsupported downmixing (%d)", i_snd_rc );
+                goto error;
+            }
+        }
+
+        /* Set rate. */
+        if ( (i_snd_rc = snd_pcm_hw_params_set_rate_near( p_sys->p_snd_pcm,
+                                 p_hw, p_aout->output.output.i_rate,
+                                 NULL )) < 0 )
+        {
+            msg_Err( p_aout, "unable to set sample rate" );
+            goto error;
+        }
+        p_aout->output.output.i_rate = i_snd_rc;
     }
-    p_aout->output.output.i_rate = i_snd_rc;
 
+    /* Set buffer size. */
     i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm, p_hw,
                                                        p_sys->i_buffer_size );
     if( i_snd_rc < 0 )
     {
-        msg_Err( p_aout, "unable to set buffer time" );
-        return -1;
+        msg_Err( p_aout, "unable to set buffer size" );
+        goto error;
     }
-    p_sys->i_buffer_size = i_snd_rc;
 
+    /* Set period size. */
     i_snd_rc = snd_pcm_hw_params_set_period_size_near(
-                    p_sys->p_snd_pcm, p_hw, p_aout->output.i_nb_samples, NULL );
+                  p_sys->p_snd_pcm, p_hw, p_aout->output.i_nb_samples, NULL );
     if( i_snd_rc < 0 )
     {
         msg_Err( p_aout, "unable to set period size" );
-        return -1;
+        goto error;
     }
     p_aout->output.i_nb_samples = i_snd_rc;
 
-    i_snd_rc = snd_pcm_hw_params( p_sys->p_snd_pcm, p_hw );
-    if (i_snd_rc < 0)
+    /* Write hardware configuration. */
+    if ( snd_pcm_hw_params( p_sys->p_snd_pcm, p_hw ) < 0 )
     {
         msg_Err( p_aout, "unable to set hardware configuration" );
-        return -1;
+        goto error;
     }
 
     p_sys->i_period_time = snd_pcm_hw_params_get_period_time( p_hw, NULL );
@@ -306,11 +301,11 @@ static int Open( vlc_object_t *p_this )
     i_snd_rc = snd_pcm_sw_params_set_avail_min( p_sys->p_snd_pcm, p_sw,
                                                 p_aout->output.i_nb_samples );
 
-    i_snd_rc = snd_pcm_sw_params( p_sys->p_snd_pcm, p_sw );
-    if( i_snd_rc < 0 )
+    /* Write software configuration. */
+    if ( snd_pcm_sw_params( p_sys->p_snd_pcm, p_sw ) < 0 )
     {
         msg_Err( p_aout, "unable to set software configuration" );
-        return -1;
+        goto error;
     }
 
 #ifdef DEBUG
@@ -326,11 +321,18 @@ static int Open( vlc_object_t *p_this )
                            VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
     {
         msg_Err( p_aout, "cannot create ALSA thread (%s)", strerror(errno) );
-        free( p_sys );
-        return -1;
+        goto error;
     }
 
     return 0;
+
+error:
+    snd_pcm_close( p_sys->p_snd_pcm );
+#ifdef DEBUG
+    snd_output_close( p_sys->p_snd_stderr );
+#endif
+    free( p_sys );
+    return VLC_EGENERIC;
 }
 
 /*****************************************************************************
@@ -341,7 +343,7 @@ static void Play( aout_instance_t *p_aout )
 }
 
 /*****************************************************************************
- * Close: close the Alsa device
+ * Close: close the ALSA device
  *****************************************************************************/
 static void Close( vlc_object_t *p_this )
 {
@@ -352,15 +354,12 @@ static void Close( vlc_object_t *p_this )
     p_aout->b_die = 1;
     vlc_thread_join( p_aout );
 
-    if( p_sys->p_snd_pcm )
-    {
-        i_snd_rc = snd_pcm_close( p_sys->p_snd_pcm );
+    i_snd_rc = snd_pcm_close( p_sys->p_snd_pcm );
 
-        if( i_snd_rc > 0 )
-        {
-            msg_Err( p_aout, "failed closing ALSA device (%s)",
-                             snd_strerror( i_snd_rc ) );
-        }
+    if( i_snd_rc > 0 )
+    {
+        msg_Err( p_aout, "failed closing ALSA device (%s)",
+                         snd_strerror( i_snd_rc ) );
     }
 
 #ifdef DEBUG
@@ -383,6 +382,8 @@ static int ALSAThread( aout_instance_t * p_aout )
 
         /* Sleep during less than one period to avoid a lot of buffer
            underruns */
+
+        /* Why do we need to sleep ? --Meuuh */
         msleep( p_sys->i_period_time >> 2 );
     }
 
@@ -409,13 +410,13 @@ static void ALSAFill( aout_instance_t * p_aout )
     i_snd_rc = snd_pcm_wait( p_sys->p_snd_pcm, THREAD_SLEEP );
     if( i_snd_rc < 0 )
     {
-        msg_Err( p_aout, "alsa device not ready !!! (%s)",
+        msg_Err( p_aout, "ALSA device not ready !!! (%s)",
                          snd_strerror( i_snd_rc ) );
         return;
     }
 
     /* Fill in the buffer until space or audio output buffer shortage */
-    while( VLC_TRUE )
+    for ( ; ; )
     {
         /* Get the status */
         i_snd_rc = snd_pcm_status( p_sys->p_snd_pcm, p_status );
@@ -466,7 +467,8 @@ static void ALSAFill( aout_instance_t * p_aout )
             next_date = (mtime_t)ts_next.tv_sec * 1000000 + ts_next.tv_usec;
 
             p_buffer = aout_OutputNextBuffer( p_aout, next_date,
-                                              p_sys->b_can_sleek );
+                        (p_aout->output.output.i_format !=
+                            VLC_FOURCC('s','p','d','i')) );
 
             /* Audio output buffer shortage -> stop the fill process and
                wait in ALSAThread */
@@ -481,10 +483,8 @@ static void ALSAFill( aout_instance_t * p_aout )
                 msg_Err( p_aout, "write failed (%s)",
                                  snd_strerror( i_snd_rc ) );
             }
-            else
-            {
-                aout_BufferFree( p_buffer );
-            }
+
+            aout_BufferFree( p_buffer );
         }
     }
 }
index e24c08a..71b8292 100644 (file)
@@ -2,7 +2,7 @@
  * arts.c : aRts module
  *****************************************************************************
  * Copyright (C) 2001-2002 VideoLAN
- * $Id: arts.c,v 1.13 2002/10/04 18:07:21 sam Exp $
+ * $Id: arts.c,v 1.14 2002/10/20 12:23:47 massiot Exp $
  *
  * Authors: Emmanuel Blindauer <manu@agat.net>
  *          Samuel Hocevar <sam@zoy.org>
@@ -77,6 +77,7 @@ static int Open( vlc_object_t *p_this )
     aout_instance_t *p_aout = (aout_instance_t *)p_this;
     struct aout_sys_t * p_sys;
     int i_err;
+    int i_nb_channels;
 
     /* Allocate structure */
     p_sys = malloc( sizeof( aout_sys_t ) );
@@ -99,19 +100,22 @@ static int Open( vlc_object_t *p_this )
     p_aout->output.pf_play = Play;
     aout_VolumeSoftInit( p_aout );
 
-    p_sys->stream = NULL;
-
-    if( p_sys->stream )
+    p_aout->output.output.i_format = AOUT_FMT_S16_NE;
+    i_nb_channels = aout_FormatNbChannels( &p_aout->output.output );
+    if ( i_nb_channels > 2 )
     {
-        arts_close_stream( p_sys->stream );
+        /* aRts doesn't support more than two channels. */
+        i_nb_channels = 2;
+        p_aout->output.output.i_channels = AOUT_CHAN_STEREO;
     }
 
     /* Open a socket for playing a stream, set format to 16 bits */
     p_sys->stream = arts_play_stream( p_aout->output.output.i_rate, 16,
-                                      p_aout->output.output.i_channels, "vlc" );
+                                      i_nb_channels, "vlc" );
     if( p_sys->stream == NULL )
     {
         msg_Err( p_aout, "cannot open aRts socket" );
+        free( p_sys );
         return -1;
     }
 
@@ -128,16 +132,15 @@ static int Open( vlc_object_t *p_this )
                      arts_stream_get( p_sys->stream, ARTS_P_PACKET_COUNT ),
                      arts_stream_get( p_sys->stream, ARTS_P_PACKET_SIZE ) );
 
-    p_aout->output.output.i_format = AOUT_FMT_S16_NE;
-    p_aout->output.i_nb_samples = p_sys->i_size
-                                   / sizeof(u16)
-                                   / p_aout->output.output.i_channels;
+    p_aout->output.i_nb_samples = p_sys->i_size / sizeof(u16) / i_nb_channels;
 
     /* Create aRts thread and wait for its readiness. */
     if( vlc_thread_create( p_aout, "aout", aRtsThread,
                            VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
     {
         msg_Err( p_aout, "cannot create aRts thread (%s)", strerror(errno) );
+        arts_close_stream( p_sys->stream );
+        arts_free();
         free( p_sys );
         return -1;
     }
@@ -164,11 +167,7 @@ static void Close( vlc_object_t *p_this )
     p_aout->b_die = 1;
     vlc_thread_join( p_aout );
 
-    if( p_sys->stream )
-    {
-        arts_close_stream( p_sys->stream );
-    }
-
+    arts_close_stream( p_sys->stream );
     arts_free();
     free( p_sys );
 }
index ad8684e..fb3d426 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
- * aout.c: Windows DirectX audio output method
+ * directx.c: Windows DirectX audio output method
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: directx.c,v 1.3 2002/10/11 10:08:06 gbazin Exp $
+ * $Id: directx.c,v 1.4 2002/10/20 12:23:47 massiot Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
@@ -130,7 +130,7 @@ static int OpenAudio( vlc_object_t *p_this )
     if( p_aout->output.p_sys == NULL )
     {
         msg_Err( p_aout, "out of memory" );
-        return 1;
+        return VLC_EGENERIC;
     }
 
     /* Initialize some variables */
@@ -223,7 +223,7 @@ static int OpenAudio( vlc_object_t *p_this )
 
  error:
     CloseAudio( VLC_OBJECT(p_aout) );
-    return 1;
+    return VLC_EGENERIC;
 }
 
 /*****************************************************************************
@@ -269,12 +269,7 @@ static void CloseAudio( vlc_object_t *p_this )
     if( p_aout->output.p_sys->hdsound_dll )
        FreeLibrary( p_aout->output.p_sys->hdsound_dll );
 
-    /* Close the Output. */
-    if ( p_aout->output.p_sys  )
-    { 
-        free( p_aout->output.p_sys );
-        p_aout->output.p_sys = NULL;
-    }
+    free( p_aout->output.p_sys );
 }
 
 /*****************************************************************************
@@ -355,14 +350,19 @@ static int DirectxCreateSecondaryBuffer( aout_instance_t *p_aout )
     WAVEFORMATEX         waveformat;
     DSBUFFERDESC         dsbdesc;
     DSBCAPS              dsbcaps;
+    int                  i_nb_channels;
 
-    if( p_aout->output.output.i_channels > 2 )
-        p_aout->output.output.i_channels = 2;
+    i_nb_channels = aout_FormatNbChannels( &p_aout->output.output );
+    if ( i_nb_channels > 2 )
+    {
+        i_nb_channels = 2;
+        p_aout->output.output.i_channels = AOUT_CHAN_STEREO;
+    }
 
     /* First set the buffer format */
     memset(&waveformat, 0, sizeof(WAVEFORMATEX));
     waveformat.wFormatTag      = WAVE_FORMAT_PCM;
-    waveformat.nChannels       = p_aout->output.output.i_channels;
+    waveformat.nChannels       = i_nb_channels;
     waveformat.nSamplesPerSec  = p_aout->output.output.i_rate;
     waveformat.wBitsPerSample  = 16;
     waveformat.nBlockAlign     = waveformat.wBitsPerSample / 8 *
@@ -377,7 +377,7 @@ static int DirectxCreateSecondaryBuffer( aout_instance_t *p_aout )
                     | DSBCAPS_CTRLPOSITIONNOTIFY     /* We need notification */
                     | DSBCAPS_GLOBALFOCUS;      /* Allows background playing */
     dsbdesc.dwBufferBytes = FRAME_SIZE * 2 /* frames*/ *      /* buffer size */
-                            sizeof(s16) * p_aout->output.output.i_channels;
+                            sizeof(s16) * i_nb_channels;
     dsbdesc.lpwfxFormat = &waveformat;
  
     if( IDirectSound_CreateSoundBuffer( p_aout->output.p_sys->p_dsobject,
@@ -391,7 +391,7 @@ static int DirectxCreateSecondaryBuffer( aout_instance_t *p_aout )
 
     /* backup the size of a frame */
     p_aout->output.p_sys->p_notif->i_buffer_size = FRAME_SIZE * sizeof(s16)
-                                            * p_aout->output.output.i_channels;
+                                            * i_nb_channels;
 
     memset(&dsbcaps, 0, sizeof(DSBCAPS));
     dsbcaps.dwSize = sizeof(DSBCAPS);
@@ -439,7 +439,7 @@ static int DirectxCreateSecondaryBuffer( aout_instance_t *p_aout )
         IDirectSoundBuffer_Release( p_aout->output.p_sys->p_dsbuffer );
         p_aout->output.p_sys->p_dsnotify = NULL;
     }
-    return 1;
+    return VLC_EGENERIC;
 }
 
 /*****************************************************************************
index 496f1c9..055a1a8 100644 (file)
@@ -2,7 +2,7 @@
  * esd.c : EsounD module
  *****************************************************************************
  * Copyright (C) 2000, 2001 VideoLAN
- * $Id: esd.c,v 1.13 2002/09/18 21:21:23 massiot Exp $
+ * $Id: esd.c,v 1.14 2002/10/20 12:23:47 massiot Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
@@ -75,6 +75,7 @@ static int Open( vlc_object_t *p_this )
 {
     aout_instance_t *p_aout = (aout_instance_t *)p_this;
     struct aout_sys_t * p_sys;
+    int i_nb_channels;
 
     /* Allocate structure */
     p_sys = malloc( sizeof( aout_sys_t ) );
@@ -93,7 +94,16 @@ static int Open( vlc_object_t *p_this )
     p_sys->esd_format = ESD_BITS16 | ESD_STREAM | ESD_PLAY;
     p_sys->esd_format &= ~ESD_MASK_CHAN;
 
-    switch( p_aout->output.output.i_channels )
+    p_aout->output.output.i_format = AOUT_FMT_S16_NE;
+    i_nb_channels = aout_FormatNbChannels( &p_aout->output.output );
+    if ( i_nb_channels > 2 )
+    {
+        /* EsounD doesn't support more than two channels. */
+        i_nb_channels = 2;
+        p_aout->output.output.i_channels = AOUT_CHAN_STEREO;
+    }
+
+    switch( i_nb_channels )
     {
     case 1:
         p_sys->esd_format |= ESD_MONO;
@@ -101,8 +111,6 @@ static int Open( vlc_object_t *p_this )
     case 2:
         p_sys->esd_format |= ESD_STEREO;
         break;
-    default:
-        return -1;
     }
 
     /* open a socket for playing a stream
@@ -113,10 +121,10 @@ static int Open( vlc_object_t *p_this )
     {
         msg_Err( p_aout, "cannot open esound socket (format 0x%08x at %ld Hz)",
                          p_sys->esd_format, p_aout->output.output.i_rate );
+        free( p_sys );
         return -1;
     }
 
-    p_aout->output.output.i_format = AOUT_FMT_S16_NE;
     p_aout->output.i_nb_samples = ESD_BUF_SIZE * 2;
 
     /* ESD latency is calculated for 44100 Hz. We don't have any way to get the
@@ -135,6 +143,7 @@ static int Open( vlc_object_t *p_this )
                            VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
     {
         msg_Err( p_aout, "cannot create ESD thread (%s)", strerror(errno) );
+        close( p_sys->i_fd );
         free( p_sys );
         return -1;
     }
index 500a0cd..83e3628 100644 (file)
@@ -2,7 +2,7 @@
  * file.c : audio output which writes the samples to a file
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: file.c,v 1.12 2002/09/30 21:32:32 massiot Exp $
+ * $Id: file.c,v 1.13 2002/10/20 12:23:47 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -98,7 +98,6 @@ static int Open( vlc_object_t * p_this )
     if ( p_file == NULL ) return -1;
 
     p_aout->output.pf_play = Play;
-    aout_VolumeSoftInit( p_aout );
 
     while ( *ppsz_compare != NULL )
     {
@@ -117,15 +116,17 @@ static int Open( vlc_object_t * p_this )
     }
 
     p_aout->output.output.i_format = format_int[i];
-    if ( p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i') )
+    if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
     {
         p_aout->output.i_nb_samples = A52_FRAME_NB;
         p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
         p_aout->output.output.i_frame_length = A52_FRAME_NB;
+        aout_VolumeNoneInit( p_aout );
     }
     else
     {
         p_aout->output.i_nb_samples = FRAME_SIZE;
+        aout_VolumeSoftInit( p_aout );
     }
     return 0;
 }
index eda9e56..9204b15 100644 (file)
@@ -2,7 +2,7 @@
  * oss.c : OSS /dev/dsp module for vlc
  *****************************************************************************
  * Copyright (C) 2000-2002 VideoLAN
- * $Id: oss.c,v 1.29 2002/10/02 15:37:58 sigmunau Exp $
+ * $Id: oss.c,v 1.30 2002/10/20 12:23:47 massiot Exp $
  *
  * Authors: Michel Kaempf <maxx@via.ecp.fr>
  *          Samuel Hocevar <sam@zoy.org>
@@ -64,6 +64,7 @@ struct aout_sys_t
     int                   i_fd;
 };
 
+/* This must be a power of 2. */
 #define FRAME_SIZE 1024
 #define FRAME_COUNT 8
 #define A52_FRAME_NB 1536
@@ -82,10 +83,11 @@ static int  OSSThread    ( aout_instance_t * );
  *****************************************************************************/
 vlc_module_begin();
     add_category_hint( N_("OSS"), NULL );
-    add_file( "dspdev", "/dev/dsp", NULL, N_("OSS dsp device"), NULL );
+    add_file( "dspdev", "/dev/dsp", aout_FindAndRestart,
+              N_("OSS dsp device"), NULL );
     set_description( _("Linux OSS /dev/dsp module") );
     set_capability( "audio output", 100 );
-    add_shortcut( "dsp" );
+    add_shortcut( "oss" );
     set_callbacks( Open, Close );
 vlc_module_end();
 
@@ -100,11 +102,6 @@ static int Open( vlc_object_t *p_this )
     aout_instance_t * p_aout = (aout_instance_t *)p_this;
     struct aout_sys_t * p_sys;
     char * psz_device;
-    int i_format, i_format_orig;
-    int i_rate;
-    int i_frame_size;
-    int i_fragments;
-    vlc_bool_t b_stereo;
 
     /* Allocate structure */
     p_aout->output.p_sys = p_sys = malloc( sizeof( aout_sys_t ) );
@@ -114,7 +111,7 @@ static int Open( vlc_object_t *p_this )
         return VLC_ENOMEM;
     }
 
-    /* Initialize some variables */
+    /* Get device name */
     if( (psz_device = config_GetPsz( p_aout, "dspdev" )) == NULL )
     {
         msg_Err( p_aout, "no audio device given (maybe /dev/dsp ?)" );
@@ -138,98 +135,187 @@ static int Open( vlc_object_t *p_this )
     if( ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 )
     {
         msg_Err( p_aout, "cannot reset OSS audio device" );
+        close( p_sys->i_fd );
+        free( p_sys );
         return VLC_EGENERIC;
     }
     
-    /* Set the fragment size
-     * i_fragment = xxxxyyyy where: xxxx        is fragtotal
-     *                              1 << yyyy   is fragsize */
-    i_fragments = 0;
-    i_frame_size = FRAME_SIZE;
-    while( i_frame_size >>= 1 )
-    {
-        ++i_fragments;
-    }
-    i_fragments |= FRAME_COUNT << 16;
-    if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFRAGMENT, &i_fragments ) < 0 )
-    {
-        msg_Err( p_aout, "cannot set fragment size (%.8x)", i_fragments );
-        return VLC_EGENERIC;
-    }
-
     /* Set the output format */
-    if ( p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i') )
+    if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
     {
-        i_format = AFMT_AC3;
-        i_format_orig = AFMT_AC3;
-        p_aout->output.i_nb_samples = A52_FRAME_NB;
-        p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
-        p_aout->output.output.i_frame_length = A52_FRAME_NB;
+        int i_format = AFMT_AC3;
 
-        aout_VolumeNoneInit( p_aout );
+        if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0
+             || i_format != AFMT_AC3 )
+        {
+            p_aout->output.output.i_format = AOUT_FMT_S16_NE;
+        }
+        else
+        {
+            p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i');
+            p_aout->output.i_nb_samples = A52_FRAME_NB;
+            p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
+            p_aout->output.output.i_frame_length = A52_FRAME_NB;
+
+            aout_VolumeNoneInit( p_aout );
+        }
     }
-    else
+
+    if ( !AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
     {
+        int i_format = AFMT_S16_NE;
+        int i_frame_size, i_fragments;
+        int i_rate;
+        int i_nb_channels;
+
+        if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 )
+        {
+            msg_Err( p_aout, "cannot set audio output format" );
+            close( p_sys->i_fd );
+            free( p_sys );
+            return VLC_EGENERIC;
+        }
+
+        switch ( i_format )
+        {
+        case AFMT_U8:
+            p_aout->output.output.i_format = VLC_FOURCC('u','8',' ',' ');
+            break;
+        case AFMT_S8:
+            p_aout->output.output.i_format = VLC_FOURCC('s','8',' ',' ');
+            break;
+        case AFMT_U16_LE:
+            p_aout->output.output.i_format = VLC_FOURCC('u','1','6','l');
+            break;
+        case AFMT_S16_LE:
+            p_aout->output.output.i_format = VLC_FOURCC('s','1','6','l');
+            break;
+        case AFMT_U16_BE:
+            p_aout->output.output.i_format = VLC_FOURCC('u','1','6','b');
+            break;
+        case AFMT_S16_BE:
+            p_aout->output.output.i_format = VLC_FOURCC('s','1','6','b');
+            break;
+        default:
+            msg_Err( p_aout, "OSS fell back to an unknown format (%d)",
+                     i_format );
+            close( p_sys->i_fd );
+            free( p_sys );
+            return VLC_EGENERIC;
+        }
+
         p_aout->output.output.i_format = AOUT_FMT_S16_NE;
-        i_format = AFMT_S16_NE;
-        i_format_orig = AFMT_S16_NE;
         p_aout->output.i_nb_samples = FRAME_SIZE;
 
         aout_VolumeSoftInit( p_aout );
-    }
 
-    if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0
-         || i_format != i_format_orig )
-    {
-        if ( i_format_orig == AFMT_AC3 )
+        /* Set the fragment size
+         * i_fragment = xxxxyyyy where: xxxx        is fragtotal
+         *                              1 << yyyy   is fragsize */
+        i_fragments = 0;
+        i_frame_size = FRAME_SIZE;
+        while( i_frame_size >>= 1 )
         {
-            /* Retry with S16 */
-            msg_Warn( p_aout, "cannot set audio output format (%i)", i_format_orig );
-            p_aout->output.output.i_format = AOUT_FMT_S16_NE;
-            i_format = AFMT_S16_NE;
-            i_format_orig = AFMT_S16_NE;
-            p_aout->output.i_nb_samples = FRAME_SIZE;
-            if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0
-                 || i_format != i_format_orig )
-            {
-                msg_Err( p_aout, "cannot set audio output format (%i)",
-                         i_format_orig );
-                return VLC_EGENERIC;
-            }
+            ++i_fragments;
         }
-        else
+        i_fragments |= FRAME_COUNT << 16;
+        if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFRAGMENT, &i_fragments ) < 0 )
         {
-            msg_Err( p_aout, "cannot set audio output format (%i)", i_format_orig );
-            return VLC_EGENERIC;
+            msg_Warn( p_aout, "cannot set fragment size (%.8x)", i_fragments );
         }
-    }
 
-    if ( p_aout->output.output.i_format != VLC_FOURCC('s','p','d','i') )
-    {
-        /* FIXME */
-        if ( p_aout->output.output.i_channels > 2 )
+        /* These cases are desperate because of the OSS API and A/52 spec. */
+        switch ( p_aout->output.output.i_channels )
         {
-            msg_Warn( p_aout, "only two channels are supported at the moment" );
-            /* Trigger downmixing */
-            p_aout->output.output.i_channels = 2;
+            case AOUT_CHAN_3F:
+            case AOUT_CHAN_2F1R:
+            case AOUT_CHAN_3F1R:
+            case AOUT_CHAN_STEREO | AOUT_CHAN_LFE:
+            case AOUT_CHAN_2F1R | AOUT_CHAN_LFE:
+            case AOUT_CHAN_3F1R | AOUT_CHAN_LFE:
+            case AOUT_CHAN_DOLBY | AOUT_CHAN_LFE:
+                p_aout->output.output.i_channels = AOUT_CHAN_STEREO;
+                break;
+            case AOUT_CHAN_CHANNEL | AOUT_CHAN_LFE:
+            case AOUT_CHAN_CHANNEL1 | AOUT_CHAN_LFE:
+            case AOUT_CHAN_CHANNEL2 | AOUT_CHAN_LFE:
+            case AOUT_CHAN_MONO | AOUT_CHAN_LFE:
+            case AOUT_CHAN_2F2R | AOUT_CHAN_LFE:
+                p_aout->output.output.i_channels &= ~AOUT_CHAN_LFE;
+                break;
+            case AOUT_CHAN_3F2R:
+                p_aout->output.output.i_channels = AOUT_CHAN_2F2R;
+                break;
         }
+        /* In a nutshell, possible types : AOUT_CHAN_STEREO (and al.),
+           AOUT_CHAN_2F2R, AOUT_CHAN_3F1R | AOUT_CHAN_LFE. */
 
-        /* Set the number of channels */
-        b_stereo = p_aout->output.output.i_channels - 1;
+        i_nb_channels = aout_FormatNbChannels( &p_aout->output.output );
+
+        if ( i_nb_channels > 2 )
+        {
+            /* Check that the device supports this. */
+
+#ifdef SNDCTL_DSP_GETCHANNELMASK
+            int i_chanmask;
+            if ( ioctl( p_sys->i_fd, SNDCTL_DSP_GETCHANNELMASK,
+                        &i_chanmask ) == 0 )
+            {
+                if ( !(i_chanmask & DSP_BIND_FRONT) )
+                {
+                    msg_Err( p_aout, "No front channels ! (%x)",
+                             i_chanmask );
+                    close( p_sys->i_fd );
+                    free( p_sys );
+                    return VLC_EGENERIC;
+                }
+
+                if ( !(i_chanmask & DSP_BIND_SURR) )
+                {
+                    p_aout->output.output.i_channels = AOUT_CHAN_STEREO;
+                    i_nb_channels = 2;
+                }
+                if ( p_aout->output.output.i_channels ==
+                         (AOUT_CHAN_3F2R | AOUT_CHAN_LFE)
+                      && !(i_chanmask & DSP_BIND_CENTER_LFE) )
+                {
+                    p_aout->output.output.i_channels = AOUT_CHAN_2F2R;
+                    i_nb_channels = 4;
+                }
+            }
+            else
+#endif
+            {
+                /* The driver doesn't support this call, assume it is stereo. */
+                p_aout->output.output.i_channels = AOUT_CHAN_STEREO;
+                i_nb_channels = 2;
+            }
+        }
 
-        if( ioctl( p_sys->i_fd, SNDCTL_DSP_STEREO, &b_stereo ) < 0 )
+        /* Set the number of channels */
+        if( ioctl( p_sys->i_fd, SNDCTL_DSP_CHANNELS, &i_nb_channels ) < 0 )
         {
             msg_Err( p_aout, "cannot set number of audio channels (%i)",
                               p_aout->output.output.i_channels );
+            close( p_sys->i_fd );
+            free( p_sys );
             return VLC_EGENERIC;
         }
 
-        if ( b_stereo + 1 != p_aout->output.output.i_channels )
+        if ( i_nb_channels != aout_FormatNbChannels( &p_aout->output.output ) )
         {
-            msg_Warn( p_aout, "driver forced up/downmixing %li->%li",
-                              p_aout->output.output.i_channels,
-                              b_stereo + 1 );
-            p_aout->output.output.i_channels = b_stereo + 1;
+            switch ( i_nb_channels )
+            {
+            case 1: p_aout->output.output.i_channels = AOUT_CHAN_MONO; break;
+            case 2: p_aout->output.output.i_channels = AOUT_CHAN_STEREO; break;
+            case 4: p_aout->output.output.i_channels = AOUT_CHAN_2F2R; break;
+            default:
+                msg_Err( p_aout, "Unsupported downmixing (%d)", i_nb_channels );
+                close( p_sys->i_fd );
+                free( p_sys );
+                return VLC_EGENERIC;
+            }
         }
 
         /* Set the output rate */
@@ -238,13 +324,13 @@ static int Open( vlc_object_t *p_this )
         {
             msg_Err( p_aout, "cannot set audio output rate (%i)",
                              p_aout->output.output.i_rate );
+            close( p_sys->i_fd );
+            free( p_sys );
             return VLC_EGENERIC;
         }
 
         if( i_rate != p_aout->output.output.i_rate )
         {
-            msg_Warn( p_aout, "driver forced resampling %li->%li",
-                              p_aout->output.output.i_rate, i_rate );
             p_aout->output.output.i_rate = i_rate;
         }
     }
index aa3cc92..35f7d74 100644 (file)
@@ -2,7 +2,7 @@
  * waveout.c : Windows waveOut plugin for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: waveout.c,v 1.8 2002/10/11 10:08:06 gbazin Exp $
+ * $Id: waveout.c,v 1.9 2002/10/20 12:23:47 massiot Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *      
@@ -92,6 +92,7 @@ static int Open( vlc_object_t *p_this )
 {   
     aout_instance_t *p_aout = (aout_instance_t *)p_this;
     aout_buffer_t *p_buffer;
+    int i_nb_channels;
 
     /* Allocate structure */
     p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) );
@@ -99,44 +100,43 @@ static int Open( vlc_object_t *p_this )
     if( p_aout->output.p_sys == NULL )
     {
         msg_Err( p_aout, "out of memory" );
-        return 1;
+        return VLC_EGENERIC;
     }
 
     p_aout->output.pf_play = Play;
     aout_VolumeSoftInit( p_aout );
 
-    /* FIXME */
-    if ( p_aout->output.output.i_channels > 2 )
+    i_nb_channels = aout_FormatNbChannels( &p_aout->output.output );
+    if ( i_nb_channels > 2 )
     {
-        msg_Warn( p_aout, "only two channels are supported at the moment" );
-        /* Trigger downmixing */
-        p_aout->output.output.i_channels = 2;
+        /* Waveout doesn't support more than two channels. */
+        i_nb_channels = 2;
+        p_aout->output.output.i_channels = AOUT_CHAN_STEREO;
     }
 
     /* We need to open the device with default values to be sure it is
      * available */
-    if ( OpenWaveOut( p_aout, WAVE_FORMAT_PCM,
-                      p_aout->output.output.i_channels,
+    if ( OpenWaveOut( p_aout, WAVE_FORMAT_PCM, i_nb_channels,
                       p_aout->output.output.i_rate ) )
     {
         msg_Err( p_aout, "cannot open waveout audio device with output "
                          "rate (%i)",
                           p_aout->output.output.i_rate );
-        return 1;
+        return VLC_EGENERIC;
 
-        if ( OpenWaveOut( p_aout, WAVE_FORMAT_PCM,
-                          p_aout->output.output.i_channels,
+        if ( OpenWaveOut( p_aout, WAVE_FORMAT_PCM, i_nb_channels,
                           44100 ) )
         {
             msg_Err( p_aout, "cannot open waveout audio device with output "
                              "rate (44100)" );
-            return 1;
+            return VLC_EGENERIC;
         }
+        p_aout->output.output.i_rate = 44100;
     }
 
     waveOutReset( p_aout->output.p_sys->h_waveout );
 
-    /* calculate the frame size in bytes */
+    /* Calculate the frame size in bytes */
     p_aout->output.p_sys->i_buffer_size = FRAME_SIZE * sizeof(s16)
                                   * p_aout->output.p_sys->waveformat.nChannels;
     /* Allocate silence buffer */
@@ -194,11 +194,7 @@ static void Close( vlc_object_t *p_this )
     /* Free silence buffer */
     free( p_aout->output.p_sys->p_silence_buffer );
 
-    if( p_aout->output.p_sys != NULL )
-    { 
-        free( p_aout->output.p_sys );
-        p_aout->output.p_sys = NULL;
-    }
+    free( p_aout->output.p_sys );
 }
 
 /*****************************************************************************
index ed49f0d..4041d61 100644 (file)
@@ -2,9 +2,9 @@
  * idctaltivec.c : AltiVec IDCT module
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: idctaltivec.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ * $Id: idctaltivec.c,v 1.2 2002/10/20 12:23:47 massiot Exp $
  *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ * Authors: Michel Lespinasse <walken@zoy.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 71e4e51..402e6c4 100644 (file)
@@ -2,7 +2,7 @@
  * vpar_synchro.c : frame dropping routines
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: synchro.c,v 1.2 2002/08/04 18:39:41 sam Exp $
+ * $Id: synchro.c,v 1.3 2002/10/20 12:23:47 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Samuel Hocevar <sam@via.ecp.fr>
@@ -377,9 +377,9 @@ void vpar_SynchroNewPicture( vpar_thread_t * p_vpar, int i_coding_type,
         if( p_vpar->synchro.i_eta_p
              && p_vpar->synchro.i_eta_p != p_vpar->synchro.i_n_p )
         {
-            msg_Warn( p_vpar->p_fifo,
-                      "stream periodicity changed from P[%d] to P[%d]",
-                      p_vpar->synchro.i_n_p, p_vpar->synchro.i_eta_p );
+            msg_Dbg( p_vpar->p_fifo,
+                     "stream periodicity changed from P[%d] to P[%d]",
+                     p_vpar->synchro.i_n_p, p_vpar->synchro.i_eta_p );
             p_vpar->synchro.i_n_p = p_vpar->synchro.i_eta_p;
         }
         p_vpar->synchro.i_eta_p = p_vpar->synchro.i_eta_b = 0;
index 107094b..dd8f963 100644 (file)
@@ -2,7 +2,7 @@
  * system.c: helper module for TS, PS and PES management
  *****************************************************************************
  * Copyright (C) 1998-2002 VideoLAN
- * $Id: system.c,v 1.5 2002/10/03 21:45:16 massiot Exp $
+ * $Id: system.c,v 1.6 2002/10/20 12:23:48 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Michel Lespinasse <walken@via.ecp.fr>
@@ -654,6 +654,7 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
                 p_es->i_cat = AUDIO_ES;
                 break;
             case A52_AUDIO_ES:
+            case A52DVB_AUDIO_ES:
                 p_es->i_fourcc = VLC_FOURCC('a','5','2','b');
                 p_es->i_cat = AUDIO_ES;
                 break;
index 11e1524..d9f3af9 100644 (file)
@@ -2,7 +2,7 @@
  * system.h: MPEG demultiplexing.
  *****************************************************************************
  * Copyright (C) 1999-2002 VideoLAN
- * $Id: system.h,v 1.2 2002/08/30 22:22:24 massiot Exp $
+ * $Id: system.h,v 1.3 2002/10/20 12:23:48 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -46,6 +46,7 @@
 #define MPEG2_VIDEO_ES      0x02
 #define MPEG1_AUDIO_ES      0x03
 #define MPEG2_AUDIO_ES      0x04
+#define A52DVB_AUDIO_ES     0x06
 #define A52_AUDIO_ES        0x81
 /* These ones might violate the usage : */
 #define DVD_SPU_ES          0x82
index 83a541d..ba1b591 100644 (file)
@@ -2,7 +2,7 @@
  * mpeg_ts.c : Transport Stream input module for vlc
  *****************************************************************************
  * Copyright (C) 2000-2001 VideoLAN
- * $Id: ts.c,v 1.7 2002/10/12 21:31:56 gbazin Exp $
+ * $Id: ts.c,v 1.8 2002/10/20 12:23:48 massiot Exp $
  *
  * Authors: Henri Fallon <henri@via.ecp.fr>
  *          Johan Bilien <jobi@via.ecp.fr>
@@ -638,6 +638,7 @@ static void TSDecodePMT( input_thread_t * p_input, es_descriptor_t * p_es )
                             p_new_es->i_cat = AUDIO_ES;
                             break;
                         case A52_AUDIO_ES:
+                        case A52DVB_AUDIO_ES:
                             if ( !b_vls_compat )
                                 p_new_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
                             else
@@ -903,6 +904,7 @@ void TS_DVBPSI_HandlePMT( input_thread_t * p_input, dvbpsi_pmt_t * p_new_pmt )
                     p_new_es->i_cat = AUDIO_ES;
                     break;
                 case A52_AUDIO_ES:
+                case A52DVB_AUDIO_ES:
                     if ( !b_vls_compat )
                         p_new_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
                     else
@@ -994,6 +996,7 @@ void TS_DVBPSI_HandlePMT( input_thread_t * p_input, dvbpsi_pmt_t * p_new_pmt )
                         strcat( p_new_es->psz_desc, " (lpcm)" );
                         break;
                     case A52_AUDIO_ES:
+                    case A52DVB_AUDIO_ES:
                     case A52B_AUDIO_ES:
                         strcat( p_new_es->psz_desc, " (A52)" );
                         break;
index 4043eb2..e3d8afe 100644 (file)
@@ -2,7 +2,7 @@
  * common.c : audio output management of common data structures
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: common.c,v 1.2 2002/09/30 21:32:33 massiot Exp $
+ * $Id: common.c,v 1.3 2002/10/20 12:23:48 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -166,6 +166,66 @@ void aout_FormatPrepare( audio_sample_format_t * p_format )
     p_format->i_frame_length = 1;
 }
 
+/*****************************************************************************
+ * FormatPrintChannels : print a channel in a human-readable form
+ *****************************************************************************/
+static const char * FormatPrintChannels( int i_channels )
+{
+    switch ( i_channels )
+    {
+    case AOUT_CHAN_CHANNEL: return "CHANNEL";
+    case AOUT_CHAN_CHANNEL1: return "CHANNEL1";
+    case AOUT_CHAN_CHANNEL2: return "CHANNEL2";
+    case AOUT_CHAN_MONO: return "MONO";
+    case AOUT_CHAN_STEREO: return "STEREO";
+    case AOUT_CHAN_3F: return "3F";
+    case AOUT_CHAN_2F1R: return "2F1R";
+    case AOUT_CHAN_3F1R: return "3F1R";
+    case AOUT_CHAN_2F2R: return "2F2R";
+    case AOUT_CHAN_3F2R: return "3F2R";
+    case AOUT_CHAN_DOLBY: return "DOLBY";
+    case AOUT_CHAN_CHANNEL | AOUT_CHAN_LFE: return "CHANNEL|LFE";
+    case AOUT_CHAN_CHANNEL1 | AOUT_CHAN_LFE: return "CHANNEL1|LFE";
+    case AOUT_CHAN_CHANNEL2 | AOUT_CHAN_LFE: return "CHANNEL2|LFE";
+    case AOUT_CHAN_MONO | AOUT_CHAN_LFE: return "MONO|LFE";
+    case AOUT_CHAN_STEREO | AOUT_CHAN_LFE: return "STEREO|LFE";
+    case AOUT_CHAN_3F | AOUT_CHAN_LFE: return "3F|LFE";
+    case AOUT_CHAN_2F1R | AOUT_CHAN_LFE: return "2F1R|LFE";
+    case AOUT_CHAN_3F1R | AOUT_CHAN_LFE: return "3F1R|LFE";
+    case AOUT_CHAN_2F2R | AOUT_CHAN_LFE: return "2F2R|LFE";
+    case AOUT_CHAN_3F2R | AOUT_CHAN_LFE: return "3F2R|LFE";
+    case AOUT_CHAN_DOLBY | AOUT_CHAN_LFE: return "DOLBY|LFE";
+    }
+
+    return "ERROR";
+}
+
+/*****************************************************************************
+ * aout_FormatPrint : print a format in a human-readable form
+ *****************************************************************************/
+void aout_FormatPrint( aout_instance_t * p_aout, const char * psz_text,
+                       audio_sample_format_t * p_format )
+{
+    msg_Dbg( p_aout, "%s format='%4.4s' rate=%d channels=%s", psz_text,
+             (char *)&p_format->i_format, p_format->i_rate,
+             FormatPrintChannels( p_format->i_channels ) );
+}
+
+/*****************************************************************************
+ * aout_FormatsPrint : print two formats in a human-readable form
+ *****************************************************************************/
+void aout_FormatsPrint( aout_instance_t * p_aout, const char * psz_text,
+                        audio_sample_format_t * p_format1,
+                        audio_sample_format_t * p_format2 )
+{
+    msg_Dbg( p_aout, "%s format='%4.4s'->'%4.4s' rate=%d->%d channels=%s->%s",
+             psz_text,
+             (char *)&p_format1->i_format, (char *)&p_format2->i_format,
+             p_format1->i_rate, p_format2->i_rate,
+             FormatPrintChannels( p_format1->i_channels ),
+             FormatPrintChannels( p_format2->i_channels ) );
+}
+
 
 /*
  * FIFO management (internal) - please understand that solving race conditions
index 930fd85..382ca6a 100644 (file)
@@ -2,7 +2,7 @@
  * filters.c : audio output filters management
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: filters.c,v 1.11 2002/09/30 21:32:33 massiot Exp $
+ * $Id: filters.c,v 1.12 2002/10/20 12:23:48 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -128,11 +128,7 @@ int aout_FiltersCreatePipeline( aout_instance_t * p_aout,
         return 0;
     }
 
-    msg_Dbg( p_aout, "filter(s) format=%4.4s->%4.4s rate=%d->%d channels=%d->%d",
-             (char *)&p_input_format->i_format,
-             (char *)&p_output_format->i_format,
-             p_input_format->i_rate, p_output_format->i_rate,
-             p_input_format->i_channels, p_output_format->i_channels );
+    aout_FormatsPrint( p_aout, "filter(s)", p_input_format, p_output_format );
 
     /* Try to find a filter to do the whole conversion. */
     pp_filters[0] = FindFilter( p_aout, p_input_format, p_output_format );
index ac4ff72..6f6af6b 100644 (file)
@@ -2,7 +2,7 @@
  * input.c : internal management of input streams for the audio output
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: input.c,v 1.16 2002/10/09 22:54:22 massiot Exp $
+ * $Id: input.c,v 1.17 2002/10/20 12:23:48 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -43,6 +43,8 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input )
 {
     audio_sample_format_t intermediate_format;
 
+    aout_FormatPrint( p_aout, "input", &p_input->input );
+
     /* Prepare FIFO. */
     aout_FifoInit( p_aout, &p_input->fifo, p_aout->mixer.mixer.i_rate );
     p_input->p_first_byte_to_mix = NULL;
@@ -162,7 +164,7 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
          * pauses the stream (or if the decoder is buggy, which cannot
          * happen :). */
         msg_Warn( p_aout, "computed PTS is out of range (%lld), clearing out",
-                  start_date );
+                  mdate() - start_date );
         vlc_mutex_lock( &p_aout->input_fifos_lock );
         aout_FifoSet( p_aout, &p_input->fifo, 0 );
         vlc_mutex_unlock( &p_aout->input_fifos_lock );
index 17e59ba..c5fcd43 100644 (file)
@@ -2,7 +2,7 @@
  * intf.c : audio output API towards the interface modules
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: intf.c,v 1.4 2002/09/26 22:40:25 massiot Exp $
+ * $Id: intf.c,v 1.5 2002/10/20 12:23:48 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -355,3 +355,16 @@ int aout_Restart( aout_instance_t * p_aout )
     return b_error;
 }
 
+/*****************************************************************************
+ * aout_FindAndRestart : find the audio output instance and restart
+ *****************************************************************************/
+void aout_FindAndRestart( vlc_object_t * p_this )
+{
+    aout_instance_t * p_aout = vlc_object_find( p_this, VLC_OBJECT_AOUT,
+                                                FIND_ANYWHERE );
+
+    if ( p_aout == NULL ) return;
+
+    aout_Restart( p_aout );
+    vlc_object_release( p_aout );
+}
index 4e99004..8d183e8 100644 (file)
@@ -2,7 +2,7 @@
  * mixer.c : audio output mixing operations
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: mixer.c,v 1.17 2002/09/28 13:05:16 massiot Exp $
+ * $Id: mixer.c,v 1.18 2002/10/20 12:23:48 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -136,6 +136,14 @@ static int MixBuffer( aout_instance_t * p_aout )
             if ( p_input->b_error ) continue;
 
             p_buffer = p_fifo->p_first;
+            while ( p_buffer != NULL && p_buffer->start_date < mdate() )
+            {
+                msg_Warn( p_aout, "input PTS is out of range (%lld), trashing",
+                          mdate() - p_buffer->start_date );
+                aout_BufferFree( aout_FifoPop( p_aout, p_fifo ) );
+                p_buffer = p_fifo->p_first;
+            }
+
             if ( p_buffer == NULL )
             {
                 break;
index f7e6e03..058aa50 100644 (file)
@@ -2,7 +2,7 @@
  * output.c : internal management of output streams for the audio output
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: output.c,v 1.17 2002/10/03 18:56:09 sam Exp $
+ * $Id: output.c,v 1.18 2002/10/20 12:23:48 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -59,6 +59,12 @@ int aout_OutputNew( aout_instance_t * p_aout,
                      = (p_aout->p_libvlc->i_cpu & CPU_CAPABILITY_FPU) ?
                         VLC_FOURCC('f','l','3','2') :
                         VLC_FOURCC('f','i','3','2');
+
+        if ( p_aout->output.output.i_channels == AOUT_CHAN_DOLBY )
+        {
+            /* Do not do Dolby surround unless the user requests it. */
+            p_aout->output.output.i_channels = AOUT_CHAN_STEREO;
+        }
     }
     aout_FormatPrepare( &p_aout->output.output );
 
@@ -81,10 +87,7 @@ int aout_OutputNew( aout_instance_t * p_aout,
 
     vlc_mutex_unlock( &p_aout->output_fifo_lock );
 
-    msg_Dbg( p_aout, "output format=%4.4s rate=%d channels=%d",
-             (char *)&p_aout->output.output.i_format,
-             p_aout->output.output.i_rate,
-             p_aout->output.output.i_channels );
+    aout_FormatPrint( p_aout, "output", &p_aout->output.output );
 
     /* Calculate the resulting mixer output format. */
     memcpy( &p_aout->mixer.mixer, &p_aout->output.output,
@@ -103,9 +106,7 @@ int aout_OutputNew( aout_instance_t * p_aout,
         p_aout->mixer.mixer.i_format = p_format->i_format;
     }
 
-    msg_Dbg( p_aout, "mixer format=%4.4s rate=%d channels=%d",
-             (char *)&p_aout->mixer.mixer.i_format, p_aout->mixer.mixer.i_rate,
-             p_aout->mixer.mixer.i_channels );
+    aout_FormatPrint( p_aout, "mixer", &p_aout->output.output );
 
     /* Create filters. */
     if ( aout_FiltersCreatePipeline( p_aout, p_aout->output.pp_filters,