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

James Almer jamrial at gmail.com
Wed Jan 19 19:29:24 EET 2022


On 1/19/2022 2:20 PM, Andreas Rheinhardt wrote:
> James Almer:
>> Signed-off-by: James Almer <jamrial at 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 at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".


More information about the ffmpeg-devel mailing list