* modules/audio_output/alsa.c: we now open the device in SetFormat because

    it depends on the audio format. Cosmetic changes. The S/PDIF output may
    work.
parent d2e838ba
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* alsa.c : alsa plugin for vlc * alsa.c : alsa plugin for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2000-2001 VideoLAN * Copyright (C) 2000-2001 VideoLAN
* $Id: alsa.c,v 1.3 2002/08/15 10:31:44 bozo Exp $ * $Id: alsa.c,v 1.4 2002/08/19 17:07:14 bozo Exp $
* *
* Authors: Henri Fallon <henri@videolan.org> - Original Author * Authors: Henri Fallon <henri@videolan.org> - Original Author
* Jeffrey Baker <jwbaker@acm.org> - Port to ALSA 1.0 API * Jeffrey Baker <jwbaker@acm.org> - Port to ALSA 1.0 API
...@@ -54,18 +54,22 @@ struct aout_sys_t ...@@ -54,18 +54,22 @@ struct aout_sys_t
volatile vlc_bool_t b_initialized; volatile vlc_bool_t b_initialized;
volatile vlc_bool_t b_can_sleek;
#ifdef DEBUG #ifdef DEBUG
snd_output_t * p_snd_stderr; snd_output_t * p_snd_stderr;
#endif #endif
}; };
#define A52_FRAME_NB 1536
/* These values are in frames. /* These values are in frames.
To convert them to a numer of bytes you have to multiply them by the To convert them to a number of bytes you have to multiply them by the
number of channel(s) (eg. 2 for stereo) and the size of a sample (eg. number of channel(s) (eg. 2 for stereo) and the size of a sample (eg.
2 for s16). */ 2 for s16). */
#define ALSA_DEFAULT_PERIOD_SIZE 2048 #define ALSA_DEFAULT_PERIOD_SIZE 2048
#define ALSA_DEFAULT_BUFFER_SIZE ( ALSA_DEFAULT_PERIOD_SIZE << 4 ) #define ALSA_DEFAULT_BUFFER_SIZE ( ALSA_DEFAULT_PERIOD_SIZE << 4 )
#define ALSA_SPDIF_PERIOD_SIZE 1536 #define ALSA_SPDIF_PERIOD_SIZE A52_FRAME_NB
#define ALSA_SPDIF_BUFFER_SIZE ( ALSA_SPDIF_PERIOD_SIZE << 4 ) #define ALSA_SPDIF_BUFFER_SIZE ( ALSA_SPDIF_PERIOD_SIZE << 4 )
/***************************************************************************** /*****************************************************************************
...@@ -101,12 +105,6 @@ static int Open( vlc_object_t *p_this ) ...@@ -101,12 +105,6 @@ static int Open( vlc_object_t *p_this )
{ {
aout_instance_t * p_aout = (aout_instance_t *)p_this; aout_instance_t * p_aout = (aout_instance_t *)p_this;
struct aout_sys_t * p_sys; struct aout_sys_t * p_sys;
char * psz_device;
/* Allows user to choose which ALSA device to use */
char psz_alsadev[128];
char * psz_userdev;
int i_snd_rc;
/* Allocate structures */ /* Allocate structures */
p_aout->output.p_sys = p_sys = malloc( sizeof( aout_sys_t ) ); p_aout->output.p_sys = p_sys = malloc( sizeof( aout_sys_t ) );
...@@ -116,10 +114,47 @@ static int Open( vlc_object_t *p_this ) ...@@ -116,10 +114,47 @@ static int Open( vlc_object_t *p_this )
return -1; return -1;
} }
/* Create ALSA thread and wait for its readiness. */
p_sys->b_initialized = VLC_FALSE;
if( vlc_thread_create( p_aout, "aout", ALSAThread, VLC_FALSE ) )
{
msg_Err( p_aout, "cannot create ALSA thread (%s)", strerror(errno) );
free( p_sys );
return -1;
}
p_aout->output.pf_setformat = SetFormat;
p_aout->output.pf_play = Play;
#ifdef DEBUG #ifdef DEBUG
snd_output_stdio_attach( &p_sys->p_snd_stderr, stderr, 0 ); snd_output_stdio_attach( &p_sys->p_snd_stderr, stderr, 0 );
#endif #endif
return 0;
}
/*****************************************************************************
* SetFormat : sets the alsa output format
*****************************************************************************
* This function prepares the device, sets the rate, format, the mode
* ( "play as soon as you have data" ), and buffer information.
*****************************************************************************/
static int SetFormat( aout_instance_t * p_aout )
{
struct aout_sys_t * p_sys = p_aout->output.p_sys;
int i_snd_rc;
char * psz_device;
char psz_alsadev[128];
char * psz_userdev;
int i_format;
int i_channels;
snd_pcm_hw_params_t *p_hw;
snd_pcm_sw_params_t *p_sw;
/* Read in ALSA device preferences from configuration */ /* Read in ALSA device preferences from configuration */
psz_userdev = config_GetPsz( p_aout, "alsa-device" ); psz_userdev = config_GetPsz( p_aout, "alsa-device" );
...@@ -132,6 +167,9 @@ static int Open( vlc_object_t *p_this ) ...@@ -132,6 +167,9 @@ static int Open( vlc_object_t *p_this )
/* Use the internal logic to decide on the device name */ /* Use the internal logic to decide on the device name */
if ( p_aout->output.output.i_format == AOUT_FMT_SPDIF ) if ( p_aout->output.output.i_format == AOUT_FMT_SPDIF )
{ {
/* 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]; unsigned char s[4];
s[0] = IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO; s[0] = IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO;
s[1] = IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER; s[1] = IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER;
...@@ -141,14 +179,10 @@ static int Open( vlc_object_t *p_this ) ...@@ -141,14 +179,10 @@ static int Open( vlc_object_t *p_this )
"iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x", "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
s[0], s[1], s[2], s[3] ); s[0], s[1], s[2], s[3] );
psz_device = psz_alsadev; psz_device = psz_alsadev;
p_sys->i_buffer_size = ALSA_SPDIF_BUFFER_SIZE;
p_aout->output.i_nb_samples = ALSA_SPDIF_PERIOD_SIZE;
} }
else else
{ {
psz_device = "default"; psz_device = "default";
p_sys->i_buffer_size = ALSA_DEFAULT_BUFFER_SIZE;
p_aout->output.i_nb_samples = ALSA_DEFAULT_PERIOD_SIZE;
} }
} }
...@@ -161,52 +195,29 @@ static int Open( vlc_object_t *p_this ) ...@@ -161,52 +195,29 @@ static int Open( vlc_object_t *p_this )
psz_device, snd_strerror(i_snd_rc) ); psz_device, snd_strerror(i_snd_rc) );
if( psz_userdev ) if( psz_userdev )
free( psz_userdev ); free( psz_userdev );
free( p_sys );
p_sys->p_snd_pcm = NULL; p_sys->p_snd_pcm = NULL;
return -1; return -1;
} }
if( psz_userdev ) if( psz_userdev )
{
free( psz_userdev ); free( psz_userdev );
}
/* Create ALSA thread and wait for its readiness. */ /* Default settings */
p_sys->b_initialized = VLC_FALSE; p_sys->b_can_sleek = VLC_FALSE;
if( vlc_thread_create( p_aout, "aout", ALSAThread, VLC_FALSE ) ) i_channels = p_aout->output.output.i_channels;
if ( p_aout->output.output.i_format == AOUT_FMT_SPDIF )
{ {
msg_Err( p_aout, "cannot create ALSA thread (%s)", strerror(errno) ); p_sys->i_buffer_size = ALSA_SPDIF_BUFFER_SIZE;
if( psz_userdev ) p_aout->output.i_nb_samples = ALSA_SPDIF_PERIOD_SIZE;
free( psz_userdev ); }
free( p_sys ); else
return -1; {
p_sys->i_buffer_size = ALSA_DEFAULT_BUFFER_SIZE;
p_aout->output.i_nb_samples = ALSA_DEFAULT_PERIOD_SIZE;
} }
p_aout->output.pf_setformat = SetFormat;
p_aout->output.pf_play = Play;
return 0;
}
/*****************************************************************************
* SetFormat : sets the alsa output format
*****************************************************************************
* This function prepares the device, sets the rate, format, the mode
* ( "play as soon as you have data" ), and buffer information.
*****************************************************************************/
static int SetFormat( aout_instance_t * p_aout )
{
struct aout_sys_t * p_sys = p_aout->output.p_sys;
int i_snd_rc;
int i_format;
snd_pcm_hw_params_t *p_hw;
snd_pcm_sw_params_t *p_sw;
snd_pcm_hw_params_alloca(&p_hw);
snd_pcm_sw_params_alloca(&p_sw);
/* Compute the settings */
switch (p_aout->output.output.i_format) switch (p_aout->output.output.i_format)
{ {
case AOUT_FMT_MU_LAW: i_format = SND_PCM_FORMAT_MU_LAW; break; case AOUT_FMT_MU_LAW: i_format = SND_PCM_FORMAT_MU_LAW; break;
...@@ -219,6 +230,15 @@ static int SetFormat( aout_instance_t * p_aout ) ...@@ -219,6 +230,15 @@ static int SetFormat( aout_instance_t * p_aout )
case AOUT_FMT_U16_LE: i_format = SND_PCM_FORMAT_U16_LE; break; case AOUT_FMT_U16_LE: i_format = SND_PCM_FORMAT_U16_LE; break;
case AOUT_FMT_U16_BE: i_format = SND_PCM_FORMAT_U16_BE; break; case AOUT_FMT_U16_BE: i_format = SND_PCM_FORMAT_U16_BE; break;
case AOUT_FMT_FLOAT32: i_format = SND_PCM_FORMAT_FLOAT; break; case AOUT_FMT_FLOAT32: i_format = SND_PCM_FORMAT_FLOAT; break;
case AOUT_FMT_SPDIF:
/* 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_sec =
p_aout->output.output.i_rate * AOUT_SPDIF_SIZE /
ALSA_SPDIF_PERIOD_SIZE;
break;
case AOUT_FMT_FIXED32: case AOUT_FMT_FIXED32:
default: default:
msg_Err( p_aout, "audio output format 0x%x not supported", msg_Err( p_aout, "audio output format 0x%x not supported",
...@@ -227,6 +247,9 @@ static int SetFormat( aout_instance_t * p_aout ) ...@@ -227,6 +247,9 @@ static int SetFormat( aout_instance_t * p_aout )
break; break;
} }
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 ); i_snd_rc = snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw );
if( i_snd_rc < 0 ) if( i_snd_rc < 0 )
{ {
...@@ -250,7 +273,7 @@ static int SetFormat( aout_instance_t * p_aout ) ...@@ -250,7 +273,7 @@ static int SetFormat( aout_instance_t * p_aout )
} }
i_snd_rc = snd_pcm_hw_params_set_channels( p_sys->p_snd_pcm, p_hw, i_snd_rc = snd_pcm_hw_params_set_channels( p_sys->p_snd_pcm, p_hw,
p_aout->output.output.i_channels ); i_channels );
if( i_snd_rc < 0 ) if( i_snd_rc < 0 )
{ {
msg_Err( p_aout, "unable to set number of output channels" ); msg_Err( p_aout, "unable to set number of output channels" );
...@@ -348,6 +371,10 @@ static void Close( vlc_object_t *p_this ) ...@@ -348,6 +371,10 @@ static void Close( vlc_object_t *p_this )
} }
} }
#ifdef DEBUG
snd_output_close( p_sys->p_snd_stderr );
#endif
free( p_sys ); free( p_sys );
} }
...@@ -449,7 +476,8 @@ static void ALSAFill( aout_instance_t * p_aout ) ...@@ -449,7 +476,8 @@ static void ALSAFill( aout_instance_t * p_aout )
snd_pcm_status_get_tstamp( p_status, &ts_next ); snd_pcm_status_get_tstamp( p_status, &ts_next );
next_date = (mtime_t)ts_next.tv_sec * 1000000 + ts_next.tv_usec; next_date = (mtime_t)ts_next.tv_sec * 1000000 + ts_next.tv_usec;
p_buffer = aout_OutputNextBuffer( p_aout, next_date, 0 ); p_buffer = aout_OutputNextBuffer( p_aout, next_date,
p_sys->b_can_sleek );
/* Audio output buffer shortage -> stop the fill process and /* Audio output buffer shortage -> stop the fill process and
wait in ALSAThread */ wait in ALSAThread */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment