Commit cc4db561 authored by Jean-Paul Saman's avatar Jean-Paul Saman

access/alsa.c: capture audio in a seperate thread

On some systems the latency for audio capture when used with input-slave
is too big, resulting in poll timeouts and no audio. Running the audio
capture in a separate thread solves this latency issue.
parent e0a5dde7
...@@ -118,6 +118,19 @@ static int OpenAudioDev( demux_t *, const char * ); ...@@ -118,6 +118,19 @@ static int OpenAudioDev( demux_t *, const char * );
static bool ProbeAudioDevAlsa( demux_t *, const char * ); static bool ProbeAudioDevAlsa( demux_t *, const char * );
static char *ListAvailableDevices( demux_t *, bool b_probe ); static char *ListAvailableDevices( demux_t *, bool b_probe );
/* --- AudioGrab Thread --- */
typedef struct audio_grab_s
{
VLC_COMMON_MEMBERS
demux_t *p_demux;
block_fifo_t *p_fifo;
} audio_grab_t;
static void *AudioThread( vlc_object_t * );
/* --- AudioGrab Thread --- */
struct demux_sys_t struct demux_sys_t
{ {
/* Audio */ /* Audio */
...@@ -134,6 +147,8 @@ struct demux_sys_t ...@@ -134,6 +147,8 @@ struct demux_sys_t
int i_alsa_chunk_size; int i_alsa_chunk_size;
int64_t i_next_demux_date; /* Used to handle alsa:// as input-slave properly */ int64_t i_next_demux_date; /* Used to handle alsa:// as input-slave properly */
audio_grab_t *p_grab;
}; };
static int FindMainDevice( demux_t *p_demux, const char *psz_device ) static int FindMainDevice( demux_t *p_demux, const char *psz_device )
...@@ -268,6 +283,30 @@ static int DemuxOpen( vlc_object_t *p_this ) ...@@ -268,6 +283,30 @@ static int DemuxOpen( vlc_object_t *p_this )
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_sys->p_grab = vlc_object_create( p_demux, sizeof(audio_grab_t) );
if( !p_sys->p_grab )
{
DemuxClose( p_this );
return VLC_ENOMEM;
}
p_sys->p_grab->p_demux = p_demux;
p_sys->p_grab->p_fifo = block_FifoNew();
if( !p_sys->p_grab->p_fifo )
{
vlc_object_release( p_sys->p_grab );
p_sys->p_grab = NULL;
DemuxClose( p_this );
return VLC_ENOMEM;
}
if( vlc_thread_create( p_sys->p_grab, "AudioGrab Thread",
AudioThread, VLC_THREAD_PRIORITY_INPUT) < 0 )
{
msg_Err( p_this, "Failed to create Audio Capture Thread" );
DemuxClose( p_this );
return VLC_EGENERIC;
}
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -279,6 +318,15 @@ static void DemuxClose( vlc_object_t *p_this ) ...@@ -279,6 +318,15 @@ static void DemuxClose( vlc_object_t *p_this )
demux_t *p_demux = (demux_t *)p_this; demux_t *p_demux = (demux_t *)p_this;
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
if( p_sys->p_grab )
{
vlc_object_kill( p_sys->p_grab );
vlc_thread_join( p_sys->p_grab );
if( p_sys->p_grab->p_fifo )
block_FifoRelease( p_sys->p_grab->p_fifo );
vlc_object_release( p_sys->p_grab );
}
if( p_sys->p_alsa_pcm ) if( p_sys->p_alsa_pcm )
{ {
snd_pcm_close( p_sys->p_alsa_pcm ); snd_pcm_close( p_sys->p_alsa_pcm );
...@@ -332,34 +380,65 @@ static int DemuxControl( demux_t *p_demux, int i_query, va_list args ) ...@@ -332,34 +380,65 @@ static int DemuxControl( demux_t *p_demux, int i_query, va_list args )
static int Demux( demux_t *p_demux ) static int Demux( demux_t *p_demux )
{ {
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
block_t *p_block;
do
{
if( block_FifoCount( p_sys->p_grab->p_fifo ) <= 0 )
break;
p_block = block_FifoGet( p_sys->p_grab->p_fifo );
if( !p_block ) break;
mtime_t i_pts = p_block->i_pts;
es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts );
es_out_Send( p_demux->out, p_sys->p_es, p_block );
p_block = NULL;
if( p_sys->i_next_demux_date <= 0 &&
i_pts >= p_sys->i_next_demux_date )
break;
} while( vlc_object_alive(p_demux) );
return 1;
}
static void *AudioThread( vlc_object_t *p_this )
{
audio_grab_t *p_grab = (audio_grab_t *) p_this;
demux_t *p_demux = (demux_t *) p_grab->p_demux;
demux_sys_t *p_sys = (demux_sys_t *) p_demux->p_sys;
block_t *p_block = NULL; block_t *p_block = NULL;
do do
{ {
if( p_block )
{
es_out_Send( p_demux->out, p_sys->p_es, p_block );
p_block = NULL;
}
/* Wait for data */ /* Wait for data */
int i_wait = snd_pcm_wait( p_sys->p_alsa_pcm, 10 ); /* See poll() comment in oss.c */ int i_wait = snd_pcm_wait( p_sys->p_alsa_pcm, 10 ); /* See poll() comment in oss.c */
#if 0
msg_Info( p_demux, "ALSA snd_pcm_wait returned (%d): %s %"PRId64,
i_wait, snd_strerror(i_wait), mdate() );
#endif
switch( i_wait ) switch( i_wait )
{ {
case 1: case 1:
{ {
p_block = GrabAudio( p_demux ); p_block = GrabAudio( p_demux );
if( p_block ) if( p_block )
es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts ); {
block_FifoPut( p_sys->p_grab->p_fifo, p_block );
p_block = NULL;
}
} }
/* FIXME: this is a copy paste from below. Shouldn't be needed /* FIXME: this is a copy paste from below. Shouldn't be needed
* twice. */ * twice. */
case -EPIPE: case -EPIPE:
{
/* xrun */ /* xrun */
snd_pcm_prepare( p_sys->p_alsa_pcm ); snd_pcm_prepare( p_sys->p_alsa_pcm );
break; break;
}
case -ESTRPIPE: case -ESTRPIPE:
{ {
/* suspend */ /* suspend */
...@@ -368,14 +447,23 @@ static int Demux( demux_t *p_demux ) ...@@ -368,14 +447,23 @@ static int Demux( demux_t *p_demux )
break; break;
} }
/* </FIXME> */ /* </FIXME> */
default:
{
if (i_wait == 0)
{
snd_pcm_prepare( p_sys->p_alsa_pcm );
}
else
msg_Err(p_demux, "returned: %d (%s)", i_wait, snd_strerror(i_wait));
break;
}
} }
} while( p_block && p_sys->i_next_demux_date > 0 && } while( vlc_object_alive( p_grab ) );
p_block->i_pts < p_sys->i_next_demux_date );
if( p_block ) if( p_block )
es_out_Send( p_demux->out, p_sys->p_es, p_block ); block_Release( p_block );
return 1; return NULL;
} }
...@@ -409,9 +497,14 @@ static block_t* GrabAudio( demux_t *p_demux ) ...@@ -409,9 +497,14 @@ static block_t* GrabAudio( demux_t *p_demux )
case -EAGAIN: case -EAGAIN:
break; break;
case -EPIPE: case -EPIPE:
{
/* xrun */ /* xrun */
snd_pcm_prepare( p_sys->p_alsa_pcm ); int err = 0;
if ((err = snd_pcm_prepare( p_sys->p_alsa_pcm )) < 0 )
msg_Info( p_demux, "GrabAudio ALSA snd_pcm_prepare returned (%s)",
snd_strerror(err) );
break; break;
}
case -ESTRPIPE: case -ESTRPIPE:
/* suspend */ /* suspend */
i_resume = snd_pcm_resume( p_sys->p_alsa_pcm ); i_resume = snd_pcm_resume( p_sys->p_alsa_pcm );
...@@ -462,7 +555,9 @@ static block_t* GrabAudio( demux_t *p_demux ) ...@@ -462,7 +555,9 @@ static block_t* GrabAudio( demux_t *p_demux )
p_block->i_pts = p_block->i_dts = p_block->i_pts = p_block->i_dts =
mdate() - INT64_C(1000000) * (mtime_t)i_correct / mdate() - INT64_C(1000000) * (mtime_t)i_correct /
2 / ( p_sys->b_stereo ? 2 : 1) / p_sys->i_sample_rate; 2 / ( p_sys->b_stereo ? 2 : 1) / p_sys->i_sample_rate;
#if 0
msg_Info( p_demux, "ALSA snd_pcm_read returned (%d bytes)", i_read );
#endif
return p_block; return p_block;
} }
......
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