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

Reply via email to