@ -1970,25 +1970,19 @@ static void update_sample_display(VideoState *is, short *samples, int samples_si
}
}
/* return the new audio buffer size (samples can be added or deleted
to get better sync if video or external master clock ) */
static int synchronize_audio ( VideoState * is , short * samples ,
int samples_size1 , double pts )
/* return the wanted number of samples to get better sync if sync_type is video
* or external master clock */
static int synchronize_audio ( VideoState * is , int nb_samples )
{
int n , samples_size ;
double ref_clock ;
n = av_get_bytes_per_sample ( is - > audio_tgt_fmt ) * is - > audio_tgt_channels ;
samples_size = samples_size1 ;
int wanted_nb_samples = nb_samples ;
/* if not master, then we try to remove or add samples to correct the clock */
if ( ( ( is - > av_sync_type = = AV_SYNC_VIDEO_MASTER & & is - > video_st ) | |
is - > av_sync_type = = AV_SYNC_EXTERNAL_CLOCK ) ) {
double diff , avg_diff ;
int wanted_size , min_size , max_size , nb_samples ;
int min_nb_samples , max_nb_samples ;
ref_clock = get_master_clock ( is ) ;
diff = get_audio_clock ( is ) - ref_clock ;
diff = get_audio_clock ( is ) - get_master_clock ( is ) ;
if ( diff < AV_NOSYNC_THRESHOLD ) {
is - > audio_diff_cum = diff + is - > audio_diff_avg_coef * is - > audio_diff_cum ;
@ -2000,38 +1994,13 @@ static int synchronize_audio(VideoState *is, short *samples,
avg_diff = is - > audio_diff_cum * ( 1.0 - is - > audio_diff_avg_coef ) ;
if ( fabs ( avg_diff ) > = is - > audio_diff_threshold ) {
wanted_size = samples_size + ( ( int ) ( diff * is - > audio_tgt_freq ) * n ) ;
nb_samples = samples_size / n ;
min_size = ( ( nb_samples * ( 100 - SAMPLE_CORRECTION_PERCENT_MAX ) ) / 100 ) * n ;
max_size = ( ( nb_samples * ( 100 + SAMPLE_CORRECTION_PERCENT_MAX ) ) / 100 ) * n ;
if ( wanted_size < min_size )
wanted_size = min_size ;
else if ( wanted_size > FFMIN3 ( max_size , samples_size , sizeof ( is - > audio_buf2 ) ) )
wanted_size = FFMIN3 ( max_size , samples_size , sizeof ( is - > audio_buf2 ) ) ;
/* add or remove samples to correction the synchro */
if ( wanted_size < samples_size ) {
/* remove samples */
samples_size = wanted_size ;
} else if ( wanted_size > samples_size ) {
uint8_t * samples_end , * q ;
int nb ;
/* add samples */
nb = ( samples_size - wanted_size ) ;
samples_end = ( uint8_t * ) samples + samples_size - n ;
q = samples_end + n ;
while ( nb > 0 ) {
memcpy ( q , samples_end , n ) ;
q + = n ;
nb - = n ;
}
samples_size = wanted_size ;
}
wanted_nb_samples = nb_samples + ( int ) ( diff * is - > audio_src_freq ) ;
min_nb_samples = ( ( nb_samples * ( 100 - SAMPLE_CORRECTION_PERCENT_MAX ) / 100 ) ) ;
max_nb_samples = ( ( nb_samples * ( 100 + SAMPLE_CORRECTION_PERCENT_MAX ) / 100 ) ) ;
wanted_nb_samples = FFMIN ( FFMAX ( wanted_nb_samples , min_nb_samples ) , max_nb_samples ) ;
}
av_dlog ( NULL , " diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f \n " ,
diff , avg_diff , samples_size - samples_size1 ,
diff , avg_diff , wanted_nb_samples - nb_samples ,
is - > audio_clock , is - > video_clock , is - > audio_diff_threshold ) ;
}
} else {
@ -2042,7 +2011,7 @@ static int synchronize_audio(VideoState *is, short *samples,
}
}
return samples_size ;
return wanted_nb_ samples;
}
/* decode one audio frame and returns its uncompressed size */
@ -2057,6 +2026,7 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr)
double pts ;
int new_packet = 0 ;
int flush_complete = 0 ;
int wanted_nb_samples ;
for ( ; ; ) {
/* NOTE: the audio packet can contain several frames */
@ -2091,8 +2061,12 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr)
dec - > sample_fmt , 1 ) ;
dec_channel_layout = ( dec - > channel_layout & & dec - > channels = = av_get_channel_layout_nb_channels ( dec - > channel_layout ) ) ? dec - > channel_layout : av_get_default_channel_layout ( dec - > channels ) ;
wanted_nb_samples = synchronize_audio ( is , is - > frame - > nb_samples ) ;
if ( dec - > sample_fmt ! = is - > audio_src_fmt | | dec_channel_layout ! = is - > audio_src_channel_layout | | dec - > sample_rate ! = is - > audio_src_freq ) {
if ( dec - > sample_fmt ! = is - > audio_src_fmt | |
dec_channel_layout ! = is - > audio_src_channel_layout | |
dec - > sample_rate ! = is - > audio_src_freq | |
( wanted_nb_samples ! = is - > frame - > nb_samples & & ! is - > swr_ctx ) ) {
if ( is - > swr_ctx )
swr_free ( & is - > swr_ctx ) ;
is - > swr_ctx = swr_alloc_set_opts ( NULL ,
@ -2119,8 +2093,15 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr)
if ( is - > swr_ctx ) {
const uint8_t * in [ ] = { is - > frame - > data [ 0 ] } ;
uint8_t * out [ ] = { is - > audio_buf2 } ;
if ( wanted_nb_samples ! = is - > frame - > nb_samples ) {
if ( swr_set_compensation ( is - > swr_ctx , ( wanted_nb_samples - is - > frame - > nb_samples ) * is - > audio_tgt_freq / dec - > sample_rate ,
wanted_nb_samples * is - > audio_tgt_freq / dec - > sample_rate ) < 0 ) {
fprintf ( stderr , " swr_set_compensation() failed \n " ) ;
break ;
}
}
len2 = swr_convert ( is - > swr_ctx , out , sizeof ( is - > audio_buf2 ) / is - > audio_tgt_channels / av_get_bytes_per_sample ( is - > audio_tgt_fmt ) ,
in , data_size / dec - > channels / av_get_bytes_per_sample ( dec - > sample_fmt ) ) ;
in , is - > frame - > nb_ samples ) ;
if ( len2 < 0 ) {
fprintf ( stderr , " audio_resample() failed \n " ) ;
break ;
@ -2196,8 +2177,6 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
} else {
if ( is - > show_mode ! = SHOW_MODE_VIDEO )
update_sample_display ( is , ( int16_t * ) is - > audio_buf , audio_size ) ;
audio_size = synchronize_audio ( is , ( int16_t * ) is - > audio_buf , audio_size ,
pts ) ;
is - > audio_buf_size = audio_size ;
}
is - > audio_buf_index = 0 ;