From 8a5896ec1f635ccf0d726f7ba7a06649ebeebf25 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 27 Aug 2021 00:37:53 -0300 Subject: swresample: convert to new channel layout API Signed-off-by: James Almer --- libswresample/rematrix.c | 232 +++++++++++++++++++++++++++++++---------------- 1 file changed, 153 insertions(+), 79 deletions(-) (limited to 'libswresample/rematrix.c') diff --git a/libswresample/rematrix.c b/libswresample/rematrix.c index 94b3de88f6..37e8c2ef4b 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,140 @@ 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); + 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( out_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX - && (in_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0 - ) - out_ch_layout = AV_CH_LAYOUT_STEREO; - - 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= 0 + && av_channel_layout_index_from_channel(&out_ch_layout, i) >= 0) 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 +254,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 +284,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 +316,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 +324,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 +352,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 +360,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 +371,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 +383,17 @@ 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<= 0 + && av_channel_layout_index_from_channel(&out_ch_layout, i) >= 0); sum += fabs(matrix_param[stride*out_i + in_i]); in_i++; } @@ -350,17 +419,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; imatrix, 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 +593,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_ich_count; out_i++){ switch(s->matrix_ch[out_i][0]){ -- cgit v1.2.3