|
|
@@ -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], |
|
|
|