@ -424,11 +424,44 @@ static void swap_samplerates(AVFilterGraph *graph)
swap_samplerates_on_filter ( graph - > filters [ i ] ) ;
}
# define CH_CENTER_PAIR (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)
# define CH_FRONT_PAIR (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)
# define CH_STEREO_PAIR (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT)
# define CH_WIDE_PAIR (AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT)
# define CH_SIDE_PAIR (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)
# define CH_DIRECT_PAIR (AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT)
# define CH_BACK_PAIR (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)
/* allowable substitutions for channel pairs when comparing layouts,
* ordered by priority for both values */
static const uint64_t ch_subst [ ] [ 2 ] = {
{ CH_FRONT_PAIR , CH_CENTER_PAIR } ,
{ CH_FRONT_PAIR , CH_WIDE_PAIR } ,
{ CH_FRONT_PAIR , AV_CH_FRONT_CENTER } ,
{ CH_CENTER_PAIR , CH_FRONT_PAIR } ,
{ CH_CENTER_PAIR , CH_WIDE_PAIR } ,
{ CH_CENTER_PAIR , AV_CH_FRONT_CENTER } ,
{ CH_WIDE_PAIR , CH_FRONT_PAIR } ,
{ CH_WIDE_PAIR , CH_CENTER_PAIR } ,
{ CH_WIDE_PAIR , AV_CH_FRONT_CENTER } ,
{ AV_CH_FRONT_CENTER , CH_FRONT_PAIR } ,
{ AV_CH_FRONT_CENTER , CH_CENTER_PAIR } ,
{ AV_CH_FRONT_CENTER , CH_WIDE_PAIR } ,
{ CH_SIDE_PAIR , CH_DIRECT_PAIR } ,
{ CH_SIDE_PAIR , CH_BACK_PAIR } ,
{ CH_SIDE_PAIR , AV_CH_BACK_CENTER } ,
{ CH_BACK_PAIR , CH_DIRECT_PAIR } ,
{ CH_BACK_PAIR , CH_SIDE_PAIR } ,
{ CH_BACK_PAIR , AV_CH_BACK_CENTER } ,
{ AV_CH_BACK_CENTER , CH_BACK_PAIR } ,
{ AV_CH_BACK_CENTER , CH_DIRECT_PAIR } ,
{ AV_CH_BACK_CENTER , CH_SIDE_PAIR } ,
} ;
static void swap_channel_layouts_on_filter ( AVFilterContext * filter )
{
AVFilterLink * link = NULL ;
uint64_t chlayout ;
int i , j ;
int i , j , k ;
for ( i = 0 ; i < filter - > nb_inputs ; i + + ) {
link = filter - > inputs [ i ] ;
@ -440,27 +473,55 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter)
if ( i = = filter - > nb_inputs )
return ;
chlayout = link - > out_channel_layouts - > channel_layouts [ 0 ] ;
for ( i = 0 ; i < filter - > nb_outputs ; i + + ) {
AVFilterLink * outlink = filter - > outputs [ i ] ;
int best_idx , best_score = INT_MIN ;
int best_idx , best_score = INT_MIN , best_count_diff = INT_MAX ;
if ( outlink - > type ! = AVMEDIA_TYPE_AUDIO | |
outlink - > in_channel_layouts - > nb_channel_layouts < 2 )
continue ;
for ( j = 0 ; j < outlink - > in_channel_layouts - > nb_channel_layouts ; j + + ) {
uint64_t in_chlayout = link - > out_channel_layouts - > channel_layouts [ 0 ] ;
uint64_t out_chlayout = outlink - > in_channel_layouts - > channel_layouts [ j ] ;
int matched_channels = av_get_channel_layout_nb_channels ( chlayout &
out_chlayout ) ;
int extra_channels = av_get_channel_layout_nb_channels ( out_chlayout &
( ~ chlayout ) ) ;
int score = matched_channels - extra_channels ;
int in_channels = av_get_channel_layout_nb_channels ( in_chlayout ) ;
int out_channels = av_get_channel_layout_nb_channels ( out_chlayout ) ;
int count_diff = out_channels - in_channels ;
int matched_channels , extra_channels ;
int score = 0 ;
/* channel substitution */
for ( k = 0 ; k < FF_ARRAY_ELEMS ( ch_subst ) ; k + + ) {
uint64_t cmp0 = ch_subst [ k ] [ 0 ] ;
uint64_t cmp1 = ch_subst [ k ] [ 1 ] ;
if ( ( in_chlayout & cmp0 ) & & ( ! ( out_chlayout & cmp0 ) ) & &
( out_chlayout & cmp1 ) & & ( ! ( in_chlayout & cmp1 ) ) ) {
in_chlayout & = ~ cmp0 ;
out_chlayout & = ~ cmp1 ;
/* add score for channel match, minus a deduction for
having to do the substitution */
score + = 10 * av_get_channel_layout_nb_channels ( cmp1 ) - 2 ;
}
}
if ( score > best_score ) {
/* no penalty for LFE channel mismatch */
if ( ( in_chlayout & AV_CH_LOW_FREQUENCY ) & &
( out_chlayout & AV_CH_LOW_FREQUENCY ) )
score + = 10 ;
in_chlayout & = ~ AV_CH_LOW_FREQUENCY ;
out_chlayout & = ~ AV_CH_LOW_FREQUENCY ;
matched_channels = av_get_channel_layout_nb_channels ( in_chlayout &
out_chlayout ) ;
extra_channels = av_get_channel_layout_nb_channels ( out_chlayout &
( ~ in_chlayout ) ) ;
score + = 10 * matched_channels - 5 * extra_channels ;
if ( score > best_score | |
( count_diff < best_count_diff & & score = = best_score ) ) {
best_score = score ;
best_idx = j ;
best_count_diff = count_diff ;
}
}
FFSWAP ( uint64_t , outlink - > in_channel_layouts - > channel_layouts [ 0 ] ,