Commit cbb3e109 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

aout_OutputNextBuffer: move both FIFOs atomically and clean up

This avoids racing with decoder thread (audio input & mixer) w.r.t. the
FIFO timestamps.
parent c977aa35
......@@ -251,31 +251,26 @@ aout_buffer_t * aout_OutputNextBuffer( aout_instance_t * p_aout,
mtime_t start_date,
bool b_can_sleek )
{
aout_fifo_t *p_fifo = &p_aout->output.fifo;
aout_buffer_t * p_buffer;
mtime_t now = mdate();
aout_lock_output_fifo( p_aout );
p_buffer = p_aout->output.fifo.p_first;
/* Drop the audio sample if the audio output is really late.
* In the case of b_can_sleek, we don't use a resampler so we need to be
* a lot more severe. */
while ( p_buffer && p_buffer->i_pts <
(b_can_sleek ? start_date : now) - AOUT_PTS_TOLERANCE )
while( ((p_buffer = p_fifo->p_first) != NULL)
&& p_buffer->i_pts < (b_can_sleek ? start_date : now) - AOUT_PTS_TOLERANCE )
{
msg_Dbg( p_aout, "audio output is too slow (%"PRId64"), "
"trashing %"PRId64"us", now - p_buffer->i_pts,
p_buffer->i_length );
p_buffer = p_buffer->p_next;
aout_BufferFree( p_aout->output.fifo.p_first );
p_aout->output.fifo.p_first = p_buffer;
aout_BufferFree( aout_FifoPop( p_fifo ) );
}
if ( p_buffer == NULL )
if( p_buffer == NULL )
{
p_aout->output.fifo.pp_last = &p_aout->output.fifo.p_first;
#if 0 /* This is bad because the audio output might just be trying to fill
* in its internal buffers. And anyway, it's up to the audio output
* to deal with this kind of starvation. */
......@@ -285,17 +280,17 @@ aout_buffer_t * aout_OutputNextBuffer( aout_instance_t * p_aout,
if ( !p_aout->output.b_starving )
msg_Dbg( p_aout,
"audio output is starving (no input), playing silence" );
p_aout->output.b_starving = 1;
p_aout->output.b_starving = true;
#endif
aout_unlock_output_fifo( p_aout );
return NULL;
}
mtime_t delta = start_date - p_buffer->i_pts;
/* Here we suppose that all buffers have the same duration - this is
* generally true, and anyway if it's wrong it won't be a disaster.
*/
if ( p_buffer->i_pts > start_date + p_buffer->i_length )
if ( 0 > delta + p_buffer->i_length )
/*
* + AOUT_PTS_TOLERANCE )
* There is no reason to want that, it just worsen the scheduling of
......@@ -303,43 +298,31 @@ aout_buffer_t * aout_OutputNextBuffer( aout_instance_t * p_aout,
* --Gibalou
*/
{
const mtime_t i_delta = p_buffer->i_pts - start_date;
aout_unlock_output_fifo( p_aout );
if ( !p_aout->output.b_starving )
msg_Dbg( p_aout, "audio output is starving (%"PRId64"), "
"playing silence", i_delta );
p_aout->output.b_starving = 1;
"playing silence", -delta );
p_aout->output.b_starving = true;
aout_unlock_output_fifo( p_aout );
return NULL;
}
p_aout->output.b_starving = 0;
p_aout->output.fifo.p_first = p_buffer->p_next;
if ( p_buffer->p_next == NULL )
{
p_aout->output.fifo.pp_last = &p_aout->output.fifo.p_first;
}
p_aout->output.b_starving = false;
p_buffer = aout_FifoPop( p_fifo );
if( !b_can_sleek )
{
mtime_t difference = start_date - p_buffer->i_pts;
if( difference > AOUT_PTS_TOLERANCE
|| difference < -AOUT_PTS_TOLERANCE )
if( delta > AOUT_PTS_TOLERANCE || delta < -AOUT_PTS_TOLERANCE )
{
aout_unlock_output_fifo( p_aout );
/* Try to compensate the drift by doing some resampling. */
msg_Warn( p_aout, "output date isn't PTS date, requesting "
"resampling (%"PRId64")", difference );
aout_FifoMoveDates( &p_aout->output.fifo, difference );
aout_unlock_output_fifo( p_aout );
"resampling (%"PRId64")", delta );
aout_lock_input_fifos( p_aout );
aout_fifo_t *p_fifo = &p_aout->p_input->mixer.fifo;
aout_FifoMoveDates( p_fifo, difference );
aout_lock_output_fifo( p_aout );
aout_FifoMoveDates( &p_aout->p_input->mixer.fifo, delta );
aout_FifoMoveDates( p_fifo, delta );
aout_unlock_input_fifos( p_aout );
return p_buffer;
}
}
aout_unlock_output_fifo( p_aout );
......
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