diff mbox series

[FFmpeg-devel,274/281] swresample: convert to new channel layout API

Message ID 20220113020913.870-5-jamrial@gmail.com
State New
Headers show
Series New channel layout API | expand

Commit Message

James Almer Jan. 13, 2022, 2:09 a.m. UTC
Signed-off-by: James Almer <jamrial@gmail.com>
---
 libswresample/options.c             |  33 +++-
 libswresample/rematrix.c            | 237 ++++++++++++++++++----------
 libswresample/rematrix_template.c   |   7 +-
 libswresample/swresample.c          | 152 +++++++++++++++---
 libswresample/swresample.h          |  63 ++++++++
 libswresample/swresample_frame.c    |  65 +++++++-
 libswresample/swresample_internal.h |  10 +-
 7 files changed, 445 insertions(+), 122 deletions(-)

Comments

Andreas Rheinhardt Jan. 19, 2022, 5:20 p.m. UTC | #1
James Almer:
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>  libswresample/options.c             |  33 +++-
>  libswresample/rematrix.c            | 237 ++++++++++++++++++----------
>  libswresample/rematrix_template.c   |   7 +-
>  libswresample/swresample.c          | 152 +++++++++++++++---
>  libswresample/swresample.h          |  63 ++++++++

This header still contains many references to swr_alloc_set_opts().

>  libswresample/swresample_frame.c    |  65 +++++++-
>  libswresample/swresample_internal.h |  10 +-
>  7 files changed, 445 insertions(+), 122 deletions(-)
> 
> diff --git a/libswresample/options.c b/libswresample/options.c
> index 6911709157..ffa27c590d 100644
> --- a/libswresample/options.c
> +++ b/libswresample/options.c
> @@ -34,12 +34,19 @@
>  
>  #define OFFSET(x) offsetof(SwrContext,x)
>  #define PARAM AV_OPT_FLAG_AUDIO_PARAM
> +#define DEPREC AV_OPT_FLAG_DEPRECATED
>  
>  static const AVOption options[]={
> -{"ich"                  , "set input channel count"     , OFFSET(user_in_ch_count  ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
> -{"in_channel_count"     , "set input channel count"     , OFFSET(user_in_ch_count  ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
> -{"och"                  , "set output channel count"    , OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
> -{"out_channel_count"    , "set output channel count"    , OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
> +#if FF_API_OLD_CHANNEL_LAYOUT
> +{"ich"                  , "set input channel count (Deprecated, use ichl)",
> +                                                          OFFSET(user_in_ch_count  ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM|DEPREC},
> +{"in_channel_count"     , "set input channel count (Deprecated, use in_chlayout)",
> +                                                          OFFSET(user_in_ch_count  ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM|DEPREC},
> +{"och"                  , "set output channel count (Deprecated, use ochl)",
> +                                                          OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM|DEPREC},
> +{"out_channel_count"    , "set output channel count (Deprecated, use out_chlayout)",
> +                                                          OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM|DEPREC},
> +#endif
>  {"uch"                  , "set used channel count"      , OFFSET(user_used_ch_count), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
>  {"used_channel_count"   , "set used channel count"      , OFFSET(user_used_ch_count), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
>  {"isr"                  , "set input sample rate"       , OFFSET( in_sample_rate), AV_OPT_TYPE_INT  , {.i64=0                     }, 0      , INT_MAX   , PARAM},
> @@ -52,10 +59,20 @@ static const AVOption options[]={
>  {"out_sample_fmt"       , "set output sample format"    , OFFSET(out_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1   , INT_MAX, PARAM},
>  {"tsf"                  , "set internal sample format"  , OFFSET(user_int_sample_fmt), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1   , INT_MAX, PARAM},
>  {"internal_sample_fmt"  , "set internal sample format"  , OFFSET(user_int_sample_fmt), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1   , INT_MAX, PARAM},
> -{"icl"                  , "set input channel layout"    , OFFSET(user_in_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0           }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"},
> -{"in_channel_layout"    , "set input channel layout"    , OFFSET(user_in_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0           }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"},
> -{"ocl"                  , "set output channel layout"   , OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0           }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"},
> -{"out_channel_layout"   , "set output channel layout"   , OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0           }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"},
> +#if FF_API_OLD_CHANNEL_LAYOUT
> +{"icl"                  , "set input channel layout (Deprecated, use ichl)",
> +                                                          OFFSET(user_in_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0          }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"},
> +{"in_channel_layout"    , "set input channel layout (Deprecated, use in_chlayout)",
> +                                                          OFFSET(user_in_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0          }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"},
> +{"ocl"                  , "set output channel layout (Deprecated, use ochl)",
> +                                                          OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0         }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"},
> +{"out_channel_layout"   , "set output channel layout (Deprecated, use out_chlayout)",
> +                                                          OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0         }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"},
> +#endif
> +{"ichl"                 , "set input channel layout"    , OFFSET(user_in_chlayout ), AV_OPT_TYPE_CHLAYOUT, {.str=NULL             }, 0, 0 , PARAM, "chlayout"},
> +{"in_chlayout"          , "set input channel layout"    , OFFSET(user_in_chlayout ), AV_OPT_TYPE_CHLAYOUT, {.str=NULL             }, 0, 0 , PARAM, "chlayout"},
> +{"ochl"                 , "set output channel layout"   , OFFSET(user_out_chlayout), AV_OPT_TYPE_CHLAYOUT, {.str=NULL             }, 0, 0 , PARAM, "chlayout"},
> +{"out_chlayout"         , "set output channel layout"   , OFFSET(user_out_chlayout), AV_OPT_TYPE_CHLAYOUT, {.str=NULL             }, 0, 0 , PARAM, "chlayout"},
>  {"clev"                 , "set center mix level"        , OFFSET(clev           ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB                }, -32    , 32        , PARAM},
>  {"center_mix_level"     , "set center mix level"        , OFFSET(clev           ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB                }, -32    , 32        , PARAM},
>  {"slev"                 , "set surround mix level"      , OFFSET(slev           ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB                }, -32    , 32        , PARAM},
> diff --git a/libswresample/rematrix.c b/libswresample/rematrix.c
> index 94b3de88f6..35086c218d 100644
> --- a/libswresample/rematrix.c
> +++ b/libswresample/rematrix.c
> @@ -64,15 +64,37 @@
>  int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride)
>  {
>      int nb_in, nb_out, in, out;
> +    int user_in_chlayout_nb_channels, user_out_chlayout_nb_channels;
>  
>      if (!s || s->in_convert) // s needs to be allocated but not initialized
>          return AVERROR(EINVAL);
>      memset(s->matrix, 0, sizeof(s->matrix));
>      memset(s->matrix_flt, 0, sizeof(s->matrix_flt));
> -    nb_in = (s->user_in_ch_count > 0) ? s->user_in_ch_count :
> -        av_get_channel_layout_nb_channels(s->user_in_ch_layout);
> -    nb_out = (s->user_out_ch_count > 0) ? s->user_out_ch_count :
> -        av_get_channel_layout_nb_channels(s->user_out_ch_layout);
> +
> +#if FF_API_OLD_CHANNEL_LAYOUT
> +FF_DISABLE_DEPRECATION_WARNINGS
> +    user_in_chlayout_nb_channels = av_get_channel_layout_nb_channels(s->user_in_ch_layout);
> +FF_ENABLE_DEPRECATION_WARNINGS
> +    if (!user_in_chlayout_nb_channels)
> +#endif
> +    user_in_chlayout_nb_channels = s->user_in_chlayout.nb_channels;
> +    nb_in =
> +#if FF_API_OLD_CHANNEL_LAYOUT
> +            (s->user_in_ch_count > 0) ? s->user_in_ch_count :
> +#endif
> +            user_in_chlayout_nb_channels;
> +#if FF_API_OLD_CHANNEL_LAYOUT
> +FF_DISABLE_DEPRECATION_WARNINGS
> +    user_out_chlayout_nb_channels = av_get_channel_layout_nb_channels(s->user_out_ch_layout);
> +FF_ENABLE_DEPRECATION_WARNINGS
> +    if (!user_out_chlayout_nb_channels)
> +#endif
> +    user_out_chlayout_nb_channels = s->user_out_chlayout.nb_channels;
> +    nb_out =
> +#if FF_API_OLD_CHANNEL_LAYOUT
> +             (s->user_out_ch_count > 0) ? s->user_out_ch_count :
> +#endif
> +             user_out_chlayout_nb_channels;
>      for (out = 0; out < nb_out; out++) {
>          for (in = 0; in < nb_in; in++)
>              s->matrix_flt[out][in] = s->matrix[out][in] = matrix[in];
> @@ -88,95 +110,141 @@ static int even(int64_t layout){
>      return 0;
>  }
>  
> -static int64_t clean_layout(void *s, int64_t layout){
> -    if(layout && layout != AV_CH_FRONT_CENTER && !(layout&(layout-1))) {
> +static int clean_layout(AVChannelLayout *out, const AVChannelLayout *in, void *s)
> +{
> +    int ret = 0;
> +
> +    if(av_channel_layout_index_from_channel(in, AV_CH_FRONT_CENTER) < 0 && in->nb_channels == 1) {
>          char buf[128];
> -        av_get_channel_layout_string(buf, sizeof(buf), -1, layout);
> +        av_channel_layout_describe(in, buf, sizeof(buf));
>          av_log(s, AV_LOG_VERBOSE, "Treating %s as mono\n", buf);
> -        return AV_CH_FRONT_CENTER;
> -    }
> +        *out = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
> +    } else
> +        ret = av_channel_layout_copy(out, in);
>  
> -    return layout;
> +    return ret;
>  }
>  
> -static int sane_layout(int64_t layout){
> -    if(!(layout & AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker
> +static int sane_layout(AVChannelLayout *ch_layout) {
> +    if (ch_layout->order != AV_CHANNEL_ORDER_NATIVE)
> +        return 0;
> +    if(!av_channel_layout_subset(ch_layout, AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker
>          return 0;
> -    if(!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT))) // no asymetric front
> +    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)))) // no asymetric front
>          return 0;
> -    if(!even(layout & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)))   // no asymetric side
> +    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT))))   // no asymetric side
>          return 0;
> -    if(!even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)))
> +    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT))))
>          return 0;
> -    if(!even(layout & (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)))
> +    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER))))
>          return 0;
> -    if(av_get_channel_layout_nb_channels(layout) >= SWR_CH_MAX)
> +    if(ch_layout->nb_channels >= SWR_CH_MAX)
>          return 0;
>  
>      return 1;
>  }
>  
> +#if FF_API_OLD_CHANNEL_LAYOUT
>  av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout_param,
>                               double center_mix_level, double surround_mix_level,
>                               double lfe_mix_level, double maxval,
>                               double rematrix_volume, double *matrix_param,
>                               int stride, enum AVMatrixEncoding matrix_encoding, void *log_context)
>  {
> -    int i, j, out_i;
> +    AVChannelLayout in_ch_layout = { 0 }, out_ch_layout = { 0 };
> +    int ret;
> +
> +    ret  = av_channel_layout_from_mask(&in_ch_layout, in_ch_layout_param);
> +    ret |= av_channel_layout_from_mask(&out_ch_layout, out_ch_layout_param);
> +    if (ret < 0)
> +        return ret;
> +
> +    return swr_build_matrix2(&in_ch_layout, &out_ch_layout, center_mix_level, surround_mix_level,
> +                             lfe_mix_level, maxval, rematrix_volume, matrix_param,
> +                             stride, matrix_encoding, log_context);
> +}
> +#endif
> +
> +av_cold int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout,
> +                              double center_mix_level, double surround_mix_level,
> +                              double lfe_mix_level, double maxval,
> +                              double rematrix_volume, double *matrix_param,
> +                              ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding, void *log_context)
> +{
> +    int i, j, out_i, ret;
> +    AVChannelLayout in_ch_layout = { 0 }, out_ch_layout = { 0 };
>      double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS]={{0}};
> -    int64_t unaccounted, in_ch_layout, out_ch_layout;
> +    int64_t unaccounted;
>      double maxcoef=0;
>      char buf[128];
>  
> -     in_ch_layout = clean_layout(log_context,  in_ch_layout_param);
> -    out_ch_layout = clean_layout(log_context, out_ch_layout_param);
> -
> -    if(   out_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX
> -       && (in_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0
> -    )
> -        out_ch_layout = AV_CH_LAYOUT_STEREO;
> +    ret  = clean_layout(&in_ch_layout, in_layout, log_context);
> +    ret |= clean_layout(&out_ch_layout, out_layout, log_context);
> +    if (ret < 0)
> +        goto fail;
>  
> -    if(    in_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX
> -       && (out_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0
> -    )
> -        in_ch_layout = AV_CH_LAYOUT_STEREO;
> -
> -    if (in_ch_layout == AV_CH_LAYOUT_22POINT2 &&
> -        out_ch_layout != AV_CH_LAYOUT_22POINT2) {
> -        in_ch_layout = (AV_CH_LAYOUT_7POINT1_WIDE_BACK|AV_CH_BACK_CENTER);
> -        av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout);
> +    if(   !av_channel_layout_compare(&out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO_DOWNMIX)
> +       && !av_channel_layout_subset(&in_ch_layout, AV_CH_LAYOUT_STEREO_DOWNMIX)
> +    ) {
> +        av_channel_layout_uninit(&out_ch_layout);
> +        out_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
> +    }
> +    if(   !av_channel_layout_compare(&in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO_DOWNMIX)
> +       && !av_channel_layout_subset(&out_ch_layout, AV_CH_LAYOUT_STEREO_DOWNMIX)
> +    ) {
> +        av_channel_layout_uninit(&in_ch_layout);
> +        in_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
> +    }
> +    if (!av_channel_layout_compare(&in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_22POINT2) &&
> +        av_channel_layout_compare(&out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_22POINT2)) {
> +        av_channel_layout_from_mask(&in_ch_layout, (AV_CH_LAYOUT_7POINT1_WIDE_BACK|AV_CH_BACK_CENTER));
> +        av_channel_layout_describe(&in_ch_layout, buf, sizeof(buf));
>          av_log(log_context, AV_LOG_WARNING,
>                 "Full-on remixing from 22.2 has not yet been implemented! "
>                 "Processing the input as '%s'\n",
>                 buf);
>      }
>  
> -    if(!sane_layout(in_ch_layout)){
> -        av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout_param);
> +    if(!av_channel_layout_check(&in_ch_layout)) {
> +        av_log(log_context, AV_LOG_ERROR, "Input channel layout is invalid\n");
> +        ret = AVERROR(EINVAL);
> +        goto fail;
> +    }
> +    if(!sane_layout(&in_ch_layout)) {
> +        av_channel_layout_describe(&in_ch_layout, buf, sizeof(buf));
>          av_log(log_context, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf);
> -        return AVERROR(EINVAL);
> +        ret = AVERROR(EINVAL);
> +        goto fail;
>      }
>  
> -    if(!sane_layout(out_ch_layout)){
> -        av_get_channel_layout_string(buf, sizeof(buf), -1, out_ch_layout_param);
> +    if(!av_channel_layout_check(&out_ch_layout)) {
> +        av_log(log_context, AV_LOG_ERROR, "Output channel layout is invalid\n");
> +        ret = AVERROR(EINVAL);
> +        goto fail;
> +    }
> +    if(!sane_layout(&out_ch_layout)) {
> +        av_channel_layout_describe(&out_ch_layout, buf, sizeof(buf));
>          av_log(log_context, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf);
> -        return AVERROR(EINVAL);
> +        ret = AVERROR(EINVAL);
> +        goto fail;
>      }
>  
>      for(i=0; i<FF_ARRAY_ELEMS(matrix); i++){
> -        if(in_ch_layout & out_ch_layout & (1ULL<<i))
> +        int idx;
> +        if(   (idx = av_channel_layout_index_from_channel(&in_ch_layout, i)) >= 0
> +           && av_channel_layout_index_from_channel(&out_ch_layout, i) == idx)
>              matrix[i][i]= 1.0;
>      }
>  
> -    unaccounted= in_ch_layout & ~out_ch_layout;
> +    unaccounted =  in_ch_layout.u.mask & ~out_ch_layout.u.mask;

Weird whitespace.

>  
>  //FIXME implement dolby surround
>  //FIXME implement full ac3
>  
>  
>      if(unaccounted & AV_CH_FRONT_CENTER){
> -        if((out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){
> -            if(in_ch_layout & AV_CH_LAYOUT_STEREO) {
> +        if(av_channel_layout_subset(&out_ch_layout, AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){
> +            if(av_channel_layout_subset(&in_ch_layout, AV_CH_LAYOUT_STEREO)) {

Missing whitespace. Applies to the whole patch.

>                  matrix[ FRONT_LEFT][FRONT_CENTER]+= center_mix_level;
>                  matrix[FRONT_RIGHT][FRONT_CENTER]+= center_mix_level;
>              } else {
> @@ -187,23 +255,23 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>              av_assert0(0);
>      }
>      if(unaccounted & AV_CH_LAYOUT_STEREO){
> -        if(out_ch_layout & AV_CH_FRONT_CENTER){
> +        if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){
>              matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2;
>              matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2;
> -            if(in_ch_layout & AV_CH_FRONT_CENTER)
> +            if(av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_FRONT_CENTER) >= 0)
>                  matrix[FRONT_CENTER][ FRONT_CENTER] = center_mix_level*sqrt(2);
>          }else
>              av_assert0(0);
>      }
>  
>      if(unaccounted & AV_CH_BACK_CENTER){
> -        if(out_ch_layout & AV_CH_BACK_LEFT){
> +        if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_LEFT) >= 0){
>              matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2;
>              matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2;
> -        }else if(out_ch_layout & AV_CH_SIDE_LEFT){
> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_SIDE_LEFT) >= 0){
>              matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2;
>              matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2;
> -        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0){
>              if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
>                  matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
>                  if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
> @@ -217,24 +285,24 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>                  matrix[ FRONT_LEFT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
>                  matrix[FRONT_RIGHT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
>              }
> -        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){
>              matrix[ FRONT_CENTER][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
>          }else
>              av_assert0(0);
>      }
>      if(unaccounted & AV_CH_BACK_LEFT){
> -        if(out_ch_layout & AV_CH_BACK_CENTER){
> +        if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_CENTER) >= 0){
>              matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2;
>              matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2;
> -        }else if(out_ch_layout & AV_CH_SIDE_LEFT){
> -            if(in_ch_layout & AV_CH_SIDE_LEFT){
> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_SIDE_LEFT) >= 0){
> +            if(av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_SIDE_LEFT) >= 0){
>                  matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2;
>                  matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2;
>              }else{
>              matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0;
>              matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0;
>              }
> -        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0){
>              if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
>                  matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2;
>                  matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
> @@ -249,7 +317,7 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>                  matrix[ FRONT_LEFT][ BACK_LEFT] += surround_mix_level;
>                  matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
>              }
> -        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){
>              matrix[ FRONT_CENTER][BACK_LEFT ]+= surround_mix_level*M_SQRT1_2;
>              matrix[ FRONT_CENTER][BACK_RIGHT]+= surround_mix_level*M_SQRT1_2;
>          }else
> @@ -257,20 +325,20 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>      }
>  
>      if(unaccounted & AV_CH_SIDE_LEFT){
> -        if(out_ch_layout & AV_CH_BACK_LEFT){
> +        if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_LEFT) >= 0){
>              /* if back channels do not exist in the input, just copy side
>                 channels to back channels, otherwise mix side into back */
> -            if (in_ch_layout & AV_CH_BACK_LEFT) {
> +            if (av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_BACK_LEFT) >= 0) {
>                  matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
>                  matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
>              } else {
>                  matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
>                  matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
>              }
> -        }else if(out_ch_layout & AV_CH_BACK_CENTER){
> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_CENTER) >= 0){
>              matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2;
>              matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2;
> -        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0){
>              if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
>                  matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2;
>                  matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
> @@ -285,7 +353,7 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>                  matrix[ FRONT_LEFT][ SIDE_LEFT] += surround_mix_level;
>                  matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
>              }
> -        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){
>              matrix[ FRONT_CENTER][SIDE_LEFT ]+= surround_mix_level * M_SQRT1_2;
>              matrix[ FRONT_CENTER][SIDE_RIGHT]+= surround_mix_level * M_SQRT1_2;
>          }else
> @@ -293,10 +361,10 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>      }
>  
>      if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){
> -        if(out_ch_layout & AV_CH_FRONT_LEFT){
> +        if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0){
>              matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0;
>              matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0;
> -        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){
>              matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2;
>              matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2;
>          }else
> @@ -304,9 +372,9 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>      }
>      /* mix LFE into front left/right or center */
>      if (unaccounted & AV_CH_LOW_FREQUENCY) {
> -        if (out_ch_layout & AV_CH_FRONT_CENTER) {
> +        if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) {
>              matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level;
> -        } else if (out_ch_layout & AV_CH_FRONT_LEFT) {
> +        } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) {
>              matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
>              matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
>          } else
> @@ -316,15 +384,19 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>      for(out_i=i=0; i<64; i++){
>          double sum=0;
>          int in_i=0;
> -        if((out_ch_layout & (1ULL<<i)) == 0)
> +        if(av_channel_layout_index_from_channel(&out_ch_layout, i) < 0)
>              continue;
>          for(j=0; j<64; j++){
> -            if((in_ch_layout & (1ULL<<j)) == 0)
> +            if(av_channel_layout_index_from_channel(&in_ch_layout, j) < 0)
>                 continue;
>              if (i < FF_ARRAY_ELEMS(matrix) && j < FF_ARRAY_ELEMS(matrix[0]))
>                  matrix_param[stride*out_i + in_i] = matrix[i][j];
> -            else
> -                matrix_param[stride*out_i + in_i] = i == j && (in_ch_layout & out_ch_layout & (1ULL<<i));
> +            else {
> +                int idx;
> +                matrix_param[stride*out_i + in_i] = i == j &&
> +                (   (idx = av_channel_layout_index_from_channel(&in_ch_layout, i)) >= 0
> +                 && av_channel_layout_index_from_channel(&out_ch_layout, i) == idx);
> +            }
>              sum += fabs(matrix_param[stride*out_i + in_i]);
>              in_i++;
>          }
> @@ -350,17 +422,22 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>      }
>  
>      av_log(log_context, AV_LOG_DEBUG, "Matrix coefficients:\n");
> -    for(i=0; i<av_get_channel_layout_nb_channels(out_ch_layout); i++){
> -        const char *c =
> -            av_get_channel_name(av_channel_layout_extract_channel(out_ch_layout, i));
> -        av_log(log_context, AV_LOG_DEBUG, "%s: ", c ? c : "?");
> -        for(j=0; j<av_get_channel_layout_nb_channels(in_ch_layout); j++){
> -            c = av_get_channel_name(av_channel_layout_extract_channel(in_ch_layout, j));
> -            av_log(log_context, AV_LOG_DEBUG, "%s:%f ", c ? c : "?", matrix_param[stride*i + j]);
> +    for(i = 0; i < out_ch_layout.nb_channels; i++){
> +        av_channel_name(buf, sizeof(buf), av_channel_layout_channel_from_index(&out_ch_layout, i));
> +        av_log(log_context, AV_LOG_DEBUG, "%s: ", buf);
> +        for(j = 0; j < in_ch_layout.nb_channels; j++){
> +            av_channel_name(buf, sizeof(buf), av_channel_layout_channel_from_index(&in_ch_layout, j));
> +            av_log(log_context, AV_LOG_DEBUG, "%s:%f ", buf, matrix_param[stride*i + j]);
>          }
>          av_log(log_context, AV_LOG_DEBUG, "\n");
>      }
> -    return 0;
> +
> +    ret = 0;
> +fail:
> +    av_channel_layout_uninit(&in_ch_layout);
> +    av_channel_layout_uninit(&out_ch_layout);
> +
> +    return ret;
>  }
>  
>  av_cold static int auto_matrix(SwrContext *s)
> @@ -377,7 +454,7 @@ av_cold static int auto_matrix(SwrContext *s)
>          maxval = INT_MAX;
>  
>      memset(s->matrix, 0, sizeof(s->matrix));
> -    ret = swr_build_matrix(s->in_ch_layout, s->out_ch_layout,
> +    ret = swr_build_matrix2(&s->in_ch_layout, &s->out_ch_layout,
>                             s->clev, s->slev, s->lfe_mix_level,
>                             maxval, s->rematrix_volume, (double*)s->matrix,
>                             s->matrix[1] - s->matrix[0], s->matrix_encoding, s);
> @@ -519,8 +596,8 @@ int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mus
>          off = len1 * out->bps;
>      }
>  
> -    av_assert0(!s->out_ch_layout || out->ch_count == av_get_channel_layout_nb_channels(s->out_ch_layout));
> -    av_assert0(!s-> in_ch_layout || in ->ch_count == av_get_channel_layout_nb_channels(s-> in_ch_layout));
> +    av_assert0(s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC || out->ch_count == s->out_ch_layout.nb_channels);
> +    av_assert0(s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC || in ->ch_count == s->in_ch_layout.nb_channels);
>  
>      for(out_i=0; out_i<out->ch_count; out_i++){
>          switch(s->matrix_ch[out_i][0]){
> diff --git a/libswresample/rematrix_template.c b/libswresample/rematrix_template.c
> index add65e3155..f5a508361c 100644
> --- a/libswresample/rematrix_template.c
> +++ b/libswresample/rematrix_template.c
> @@ -88,13 +88,16 @@ static void RENAME(mix8to2)(SAMPLE **out, const SAMPLE **in, COEFF *coeffp, inte
>  }
>  
>  static RENAME(mix_any_func_type) *RENAME(get_mix_any_func)(SwrContext *s){
> -    if(   s->out_ch_layout == AV_CH_LAYOUT_STEREO && (s->in_ch_layout == AV_CH_LAYOUT_5POINT1 || s->in_ch_layout == AV_CH_LAYOUT_5POINT1_BACK)
> +    if(   !av_channel_layout_compare(&s->out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)
> +       && (   !av_channel_layout_compare(&s->in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1)
> +           || !av_channel_layout_compare(&s->in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK))
>         && s->matrix[0][2] == s->matrix[1][2] && s->matrix[0][3] == s->matrix[1][3]
>         && !s->matrix[0][1] && !s->matrix[0][5] && !s->matrix[1][0] && !s->matrix[1][4]
>      )
>          return RENAME(mix6to2);
>  
> -    if(   s->out_ch_layout == AV_CH_LAYOUT_STEREO && s->in_ch_layout == AV_CH_LAYOUT_7POINT1
> +    if(   !av_channel_layout_compare(&s->out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)
> +       && !av_channel_layout_compare(&s->in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1)
>         && s->matrix[0][2] == s->matrix[1][2] && s->matrix[0][3] == s->matrix[1][3]
>         && !s->matrix[0][1] && !s->matrix[0][5] && !s->matrix[1][0] && !s->matrix[1][4]
>         && !s->matrix[0][7] && !s->matrix[1][6]
> diff --git a/libswresample/swresample.c b/libswresample/swresample.c
> index 16734c9df9..f8fbd9134b 100644
> --- a/libswresample/swresample.c
> +++ b/libswresample/swresample.c
> @@ -56,6 +56,8 @@ int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map){
>      return 0;
>  }
>  
> +#if FF_API_OLD_CHANNEL_LAYOUT
> +FF_DISABLE_DEPRECATION_WARNINGS
>  struct SwrContext *swr_alloc_set_opts(struct SwrContext *s,
>                                        int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
>                                        int64_t  in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
> @@ -97,6 +99,58 @@ fail:
>      swr_free(&s);
>      return NULL;
>  }
> +FF_ENABLE_DEPRECATION_WARNINGS
> +#endif
> +
> +int swr_alloc_set_opts2(struct SwrContext **ps,
> +                        AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
> +                        AVChannelLayout *in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
> +                        int log_offset, void *log_ctx) {
> +    struct SwrContext *s = *ps;
> +    int ret;
> +
> +    if (!s) s = swr_alloc();
> +    if (!s) return AVERROR(ENOMEM);
> +
> +    s->log_level_offset= log_offset;
> +    s->log_ctx= log_ctx;

This has been copied from swr_alloc_set_opts without fixing whitespace
issues.

> +
> +    if ((ret = av_opt_set_chlayout(s, "ochl", out_ch_layout, 0)) < 0)
> +        goto fail;
> +
> +    if ((ret = av_opt_set_int(s, "osf", out_sample_fmt, 0)) < 0)
> +        goto fail;
> +
> +    if ((ret = av_opt_set_int(s, "osr", out_sample_rate, 0)) < 0)
> +        goto fail;
> +
> +    if ((ret = av_opt_set_chlayout(s, "ichl", in_ch_layout, 0)) < 0)
> +        goto fail;
> +
> +    if ((ret = av_opt_set_int(s, "isf", in_sample_fmt, 0)) < 0)
> +        goto fail;
> +
> +    if ((ret = av_opt_set_int(s, "isr", in_sample_rate, 0)) < 0)
> +        goto fail;
> +
> +    av_opt_set_int(s, "uch", 0, 0);
> +
> +#if FF_API_OLD_CHANNEL_LAYOUT
> +    // Clear old API values so they don't take precedence in swr_init()
> +    av_opt_set_int(s, "icl", 0, 0);
> +    av_opt_set_int(s, "ocl", 0, 0);
> +    av_opt_set_int(s, "ich", 0, 0);
> +    av_opt_set_int(s, "och", 0, 0);
> +#endif
> +
> +    *ps = s;
> +
> +    return 0;
> +fail:
> +    av_log(s, AV_LOG_ERROR, "Failed to set option\n");
> +    swr_free(ps);

In case s has been allocated by this function, it leaks. *ps = s needs
to be moved directly after allocation.

And why don't you implement the old API in terms of the new API?

> +    return ret;
> +}
>  
>  static void set_audiodata_fmt(AudioData *a, enum AVSampleFormat fmt){
>      a->fmt   = fmt;
> @@ -125,6 +179,8 @@ static void clear_context(SwrContext *s){
>      free_temp(&s->drop_temp);
>      free_temp(&s->dither.noise);
>      free_temp(&s->dither.temp);
> +    av_channel_layout_uninit(&s->in_ch_layout);
> +    av_channel_layout_uninit(&s->out_ch_layout);
>      swri_audio_convert_free(&s-> in_convert);
>      swri_audio_convert_free(&s->out_convert);
>      swri_audio_convert_free(&s->full_convert);
> @@ -138,6 +194,9 @@ av_cold void swr_free(SwrContext **ss){
>      SwrContext *s= *ss;
>      if(s){
>          clear_context(s);
> +        av_channel_layout_uninit(&s->user_in_chlayout);
> +        av_channel_layout_uninit(&s->user_out_chlayout);
> +
>          if (s->resampler)
>              s->resampler->free(&s->resample);
>      }
> @@ -172,25 +231,66 @@ av_cold int swr_init(struct SwrContext *s){
>          av_log(s, AV_LOG_ERROR, "Requested output sample rate %d is invalid\n", s->out_sample_rate);
>          return AVERROR(EINVAL);
>      }
> +    s->used_ch_count = s->user_used_ch_count;
> +#if FF_API_OLD_CHANNEL_LAYOUT
>      s->out.ch_count  = s-> user_out_ch_count;
>      s-> in.ch_count  = s->  user_in_ch_count;
> -    s->used_ch_count = s->user_used_ch_count;
>  
> -    s-> in_ch_layout = s-> user_in_ch_layout;
> -    s->out_ch_layout = s->user_out_ch_layout;
> +    // if the old/new fields are set inconsistently, prefer the old ones
> +    if ((s->user_in_ch_count && s->user_in_ch_count != s->user_in_chlayout.nb_channels) ||
> +        (s->user_in_ch_layout && (s->user_in_chlayout.order != AV_CHANNEL_ORDER_NATIVE ||
> +                                  s->user_in_chlayout.u.mask != s->user_in_ch_layout))) {
> +        av_channel_layout_uninit(&s->in_ch_layout);
> +        if (s->user_in_ch_layout)
> +            av_channel_layout_from_mask(&s->in_ch_layout, s->user_in_ch_layout);
> +        else {
> +            s->in_ch_layout.order       = AV_CHANNEL_ORDER_UNSPEC;
> +            s->in_ch_layout.nb_channels = s->user_in_ch_count;
> +        }
> +    } else
> +        av_channel_layout_copy(&s->in_ch_layout, &s->user_in_chlayout);
> +
> +    if ((s->user_out_ch_count && s->user_out_ch_count != s->user_out_chlayout.nb_channels) ||
> +        (s->user_out_ch_layout && (s->user_out_chlayout.order != AV_CHANNEL_ORDER_NATIVE ||
> +                                   s->user_out_chlayout.u.mask != s->user_out_ch_layout))) {
> +        av_channel_layout_uninit(&s->out_ch_layout);
> +        if (s->user_out_ch_layout)
> +            av_channel_layout_from_mask(&s->out_ch_layout, s->user_out_ch_layout);
> +        else {
> +            s->out_ch_layout.order       = AV_CHANNEL_ORDER_UNSPEC;
> +            s->out_ch_layout.nb_channels = s->user_out_ch_count;
> +        }
> +    } else
> +        av_channel_layout_copy(&s->out_ch_layout, &s->user_out_chlayout);
> +
> +    if (!s->out.ch_count && !s->user_out_ch_layout)
> +        s->out.ch_count  = s->out_ch_layout.nb_channels;
> +    if (!s-> in.ch_count && !s-> user_in_ch_layout)
> +        s-> in.ch_count  = s->in_ch_layout.nb_channels;
> +#else
> +    s->out.ch_count  = s-> user_out_chlayout.nb_channels;
> +    s-> in.ch_count  = s->  user_in_chlayout.nb_channels;
> +
> +    ret  = av_channel_layout_copy(&s->in_ch_layout, &s->user_in_chlayout);
> +    ret |= av_channel_layout_copy(&s->out_ch_layout, &s->user_out_chlayout);
> +    if (ret < 0)
> +        return ret;
> +#endif
>  
>      s->int_sample_fmt= s->user_int_sample_fmt;
>  
>      s->dither.method = s->user_dither_method;
>  
> -    if(av_get_channel_layout_nb_channels(s-> in_ch_layout) > SWR_CH_MAX) {
> -        av_log(s, AV_LOG_WARNING, "Input channel layout 0x%"PRIx64" is invalid or unsupported.\n", s-> in_ch_layout);
> -        s->in_ch_layout = 0;
> +    if (!av_channel_layout_check(&s->in_ch_layout) || s->in_ch_layout.nb_channels > SWR_CH_MAX) {
> +        av_channel_layout_describe(&s->in_ch_layout, l1, sizeof(l1));
> +        av_log(s, AV_LOG_WARNING, "Input channel layout \"%s\" is invalid or unsupported.\n", l1);
> +        av_channel_layout_uninit(&s->in_ch_layout);
>      }
>  
> -    if(av_get_channel_layout_nb_channels(s->out_ch_layout) > SWR_CH_MAX) {
> -        av_log(s, AV_LOG_WARNING, "Output channel layout 0x%"PRIx64" is invalid or unsupported.\n", s->out_ch_layout);
> -        s->out_ch_layout = 0;
> +    if (!av_channel_layout_check(&s->out_ch_layout) || s->out_ch_layout.nb_channels > SWR_CH_MAX) {
> +        av_channel_layout_describe(&s->out_ch_layout, l2, sizeof(l2));
> +        av_log(s, AV_LOG_WARNING, "Output channel layout \"%s\" is invalid or unsupported.\n", l2);
> +        av_channel_layout_uninit(&s->out_ch_layout);
>      }
>  
>      switch(s->engine){
> @@ -206,17 +306,18 @@ av_cold int swr_init(struct SwrContext *s){
>      if(!s->used_ch_count)
>          s->used_ch_count= s->in.ch_count;
>  
> -    if(s->used_ch_count && s-> in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s-> in_ch_layout)){
> +    if(s->used_ch_count && s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_count != s->in_ch_layout.nb_channels){
>          av_log(s, AV_LOG_WARNING, "Input channel layout has a different number of channels than the number of used channels, ignoring layout\n");
> -        s-> in_ch_layout= 0;
> +        av_channel_layout_uninit(&s->in_ch_layout);
>      }
>  
> -    if(!s-> in_ch_layout)
> -        s-> in_ch_layout= av_get_default_channel_layout(s->used_ch_count);
> -    if(!s->out_ch_layout)
> -        s->out_ch_layout= av_get_default_channel_layout(s->out.ch_count);
> +    if(!s->in_ch_layout.nb_channels || s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
> +        av_channel_layout_default(&s->in_ch_layout, s->used_ch_count);
> +    if(!s->out_ch_layout.nb_channels || s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
> +        av_channel_layout_default(&s->out_ch_layout, s->out.ch_count);
>  
> -    s->rematrix= s->out_ch_layout  !=s->in_ch_layout || s->rematrix_volume!=1.0 ||
> +    s->rematrix= av_channel_layout_compare(&s->out_ch_layout, &s->in_ch_layout) ||
> +                 s->rematrix_volume!=1.0 ||
>                   s->rematrix_custom;
>  
>      if(s->int_sample_fmt == AV_SAMPLE_FMT_NONE){
> @@ -291,33 +392,36 @@ av_cold int swr_init(struct SwrContext *s){
>  
>  #define RSC 1 //FIXME finetune
>      if(!s-> in.ch_count)
> -        s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout);
> +        s-> in.ch_count = s->in_ch_layout.nb_channels;
>      if(!s->used_ch_count)
>          s->used_ch_count= s->in.ch_count;
>      if(!s->out.ch_count)
> -        s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout);
> +        s->out.ch_count = s->out_ch_layout.nb_channels;
>  
>      if(!s-> in.ch_count){
> -        av_assert0(!s->in_ch_layout);
> +        av_assert0(s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC);
>          av_log(s, AV_LOG_ERROR, "Input channel count and layout are unset\n");
>          ret = AVERROR(EINVAL);
>          goto fail;
>      }
>  
> -    av_get_channel_layout_string(l1, sizeof(l1), s-> in.ch_count, s-> in_ch_layout);
> -    av_get_channel_layout_string(l2, sizeof(l2), s->out.ch_count, s->out_ch_layout);
> -    if (s->out_ch_layout && s->out.ch_count != av_get_channel_layout_nb_channels(s->out_ch_layout)) {
> +#if FF_API_OLD_CHANNEL_LAYOUT
> +    av_channel_layout_describe(&s->out_ch_layout, l1, sizeof(l1));
> +    if (s->out_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->out.ch_count != s->out_ch_layout.nb_channels) {
>          av_log(s, AV_LOG_ERROR, "Output channel layout %s mismatches specified channel count %d\n", l2, s->out.ch_count);
>          ret = AVERROR(EINVAL);
>          goto fail;
>      }
> -    if (s->in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s->in_ch_layout)) {
> +#endif
> +    av_channel_layout_describe(&s->in_ch_layout, l1, sizeof(l1));
> +    if (s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_count != s->in_ch_layout.nb_channels) {
>          av_log(s, AV_LOG_ERROR, "Input channel layout %s mismatches specified channel count %d\n", l1, s->used_ch_count);
>          ret = AVERROR(EINVAL);
>          goto fail;
>      }
>  
> -    if ((!s->out_ch_layout || !s->in_ch_layout) && s->used_ch_count != s->out.ch_count && !s->rematrix_custom) {
> +    if ((   s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC
> +         || s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) && s->used_ch_count != s->out.ch_count && !s->rematrix_custom) {
>          av_log(s, AV_LOG_ERROR, "Rematrix is needed between %s and %s "
>                 "but there is not enough information to do it\n", l1, l2);
>          ret = AVERROR(EINVAL);
> diff --git a/libswresample/swresample.h b/libswresample/swresample.h
> index c7b84fbcac..c6ff2345e9 100644
> --- a/libswresample/swresample.h
> +++ b/libswresample/swresample.h
> @@ -227,6 +227,7 @@ int swr_init(struct SwrContext *s);
>   */
>  int swr_is_initialized(struct SwrContext *s);
>  
> +#if FF_API_OLD_CHANNEL_LAYOUT
>  /**
>   * Allocate SwrContext if needed and set/reset common parameters.
>   *
> @@ -246,12 +247,40 @@ int swr_is_initialized(struct SwrContext *s);
>   *
>   * @see swr_init(), swr_free()
>   * @return NULL on error, allocated context otherwise
> + * @deprecated use @ref swr_alloc_set_opts2()
>   */
> +attribute_deprecated
>  struct SwrContext *swr_alloc_set_opts(struct SwrContext *s,
>                                        int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
>                                        int64_t  in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
>                                        int log_offset, void *log_ctx);
> +#endif
>  
> +/**
> + * Allocate SwrContext if needed and set/reset common parameters.
> + *
> + * This function does not require s to be allocated with swr_alloc(). On the
> + * other hand, swr_alloc() can use swr_alloc_set_opts() to set the parameters
> + * on the allocated context.
> + *
> + * @param ps              Pointer to an existing Swr context if available, or to NULL if not.
> + *                        On success, *ps will be set the allocated context.

This does not sound like proper English to me.
Moreover, it does not document that an already allocated context will be
freed here on error.

> + * @param out_ch_layout   output channel layout (AV_CH_LAYOUT_*)
> + * @param out_sample_fmt  output sample format (AV_SAMPLE_FMT_*).
> + * @param out_sample_rate output sample rate (frequency in Hz)
> + * @param in_ch_layout    input channel layout (AV_CH_LAYOUT_*)
> + * @param in_sample_fmt   input sample format (AV_SAMPLE_FMT_*).
> + * @param in_sample_rate  input sample rate (frequency in Hz)
> + * @param log_offset      logging level offset
> + * @param log_ctx         parent logging context, can be NULL
> + *
> + * @see swr_init(), swr_free()
> + * @return 0 on success, a negative AVERROR code on error.
> + */
> +int swr_alloc_set_opts2(struct SwrContext **ps,
> +                        AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
> +                        AVChannelLayout *in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
> +                        int log_offset, void *log_ctx);
>  /**
>   * @}
>   *
> @@ -362,6 +391,7 @@ int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensatio
>   */
>  int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map);
>  
> +#if FF_API_OLD_CHANNEL_LAYOUT
>  /**
>   * Generate a channel mixing matrix.
>   *
> @@ -384,13 +414,46 @@ int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map);
>   * @param matrix_encoding     matrixed stereo downmix mode (e.g. dplii)
>   * @param log_ctx             parent logging context, can be NULL
>   * @return                    0 on success, negative AVERROR code on failure
> + * @deprecated                use @ref swr_build_matrix2()
>   */
> +attribute_deprecated
>  int swr_build_matrix(uint64_t in_layout, uint64_t out_layout,
>                       double center_mix_level, double surround_mix_level,
>                       double lfe_mix_level, double rematrix_maxval,
>                       double rematrix_volume, double *matrix,
>                       int stride, enum AVMatrixEncoding matrix_encoding,
>                       void *log_ctx);
> +#endif
> +
> +/**
> + * Generate a channel mixing matrix.
> + *
> + * This function is the one used internally by libswresample for building the
> + * default mixing matrix. It is made public just as a utility function for
> + * building custom matrices.
> + *
> + * @param in_layout           input channel layout
> + * @param out_layout          output channel layout
> + * @param center_mix_level    mix level for the center channel
> + * @param surround_mix_level  mix level for the surround channel(s)
> + * @param lfe_mix_level       mix level for the low-frequency effects channel
> + * @param rematrix_maxval     if 1.0, coefficients will be normalized to prevent
> + *                            overflow. if INT_MAX, coefficients will not be
> + *                            normalized.
> + * @param[out] matrix         mixing coefficients; matrix[i + stride * o] is
> + *                            the weight of input channel i in output channel o.

The parameter below is named matrix_param.

> + * @param stride              distance between adjacent input channels in the
> + *                            matrix array
> + * @param matrix_encoding     matrixed stereo downmix mode (e.g. dplii)
> + * @param log_ctx             parent logging context, can be NULL
> + * @return                    0 on success, negative AVERROR code on failure
> + */
> +int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout,
> +                      double center_mix_level, double surround_mix_level,
> +                      double lfe_mix_level, double maxval,
> +                      double rematrix_volume, double *matrix_param,
> +                      ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding,
> +                      void *log_context);
>  
>  /**
>   * Set a customized remix matrix.
> diff --git a/libswresample/swresample_frame.c b/libswresample/swresample_frame.c
> index d95c1cc537..747cf119a9 100644
> --- a/libswresample/swresample_frame.c
> +++ b/libswresample/swresample_frame.c
> @@ -29,7 +29,19 @@ int swr_config_frame(SwrContext *s, const AVFrame *out, const AVFrame *in)
>      swr_close(s);
>  
>      if (in) {
> -        if (av_opt_set_int(s, "icl", in->channel_layout, 0) < 0)
> +        AVChannelLayout in_ch_layout = { 0 };
> +#if FF_API_OLD_CHANNEL_LAYOUT
> +FF_DISABLE_DEPRECATION_WARNINGS
> +        // if the old/new fields are set inconsistently, prefer the old ones
> +        if ((in->channel_layout && (in->ch_layout.order != AV_CHANNEL_ORDER_NATIVE ||
> +                                    in->ch_layout.u.mask != in->channel_layout))) {
> +            av_channel_layout_from_mask(&in_ch_layout, in->channel_layout);
> +FF_ENABLE_DEPRECATION_WARNINGS
> +        } else
> +#endif
> +        if (av_channel_layout_copy(&in_ch_layout, &in->ch_layout) < 0)
> +            goto fail;
> +        if (av_opt_set_chlayout(s, "ichl", &in_ch_layout, 0) < 0)
>              goto fail;
>          if (av_opt_set_int(s, "isf", in->format, 0) < 0)
>              goto fail;
> @@ -38,7 +50,19 @@ int swr_config_frame(SwrContext *s, const AVFrame *out, const AVFrame *in)
>      }
>  
>      if (out) {
> -        if (av_opt_set_int(s, "ocl", out->channel_layout, 0) < 0)
> +        AVChannelLayout out_ch_layout = { 0 };
> +#if FF_API_OLD_CHANNEL_LAYOUT
> +FF_DISABLE_DEPRECATION_WARNINGS
> +        // if the old/new fields are set inconsistently, prefer the old ones
> +        if ((out->channel_layout && (out->ch_layout.order != AV_CHANNEL_ORDER_NATIVE ||
> +                                     out->ch_layout.u.mask != out->channel_layout))) {
> +            av_channel_layout_from_mask(&out_ch_layout, out->channel_layout);
> +FF_ENABLE_DEPRECATION_WARNINGS
> +        } else
> +#endif
> +        if (av_channel_layout_copy(&out_ch_layout, &out->ch_layout) < 0)
> +            goto fail;
> +        if (av_opt_set_chlayout(s, "ochl", &out_ch_layout, 0) < 0)
>              goto fail;
>          if (av_opt_set_int(s, "osf", out->format,  0) < 0)
>              goto fail;
> @@ -58,7 +82,19 @@ static int config_changed(SwrContext *s,
>      int ret = 0;
>  
>      if (in) {
> -        if (s->in_ch_layout   != in->channel_layout ||
> +        AVChannelLayout in_ch_layout = { 0 };
> +#if FF_API_OLD_CHANNEL_LAYOUT
> +FF_DISABLE_DEPRECATION_WARNINGS
> +        // if the old/new fields are set inconsistently, prefer the old ones
> +        if ((in->channel_layout && (in->ch_layout.order != AV_CHANNEL_ORDER_NATIVE ||
> +                                    in->ch_layout.u.mask != in->channel_layout))) {
> +            av_channel_layout_from_mask(&in_ch_layout, in->channel_layout);
> +FF_ENABLE_DEPRECATION_WARNINGS
> +        } else
> +#endif
> +        if ((ret = av_channel_layout_copy(&in_ch_layout, &in->ch_layout)) < 0)
> +            return ret;
> +        if (av_channel_layout_compare(&s->in_ch_layout, &in_ch_layout) ||
>              s->in_sample_rate != in->sample_rate ||
>              s->in_sample_fmt  != in->format) {
>              ret |= AVERROR_INPUT_CHANGED;
> @@ -66,7 +102,19 @@ static int config_changed(SwrContext *s,
>      }
>  
>      if (out) {
> -        if (s->out_ch_layout   != out->channel_layout ||
> +        AVChannelLayout out_ch_layout = { 0 };
> +#if FF_API_OLD_CHANNEL_LAYOUT
> +FF_DISABLE_DEPRECATION_WARNINGS
> +        // if the old/new fields are set inconsistently, prefer the old ones
> +        if ((out->channel_layout && (out->ch_layout.order != AV_CHANNEL_ORDER_NATIVE ||
> +                                     out->ch_layout.u.mask != out->channel_layout))) {
> +            av_channel_layout_from_mask(&out_ch_layout, out->channel_layout);
> +FF_ENABLE_DEPRECATION_WARNINGS
> +        } else
> +#endif
> +        if ((ret = av_channel_layout_copy(&out_ch_layout, &out->ch_layout)) < 0)
> +            return ret;
> +        if (av_channel_layout_compare(&s->out_ch_layout, &out_ch_layout) ||
>              s->out_sample_rate != out->sample_rate ||
>              s->out_sample_fmt  != out->format) {
>              ret |= AVERROR_OUTPUT_CHANGED;
> @@ -116,7 +164,14 @@ static inline int available_samples(AVFrame *out)
>      if (av_sample_fmt_is_planar(out->format)) {
>          return samples;
>      } else {
> -        int channels = av_get_channel_layout_nb_channels(out->channel_layout);
> +        int channels;
> +#if FF_API_OLD_CHANNEL_LAYOUT
> +FF_DISABLE_DEPRECATION_WARNINGS
> +        channels = av_get_channel_layout_nb_channels(out->channel_layout);
> +FF_ENABLE_DEPRECATION_WARNINGS
> +        if (!channels)
> +#endif
> +        channels = out->ch_layout.nb_channels;
>          return samples / channels;
>      }
>  }
> diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h
> index f2ea5a226d..262a0e2b8c 100644
> --- a/libswresample/swresample_internal.h
> +++ b/libswresample/swresample_internal.h
> @@ -99,8 +99,8 @@ struct SwrContext {
>      enum AVSampleFormat  in_sample_fmt;             ///< input sample format
>      enum AVSampleFormat int_sample_fmt;             ///< internal sample format (AV_SAMPLE_FMT_FLTP or AV_SAMPLE_FMT_S16P)
>      enum AVSampleFormat out_sample_fmt;             ///< output sample format
> -    int64_t  in_ch_layout;                          ///< input channel layout
> -    int64_t out_ch_layout;                          ///< output channel layout
> +    AVChannelLayout  in_ch_layout;                  ///< input channel layout
> +    AVChannelLayout out_ch_layout;                  ///< output channel layout
>      int      in_sample_rate;                        ///< input sample rate
>      int     out_sample_rate;                        ///< output sample rate
>      int flags;                                      ///< miscellaneous flags such as SWR_FLAG_RESAMPLE
> @@ -114,11 +114,15 @@ struct SwrContext {
>      int used_ch_count;                              ///< number of used input channels (mapped channel count if channel_map, otherwise in.ch_count)
>      int engine;
>  
> +    int user_used_ch_count;                         ///< User set used channel count
> +#if FF_API_OLD_CHANNEL_LAYOUT
>      int user_in_ch_count;                           ///< User set input channel count
>      int user_out_ch_count;                          ///< User set output channel count
> -    int user_used_ch_count;                         ///< User set used channel count
>      int64_t user_in_ch_layout;                      ///< User set input channel layout
>      int64_t user_out_ch_layout;                     ///< User set output channel layout
> +#endif
> +    AVChannelLayout user_in_chlayout;               ///< User set input channel layout
> +    AVChannelLayout user_out_chlayout;              ///< User set output channel layout
>      enum AVSampleFormat user_int_sample_fmt;        ///< User set internal sample format
>      int user_dither_method;                         ///< User set dither method
>  
>
James Almer Jan. 19, 2022, 5:29 p.m. UTC | #2
On 1/19/2022 2:20 PM, Andreas Rheinhardt wrote:
> James Almer:
>> Signed-off-by: James Almer <jamrial@gmail.com>
>> ---
>>   libswresample/options.c             |  33 +++-
>>   libswresample/rematrix.c            | 237 ++++++++++++++++++----------
>>   libswresample/rematrix_template.c   |   7 +-
>>   libswresample/swresample.c          | 152 +++++++++++++++---
>>   libswresample/swresample.h          |  63 ++++++++
> 
> This header still contains many references to swr_alloc_set_opts().

Will change.

> 
>>   libswresample/swresample_frame.c    |  65 +++++++-
>>   libswresample/swresample_internal.h |  10 +-
>>   7 files changed, 445 insertions(+), 122 deletions(-)
>>
>> diff --git a/libswresample/options.c b/libswresample/options.c
>> index 6911709157..ffa27c590d 100644
>> --- a/libswresample/options.c
>> +++ b/libswresample/options.c
>> @@ -34,12 +34,19 @@
>>   
>>   #define OFFSET(x) offsetof(SwrContext,x)
>>   #define PARAM AV_OPT_FLAG_AUDIO_PARAM
>> +#define DEPREC AV_OPT_FLAG_DEPRECATED
>>   
>>   static const AVOption options[]={
>> -{"ich"                  , "set input channel count"     , OFFSET(user_in_ch_count  ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
>> -{"in_channel_count"     , "set input channel count"     , OFFSET(user_in_ch_count  ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
>> -{"och"                  , "set output channel count"    , OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
>> -{"out_channel_count"    , "set output channel count"    , OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>> +{"ich"                  , "set input channel count (Deprecated, use ichl)",
>> +                                                          OFFSET(user_in_ch_count  ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM|DEPREC},
>> +{"in_channel_count"     , "set input channel count (Deprecated, use in_chlayout)",
>> +                                                          OFFSET(user_in_ch_count  ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM|DEPREC},
>> +{"och"                  , "set output channel count (Deprecated, use ochl)",
>> +                                                          OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM|DEPREC},
>> +{"out_channel_count"    , "set output channel count (Deprecated, use out_chlayout)",
>> +                                                          OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM|DEPREC},
>> +#endif
>>   {"uch"                  , "set used channel count"      , OFFSET(user_used_ch_count), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
>>   {"used_channel_count"   , "set used channel count"      , OFFSET(user_used_ch_count), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
>>   {"isr"                  , "set input sample rate"       , OFFSET( in_sample_rate), AV_OPT_TYPE_INT  , {.i64=0                     }, 0      , INT_MAX   , PARAM},
>> @@ -52,10 +59,20 @@ static const AVOption options[]={
>>   {"out_sample_fmt"       , "set output sample format"    , OFFSET(out_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1   , INT_MAX, PARAM},
>>   {"tsf"                  , "set internal sample format"  , OFFSET(user_int_sample_fmt), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1   , INT_MAX, PARAM},
>>   {"internal_sample_fmt"  , "set internal sample format"  , OFFSET(user_int_sample_fmt), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1   , INT_MAX, PARAM},
>> -{"icl"                  , "set input channel layout"    , OFFSET(user_in_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0           }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"},
>> -{"in_channel_layout"    , "set input channel layout"    , OFFSET(user_in_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0           }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"},
>> -{"ocl"                  , "set output channel layout"   , OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0           }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"},
>> -{"out_channel_layout"   , "set output channel layout"   , OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0           }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"},
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>> +{"icl"                  , "set input channel layout (Deprecated, use ichl)",
>> +                                                          OFFSET(user_in_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0          }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"},
>> +{"in_channel_layout"    , "set input channel layout (Deprecated, use in_chlayout)",
>> +                                                          OFFSET(user_in_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0          }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"},
>> +{"ocl"                  , "set output channel layout (Deprecated, use ochl)",
>> +                                                          OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0         }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"},
>> +{"out_channel_layout"   , "set output channel layout (Deprecated, use out_chlayout)",
>> +                                                          OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0         }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"},
>> +#endif
>> +{"ichl"                 , "set input channel layout"    , OFFSET(user_in_chlayout ), AV_OPT_TYPE_CHLAYOUT, {.str=NULL             }, 0, 0 , PARAM, "chlayout"},
>> +{"in_chlayout"          , "set input channel layout"    , OFFSET(user_in_chlayout ), AV_OPT_TYPE_CHLAYOUT, {.str=NULL             }, 0, 0 , PARAM, "chlayout"},
>> +{"ochl"                 , "set output channel layout"   , OFFSET(user_out_chlayout), AV_OPT_TYPE_CHLAYOUT, {.str=NULL             }, 0, 0 , PARAM, "chlayout"},
>> +{"out_chlayout"         , "set output channel layout"   , OFFSET(user_out_chlayout), AV_OPT_TYPE_CHLAYOUT, {.str=NULL             }, 0, 0 , PARAM, "chlayout"},
>>   {"clev"                 , "set center mix level"        , OFFSET(clev           ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB                }, -32    , 32        , PARAM},
>>   {"center_mix_level"     , "set center mix level"        , OFFSET(clev           ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB                }, -32    , 32        , PARAM},
>>   {"slev"                 , "set surround mix level"      , OFFSET(slev           ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB                }, -32    , 32        , PARAM},
>> diff --git a/libswresample/rematrix.c b/libswresample/rematrix.c
>> index 94b3de88f6..35086c218d 100644
>> --- a/libswresample/rematrix.c
>> +++ b/libswresample/rematrix.c
>> @@ -64,15 +64,37 @@
>>   int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride)
>>   {
>>       int nb_in, nb_out, in, out;
>> +    int user_in_chlayout_nb_channels, user_out_chlayout_nb_channels;
>>   
>>       if (!s || s->in_convert) // s needs to be allocated but not initialized
>>           return AVERROR(EINVAL);
>>       memset(s->matrix, 0, sizeof(s->matrix));
>>       memset(s->matrix_flt, 0, sizeof(s->matrix_flt));
>> -    nb_in = (s->user_in_ch_count > 0) ? s->user_in_ch_count :
>> -        av_get_channel_layout_nb_channels(s->user_in_ch_layout);
>> -    nb_out = (s->user_out_ch_count > 0) ? s->user_out_ch_count :
>> -        av_get_channel_layout_nb_channels(s->user_out_ch_layout);
>> +
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>> +FF_DISABLE_DEPRECATION_WARNINGS
>> +    user_in_chlayout_nb_channels = av_get_channel_layout_nb_channels(s->user_in_ch_layout);
>> +FF_ENABLE_DEPRECATION_WARNINGS
>> +    if (!user_in_chlayout_nb_channels)
>> +#endif
>> +    user_in_chlayout_nb_channels = s->user_in_chlayout.nb_channels;
>> +    nb_in =
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>> +            (s->user_in_ch_count > 0) ? s->user_in_ch_count :
>> +#endif
>> +            user_in_chlayout_nb_channels;
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>> +FF_DISABLE_DEPRECATION_WARNINGS
>> +    user_out_chlayout_nb_channels = av_get_channel_layout_nb_channels(s->user_out_ch_layout);
>> +FF_ENABLE_DEPRECATION_WARNINGS
>> +    if (!user_out_chlayout_nb_channels)
>> +#endif
>> +    user_out_chlayout_nb_channels = s->user_out_chlayout.nb_channels;
>> +    nb_out =
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>> +             (s->user_out_ch_count > 0) ? s->user_out_ch_count :
>> +#endif
>> +             user_out_chlayout_nb_channels;
>>       for (out = 0; out < nb_out; out++) {
>>           for (in = 0; in < nb_in; in++)
>>               s->matrix_flt[out][in] = s->matrix[out][in] = matrix[in];
>> @@ -88,95 +110,141 @@ static int even(int64_t layout){
>>       return 0;
>>   }
>>   
>> -static int64_t clean_layout(void *s, int64_t layout){
>> -    if(layout && layout != AV_CH_FRONT_CENTER && !(layout&(layout-1))) {
>> +static int clean_layout(AVChannelLayout *out, const AVChannelLayout *in, void *s)
>> +{
>> +    int ret = 0;
>> +
>> +    if(av_channel_layout_index_from_channel(in, AV_CH_FRONT_CENTER) < 0 && in->nb_channels == 1) {
>>           char buf[128];
>> -        av_get_channel_layout_string(buf, sizeof(buf), -1, layout);
>> +        av_channel_layout_describe(in, buf, sizeof(buf));
>>           av_log(s, AV_LOG_VERBOSE, "Treating %s as mono\n", buf);
>> -        return AV_CH_FRONT_CENTER;
>> -    }
>> +        *out = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
>> +    } else
>> +        ret = av_channel_layout_copy(out, in);
>>   
>> -    return layout;
>> +    return ret;
>>   }
>>   
>> -static int sane_layout(int64_t layout){
>> -    if(!(layout & AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker
>> +static int sane_layout(AVChannelLayout *ch_layout) {
>> +    if (ch_layout->order != AV_CHANNEL_ORDER_NATIVE)
>> +        return 0;
>> +    if(!av_channel_layout_subset(ch_layout, AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker
>>           return 0;
>> -    if(!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT))) // no asymetric front
>> +    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)))) // no asymetric front
>>           return 0;
>> -    if(!even(layout & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)))   // no asymetric side
>> +    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT))))   // no asymetric side
>>           return 0;
>> -    if(!even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)))
>> +    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT))))
>>           return 0;
>> -    if(!even(layout & (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)))
>> +    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER))))
>>           return 0;
>> -    if(av_get_channel_layout_nb_channels(layout) >= SWR_CH_MAX)
>> +    if(ch_layout->nb_channels >= SWR_CH_MAX)
>>           return 0;
>>   
>>       return 1;
>>   }
>>   
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>>   av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout_param,
>>                                double center_mix_level, double surround_mix_level,
>>                                double lfe_mix_level, double maxval,
>>                                double rematrix_volume, double *matrix_param,
>>                                int stride, enum AVMatrixEncoding matrix_encoding, void *log_context)
>>   {
>> -    int i, j, out_i;
>> +    AVChannelLayout in_ch_layout = { 0 }, out_ch_layout = { 0 };
>> +    int ret;
>> +
>> +    ret  = av_channel_layout_from_mask(&in_ch_layout, in_ch_layout_param);
>> +    ret |= av_channel_layout_from_mask(&out_ch_layout, out_ch_layout_param);
>> +    if (ret < 0)
>> +        return ret;
>> +
>> +    return swr_build_matrix2(&in_ch_layout, &out_ch_layout, center_mix_level, surround_mix_level,
>> +                             lfe_mix_level, maxval, rematrix_volume, matrix_param,
>> +                             stride, matrix_encoding, log_context);
>> +}
>> +#endif
>> +
>> +av_cold int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout,
>> +                              double center_mix_level, double surround_mix_level,
>> +                              double lfe_mix_level, double maxval,
>> +                              double rematrix_volume, double *matrix_param,
>> +                              ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding, void *log_context)
>> +{
>> +    int i, j, out_i, ret;
>> +    AVChannelLayout in_ch_layout = { 0 }, out_ch_layout = { 0 };
>>       double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS]={{0}};
>> -    int64_t unaccounted, in_ch_layout, out_ch_layout;
>> +    int64_t unaccounted;
>>       double maxcoef=0;
>>       char buf[128];
>>   
>> -     in_ch_layout = clean_layout(log_context,  in_ch_layout_param);
>> -    out_ch_layout = clean_layout(log_context, out_ch_layout_param);
>> -
>> -    if(   out_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX
>> -       && (in_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0
>> -    )
>> -        out_ch_layout = AV_CH_LAYOUT_STEREO;
>> +    ret  = clean_layout(&in_ch_layout, in_layout, log_context);
>> +    ret |= clean_layout(&out_ch_layout, out_layout, log_context);
>> +    if (ret < 0)
>> +        goto fail;
>>   
>> -    if(    in_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX
>> -       && (out_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0
>> -    )
>> -        in_ch_layout = AV_CH_LAYOUT_STEREO;
>> -
>> -    if (in_ch_layout == AV_CH_LAYOUT_22POINT2 &&
>> -        out_ch_layout != AV_CH_LAYOUT_22POINT2) {
>> -        in_ch_layout = (AV_CH_LAYOUT_7POINT1_WIDE_BACK|AV_CH_BACK_CENTER);
>> -        av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout);
>> +    if(   !av_channel_layout_compare(&out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO_DOWNMIX)
>> +       && !av_channel_layout_subset(&in_ch_layout, AV_CH_LAYOUT_STEREO_DOWNMIX)
>> +    ) {
>> +        av_channel_layout_uninit(&out_ch_layout);
>> +        out_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
>> +    }
>> +    if(   !av_channel_layout_compare(&in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO_DOWNMIX)
>> +       && !av_channel_layout_subset(&out_ch_layout, AV_CH_LAYOUT_STEREO_DOWNMIX)
>> +    ) {
>> +        av_channel_layout_uninit(&in_ch_layout);
>> +        in_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
>> +    }
>> +    if (!av_channel_layout_compare(&in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_22POINT2) &&
>> +        av_channel_layout_compare(&out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_22POINT2)) {
>> +        av_channel_layout_from_mask(&in_ch_layout, (AV_CH_LAYOUT_7POINT1_WIDE_BACK|AV_CH_BACK_CENTER));
>> +        av_channel_layout_describe(&in_ch_layout, buf, sizeof(buf));
>>           av_log(log_context, AV_LOG_WARNING,
>>                  "Full-on remixing from 22.2 has not yet been implemented! "
>>                  "Processing the input as '%s'\n",
>>                  buf);
>>       }
>>   
>> -    if(!sane_layout(in_ch_layout)){
>> -        av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout_param);
>> +    if(!av_channel_layout_check(&in_ch_layout)) {
>> +        av_log(log_context, AV_LOG_ERROR, "Input channel layout is invalid\n");
>> +        ret = AVERROR(EINVAL);
>> +        goto fail;
>> +    }
>> +    if(!sane_layout(&in_ch_layout)) {
>> +        av_channel_layout_describe(&in_ch_layout, buf, sizeof(buf));
>>           av_log(log_context, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf);
>> -        return AVERROR(EINVAL);
>> +        ret = AVERROR(EINVAL);
>> +        goto fail;
>>       }
>>   
>> -    if(!sane_layout(out_ch_layout)){
>> -        av_get_channel_layout_string(buf, sizeof(buf), -1, out_ch_layout_param);
>> +    if(!av_channel_layout_check(&out_ch_layout)) {
>> +        av_log(log_context, AV_LOG_ERROR, "Output channel layout is invalid\n");
>> +        ret = AVERROR(EINVAL);
>> +        goto fail;
>> +    }
>> +    if(!sane_layout(&out_ch_layout)) {
>> +        av_channel_layout_describe(&out_ch_layout, buf, sizeof(buf));
>>           av_log(log_context, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf);
>> -        return AVERROR(EINVAL);
>> +        ret = AVERROR(EINVAL);
>> +        goto fail;
>>       }
>>   
>>       for(i=0; i<FF_ARRAY_ELEMS(matrix); i++){
>> -        if(in_ch_layout & out_ch_layout & (1ULL<<i))
>> +        int idx;
>> +        if(   (idx = av_channel_layout_index_from_channel(&in_ch_layout, i)) >= 0
>> +           && av_channel_layout_index_from_channel(&out_ch_layout, i) == idx)
>>               matrix[i][i]= 1.0;
>>       }
>>   
>> -    unaccounted= in_ch_layout & ~out_ch_layout;
>> +    unaccounted =  in_ch_layout.u.mask & ~out_ch_layout.u.mask;
> 
> Weird whitespace.
> 
>>   
>>   //FIXME implement dolby surround
>>   //FIXME implement full ac3
>>   
>>   
>>       if(unaccounted & AV_CH_FRONT_CENTER){
>> -        if((out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){
>> -            if(in_ch_layout & AV_CH_LAYOUT_STEREO) {
>> +        if(av_channel_layout_subset(&out_ch_layout, AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){
>> +            if(av_channel_layout_subset(&in_ch_layout, AV_CH_LAYOUT_STEREO)) {
> 
> Missing whitespace. Applies to the whole patch.

More like the entire file. But ok, will fix the whitespace on the lines 
i change.

> 
>>                   matrix[ FRONT_LEFT][FRONT_CENTER]+= center_mix_level;
>>                   matrix[FRONT_RIGHT][FRONT_CENTER]+= center_mix_level;
>>               } else {
>> @@ -187,23 +255,23 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>>               av_assert0(0);
>>       }
>>       if(unaccounted & AV_CH_LAYOUT_STEREO){
>> -        if(out_ch_layout & AV_CH_FRONT_CENTER){
>> +        if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){
>>               matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2;
>>               matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2;
>> -            if(in_ch_layout & AV_CH_FRONT_CENTER)
>> +            if(av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_FRONT_CENTER) >= 0)
>>                   matrix[FRONT_CENTER][ FRONT_CENTER] = center_mix_level*sqrt(2);
>>           }else
>>               av_assert0(0);
>>       }
>>   
>>       if(unaccounted & AV_CH_BACK_CENTER){
>> -        if(out_ch_layout & AV_CH_BACK_LEFT){
>> +        if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_LEFT) >= 0){
>>               matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2;
>>               matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2;
>> -        }else if(out_ch_layout & AV_CH_SIDE_LEFT){
>> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_SIDE_LEFT) >= 0){
>>               matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2;
>>               matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2;
>> -        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
>> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0){
>>               if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
>>                   matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
>>                   if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
>> @@ -217,24 +285,24 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>>                   matrix[ FRONT_LEFT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
>>                   matrix[FRONT_RIGHT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
>>               }
>> -        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
>> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){
>>               matrix[ FRONT_CENTER][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
>>           }else
>>               av_assert0(0);
>>       }
>>       if(unaccounted & AV_CH_BACK_LEFT){
>> -        if(out_ch_layout & AV_CH_BACK_CENTER){
>> +        if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_CENTER) >= 0){
>>               matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2;
>>               matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2;
>> -        }else if(out_ch_layout & AV_CH_SIDE_LEFT){
>> -            if(in_ch_layout & AV_CH_SIDE_LEFT){
>> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_SIDE_LEFT) >= 0){
>> +            if(av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_SIDE_LEFT) >= 0){
>>                   matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2;
>>                   matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2;
>>               }else{
>>               matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0;
>>               matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0;
>>               }
>> -        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
>> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0){
>>               if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
>>                   matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2;
>>                   matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
>> @@ -249,7 +317,7 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>>                   matrix[ FRONT_LEFT][ BACK_LEFT] += surround_mix_level;
>>                   matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
>>               }
>> -        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
>> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){
>>               matrix[ FRONT_CENTER][BACK_LEFT ]+= surround_mix_level*M_SQRT1_2;
>>               matrix[ FRONT_CENTER][BACK_RIGHT]+= surround_mix_level*M_SQRT1_2;
>>           }else
>> @@ -257,20 +325,20 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>>       }
>>   
>>       if(unaccounted & AV_CH_SIDE_LEFT){
>> -        if(out_ch_layout & AV_CH_BACK_LEFT){
>> +        if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_LEFT) >= 0){
>>               /* if back channels do not exist in the input, just copy side
>>                  channels to back channels, otherwise mix side into back */
>> -            if (in_ch_layout & AV_CH_BACK_LEFT) {
>> +            if (av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_BACK_LEFT) >= 0) {
>>                   matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
>>                   matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
>>               } else {
>>                   matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
>>                   matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
>>               }
>> -        }else if(out_ch_layout & AV_CH_BACK_CENTER){
>> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_CENTER) >= 0){
>>               matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2;
>>               matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2;
>> -        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
>> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0){
>>               if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
>>                   matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2;
>>                   matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
>> @@ -285,7 +353,7 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>>                   matrix[ FRONT_LEFT][ SIDE_LEFT] += surround_mix_level;
>>                   matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
>>               }
>> -        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
>> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){
>>               matrix[ FRONT_CENTER][SIDE_LEFT ]+= surround_mix_level * M_SQRT1_2;
>>               matrix[ FRONT_CENTER][SIDE_RIGHT]+= surround_mix_level * M_SQRT1_2;
>>           }else
>> @@ -293,10 +361,10 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>>       }
>>   
>>       if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){
>> -        if(out_ch_layout & AV_CH_FRONT_LEFT){
>> +        if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0){
>>               matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0;
>>               matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0;
>> -        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
>> +        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){
>>               matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2;
>>               matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2;
>>           }else
>> @@ -304,9 +372,9 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>>       }
>>       /* mix LFE into front left/right or center */
>>       if (unaccounted & AV_CH_LOW_FREQUENCY) {
>> -        if (out_ch_layout & AV_CH_FRONT_CENTER) {
>> +        if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) {
>>               matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level;
>> -        } else if (out_ch_layout & AV_CH_FRONT_LEFT) {
>> +        } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) {
>>               matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
>>               matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
>>           } else
>> @@ -316,15 +384,19 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>>       for(out_i=i=0; i<64; i++){
>>           double sum=0;
>>           int in_i=0;
>> -        if((out_ch_layout & (1ULL<<i)) == 0)
>> +        if(av_channel_layout_index_from_channel(&out_ch_layout, i) < 0)
>>               continue;
>>           for(j=0; j<64; j++){
>> -            if((in_ch_layout & (1ULL<<j)) == 0)
>> +            if(av_channel_layout_index_from_channel(&in_ch_layout, j) < 0)
>>                  continue;
>>               if (i < FF_ARRAY_ELEMS(matrix) && j < FF_ARRAY_ELEMS(matrix[0]))
>>                   matrix_param[stride*out_i + in_i] = matrix[i][j];
>> -            else
>> -                matrix_param[stride*out_i + in_i] = i == j && (in_ch_layout & out_ch_layout & (1ULL<<i));
>> +            else {
>> +                int idx;
>> +                matrix_param[stride*out_i + in_i] = i == j &&
>> +                (   (idx = av_channel_layout_index_from_channel(&in_ch_layout, i)) >= 0
>> +                 && av_channel_layout_index_from_channel(&out_ch_layout, i) == idx);
>> +            }
>>               sum += fabs(matrix_param[stride*out_i + in_i]);
>>               in_i++;
>>           }
>> @@ -350,17 +422,22 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
>>       }
>>   
>>       av_log(log_context, AV_LOG_DEBUG, "Matrix coefficients:\n");
>> -    for(i=0; i<av_get_channel_layout_nb_channels(out_ch_layout); i++){
>> -        const char *c =
>> -            av_get_channel_name(av_channel_layout_extract_channel(out_ch_layout, i));
>> -        av_log(log_context, AV_LOG_DEBUG, "%s: ", c ? c : "?");
>> -        for(j=0; j<av_get_channel_layout_nb_channels(in_ch_layout); j++){
>> -            c = av_get_channel_name(av_channel_layout_extract_channel(in_ch_layout, j));
>> -            av_log(log_context, AV_LOG_DEBUG, "%s:%f ", c ? c : "?", matrix_param[stride*i + j]);
>> +    for(i = 0; i < out_ch_layout.nb_channels; i++){
>> +        av_channel_name(buf, sizeof(buf), av_channel_layout_channel_from_index(&out_ch_layout, i));
>> +        av_log(log_context, AV_LOG_DEBUG, "%s: ", buf);
>> +        for(j = 0; j < in_ch_layout.nb_channels; j++){
>> +            av_channel_name(buf, sizeof(buf), av_channel_layout_channel_from_index(&in_ch_layout, j));
>> +            av_log(log_context, AV_LOG_DEBUG, "%s:%f ", buf, matrix_param[stride*i + j]);
>>           }
>>           av_log(log_context, AV_LOG_DEBUG, "\n");
>>       }
>> -    return 0;
>> +
>> +    ret = 0;
>> +fail:
>> +    av_channel_layout_uninit(&in_ch_layout);
>> +    av_channel_layout_uninit(&out_ch_layout);
>> +
>> +    return ret;
>>   }
>>   
>>   av_cold static int auto_matrix(SwrContext *s)
>> @@ -377,7 +454,7 @@ av_cold static int auto_matrix(SwrContext *s)
>>           maxval = INT_MAX;
>>   
>>       memset(s->matrix, 0, sizeof(s->matrix));
>> -    ret = swr_build_matrix(s->in_ch_layout, s->out_ch_layout,
>> +    ret = swr_build_matrix2(&s->in_ch_layout, &s->out_ch_layout,
>>                              s->clev, s->slev, s->lfe_mix_level,
>>                              maxval, s->rematrix_volume, (double*)s->matrix,
>>                              s->matrix[1] - s->matrix[0], s->matrix_encoding, s);
>> @@ -519,8 +596,8 @@ int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mus
>>           off = len1 * out->bps;
>>       }
>>   
>> -    av_assert0(!s->out_ch_layout || out->ch_count == av_get_channel_layout_nb_channels(s->out_ch_layout));
>> -    av_assert0(!s-> in_ch_layout || in ->ch_count == av_get_channel_layout_nb_channels(s-> in_ch_layout));
>> +    av_assert0(s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC || out->ch_count == s->out_ch_layout.nb_channels);
>> +    av_assert0(s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC || in ->ch_count == s->in_ch_layout.nb_channels);
>>   
>>       for(out_i=0; out_i<out->ch_count; out_i++){
>>           switch(s->matrix_ch[out_i][0]){
>> diff --git a/libswresample/rematrix_template.c b/libswresample/rematrix_template.c
>> index add65e3155..f5a508361c 100644
>> --- a/libswresample/rematrix_template.c
>> +++ b/libswresample/rematrix_template.c
>> @@ -88,13 +88,16 @@ static void RENAME(mix8to2)(SAMPLE **out, const SAMPLE **in, COEFF *coeffp, inte
>>   }
>>   
>>   static RENAME(mix_any_func_type) *RENAME(get_mix_any_func)(SwrContext *s){
>> -    if(   s->out_ch_layout == AV_CH_LAYOUT_STEREO && (s->in_ch_layout == AV_CH_LAYOUT_5POINT1 || s->in_ch_layout == AV_CH_LAYOUT_5POINT1_BACK)
>> +    if(   !av_channel_layout_compare(&s->out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)
>> +       && (   !av_channel_layout_compare(&s->in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1)
>> +           || !av_channel_layout_compare(&s->in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK))
>>          && s->matrix[0][2] == s->matrix[1][2] && s->matrix[0][3] == s->matrix[1][3]
>>          && !s->matrix[0][1] && !s->matrix[0][5] && !s->matrix[1][0] && !s->matrix[1][4]
>>       )
>>           return RENAME(mix6to2);
>>   
>> -    if(   s->out_ch_layout == AV_CH_LAYOUT_STEREO && s->in_ch_layout == AV_CH_LAYOUT_7POINT1
>> +    if(   !av_channel_layout_compare(&s->out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)
>> +       && !av_channel_layout_compare(&s->in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1)
>>          && s->matrix[0][2] == s->matrix[1][2] && s->matrix[0][3] == s->matrix[1][3]
>>          && !s->matrix[0][1] && !s->matrix[0][5] && !s->matrix[1][0] && !s->matrix[1][4]
>>          && !s->matrix[0][7] && !s->matrix[1][6]
>> diff --git a/libswresample/swresample.c b/libswresample/swresample.c
>> index 16734c9df9..f8fbd9134b 100644
>> --- a/libswresample/swresample.c
>> +++ b/libswresample/swresample.c
>> @@ -56,6 +56,8 @@ int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map){
>>       return 0;
>>   }
>>   
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>> +FF_DISABLE_DEPRECATION_WARNINGS
>>   struct SwrContext *swr_alloc_set_opts(struct SwrContext *s,
>>                                         int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
>>                                         int64_t  in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
>> @@ -97,6 +99,58 @@ fail:
>>       swr_free(&s);
>>       return NULL;
>>   }
>> +FF_ENABLE_DEPRECATION_WARNINGS
>> +#endif
>> +
>> +int swr_alloc_set_opts2(struct SwrContext **ps,
>> +                        AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
>> +                        AVChannelLayout *in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
>> +                        int log_offset, void *log_ctx) {
>> +    struct SwrContext *s = *ps;
>> +    int ret;
>> +
>> +    if (!s) s = swr_alloc();
>> +    if (!s) return AVERROR(ENOMEM);
>> +
>> +    s->log_level_offset= log_offset;
>> +    s->log_ctx= log_ctx;
> 
> This has been copied from swr_alloc_set_opts without fixing whitespace
> issues.
> 
>> +
>> +    if ((ret = av_opt_set_chlayout(s, "ochl", out_ch_layout, 0)) < 0)
>> +        goto fail;
>> +
>> +    if ((ret = av_opt_set_int(s, "osf", out_sample_fmt, 0)) < 0)
>> +        goto fail;
>> +
>> +    if ((ret = av_opt_set_int(s, "osr", out_sample_rate, 0)) < 0)
>> +        goto fail;
>> +
>> +    if ((ret = av_opt_set_chlayout(s, "ichl", in_ch_layout, 0)) < 0)
>> +        goto fail;
>> +
>> +    if ((ret = av_opt_set_int(s, "isf", in_sample_fmt, 0)) < 0)
>> +        goto fail;
>> +
>> +    if ((ret = av_opt_set_int(s, "isr", in_sample_rate, 0)) < 0)
>> +        goto fail;
>> +
>> +    av_opt_set_int(s, "uch", 0, 0);
>> +
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>> +    // Clear old API values so they don't take precedence in swr_init()
>> +    av_opt_set_int(s, "icl", 0, 0);
>> +    av_opt_set_int(s, "ocl", 0, 0);
>> +    av_opt_set_int(s, "ich", 0, 0);
>> +    av_opt_set_int(s, "och", 0, 0);
>> +#endif
>> +
>> +    *ps = s;
>> +
>> +    return 0;
>> +fail:
>> +    av_log(s, AV_LOG_ERROR, "Failed to set option\n");
>> +    swr_free(ps);
> 
> In case s has been allocated by this function, it leaks. *ps = s needs
> to be moved directly after allocation.

Nice catch. Will fix.

> 
> And why don't you implement the old API in terms of the new API?

I'm not sure I understand what you mean.

> 
>> +    return ret;
>> +}
>>   
>>   static void set_audiodata_fmt(AudioData *a, enum AVSampleFormat fmt){
>>       a->fmt   = fmt;
>> @@ -125,6 +179,8 @@ static void clear_context(SwrContext *s){
>>       free_temp(&s->drop_temp);
>>       free_temp(&s->dither.noise);
>>       free_temp(&s->dither.temp);
>> +    av_channel_layout_uninit(&s->in_ch_layout);
>> +    av_channel_layout_uninit(&s->out_ch_layout);
>>       swri_audio_convert_free(&s-> in_convert);
>>       swri_audio_convert_free(&s->out_convert);
>>       swri_audio_convert_free(&s->full_convert);
>> @@ -138,6 +194,9 @@ av_cold void swr_free(SwrContext **ss){
>>       SwrContext *s= *ss;
>>       if(s){
>>           clear_context(s);
>> +        av_channel_layout_uninit(&s->user_in_chlayout);
>> +        av_channel_layout_uninit(&s->user_out_chlayout);
>> +
>>           if (s->resampler)
>>               s->resampler->free(&s->resample);
>>       }
>> @@ -172,25 +231,66 @@ av_cold int swr_init(struct SwrContext *s){
>>           av_log(s, AV_LOG_ERROR, "Requested output sample rate %d is invalid\n", s->out_sample_rate);
>>           return AVERROR(EINVAL);
>>       }
>> +    s->used_ch_count = s->user_used_ch_count;
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>>       s->out.ch_count  = s-> user_out_ch_count;
>>       s-> in.ch_count  = s->  user_in_ch_count;
>> -    s->used_ch_count = s->user_used_ch_count;
>>   
>> -    s-> in_ch_layout = s-> user_in_ch_layout;
>> -    s->out_ch_layout = s->user_out_ch_layout;
>> +    // if the old/new fields are set inconsistently, prefer the old ones
>> +    if ((s->user_in_ch_count && s->user_in_ch_count != s->user_in_chlayout.nb_channels) ||
>> +        (s->user_in_ch_layout && (s->user_in_chlayout.order != AV_CHANNEL_ORDER_NATIVE ||
>> +                                  s->user_in_chlayout.u.mask != s->user_in_ch_layout))) {
>> +        av_channel_layout_uninit(&s->in_ch_layout);
>> +        if (s->user_in_ch_layout)
>> +            av_channel_layout_from_mask(&s->in_ch_layout, s->user_in_ch_layout);
>> +        else {
>> +            s->in_ch_layout.order       = AV_CHANNEL_ORDER_UNSPEC;
>> +            s->in_ch_layout.nb_channels = s->user_in_ch_count;
>> +        }
>> +    } else
>> +        av_channel_layout_copy(&s->in_ch_layout, &s->user_in_chlayout);
>> +
>> +    if ((s->user_out_ch_count && s->user_out_ch_count != s->user_out_chlayout.nb_channels) ||
>> +        (s->user_out_ch_layout && (s->user_out_chlayout.order != AV_CHANNEL_ORDER_NATIVE ||
>> +                                   s->user_out_chlayout.u.mask != s->user_out_ch_layout))) {
>> +        av_channel_layout_uninit(&s->out_ch_layout);
>> +        if (s->user_out_ch_layout)
>> +            av_channel_layout_from_mask(&s->out_ch_layout, s->user_out_ch_layout);
>> +        else {
>> +            s->out_ch_layout.order       = AV_CHANNEL_ORDER_UNSPEC;
>> +            s->out_ch_layout.nb_channels = s->user_out_ch_count;
>> +        }
>> +    } else
>> +        av_channel_layout_copy(&s->out_ch_layout, &s->user_out_chlayout);
>> +
>> +    if (!s->out.ch_count && !s->user_out_ch_layout)
>> +        s->out.ch_count  = s->out_ch_layout.nb_channels;
>> +    if (!s-> in.ch_count && !s-> user_in_ch_layout)
>> +        s-> in.ch_count  = s->in_ch_layout.nb_channels;
>> +#else
>> +    s->out.ch_count  = s-> user_out_chlayout.nb_channels;
>> +    s-> in.ch_count  = s->  user_in_chlayout.nb_channels;
>> +
>> +    ret  = av_channel_layout_copy(&s->in_ch_layout, &s->user_in_chlayout);
>> +    ret |= av_channel_layout_copy(&s->out_ch_layout, &s->user_out_chlayout);
>> +    if (ret < 0)
>> +        return ret;
>> +#endif
>>   
>>       s->int_sample_fmt= s->user_int_sample_fmt;
>>   
>>       s->dither.method = s->user_dither_method;
>>   
>> -    if(av_get_channel_layout_nb_channels(s-> in_ch_layout) > SWR_CH_MAX) {
>> -        av_log(s, AV_LOG_WARNING, "Input channel layout 0x%"PRIx64" is invalid or unsupported.\n", s-> in_ch_layout);
>> -        s->in_ch_layout = 0;
>> +    if (!av_channel_layout_check(&s->in_ch_layout) || s->in_ch_layout.nb_channels > SWR_CH_MAX) {
>> +        av_channel_layout_describe(&s->in_ch_layout, l1, sizeof(l1));
>> +        av_log(s, AV_LOG_WARNING, "Input channel layout \"%s\" is invalid or unsupported.\n", l1);
>> +        av_channel_layout_uninit(&s->in_ch_layout);
>>       }
>>   
>> -    if(av_get_channel_layout_nb_channels(s->out_ch_layout) > SWR_CH_MAX) {
>> -        av_log(s, AV_LOG_WARNING, "Output channel layout 0x%"PRIx64" is invalid or unsupported.\n", s->out_ch_layout);
>> -        s->out_ch_layout = 0;
>> +    if (!av_channel_layout_check(&s->out_ch_layout) || s->out_ch_layout.nb_channels > SWR_CH_MAX) {
>> +        av_channel_layout_describe(&s->out_ch_layout, l2, sizeof(l2));
>> +        av_log(s, AV_LOG_WARNING, "Output channel layout \"%s\" is invalid or unsupported.\n", l2);
>> +        av_channel_layout_uninit(&s->out_ch_layout);
>>       }
>>   
>>       switch(s->engine){
>> @@ -206,17 +306,18 @@ av_cold int swr_init(struct SwrContext *s){
>>       if(!s->used_ch_count)
>>           s->used_ch_count= s->in.ch_count;
>>   
>> -    if(s->used_ch_count && s-> in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s-> in_ch_layout)){
>> +    if(s->used_ch_count && s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_count != s->in_ch_layout.nb_channels){
>>           av_log(s, AV_LOG_WARNING, "Input channel layout has a different number of channels than the number of used channels, ignoring layout\n");
>> -        s-> in_ch_layout= 0;
>> +        av_channel_layout_uninit(&s->in_ch_layout);
>>       }
>>   
>> -    if(!s-> in_ch_layout)
>> -        s-> in_ch_layout= av_get_default_channel_layout(s->used_ch_count);
>> -    if(!s->out_ch_layout)
>> -        s->out_ch_layout= av_get_default_channel_layout(s->out.ch_count);
>> +    if(!s->in_ch_layout.nb_channels || s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
>> +        av_channel_layout_default(&s->in_ch_layout, s->used_ch_count);
>> +    if(!s->out_ch_layout.nb_channels || s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
>> +        av_channel_layout_default(&s->out_ch_layout, s->out.ch_count);
>>   
>> -    s->rematrix= s->out_ch_layout  !=s->in_ch_layout || s->rematrix_volume!=1.0 ||
>> +    s->rematrix= av_channel_layout_compare(&s->out_ch_layout, &s->in_ch_layout) ||
>> +                 s->rematrix_volume!=1.0 ||
>>                    s->rematrix_custom;
>>   
>>       if(s->int_sample_fmt == AV_SAMPLE_FMT_NONE){
>> @@ -291,33 +392,36 @@ av_cold int swr_init(struct SwrContext *s){
>>   
>>   #define RSC 1 //FIXME finetune
>>       if(!s-> in.ch_count)
>> -        s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout);
>> +        s-> in.ch_count = s->in_ch_layout.nb_channels;
>>       if(!s->used_ch_count)
>>           s->used_ch_count= s->in.ch_count;
>>       if(!s->out.ch_count)
>> -        s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout);
>> +        s->out.ch_count = s->out_ch_layout.nb_channels;
>>   
>>       if(!s-> in.ch_count){
>> -        av_assert0(!s->in_ch_layout);
>> +        av_assert0(s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC);
>>           av_log(s, AV_LOG_ERROR, "Input channel count and layout are unset\n");
>>           ret = AVERROR(EINVAL);
>>           goto fail;
>>       }
>>   
>> -    av_get_channel_layout_string(l1, sizeof(l1), s-> in.ch_count, s-> in_ch_layout);
>> -    av_get_channel_layout_string(l2, sizeof(l2), s->out.ch_count, s->out_ch_layout);
>> -    if (s->out_ch_layout && s->out.ch_count != av_get_channel_layout_nb_channels(s->out_ch_layout)) {
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>> +    av_channel_layout_describe(&s->out_ch_layout, l1, sizeof(l1));
>> +    if (s->out_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->out.ch_count != s->out_ch_layout.nb_channels) {
>>           av_log(s, AV_LOG_ERROR, "Output channel layout %s mismatches specified channel count %d\n", l2, s->out.ch_count);
>>           ret = AVERROR(EINVAL);
>>           goto fail;
>>       }
>> -    if (s->in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s->in_ch_layout)) {
>> +#endif
>> +    av_channel_layout_describe(&s->in_ch_layout, l1, sizeof(l1));
>> +    if (s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_count != s->in_ch_layout.nb_channels) {
>>           av_log(s, AV_LOG_ERROR, "Input channel layout %s mismatches specified channel count %d\n", l1, s->used_ch_count);
>>           ret = AVERROR(EINVAL);
>>           goto fail;
>>       }
>>   
>> -    if ((!s->out_ch_layout || !s->in_ch_layout) && s->used_ch_count != s->out.ch_count && !s->rematrix_custom) {
>> +    if ((   s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC
>> +         || s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) && s->used_ch_count != s->out.ch_count && !s->rematrix_custom) {
>>           av_log(s, AV_LOG_ERROR, "Rematrix is needed between %s and %s "
>>                  "but there is not enough information to do it\n", l1, l2);
>>           ret = AVERROR(EINVAL);
>> diff --git a/libswresample/swresample.h b/libswresample/swresample.h
>> index c7b84fbcac..c6ff2345e9 100644
>> --- a/libswresample/swresample.h
>> +++ b/libswresample/swresample.h
>> @@ -227,6 +227,7 @@ int swr_init(struct SwrContext *s);
>>    */
>>   int swr_is_initialized(struct SwrContext *s);
>>   
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>>   /**
>>    * Allocate SwrContext if needed and set/reset common parameters.
>>    *
>> @@ -246,12 +247,40 @@ int swr_is_initialized(struct SwrContext *s);
>>    *
>>    * @see swr_init(), swr_free()
>>    * @return NULL on error, allocated context otherwise
>> + * @deprecated use @ref swr_alloc_set_opts2()
>>    */
>> +attribute_deprecated
>>   struct SwrContext *swr_alloc_set_opts(struct SwrContext *s,
>>                                         int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
>>                                         int64_t  in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
>>                                         int log_offset, void *log_ctx);
>> +#endif
>>   
>> +/**
>> + * Allocate SwrContext if needed and set/reset common parameters.
>> + *
>> + * This function does not require s to be allocated with swr_alloc(). On the
>> + * other hand, swr_alloc() can use swr_alloc_set_opts() to set the parameters
>> + * on the allocated context.
>> + *
>> + * @param ps              Pointer to an existing Swr context if available, or to NULL if not.
>> + *                        On success, *ps will be set the allocated context.
> 
> This does not sound like proper English to me.

Just a missing "to". Will add.

> Moreover, it does not document that an already allocated context will be
> freed here on error.

Will mention it.

> 
>> + * @param out_ch_layout   output channel layout (AV_CH_LAYOUT_*)
>> + * @param out_sample_fmt  output sample format (AV_SAMPLE_FMT_*).
>> + * @param out_sample_rate output sample rate (frequency in Hz)
>> + * @param in_ch_layout    input channel layout (AV_CH_LAYOUT_*)
>> + * @param in_sample_fmt   input sample format (AV_SAMPLE_FMT_*).
>> + * @param in_sample_rate  input sample rate (frequency in Hz)
>> + * @param log_offset      logging level offset
>> + * @param log_ctx         parent logging context, can be NULL
>> + *
>> + * @see swr_init(), swr_free()
>> + * @return 0 on success, a negative AVERROR code on error.
>> + */
>> +int swr_alloc_set_opts2(struct SwrContext **ps,
>> +                        AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
>> +                        AVChannelLayout *in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
>> +                        int log_offset, void *log_ctx);
>>   /**
>>    * @}
>>    *
>> @@ -362,6 +391,7 @@ int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensatio
>>    */
>>   int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map);
>>   
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>>   /**
>>    * Generate a channel mixing matrix.
>>    *
>> @@ -384,13 +414,46 @@ int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map);
>>    * @param matrix_encoding     matrixed stereo downmix mode (e.g. dplii)
>>    * @param log_ctx             parent logging context, can be NULL
>>    * @return                    0 on success, negative AVERROR code on failure
>> + * @deprecated                use @ref swr_build_matrix2()
>>    */
>> +attribute_deprecated
>>   int swr_build_matrix(uint64_t in_layout, uint64_t out_layout,
>>                        double center_mix_level, double surround_mix_level,
>>                        double lfe_mix_level, double rematrix_maxval,
>>                        double rematrix_volume, double *matrix,
>>                        int stride, enum AVMatrixEncoding matrix_encoding,
>>                        void *log_ctx);
>> +#endif
>> +
>> +/**
>> + * Generate a channel mixing matrix.
>> + *
>> + * This function is the one used internally by libswresample for building the
>> + * default mixing matrix. It is made public just as a utility function for
>> + * building custom matrices.
>> + *
>> + * @param in_layout           input channel layout
>> + * @param out_layout          output channel layout
>> + * @param center_mix_level    mix level for the center channel
>> + * @param surround_mix_level  mix level for the surround channel(s)
>> + * @param lfe_mix_level       mix level for the low-frequency effects channel
>> + * @param rematrix_maxval     if 1.0, coefficients will be normalized to prevent
>> + *                            overflow. if INT_MAX, coefficients will not be
>> + *                            normalized.
>> + * @param[out] matrix         mixing coefficients; matrix[i + stride * o] is
>> + *                            the weight of input channel i in output channel o.
> 
> The parameter below is named matrix_param.

Will fix.

> 
>> + * @param stride              distance between adjacent input channels in the
>> + *                            matrix array
>> + * @param matrix_encoding     matrixed stereo downmix mode (e.g. dplii)
>> + * @param log_ctx             parent logging context, can be NULL
>> + * @return                    0 on success, negative AVERROR code on failure
>> + */
>> +int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout,
>> +                      double center_mix_level, double surround_mix_level,
>> +                      double lfe_mix_level, double maxval,
>> +                      double rematrix_volume, double *matrix_param,
>> +                      ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding,
>> +                      void *log_context);
>>   
>>   /**
>>    * Set a customized remix matrix.
>> diff --git a/libswresample/swresample_frame.c b/libswresample/swresample_frame.c
>> index d95c1cc537..747cf119a9 100644
>> --- a/libswresample/swresample_frame.c
>> +++ b/libswresample/swresample_frame.c
>> @@ -29,7 +29,19 @@ int swr_config_frame(SwrContext *s, const AVFrame *out, const AVFrame *in)
>>       swr_close(s);
>>   
>>       if (in) {
>> -        if (av_opt_set_int(s, "icl", in->channel_layout, 0) < 0)
>> +        AVChannelLayout in_ch_layout = { 0 };
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>> +FF_DISABLE_DEPRECATION_WARNINGS
>> +        // if the old/new fields are set inconsistently, prefer the old ones
>> +        if ((in->channel_layout && (in->ch_layout.order != AV_CHANNEL_ORDER_NATIVE ||
>> +                                    in->ch_layout.u.mask != in->channel_layout))) {
>> +            av_channel_layout_from_mask(&in_ch_layout, in->channel_layout);
>> +FF_ENABLE_DEPRECATION_WARNINGS
>> +        } else
>> +#endif
>> +        if (av_channel_layout_copy(&in_ch_layout, &in->ch_layout) < 0)
>> +            goto fail;
>> +        if (av_opt_set_chlayout(s, "ichl", &in_ch_layout, 0) < 0)
>>               goto fail;
>>           if (av_opt_set_int(s, "isf", in->format, 0) < 0)
>>               goto fail;
>> @@ -38,7 +50,19 @@ int swr_config_frame(SwrContext *s, const AVFrame *out, const AVFrame *in)
>>       }
>>   
>>       if (out) {
>> -        if (av_opt_set_int(s, "ocl", out->channel_layout, 0) < 0)
>> +        AVChannelLayout out_ch_layout = { 0 };
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>> +FF_DISABLE_DEPRECATION_WARNINGS
>> +        // if the old/new fields are set inconsistently, prefer the old ones
>> +        if ((out->channel_layout && (out->ch_layout.order != AV_CHANNEL_ORDER_NATIVE ||
>> +                                     out->ch_layout.u.mask != out->channel_layout))) {
>> +            av_channel_layout_from_mask(&out_ch_layout, out->channel_layout);
>> +FF_ENABLE_DEPRECATION_WARNINGS
>> +        } else
>> +#endif
>> +        if (av_channel_layout_copy(&out_ch_layout, &out->ch_layout) < 0)
>> +            goto fail;
>> +        if (av_opt_set_chlayout(s, "ochl", &out_ch_layout, 0) < 0)
>>               goto fail;
>>           if (av_opt_set_int(s, "osf", out->format,  0) < 0)
>>               goto fail;
>> @@ -58,7 +82,19 @@ static int config_changed(SwrContext *s,
>>       int ret = 0;
>>   
>>       if (in) {
>> -        if (s->in_ch_layout   != in->channel_layout ||
>> +        AVChannelLayout in_ch_layout = { 0 };
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>> +FF_DISABLE_DEPRECATION_WARNINGS
>> +        // if the old/new fields are set inconsistently, prefer the old ones
>> +        if ((in->channel_layout && (in->ch_layout.order != AV_CHANNEL_ORDER_NATIVE ||
>> +                                    in->ch_layout.u.mask != in->channel_layout))) {
>> +            av_channel_layout_from_mask(&in_ch_layout, in->channel_layout);
>> +FF_ENABLE_DEPRECATION_WARNINGS
>> +        } else
>> +#endif
>> +        if ((ret = av_channel_layout_copy(&in_ch_layout, &in->ch_layout)) < 0)
>> +            return ret;
>> +        if (av_channel_layout_compare(&s->in_ch_layout, &in_ch_layout) ||
>>               s->in_sample_rate != in->sample_rate ||
>>               s->in_sample_fmt  != in->format) {
>>               ret |= AVERROR_INPUT_CHANGED;
>> @@ -66,7 +102,19 @@ static int config_changed(SwrContext *s,
>>       }
>>   
>>       if (out) {
>> -        if (s->out_ch_layout   != out->channel_layout ||
>> +        AVChannelLayout out_ch_layout = { 0 };
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>> +FF_DISABLE_DEPRECATION_WARNINGS
>> +        // if the old/new fields are set inconsistently, prefer the old ones
>> +        if ((out->channel_layout && (out->ch_layout.order != AV_CHANNEL_ORDER_NATIVE ||
>> +                                     out->ch_layout.u.mask != out->channel_layout))) {
>> +            av_channel_layout_from_mask(&out_ch_layout, out->channel_layout);
>> +FF_ENABLE_DEPRECATION_WARNINGS
>> +        } else
>> +#endif
>> +        if ((ret = av_channel_layout_copy(&out_ch_layout, &out->ch_layout)) < 0)
>> +            return ret;
>> +        if (av_channel_layout_compare(&s->out_ch_layout, &out_ch_layout) ||
>>               s->out_sample_rate != out->sample_rate ||
>>               s->out_sample_fmt  != out->format) {
>>               ret |= AVERROR_OUTPUT_CHANGED;
>> @@ -116,7 +164,14 @@ static inline int available_samples(AVFrame *out)
>>       if (av_sample_fmt_is_planar(out->format)) {
>>           return samples;
>>       } else {
>> -        int channels = av_get_channel_layout_nb_channels(out->channel_layout);
>> +        int channels;
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>> +FF_DISABLE_DEPRECATION_WARNINGS
>> +        channels = av_get_channel_layout_nb_channels(out->channel_layout);
>> +FF_ENABLE_DEPRECATION_WARNINGS
>> +        if (!channels)
>> +#endif
>> +        channels = out->ch_layout.nb_channels;
>>           return samples / channels;
>>       }
>>   }
>> diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h
>> index f2ea5a226d..262a0e2b8c 100644
>> --- a/libswresample/swresample_internal.h
>> +++ b/libswresample/swresample_internal.h
>> @@ -99,8 +99,8 @@ struct SwrContext {
>>       enum AVSampleFormat  in_sample_fmt;             ///< input sample format
>>       enum AVSampleFormat int_sample_fmt;             ///< internal sample format (AV_SAMPLE_FMT_FLTP or AV_SAMPLE_FMT_S16P)
>>       enum AVSampleFormat out_sample_fmt;             ///< output sample format
>> -    int64_t  in_ch_layout;                          ///< input channel layout
>> -    int64_t out_ch_layout;                          ///< output channel layout
>> +    AVChannelLayout  in_ch_layout;                  ///< input channel layout
>> +    AVChannelLayout out_ch_layout;                  ///< output channel layout
>>       int      in_sample_rate;                        ///< input sample rate
>>       int     out_sample_rate;                        ///< output sample rate
>>       int flags;                                      ///< miscellaneous flags such as SWR_FLAG_RESAMPLE
>> @@ -114,11 +114,15 @@ struct SwrContext {
>>       int used_ch_count;                              ///< number of used input channels (mapped channel count if channel_map, otherwise in.ch_count)
>>       int engine;
>>   
>> +    int user_used_ch_count;                         ///< User set used channel count
>> +#if FF_API_OLD_CHANNEL_LAYOUT
>>       int user_in_ch_count;                           ///< User set input channel count
>>       int user_out_ch_count;                          ///< User set output channel count
>> -    int user_used_ch_count;                         ///< User set used channel count
>>       int64_t user_in_ch_layout;                      ///< User set input channel layout
>>       int64_t user_out_ch_layout;                     ///< User set output channel layout
>> +#endif
>> +    AVChannelLayout user_in_chlayout;               ///< User set input channel layout
>> +    AVChannelLayout user_out_chlayout;              ///< User set output channel layout
>>       enum AVSampleFormat user_int_sample_fmt;        ///< User set internal sample format
>>       int user_dither_method;                         ///< User set dither method
>>   
>>
> 
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
diff mbox series

Patch

diff --git a/libswresample/options.c b/libswresample/options.c
index 6911709157..ffa27c590d 100644
--- a/libswresample/options.c
+++ b/libswresample/options.c
@@ -34,12 +34,19 @@ 
 
 #define OFFSET(x) offsetof(SwrContext,x)
 #define PARAM AV_OPT_FLAG_AUDIO_PARAM
+#define DEPREC AV_OPT_FLAG_DEPRECATED
 
 static const AVOption options[]={
-{"ich"                  , "set input channel count"     , OFFSET(user_in_ch_count  ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
-{"in_channel_count"     , "set input channel count"     , OFFSET(user_in_ch_count  ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
-{"och"                  , "set output channel count"    , OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
-{"out_channel_count"    , "set output channel count"    , OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
+#if FF_API_OLD_CHANNEL_LAYOUT
+{"ich"                  , "set input channel count (Deprecated, use ichl)",
+                                                          OFFSET(user_in_ch_count  ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM|DEPREC},
+{"in_channel_count"     , "set input channel count (Deprecated, use in_chlayout)",
+                                                          OFFSET(user_in_ch_count  ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM|DEPREC},
+{"och"                  , "set output channel count (Deprecated, use ochl)",
+                                                          OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM|DEPREC},
+{"out_channel_count"    , "set output channel count (Deprecated, use out_chlayout)",
+                                                          OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM|DEPREC},
+#endif
 {"uch"                  , "set used channel count"      , OFFSET(user_used_ch_count), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
 {"used_channel_count"   , "set used channel count"      , OFFSET(user_used_ch_count), AV_OPT_TYPE_INT, {.i64=0                    }, 0      , SWR_CH_MAX, PARAM},
 {"isr"                  , "set input sample rate"       , OFFSET( in_sample_rate), AV_OPT_TYPE_INT  , {.i64=0                     }, 0      , INT_MAX   , PARAM},
@@ -52,10 +59,20 @@  static const AVOption options[]={
 {"out_sample_fmt"       , "set output sample format"    , OFFSET(out_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1   , INT_MAX, PARAM},
 {"tsf"                  , "set internal sample format"  , OFFSET(user_int_sample_fmt), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1   , INT_MAX, PARAM},
 {"internal_sample_fmt"  , "set internal sample format"  , OFFSET(user_int_sample_fmt), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1   , INT_MAX, PARAM},
-{"icl"                  , "set input channel layout"    , OFFSET(user_in_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0           }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"},
-{"in_channel_layout"    , "set input channel layout"    , OFFSET(user_in_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0           }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"},
-{"ocl"                  , "set output channel layout"   , OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0           }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"},
-{"out_channel_layout"   , "set output channel layout"   , OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0           }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"},
+#if FF_API_OLD_CHANNEL_LAYOUT
+{"icl"                  , "set input channel layout (Deprecated, use ichl)",
+                                                          OFFSET(user_in_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0          }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"},
+{"in_channel_layout"    , "set input channel layout (Deprecated, use in_chlayout)",
+                                                          OFFSET(user_in_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0          }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"},
+{"ocl"                  , "set output channel layout (Deprecated, use ochl)",
+                                                          OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0         }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"},
+{"out_channel_layout"   , "set output channel layout (Deprecated, use out_chlayout)",
+                                                          OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0         }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"},
+#endif
+{"ichl"                 , "set input channel layout"    , OFFSET(user_in_chlayout ), AV_OPT_TYPE_CHLAYOUT, {.str=NULL             }, 0, 0 , PARAM, "chlayout"},
+{"in_chlayout"          , "set input channel layout"    , OFFSET(user_in_chlayout ), AV_OPT_TYPE_CHLAYOUT, {.str=NULL             }, 0, 0 , PARAM, "chlayout"},
+{"ochl"                 , "set output channel layout"   , OFFSET(user_out_chlayout), AV_OPT_TYPE_CHLAYOUT, {.str=NULL             }, 0, 0 , PARAM, "chlayout"},
+{"out_chlayout"         , "set output channel layout"   , OFFSET(user_out_chlayout), AV_OPT_TYPE_CHLAYOUT, {.str=NULL             }, 0, 0 , PARAM, "chlayout"},
 {"clev"                 , "set center mix level"        , OFFSET(clev           ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB                }, -32    , 32        , PARAM},
 {"center_mix_level"     , "set center mix level"        , OFFSET(clev           ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB                }, -32    , 32        , PARAM},
 {"slev"                 , "set surround mix level"      , OFFSET(slev           ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB                }, -32    , 32        , PARAM},
diff --git a/libswresample/rematrix.c b/libswresample/rematrix.c
index 94b3de88f6..35086c218d 100644
--- a/libswresample/rematrix.c
+++ b/libswresample/rematrix.c
@@ -64,15 +64,37 @@ 
 int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride)
 {
     int nb_in, nb_out, in, out;
+    int user_in_chlayout_nb_channels, user_out_chlayout_nb_channels;
 
     if (!s || s->in_convert) // s needs to be allocated but not initialized
         return AVERROR(EINVAL);
     memset(s->matrix, 0, sizeof(s->matrix));
     memset(s->matrix_flt, 0, sizeof(s->matrix_flt));
-    nb_in = (s->user_in_ch_count > 0) ? s->user_in_ch_count :
-        av_get_channel_layout_nb_channels(s->user_in_ch_layout);
-    nb_out = (s->user_out_ch_count > 0) ? s->user_out_ch_count :
-        av_get_channel_layout_nb_channels(s->user_out_ch_layout);
+
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+    user_in_chlayout_nb_channels = av_get_channel_layout_nb_channels(s->user_in_ch_layout);
+FF_ENABLE_DEPRECATION_WARNINGS
+    if (!user_in_chlayout_nb_channels)
+#endif
+    user_in_chlayout_nb_channels = s->user_in_chlayout.nb_channels;
+    nb_in =
+#if FF_API_OLD_CHANNEL_LAYOUT
+            (s->user_in_ch_count > 0) ? s->user_in_ch_count :
+#endif
+            user_in_chlayout_nb_channels;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+    user_out_chlayout_nb_channels = av_get_channel_layout_nb_channels(s->user_out_ch_layout);
+FF_ENABLE_DEPRECATION_WARNINGS
+    if (!user_out_chlayout_nb_channels)
+#endif
+    user_out_chlayout_nb_channels = s->user_out_chlayout.nb_channels;
+    nb_out =
+#if FF_API_OLD_CHANNEL_LAYOUT
+             (s->user_out_ch_count > 0) ? s->user_out_ch_count :
+#endif
+             user_out_chlayout_nb_channels;
     for (out = 0; out < nb_out; out++) {
         for (in = 0; in < nb_in; in++)
             s->matrix_flt[out][in] = s->matrix[out][in] = matrix[in];
@@ -88,95 +110,141 @@  static int even(int64_t layout){
     return 0;
 }
 
-static int64_t clean_layout(void *s, int64_t layout){
-    if(layout && layout != AV_CH_FRONT_CENTER && !(layout&(layout-1))) {
+static int clean_layout(AVChannelLayout *out, const AVChannelLayout *in, void *s)
+{
+    int ret = 0;
+
+    if(av_channel_layout_index_from_channel(in, AV_CH_FRONT_CENTER) < 0 && in->nb_channels == 1) {
         char buf[128];
-        av_get_channel_layout_string(buf, sizeof(buf), -1, layout);
+        av_channel_layout_describe(in, buf, sizeof(buf));
         av_log(s, AV_LOG_VERBOSE, "Treating %s as mono\n", buf);
-        return AV_CH_FRONT_CENTER;
-    }
+        *out = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
+    } else
+        ret = av_channel_layout_copy(out, in);
 
-    return layout;
+    return ret;
 }
 
-static int sane_layout(int64_t layout){
-    if(!(layout & AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker
+static int sane_layout(AVChannelLayout *ch_layout) {
+    if (ch_layout->order != AV_CHANNEL_ORDER_NATIVE)
+        return 0;
+    if(!av_channel_layout_subset(ch_layout, AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker
         return 0;
-    if(!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT))) // no asymetric front
+    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)))) // no asymetric front
         return 0;
-    if(!even(layout & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)))   // no asymetric side
+    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT))))   // no asymetric side
         return 0;
-    if(!even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)))
+    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT))))
         return 0;
-    if(!even(layout & (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)))
+    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER))))
         return 0;
-    if(av_get_channel_layout_nb_channels(layout) >= SWR_CH_MAX)
+    if(ch_layout->nb_channels >= SWR_CH_MAX)
         return 0;
 
     return 1;
 }
 
+#if FF_API_OLD_CHANNEL_LAYOUT
 av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout_param,
                              double center_mix_level, double surround_mix_level,
                              double lfe_mix_level, double maxval,
                              double rematrix_volume, double *matrix_param,
                              int stride, enum AVMatrixEncoding matrix_encoding, void *log_context)
 {
-    int i, j, out_i;
+    AVChannelLayout in_ch_layout = { 0 }, out_ch_layout = { 0 };
+    int ret;
+
+    ret  = av_channel_layout_from_mask(&in_ch_layout, in_ch_layout_param);
+    ret |= av_channel_layout_from_mask(&out_ch_layout, out_ch_layout_param);
+    if (ret < 0)
+        return ret;
+
+    return swr_build_matrix2(&in_ch_layout, &out_ch_layout, center_mix_level, surround_mix_level,
+                             lfe_mix_level, maxval, rematrix_volume, matrix_param,
+                             stride, matrix_encoding, log_context);
+}
+#endif
+
+av_cold int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout,
+                              double center_mix_level, double surround_mix_level,
+                              double lfe_mix_level, double maxval,
+                              double rematrix_volume, double *matrix_param,
+                              ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding, void *log_context)
+{
+    int i, j, out_i, ret;
+    AVChannelLayout in_ch_layout = { 0 }, out_ch_layout = { 0 };
     double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS]={{0}};
-    int64_t unaccounted, in_ch_layout, out_ch_layout;
+    int64_t unaccounted;
     double maxcoef=0;
     char buf[128];
 
-     in_ch_layout = clean_layout(log_context,  in_ch_layout_param);
-    out_ch_layout = clean_layout(log_context, out_ch_layout_param);
-
-    if(   out_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX
-       && (in_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0
-    )
-        out_ch_layout = AV_CH_LAYOUT_STEREO;
+    ret  = clean_layout(&in_ch_layout, in_layout, log_context);
+    ret |= clean_layout(&out_ch_layout, out_layout, log_context);
+    if (ret < 0)
+        goto fail;
 
-    if(    in_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX
-       && (out_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0
-    )
-        in_ch_layout = AV_CH_LAYOUT_STEREO;
-
-    if (in_ch_layout == AV_CH_LAYOUT_22POINT2 &&
-        out_ch_layout != AV_CH_LAYOUT_22POINT2) {
-        in_ch_layout = (AV_CH_LAYOUT_7POINT1_WIDE_BACK|AV_CH_BACK_CENTER);
-        av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout);
+    if(   !av_channel_layout_compare(&out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO_DOWNMIX)
+       && !av_channel_layout_subset(&in_ch_layout, AV_CH_LAYOUT_STEREO_DOWNMIX)
+    ) {
+        av_channel_layout_uninit(&out_ch_layout);
+        out_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
+    }
+    if(   !av_channel_layout_compare(&in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO_DOWNMIX)
+       && !av_channel_layout_subset(&out_ch_layout, AV_CH_LAYOUT_STEREO_DOWNMIX)
+    ) {
+        av_channel_layout_uninit(&in_ch_layout);
+        in_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
+    }
+    if (!av_channel_layout_compare(&in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_22POINT2) &&
+        av_channel_layout_compare(&out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_22POINT2)) {
+        av_channel_layout_from_mask(&in_ch_layout, (AV_CH_LAYOUT_7POINT1_WIDE_BACK|AV_CH_BACK_CENTER));
+        av_channel_layout_describe(&in_ch_layout, buf, sizeof(buf));
         av_log(log_context, AV_LOG_WARNING,
                "Full-on remixing from 22.2 has not yet been implemented! "
                "Processing the input as '%s'\n",
                buf);
     }
 
-    if(!sane_layout(in_ch_layout)){
-        av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout_param);
+    if(!av_channel_layout_check(&in_ch_layout)) {
+        av_log(log_context, AV_LOG_ERROR, "Input channel layout is invalid\n");
+        ret = AVERROR(EINVAL);
+        goto fail;
+    }
+    if(!sane_layout(&in_ch_layout)) {
+        av_channel_layout_describe(&in_ch_layout, buf, sizeof(buf));
         av_log(log_context, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf);
-        return AVERROR(EINVAL);
+        ret = AVERROR(EINVAL);
+        goto fail;
     }
 
-    if(!sane_layout(out_ch_layout)){
-        av_get_channel_layout_string(buf, sizeof(buf), -1, out_ch_layout_param);
+    if(!av_channel_layout_check(&out_ch_layout)) {
+        av_log(log_context, AV_LOG_ERROR, "Output channel layout is invalid\n");
+        ret = AVERROR(EINVAL);
+        goto fail;
+    }
+    if(!sane_layout(&out_ch_layout)) {
+        av_channel_layout_describe(&out_ch_layout, buf, sizeof(buf));
         av_log(log_context, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf);
-        return AVERROR(EINVAL);
+        ret = AVERROR(EINVAL);
+        goto fail;
     }
 
     for(i=0; i<FF_ARRAY_ELEMS(matrix); i++){
-        if(in_ch_layout & out_ch_layout & (1ULL<<i))
+        int idx;
+        if(   (idx = av_channel_layout_index_from_channel(&in_ch_layout, i)) >= 0
+           && av_channel_layout_index_from_channel(&out_ch_layout, i) == idx)
             matrix[i][i]= 1.0;
     }
 
-    unaccounted= in_ch_layout & ~out_ch_layout;
+    unaccounted =  in_ch_layout.u.mask & ~out_ch_layout.u.mask;
 
 //FIXME implement dolby surround
 //FIXME implement full ac3
 
 
     if(unaccounted & AV_CH_FRONT_CENTER){
-        if((out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){
-            if(in_ch_layout & AV_CH_LAYOUT_STEREO) {
+        if(av_channel_layout_subset(&out_ch_layout, AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){
+            if(av_channel_layout_subset(&in_ch_layout, AV_CH_LAYOUT_STEREO)) {
                 matrix[ FRONT_LEFT][FRONT_CENTER]+= center_mix_level;
                 matrix[FRONT_RIGHT][FRONT_CENTER]+= center_mix_level;
             } else {
@@ -187,23 +255,23 @@  av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
             av_assert0(0);
     }
     if(unaccounted & AV_CH_LAYOUT_STEREO){
-        if(out_ch_layout & AV_CH_FRONT_CENTER){
+        if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){
             matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2;
             matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2;
-            if(in_ch_layout & AV_CH_FRONT_CENTER)
+            if(av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_FRONT_CENTER) >= 0)
                 matrix[FRONT_CENTER][ FRONT_CENTER] = center_mix_level*sqrt(2);
         }else
             av_assert0(0);
     }
 
     if(unaccounted & AV_CH_BACK_CENTER){
-        if(out_ch_layout & AV_CH_BACK_LEFT){
+        if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_LEFT) >= 0){
             matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2;
             matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2;
-        }else if(out_ch_layout & AV_CH_SIDE_LEFT){
+        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_SIDE_LEFT) >= 0){
             matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2;
             matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2;
-        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
+        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0){
             if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
                 matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
                 if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
@@ -217,24 +285,24 @@  av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
                 matrix[ FRONT_LEFT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
                 matrix[FRONT_RIGHT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
             }
-        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
+        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){
             matrix[ FRONT_CENTER][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
         }else
             av_assert0(0);
     }
     if(unaccounted & AV_CH_BACK_LEFT){
-        if(out_ch_layout & AV_CH_BACK_CENTER){
+        if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_CENTER) >= 0){
             matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2;
             matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2;
-        }else if(out_ch_layout & AV_CH_SIDE_LEFT){
-            if(in_ch_layout & AV_CH_SIDE_LEFT){
+        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_SIDE_LEFT) >= 0){
+            if(av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_SIDE_LEFT) >= 0){
                 matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2;
                 matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2;
             }else{
             matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0;
             matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0;
             }
-        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
+        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0){
             if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
                 matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2;
                 matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
@@ -249,7 +317,7 @@  av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
                 matrix[ FRONT_LEFT][ BACK_LEFT] += surround_mix_level;
                 matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
             }
-        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
+        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){
             matrix[ FRONT_CENTER][BACK_LEFT ]+= surround_mix_level*M_SQRT1_2;
             matrix[ FRONT_CENTER][BACK_RIGHT]+= surround_mix_level*M_SQRT1_2;
         }else
@@ -257,20 +325,20 @@  av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
     }
 
     if(unaccounted & AV_CH_SIDE_LEFT){
-        if(out_ch_layout & AV_CH_BACK_LEFT){
+        if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_LEFT) >= 0){
             /* if back channels do not exist in the input, just copy side
                channels to back channels, otherwise mix side into back */
-            if (in_ch_layout & AV_CH_BACK_LEFT) {
+            if (av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_BACK_LEFT) >= 0) {
                 matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
                 matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
             } else {
                 matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
                 matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
             }
-        }else if(out_ch_layout & AV_CH_BACK_CENTER){
+        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_CENTER) >= 0){
             matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2;
             matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2;
-        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
+        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0){
             if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
                 matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2;
                 matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
@@ -285,7 +353,7 @@  av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
                 matrix[ FRONT_LEFT][ SIDE_LEFT] += surround_mix_level;
                 matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
             }
-        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
+        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){
             matrix[ FRONT_CENTER][SIDE_LEFT ]+= surround_mix_level * M_SQRT1_2;
             matrix[ FRONT_CENTER][SIDE_RIGHT]+= surround_mix_level * M_SQRT1_2;
         }else
@@ -293,10 +361,10 @@  av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
     }
 
     if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){
-        if(out_ch_layout & AV_CH_FRONT_LEFT){
+        if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0){
             matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0;
             matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0;
-        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
+        }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){
             matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2;
             matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2;
         }else
@@ -304,9 +372,9 @@  av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
     }
     /* mix LFE into front left/right or center */
     if (unaccounted & AV_CH_LOW_FREQUENCY) {
-        if (out_ch_layout & AV_CH_FRONT_CENTER) {
+        if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) {
             matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level;
-        } else if (out_ch_layout & AV_CH_FRONT_LEFT) {
+        } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) {
             matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
             matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
         } else
@@ -316,15 +384,19 @@  av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
     for(out_i=i=0; i<64; i++){
         double sum=0;
         int in_i=0;
-        if((out_ch_layout & (1ULL<<i)) == 0)
+        if(av_channel_layout_index_from_channel(&out_ch_layout, i) < 0)
             continue;
         for(j=0; j<64; j++){
-            if((in_ch_layout & (1ULL<<j)) == 0)
+            if(av_channel_layout_index_from_channel(&in_ch_layout, j) < 0)
                continue;
             if (i < FF_ARRAY_ELEMS(matrix) && j < FF_ARRAY_ELEMS(matrix[0]))
                 matrix_param[stride*out_i + in_i] = matrix[i][j];
-            else
-                matrix_param[stride*out_i + in_i] = i == j && (in_ch_layout & out_ch_layout & (1ULL<<i));
+            else {
+                int idx;
+                matrix_param[stride*out_i + in_i] = i == j &&
+                (   (idx = av_channel_layout_index_from_channel(&in_ch_layout, i)) >= 0
+                 && av_channel_layout_index_from_channel(&out_ch_layout, i) == idx);
+            }
             sum += fabs(matrix_param[stride*out_i + in_i]);
             in_i++;
         }
@@ -350,17 +422,22 @@  av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout
     }
 
     av_log(log_context, AV_LOG_DEBUG, "Matrix coefficients:\n");
-    for(i=0; i<av_get_channel_layout_nb_channels(out_ch_layout); i++){
-        const char *c =
-            av_get_channel_name(av_channel_layout_extract_channel(out_ch_layout, i));
-        av_log(log_context, AV_LOG_DEBUG, "%s: ", c ? c : "?");
-        for(j=0; j<av_get_channel_layout_nb_channels(in_ch_layout); j++){
-            c = av_get_channel_name(av_channel_layout_extract_channel(in_ch_layout, j));
-            av_log(log_context, AV_LOG_DEBUG, "%s:%f ", c ? c : "?", matrix_param[stride*i + j]);
+    for(i = 0; i < out_ch_layout.nb_channels; i++){
+        av_channel_name(buf, sizeof(buf), av_channel_layout_channel_from_index(&out_ch_layout, i));
+        av_log(log_context, AV_LOG_DEBUG, "%s: ", buf);
+        for(j = 0; j < in_ch_layout.nb_channels; j++){
+            av_channel_name(buf, sizeof(buf), av_channel_layout_channel_from_index(&in_ch_layout, j));
+            av_log(log_context, AV_LOG_DEBUG, "%s:%f ", buf, matrix_param[stride*i + j]);
         }
         av_log(log_context, AV_LOG_DEBUG, "\n");
     }
-    return 0;
+
+    ret = 0;
+fail:
+    av_channel_layout_uninit(&in_ch_layout);
+    av_channel_layout_uninit(&out_ch_layout);
+
+    return ret;
 }
 
 av_cold static int auto_matrix(SwrContext *s)
@@ -377,7 +454,7 @@  av_cold static int auto_matrix(SwrContext *s)
         maxval = INT_MAX;
 
     memset(s->matrix, 0, sizeof(s->matrix));
-    ret = swr_build_matrix(s->in_ch_layout, s->out_ch_layout,
+    ret = swr_build_matrix2(&s->in_ch_layout, &s->out_ch_layout,
                            s->clev, s->slev, s->lfe_mix_level,
                            maxval, s->rematrix_volume, (double*)s->matrix,
                            s->matrix[1] - s->matrix[0], s->matrix_encoding, s);
@@ -519,8 +596,8 @@  int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mus
         off = len1 * out->bps;
     }
 
-    av_assert0(!s->out_ch_layout || out->ch_count == av_get_channel_layout_nb_channels(s->out_ch_layout));
-    av_assert0(!s-> in_ch_layout || in ->ch_count == av_get_channel_layout_nb_channels(s-> in_ch_layout));
+    av_assert0(s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC || out->ch_count == s->out_ch_layout.nb_channels);
+    av_assert0(s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC || in ->ch_count == s->in_ch_layout.nb_channels);
 
     for(out_i=0; out_i<out->ch_count; out_i++){
         switch(s->matrix_ch[out_i][0]){
diff --git a/libswresample/rematrix_template.c b/libswresample/rematrix_template.c
index add65e3155..f5a508361c 100644
--- a/libswresample/rematrix_template.c
+++ b/libswresample/rematrix_template.c
@@ -88,13 +88,16 @@  static void RENAME(mix8to2)(SAMPLE **out, const SAMPLE **in, COEFF *coeffp, inte
 }
 
 static RENAME(mix_any_func_type) *RENAME(get_mix_any_func)(SwrContext *s){
-    if(   s->out_ch_layout == AV_CH_LAYOUT_STEREO && (s->in_ch_layout == AV_CH_LAYOUT_5POINT1 || s->in_ch_layout == AV_CH_LAYOUT_5POINT1_BACK)
+    if(   !av_channel_layout_compare(&s->out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)
+       && (   !av_channel_layout_compare(&s->in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1)
+           || !av_channel_layout_compare(&s->in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK))
        && s->matrix[0][2] == s->matrix[1][2] && s->matrix[0][3] == s->matrix[1][3]
        && !s->matrix[0][1] && !s->matrix[0][5] && !s->matrix[1][0] && !s->matrix[1][4]
     )
         return RENAME(mix6to2);
 
-    if(   s->out_ch_layout == AV_CH_LAYOUT_STEREO && s->in_ch_layout == AV_CH_LAYOUT_7POINT1
+    if(   !av_channel_layout_compare(&s->out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)
+       && !av_channel_layout_compare(&s->in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1)
        && s->matrix[0][2] == s->matrix[1][2] && s->matrix[0][3] == s->matrix[1][3]
        && !s->matrix[0][1] && !s->matrix[0][5] && !s->matrix[1][0] && !s->matrix[1][4]
        && !s->matrix[0][7] && !s->matrix[1][6]
diff --git a/libswresample/swresample.c b/libswresample/swresample.c
index 16734c9df9..f8fbd9134b 100644
--- a/libswresample/swresample.c
+++ b/libswresample/swresample.c
@@ -56,6 +56,8 @@  int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map){
     return 0;
 }
 
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
 struct SwrContext *swr_alloc_set_opts(struct SwrContext *s,
                                       int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
                                       int64_t  in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
@@ -97,6 +99,58 @@  fail:
     swr_free(&s);
     return NULL;
 }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+int swr_alloc_set_opts2(struct SwrContext **ps,
+                        AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
+                        AVChannelLayout *in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
+                        int log_offset, void *log_ctx) {
+    struct SwrContext *s = *ps;
+    int ret;
+
+    if (!s) s = swr_alloc();
+    if (!s) return AVERROR(ENOMEM);
+
+    s->log_level_offset= log_offset;
+    s->log_ctx= log_ctx;
+
+    if ((ret = av_opt_set_chlayout(s, "ochl", out_ch_layout, 0)) < 0)
+        goto fail;
+
+    if ((ret = av_opt_set_int(s, "osf", out_sample_fmt, 0)) < 0)
+        goto fail;
+
+    if ((ret = av_opt_set_int(s, "osr", out_sample_rate, 0)) < 0)
+        goto fail;
+
+    if ((ret = av_opt_set_chlayout(s, "ichl", in_ch_layout, 0)) < 0)
+        goto fail;
+
+    if ((ret = av_opt_set_int(s, "isf", in_sample_fmt, 0)) < 0)
+        goto fail;
+
+    if ((ret = av_opt_set_int(s, "isr", in_sample_rate, 0)) < 0)
+        goto fail;
+
+    av_opt_set_int(s, "uch", 0, 0);
+
+#if FF_API_OLD_CHANNEL_LAYOUT
+    // Clear old API values so they don't take precedence in swr_init()
+    av_opt_set_int(s, "icl", 0, 0);
+    av_opt_set_int(s, "ocl", 0, 0);
+    av_opt_set_int(s, "ich", 0, 0);
+    av_opt_set_int(s, "och", 0, 0);
+#endif
+
+    *ps = s;
+
+    return 0;
+fail:
+    av_log(s, AV_LOG_ERROR, "Failed to set option\n");
+    swr_free(ps);
+    return ret;
+}
 
 static void set_audiodata_fmt(AudioData *a, enum AVSampleFormat fmt){
     a->fmt   = fmt;
@@ -125,6 +179,8 @@  static void clear_context(SwrContext *s){
     free_temp(&s->drop_temp);
     free_temp(&s->dither.noise);
     free_temp(&s->dither.temp);
+    av_channel_layout_uninit(&s->in_ch_layout);
+    av_channel_layout_uninit(&s->out_ch_layout);
     swri_audio_convert_free(&s-> in_convert);
     swri_audio_convert_free(&s->out_convert);
     swri_audio_convert_free(&s->full_convert);
@@ -138,6 +194,9 @@  av_cold void swr_free(SwrContext **ss){
     SwrContext *s= *ss;
     if(s){
         clear_context(s);
+        av_channel_layout_uninit(&s->user_in_chlayout);
+        av_channel_layout_uninit(&s->user_out_chlayout);
+
         if (s->resampler)
             s->resampler->free(&s->resample);
     }
@@ -172,25 +231,66 @@  av_cold int swr_init(struct SwrContext *s){
         av_log(s, AV_LOG_ERROR, "Requested output sample rate %d is invalid\n", s->out_sample_rate);
         return AVERROR(EINVAL);
     }
+    s->used_ch_count = s->user_used_ch_count;
+#if FF_API_OLD_CHANNEL_LAYOUT
     s->out.ch_count  = s-> user_out_ch_count;
     s-> in.ch_count  = s->  user_in_ch_count;
-    s->used_ch_count = s->user_used_ch_count;
 
-    s-> in_ch_layout = s-> user_in_ch_layout;
-    s->out_ch_layout = s->user_out_ch_layout;
+    // if the old/new fields are set inconsistently, prefer the old ones
+    if ((s->user_in_ch_count && s->user_in_ch_count != s->user_in_chlayout.nb_channels) ||
+        (s->user_in_ch_layout && (s->user_in_chlayout.order != AV_CHANNEL_ORDER_NATIVE ||
+                                  s->user_in_chlayout.u.mask != s->user_in_ch_layout))) {
+        av_channel_layout_uninit(&s->in_ch_layout);
+        if (s->user_in_ch_layout)
+            av_channel_layout_from_mask(&s->in_ch_layout, s->user_in_ch_layout);
+        else {
+            s->in_ch_layout.order       = AV_CHANNEL_ORDER_UNSPEC;
+            s->in_ch_layout.nb_channels = s->user_in_ch_count;
+        }
+    } else
+        av_channel_layout_copy(&s->in_ch_layout, &s->user_in_chlayout);
+
+    if ((s->user_out_ch_count && s->user_out_ch_count != s->user_out_chlayout.nb_channels) ||
+        (s->user_out_ch_layout && (s->user_out_chlayout.order != AV_CHANNEL_ORDER_NATIVE ||
+                                   s->user_out_chlayout.u.mask != s->user_out_ch_layout))) {
+        av_channel_layout_uninit(&s->out_ch_layout);
+        if (s->user_out_ch_layout)
+            av_channel_layout_from_mask(&s->out_ch_layout, s->user_out_ch_layout);
+        else {
+            s->out_ch_layout.order       = AV_CHANNEL_ORDER_UNSPEC;
+            s->out_ch_layout.nb_channels = s->user_out_ch_count;
+        }
+    } else
+        av_channel_layout_copy(&s->out_ch_layout, &s->user_out_chlayout);
+
+    if (!s->out.ch_count && !s->user_out_ch_layout)
+        s->out.ch_count  = s->out_ch_layout.nb_channels;
+    if (!s-> in.ch_count && !s-> user_in_ch_layout)
+        s-> in.ch_count  = s->in_ch_layout.nb_channels;
+#else
+    s->out.ch_count  = s-> user_out_chlayout.nb_channels;
+    s-> in.ch_count  = s->  user_in_chlayout.nb_channels;
+
+    ret  = av_channel_layout_copy(&s->in_ch_layout, &s->user_in_chlayout);
+    ret |= av_channel_layout_copy(&s->out_ch_layout, &s->user_out_chlayout);
+    if (ret < 0)
+        return ret;
+#endif
 
     s->int_sample_fmt= s->user_int_sample_fmt;
 
     s->dither.method = s->user_dither_method;
 
-    if(av_get_channel_layout_nb_channels(s-> in_ch_layout) > SWR_CH_MAX) {
-        av_log(s, AV_LOG_WARNING, "Input channel layout 0x%"PRIx64" is invalid or unsupported.\n", s-> in_ch_layout);
-        s->in_ch_layout = 0;
+    if (!av_channel_layout_check(&s->in_ch_layout) || s->in_ch_layout.nb_channels > SWR_CH_MAX) {
+        av_channel_layout_describe(&s->in_ch_layout, l1, sizeof(l1));
+        av_log(s, AV_LOG_WARNING, "Input channel layout \"%s\" is invalid or unsupported.\n", l1);
+        av_channel_layout_uninit(&s->in_ch_layout);
     }
 
-    if(av_get_channel_layout_nb_channels(s->out_ch_layout) > SWR_CH_MAX) {
-        av_log(s, AV_LOG_WARNING, "Output channel layout 0x%"PRIx64" is invalid or unsupported.\n", s->out_ch_layout);
-        s->out_ch_layout = 0;
+    if (!av_channel_layout_check(&s->out_ch_layout) || s->out_ch_layout.nb_channels > SWR_CH_MAX) {
+        av_channel_layout_describe(&s->out_ch_layout, l2, sizeof(l2));
+        av_log(s, AV_LOG_WARNING, "Output channel layout \"%s\" is invalid or unsupported.\n", l2);
+        av_channel_layout_uninit(&s->out_ch_layout);
     }
 
     switch(s->engine){
@@ -206,17 +306,18 @@  av_cold int swr_init(struct SwrContext *s){
     if(!s->used_ch_count)
         s->used_ch_count= s->in.ch_count;
 
-    if(s->used_ch_count && s-> in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s-> in_ch_layout)){
+    if(s->used_ch_count && s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_count != s->in_ch_layout.nb_channels){
         av_log(s, AV_LOG_WARNING, "Input channel layout has a different number of channels than the number of used channels, ignoring layout\n");
-        s-> in_ch_layout= 0;
+        av_channel_layout_uninit(&s->in_ch_layout);
     }
 
-    if(!s-> in_ch_layout)
-        s-> in_ch_layout= av_get_default_channel_layout(s->used_ch_count);
-    if(!s->out_ch_layout)
-        s->out_ch_layout= av_get_default_channel_layout(s->out.ch_count);
+    if(!s->in_ch_layout.nb_channels || s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
+        av_channel_layout_default(&s->in_ch_layout, s->used_ch_count);
+    if(!s->out_ch_layout.nb_channels || s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
+        av_channel_layout_default(&s->out_ch_layout, s->out.ch_count);
 
-    s->rematrix= s->out_ch_layout  !=s->in_ch_layout || s->rematrix_volume!=1.0 ||
+    s->rematrix= av_channel_layout_compare(&s->out_ch_layout, &s->in_ch_layout) ||
+                 s->rematrix_volume!=1.0 ||
                  s->rematrix_custom;
 
     if(s->int_sample_fmt == AV_SAMPLE_FMT_NONE){
@@ -291,33 +392,36 @@  av_cold int swr_init(struct SwrContext *s){
 
 #define RSC 1 //FIXME finetune
     if(!s-> in.ch_count)
-        s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout);
+        s-> in.ch_count = s->in_ch_layout.nb_channels;
     if(!s->used_ch_count)
         s->used_ch_count= s->in.ch_count;
     if(!s->out.ch_count)
-        s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout);
+        s->out.ch_count = s->out_ch_layout.nb_channels;
 
     if(!s-> in.ch_count){
-        av_assert0(!s->in_ch_layout);
+        av_assert0(s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC);
         av_log(s, AV_LOG_ERROR, "Input channel count and layout are unset\n");
         ret = AVERROR(EINVAL);
         goto fail;
     }
 
-    av_get_channel_layout_string(l1, sizeof(l1), s-> in.ch_count, s-> in_ch_layout);
-    av_get_channel_layout_string(l2, sizeof(l2), s->out.ch_count, s->out_ch_layout);
-    if (s->out_ch_layout && s->out.ch_count != av_get_channel_layout_nb_channels(s->out_ch_layout)) {
+#if FF_API_OLD_CHANNEL_LAYOUT
+    av_channel_layout_describe(&s->out_ch_layout, l1, sizeof(l1));
+    if (s->out_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->out.ch_count != s->out_ch_layout.nb_channels) {
         av_log(s, AV_LOG_ERROR, "Output channel layout %s mismatches specified channel count %d\n", l2, s->out.ch_count);
         ret = AVERROR(EINVAL);
         goto fail;
     }
-    if (s->in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s->in_ch_layout)) {
+#endif
+    av_channel_layout_describe(&s->in_ch_layout, l1, sizeof(l1));
+    if (s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_count != s->in_ch_layout.nb_channels) {
         av_log(s, AV_LOG_ERROR, "Input channel layout %s mismatches specified channel count %d\n", l1, s->used_ch_count);
         ret = AVERROR(EINVAL);
         goto fail;
     }
 
-    if ((!s->out_ch_layout || !s->in_ch_layout) && s->used_ch_count != s->out.ch_count && !s->rematrix_custom) {
+    if ((   s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC
+         || s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) && s->used_ch_count != s->out.ch_count && !s->rematrix_custom) {
         av_log(s, AV_LOG_ERROR, "Rematrix is needed between %s and %s "
                "but there is not enough information to do it\n", l1, l2);
         ret = AVERROR(EINVAL);
diff --git a/libswresample/swresample.h b/libswresample/swresample.h
index c7b84fbcac..c6ff2345e9 100644
--- a/libswresample/swresample.h
+++ b/libswresample/swresample.h
@@ -227,6 +227,7 @@  int swr_init(struct SwrContext *s);
  */
 int swr_is_initialized(struct SwrContext *s);
 
+#if FF_API_OLD_CHANNEL_LAYOUT
 /**
  * Allocate SwrContext if needed and set/reset common parameters.
  *
@@ -246,12 +247,40 @@  int swr_is_initialized(struct SwrContext *s);
  *
  * @see swr_init(), swr_free()
  * @return NULL on error, allocated context otherwise
+ * @deprecated use @ref swr_alloc_set_opts2()
  */
+attribute_deprecated
 struct SwrContext *swr_alloc_set_opts(struct SwrContext *s,
                                       int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
                                       int64_t  in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
                                       int log_offset, void *log_ctx);
+#endif
 
+/**
+ * Allocate SwrContext if needed and set/reset common parameters.
+ *
+ * This function does not require s to be allocated with swr_alloc(). On the
+ * other hand, swr_alloc() can use swr_alloc_set_opts() to set the parameters
+ * on the allocated context.
+ *
+ * @param ps              Pointer to an existing Swr context if available, or to NULL if not.
+ *                        On success, *ps will be set the allocated context.
+ * @param out_ch_layout   output channel layout (AV_CH_LAYOUT_*)
+ * @param out_sample_fmt  output sample format (AV_SAMPLE_FMT_*).
+ * @param out_sample_rate output sample rate (frequency in Hz)
+ * @param in_ch_layout    input channel layout (AV_CH_LAYOUT_*)
+ * @param in_sample_fmt   input sample format (AV_SAMPLE_FMT_*).
+ * @param in_sample_rate  input sample rate (frequency in Hz)
+ * @param log_offset      logging level offset
+ * @param log_ctx         parent logging context, can be NULL
+ *
+ * @see swr_init(), swr_free()
+ * @return 0 on success, a negative AVERROR code on error.
+ */
+int swr_alloc_set_opts2(struct SwrContext **ps,
+                        AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
+                        AVChannelLayout *in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
+                        int log_offset, void *log_ctx);
 /**
  * @}
  *
@@ -362,6 +391,7 @@  int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensatio
  */
 int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map);
 
+#if FF_API_OLD_CHANNEL_LAYOUT
 /**
  * Generate a channel mixing matrix.
  *
@@ -384,13 +414,46 @@  int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map);
  * @param matrix_encoding     matrixed stereo downmix mode (e.g. dplii)
  * @param log_ctx             parent logging context, can be NULL
  * @return                    0 on success, negative AVERROR code on failure
+ * @deprecated                use @ref swr_build_matrix2()
  */
+attribute_deprecated
 int swr_build_matrix(uint64_t in_layout, uint64_t out_layout,
                      double center_mix_level, double surround_mix_level,
                      double lfe_mix_level, double rematrix_maxval,
                      double rematrix_volume, double *matrix,
                      int stride, enum AVMatrixEncoding matrix_encoding,
                      void *log_ctx);
+#endif
+
+/**
+ * Generate a channel mixing matrix.
+ *
+ * This function is the one used internally by libswresample for building the
+ * default mixing matrix. It is made public just as a utility function for
+ * building custom matrices.
+ *
+ * @param in_layout           input channel layout
+ * @param out_layout          output channel layout
+ * @param center_mix_level    mix level for the center channel
+ * @param surround_mix_level  mix level for the surround channel(s)
+ * @param lfe_mix_level       mix level for the low-frequency effects channel
+ * @param rematrix_maxval     if 1.0, coefficients will be normalized to prevent
+ *                            overflow. if INT_MAX, coefficients will not be
+ *                            normalized.
+ * @param[out] matrix         mixing coefficients; matrix[i + stride * o] is
+ *                            the weight of input channel i in output channel o.
+ * @param stride              distance between adjacent input channels in the
+ *                            matrix array
+ * @param matrix_encoding     matrixed stereo downmix mode (e.g. dplii)
+ * @param log_ctx             parent logging context, can be NULL
+ * @return                    0 on success, negative AVERROR code on failure
+ */
+int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout,
+                      double center_mix_level, double surround_mix_level,
+                      double lfe_mix_level, double maxval,
+                      double rematrix_volume, double *matrix_param,
+                      ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding,
+                      void *log_context);
 
 /**
  * Set a customized remix matrix.
diff --git a/libswresample/swresample_frame.c b/libswresample/swresample_frame.c
index d95c1cc537..747cf119a9 100644
--- a/libswresample/swresample_frame.c
+++ b/libswresample/swresample_frame.c
@@ -29,7 +29,19 @@  int swr_config_frame(SwrContext *s, const AVFrame *out, const AVFrame *in)
     swr_close(s);
 
     if (in) {
-        if (av_opt_set_int(s, "icl", in->channel_layout, 0) < 0)
+        AVChannelLayout in_ch_layout = { 0 };
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+        // if the old/new fields are set inconsistently, prefer the old ones
+        if ((in->channel_layout && (in->ch_layout.order != AV_CHANNEL_ORDER_NATIVE ||
+                                    in->ch_layout.u.mask != in->channel_layout))) {
+            av_channel_layout_from_mask(&in_ch_layout, in->channel_layout);
+FF_ENABLE_DEPRECATION_WARNINGS
+        } else
+#endif
+        if (av_channel_layout_copy(&in_ch_layout, &in->ch_layout) < 0)
+            goto fail;
+        if (av_opt_set_chlayout(s, "ichl", &in_ch_layout, 0) < 0)
             goto fail;
         if (av_opt_set_int(s, "isf", in->format, 0) < 0)
             goto fail;
@@ -38,7 +50,19 @@  int swr_config_frame(SwrContext *s, const AVFrame *out, const AVFrame *in)
     }
 
     if (out) {
-        if (av_opt_set_int(s, "ocl", out->channel_layout, 0) < 0)
+        AVChannelLayout out_ch_layout = { 0 };
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+        // if the old/new fields are set inconsistently, prefer the old ones
+        if ((out->channel_layout && (out->ch_layout.order != AV_CHANNEL_ORDER_NATIVE ||
+                                     out->ch_layout.u.mask != out->channel_layout))) {
+            av_channel_layout_from_mask(&out_ch_layout, out->channel_layout);
+FF_ENABLE_DEPRECATION_WARNINGS
+        } else
+#endif
+        if (av_channel_layout_copy(&out_ch_layout, &out->ch_layout) < 0)
+            goto fail;
+        if (av_opt_set_chlayout(s, "ochl", &out_ch_layout, 0) < 0)
             goto fail;
         if (av_opt_set_int(s, "osf", out->format,  0) < 0)
             goto fail;
@@ -58,7 +82,19 @@  static int config_changed(SwrContext *s,
     int ret = 0;
 
     if (in) {
-        if (s->in_ch_layout   != in->channel_layout ||
+        AVChannelLayout in_ch_layout = { 0 };
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+        // if the old/new fields are set inconsistently, prefer the old ones
+        if ((in->channel_layout && (in->ch_layout.order != AV_CHANNEL_ORDER_NATIVE ||
+                                    in->ch_layout.u.mask != in->channel_layout))) {
+            av_channel_layout_from_mask(&in_ch_layout, in->channel_layout);
+FF_ENABLE_DEPRECATION_WARNINGS
+        } else
+#endif
+        if ((ret = av_channel_layout_copy(&in_ch_layout, &in->ch_layout)) < 0)
+            return ret;
+        if (av_channel_layout_compare(&s->in_ch_layout, &in_ch_layout) ||
             s->in_sample_rate != in->sample_rate ||
             s->in_sample_fmt  != in->format) {
             ret |= AVERROR_INPUT_CHANGED;
@@ -66,7 +102,19 @@  static int config_changed(SwrContext *s,
     }
 
     if (out) {
-        if (s->out_ch_layout   != out->channel_layout ||
+        AVChannelLayout out_ch_layout = { 0 };
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+        // if the old/new fields are set inconsistently, prefer the old ones
+        if ((out->channel_layout && (out->ch_layout.order != AV_CHANNEL_ORDER_NATIVE ||
+                                     out->ch_layout.u.mask != out->channel_layout))) {
+            av_channel_layout_from_mask(&out_ch_layout, out->channel_layout);
+FF_ENABLE_DEPRECATION_WARNINGS
+        } else
+#endif
+        if ((ret = av_channel_layout_copy(&out_ch_layout, &out->ch_layout)) < 0)
+            return ret;
+        if (av_channel_layout_compare(&s->out_ch_layout, &out_ch_layout) ||
             s->out_sample_rate != out->sample_rate ||
             s->out_sample_fmt  != out->format) {
             ret |= AVERROR_OUTPUT_CHANGED;
@@ -116,7 +164,14 @@  static inline int available_samples(AVFrame *out)
     if (av_sample_fmt_is_planar(out->format)) {
         return samples;
     } else {
-        int channels = av_get_channel_layout_nb_channels(out->channel_layout);
+        int channels;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+        channels = av_get_channel_layout_nb_channels(out->channel_layout);
+FF_ENABLE_DEPRECATION_WARNINGS
+        if (!channels)
+#endif
+        channels = out->ch_layout.nb_channels;
         return samples / channels;
     }
 }
diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h
index f2ea5a226d..262a0e2b8c 100644
--- a/libswresample/swresample_internal.h
+++ b/libswresample/swresample_internal.h
@@ -99,8 +99,8 @@  struct SwrContext {
     enum AVSampleFormat  in_sample_fmt;             ///< input sample format
     enum AVSampleFormat int_sample_fmt;             ///< internal sample format (AV_SAMPLE_FMT_FLTP or AV_SAMPLE_FMT_S16P)
     enum AVSampleFormat out_sample_fmt;             ///< output sample format
-    int64_t  in_ch_layout;                          ///< input channel layout
-    int64_t out_ch_layout;                          ///< output channel layout
+    AVChannelLayout  in_ch_layout;                  ///< input channel layout
+    AVChannelLayout out_ch_layout;                  ///< output channel layout
     int      in_sample_rate;                        ///< input sample rate
     int     out_sample_rate;                        ///< output sample rate
     int flags;                                      ///< miscellaneous flags such as SWR_FLAG_RESAMPLE
@@ -114,11 +114,15 @@  struct SwrContext {
     int used_ch_count;                              ///< number of used input channels (mapped channel count if channel_map, otherwise in.ch_count)
     int engine;
 
+    int user_used_ch_count;                         ///< User set used channel count
+#if FF_API_OLD_CHANNEL_LAYOUT
     int user_in_ch_count;                           ///< User set input channel count
     int user_out_ch_count;                          ///< User set output channel count
-    int user_used_ch_count;                         ///< User set used channel count
     int64_t user_in_ch_layout;                      ///< User set input channel layout
     int64_t user_out_ch_layout;                     ///< User set output channel layout
+#endif
+    AVChannelLayout user_in_chlayout;               ///< User set input channel layout
+    AVChannelLayout user_out_chlayout;              ///< User set output channel layout
     enum AVSampleFormat user_int_sample_fmt;        ///< User set internal sample format
     int user_dither_method;                         ///< User set dither method