On Fri, 13 Jul 2012 20:31:58 -0400, Justin Ruggles <[email protected]> wrote: > Allow substitution of channel pairs in the input for nearby channel pairs in > the output in order to get a closer match. Also weigh LFE channel mismatch > differently to favor matching the same layout without LFE over one less > channel with LFE. > --- > libavfilter/avfiltergraph.c | 83 > +++++++++++++++++++++++++++++++++++++------ > 1 files changed, 72 insertions(+), 11 deletions(-) > > diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c > index c147c3b..725fcd4 100644 > --- a/libavfilter/avfiltergraph.c > +++ b/libavfilter/avfiltergraph.c > @@ -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, AV_CH_FRONT_CENTER }, > + { CH_CENTER_PAIR, CH_WIDE_PAIR }, > + { CH_WIDE_PAIR, CH_FRONT_PAIR }, > + { CH_WIDE_PAIR, AV_CH_FRONT_CENTER }, > + { CH_WIDE_PAIR, CH_CENTER_PAIR }, > + { 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 &= ~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], > -- > 1.7.1
LGTM -- Anton Khirnov _______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
