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