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

Change audio output tolerance times

Maximum buffering time (AOUT_MAX_PREPARE_TIME) is increased to 2
seconds, consistent with increases in audio hardware buffer sizes.
In practice however, this is bound to the input PTS delay.

Maximum advance time is updated accordingly (+ 1 second).

Lip desynchronization tolerance is segregated, following EBU R37:
 - 40 ms (as before) maximum audio advance
 - 60 ms maximum audio delay.
parent 25f179e1
...@@ -33,19 +33,24 @@ ...@@ -33,19 +33,24 @@
/* Buffers which arrive in advance of more than AOUT_MAX_ADVANCE_TIME /* Buffers which arrive in advance of more than AOUT_MAX_ADVANCE_TIME
* will be considered as bogus and be trashed */ * will be considered as bogus and be trashed */
#define AOUT_MAX_ADVANCE_TIME (DEFAULT_PTS_DELAY * 5) #define AOUT_MAX_ADVANCE_TIME (AOUT_MAX_PREPARE_TIME + CLOCK_FREQ)
/* Buffers which arrive in advance of more than AOUT_MAX_PREPARE_TIME /* Buffers which arrive in advance of more than AOUT_MAX_PREPARE_TIME
* will cause the calling thread to sleep */ * will cause the calling thread to sleep */
#define AOUT_MAX_PREPARE_TIME (CLOCK_FREQ/2) #define AOUT_MAX_PREPARE_TIME (2 * CLOCK_FREQ)
/* Buffers which arrive after pts - AOUT_MIN_PREPARE_TIME will be trashed /* Buffers which arrive after pts - AOUT_MIN_PREPARE_TIME will be trashed
* to avoid too heavy resampling */ * to avoid too heavy resampling */
#define AOUT_MIN_PREPARE_TIME (CLOCK_FREQ/25) #define AOUT_MIN_PREPARE_TIME AOUT_MAX_PTS_ADVANCE
/* Max acceptable delay between the coded PTS and the actual presentation /* Tolerance values from EBU Recommendation 37 */
* time, without resampling */ /** Maximum advance of actual audio playback time to coded PTS,
#define AOUT_PTS_TOLERANCE (CLOCK_FREQ/25) * above which downsampling will be performed */
#define AOUT_MAX_PTS_ADVANCE (CLOCK_FREQ / 25)
/** Maximum delay of actual audio playback time from coded PTS,
* above which upsampling will be performed */
#define AOUT_MAX_PTS_DELAY (3 * CLOCK_FREQ / 50)
/* Max acceptable resampling (in %) */ /* Max acceptable resampling (in %) */
#define AOUT_MAX_RESAMPLING 10 #define AOUT_MAX_RESAMPLING 10
......
...@@ -569,7 +569,8 @@ static void* ALSAThread( void *data ) ...@@ -569,7 +569,8 @@ static void* ALSAThread( void *data )
/* Wait for the exact time to start playing (avoids resampling) */ /* Wait for the exact time to start playing (avoids resampling) */
vlc_sem_wait( &p_sys->wait ); vlc_sem_wait( &p_sys->wait );
mwait( p_sys->start_date - AOUT_PTS_TOLERANCE / 4 ); mwait( p_sys->start_date - AOUT_MAX_PTS_ADVANCE / 4 );
#warning Should wait for buffer availability instead!
for(;;) for(;;)
ALSAFill( p_aout ); ALSAFill( p_aout );
......
...@@ -1028,7 +1028,7 @@ static void* DirectSoundThread( void *data ) ...@@ -1028,7 +1028,7 @@ static void* DirectSoundThread( void *data )
if( !vlc_atomic_get( &p_notif->abort) ) if( !vlc_atomic_get( &p_notif->abort) )
{ {
HRESULT dsresult; HRESULT dsresult;
mwait( p_notif->start_date - AOUT_PTS_TOLERANCE / 2 ); mwait( p_notif->start_date - AOUT_MAX_PTS_ADVANCE / 2 );
/* start playing the buffer */ /* start playing the buffer */
dsresult = IDirectSoundBuffer_Play( p_aout->output.p_sys->p_dsbuffer, dsresult = IDirectSoundBuffer_Play( p_aout->output.p_sys->p_dsbuffer,
......
...@@ -633,7 +633,7 @@ static void* OSSThread( void *obj ) ...@@ -633,7 +633,7 @@ static void* OSSThread( void *obj )
else else
{ {
mtime_t delay = next_date - mdate(); mtime_t delay = next_date - mdate();
if( delay > AOUT_PTS_TOLERANCE ) if( delay > AOUT_MAX_PTS_ADVANCE )
{ {
msleep( delay / 2 ); msleep( delay / 2 );
} }
......
...@@ -887,10 +887,10 @@ static void* WaveOutThread( void *data ) ...@@ -887,10 +887,10 @@ static void* WaveOutThread( void *data )
return NULL; return NULL;
msg_Dbg( p_aout, "will start to play in %"PRId64" us", msg_Dbg( p_aout, "will start to play in %"PRId64" us",
(p_sys->start_date - AOUT_PTS_TOLERANCE/4)-mdate()); (p_sys->start_date - AOUT_MAX_PTS_ADVANCE/4)-mdate());
// than wait a short time... before grabbing first frames // than wait a short time... before grabbing first frames
mwait( p_sys->start_date - AOUT_PTS_TOLERANCE/4 ); mwait( p_sys->start_date - AOUT_MAX_PTS_ADVANCE/4 );
#define waveout_warn(msg) msg_Warn( p_aout, "aout_OutputNextBuffer no buffer "\ #define waveout_warn(msg) msg_Warn( p_aout, "aout_OutputNextBuffer no buffer "\
"got next_date=%d ms, "\ "got next_date=%d ms, "\
...@@ -937,7 +937,7 @@ static void* WaveOutThread( void *data ) ...@@ -937,7 +937,7 @@ static void* WaveOutThread( void *data )
// means we are too early to request a new buffer? // means we are too early to request a new buffer?
waveout_warn("waiting...") waveout_warn("waiting...")
next_date = aout_FifoFirstDate( &p_aout->output.fifo ); next_date = aout_FifoFirstDate( &p_aout->output.fifo );
mwait( next_date - AOUT_PTS_TOLERANCE/4 ); mwait( next_date - AOUT_MAX_PTS_ADVANCE/4 );
next_date = mdate(); next_date = mdate();
p_buffer = aout_OutputNextBuffer( p_aout, next_date, p_buffer = aout_OutputNextBuffer( p_aout, next_date,
b_sleek ); b_sleek );
......
...@@ -573,11 +573,9 @@ void aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -573,11 +573,9 @@ void aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
if( !start_date ) if( !start_date )
start_date = p_buffer->i_pts; start_date = p_buffer->i_pts;
mtime_t tolerance = 3 * AOUT_PTS_TOLERANCE
* i_input_rate / INPUT_RATE_DEFAULT;
mtime_t drift = start_date - p_buffer->i_pts; mtime_t drift = start_date - p_buffer->i_pts;
if( drift < -tolerance ) if( drift < -i_input_rate * 3 * AOUT_MAX_PTS_ADVANCE / INPUT_RATE_DEFAULT )
{ {
msg_Warn( p_aout, "buffer way too early (%"PRId64"), clearing queue", msg_Warn( p_aout, "buffer way too early (%"PRId64"), clearing queue",
drift ); drift );
...@@ -589,7 +587,8 @@ void aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -589,7 +587,8 @@ void aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
start_date = p_buffer->i_pts; start_date = p_buffer->i_pts;
drift = 0; drift = 0;
} }
else if( drift > +tolerance ) else
if( drift > +i_input_rate * 3 * AOUT_MAX_PTS_DELAY / INPUT_RATE_DEFAULT )
{ {
msg_Warn( p_aout, "buffer way too late (%"PRId64"), dropping buffer", msg_Warn( p_aout, "buffer way too late (%"PRId64"), dropping buffer",
drift ); drift );
...@@ -607,7 +606,7 @@ void aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -607,7 +606,7 @@ void aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
/* Run the resampler if needed. /* Run the resampler if needed.
* We first need to calculate the output rate of this resampler. */ * We first need to calculate the output rate of this resampler. */
if ( ( p_input->i_resampling_type == AOUT_RESAMPLING_NONE ) && if ( ( p_input->i_resampling_type == AOUT_RESAMPLING_NONE ) &&
( drift < -AOUT_PTS_TOLERANCE || drift > +AOUT_PTS_TOLERANCE ) && ( drift < -AOUT_MAX_PTS_ADVANCE || drift > +AOUT_MAX_PTS_DELAY ) &&
p_input->i_nb_resamplers > 0 ) p_input->i_nb_resamplers > 0 )
{ {
/* Can happen in several circumstances : /* Can happen in several circumstances :
......
...@@ -275,7 +275,7 @@ aout_buffer_t * aout_OutputNextBuffer( aout_instance_t * p_aout, ...@@ -275,7 +275,7 @@ aout_buffer_t * aout_OutputNextBuffer( aout_instance_t * p_aout,
* 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_fifo->p_first) != NULL) while( ((p_buffer = p_fifo->p_first) != NULL)
&& p_buffer->i_pts < (b_can_sleek ? start_date : now) - AOUT_PTS_TOLERANCE ) && p_buffer->i_pts < (b_can_sleek ? start_date : now) - AOUT_MAX_PTS_DELAY )
{ {
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,
...@@ -304,12 +304,6 @@ aout_buffer_t * aout_OutputNextBuffer( aout_instance_t * p_aout, ...@@ -304,12 +304,6 @@ aout_buffer_t * aout_OutputNextBuffer( aout_instance_t * p_aout,
* 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 ( 0 > delta + 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
* an audio sample after an output starvation (ie. on start or on resume)
* --Gibalou
*/
{ {
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"), "
...@@ -322,17 +316,15 @@ aout_buffer_t * aout_OutputNextBuffer( aout_instance_t * p_aout, ...@@ -322,17 +316,15 @@ aout_buffer_t * aout_OutputNextBuffer( aout_instance_t * p_aout,
p_aout->output.b_starving = false; p_aout->output.b_starving = false;
p_buffer = aout_FifoPop( p_fifo ); p_buffer = aout_FifoPop( p_fifo );
if( !b_can_sleek ) if( !b_can_sleek
&& ( delta > AOUT_MAX_PTS_DELAY || delta < -AOUT_MAX_PTS_ADVANCE ) )
{ {
if( delta > AOUT_PTS_TOLERANCE || delta < -AOUT_PTS_TOLERANCE ) /* Try to compensate the drift by doing some resampling. */
{ msg_Warn( p_aout, "output date isn't PTS date, requesting "
/* Try to compensate the drift by doing some resampling. */ "resampling (%"PRId64")", delta );
msg_Warn( p_aout, "output date isn't PTS date, requesting "
"resampling (%"PRId64")", delta );
aout_FifoMoveDates( &p_aout->p_input->mixer.fifo, delta ); aout_FifoMoveDates( &p_aout->p_input->mixer.fifo, delta );
aout_FifoMoveDates( p_fifo, delta ); aout_FifoMoveDates( p_fifo, delta );
}
} }
out: out:
aout_unlock( p_aout ); aout_unlock( 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