From 223c70cf1d8b816b59dede36a21492d7e8542e06 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 17 Feb 2023 15:41:56 -0300 Subject: [PATCH] swresample/swresample: add a used channel layout option using the new API Replaces the "used channel count" option, which is now deprecated. Signed-off-by: James Almer --- doc/resampler.texi | 4 +-- libswresample/options.c | 6 ++-- libswresample/rematrix.c | 2 +- libswresample/swresample.c | 56 ++++++++++++++++++----------- libswresample/swresample_internal.h | 5 +-- libswresample/x86/rematrix_init.c | 2 +- 6 files changed, 46 insertions(+), 29 deletions(-) diff --git a/doc/resampler.texi b/doc/resampler.texi index d55654e7bc..a6224eefb3 100644 --- a/doc/resampler.texi +++ b/doc/resampler.texi @@ -11,8 +11,8 @@ programmatic use. @table @option -@item uch, used_channel_count -Set the number of used input channels. Default value is 0. This option is +@item uchl, used_chlayout +Set used input channel layout. Default is unset. This option is only used for special remapping. @item isr, in_sample_rate diff --git a/libswresample/options.c b/libswresample/options.c index ffa27c590d..fb109fdbab 100644 --- a/libswresample/options.c +++ b/libswresample/options.c @@ -46,9 +46,9 @@ static const AVOption options[]={ 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}, +{"uch" , "set used channel count" , OFFSET(user_used_ch_count), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM|DEPREC}, +{"used_channel_count" , "set used channel count" , OFFSET(user_used_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}, {"in_sample_rate" , "set input sample rate" , OFFSET( in_sample_rate), AV_OPT_TYPE_INT , {.i64=0 }, 0 , INT_MAX , PARAM}, {"osr" , "set output sample rate" , OFFSET(out_sample_rate), AV_OPT_TYPE_INT , {.i64=0 }, 0 , INT_MAX , PARAM}, @@ -73,6 +73,8 @@ static const AVOption options[]={ {"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"}, +{"uchl" , "set used channel layout" , OFFSET(user_used_chlayout), AV_OPT_TYPE_CHLAYOUT, {.str=NULL }, 0, 0 , PARAM, "chlayout"}, +{"used_chlayout" , "set used channel layout" , OFFSET(user_used_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 0c3fff6c42..79e8a43eac 100644 --- a/libswresample/rematrix.c +++ b/libswresample/rematrix.c @@ -492,7 +492,7 @@ av_cold static int auto_matrix(SwrContext *s) av_cold int swri_rematrix_init(SwrContext *s){ int i, j; - int nb_in = s->used_ch_count; + int nb_in = s->used_ch_layout.nb_channels; int nb_out = s->out.ch_count; s->mix_any_f = NULL; diff --git a/libswresample/swresample.c b/libswresample/swresample.c index 5884f8d533..6dc329a9d0 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -161,6 +161,7 @@ static void clear_context(SwrContext *s){ free_temp(&s->dither.temp); av_channel_layout_uninit(&s->in_ch_layout); av_channel_layout_uninit(&s->out_ch_layout); + av_channel_layout_uninit(&s->used_ch_layout); swri_audio_convert_free(&s-> in_convert); swri_audio_convert_free(&s->out_convert); swri_audio_convert_free(&s->full_convert); @@ -176,6 +177,7 @@ av_cold void swr_free(SwrContext **ss){ clear_context(s); av_channel_layout_uninit(&s->user_in_chlayout); av_channel_layout_uninit(&s->user_out_chlayout); + av_channel_layout_uninit(&s->user_used_chlayout); if (s->resampler) s->resampler->free(&s->resample); @@ -211,12 +213,20 @@ 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; // if the old/new fields are set inconsistently, prefer the old ones + if (s->user_used_ch_count && s->user_used_ch_count != s->user_used_chlayout.nb_channels) { + av_channel_layout_uninit(&s->used_ch_layout); + s->used_ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + s->used_ch_layout.nb_channels = s->user_used_ch_count; + } else if (av_channel_layout_check(&s->user_used_chlayout)) { + ret = av_channel_layout_copy(&s->used_ch_layout, &s->user_used_chlayout); + if (ret < 0) + return ret; + } 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))) { @@ -243,9 +253,9 @@ av_cold int swr_init(struct SwrContext *s){ } else if (av_channel_layout_check(&s->user_out_chlayout)) av_channel_layout_copy(&s->out_ch_layout, &s->user_out_chlayout); - if (!s->out.ch_count && !s->user_out_ch_layout) + if (!s->out.ch_count) s->out.ch_count = s->out_ch_layout.nb_channels; - if (!s-> in.ch_count && !s-> user_in_ch_layout) + if (!s-> in.ch_count) s-> in.ch_count = s->in_ch_layout.nb_channels; if (!(ret = av_channel_layout_check(&s->in_ch_layout)) || s->in_ch_layout.nb_channels > SWR_CH_MAX) { @@ -281,6 +291,7 @@ av_cold int swr_init(struct SwrContext *s){ 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); + ret |= av_channel_layout_copy(&s->used_ch_layout, &s->user_used_chlayout); if (ret < 0) return ret; #endif @@ -299,16 +310,19 @@ av_cold int swr_init(struct SwrContext *s){ return AVERROR(EINVAL); } - if(!s->used_ch_count) - s->used_ch_count= s->in.ch_count; + if (!av_channel_layout_check(&s->used_ch_layout)) + av_channel_layout_default(&s->used_ch_layout, s->in.ch_count); - 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"); + if (s->used_ch_layout.nb_channels != s->in_ch_layout.nb_channels) av_channel_layout_uninit(&s->in_ch_layout); - } - if (s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) - av_channel_layout_default(&s->in_ch_layout, s->used_ch_count); + if (s->used_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) + av_channel_layout_default(&s->used_ch_layout, s->used_ch_layout.nb_channels); + if (s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) { + ret = av_channel_layout_copy(&s->in_ch_layout, &s->used_ch_layout); + if (ret < 0) + return ret; + } if (s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) av_channel_layout_default(&s->out_ch_layout, s->out.ch_count); @@ -389,8 +403,8 @@ av_cold int swr_init(struct SwrContext *s){ #define RSC 1 //FIXME finetune if(!s-> in.ch_count) s-> in.ch_count = s->in_ch_layout.nb_channels; - if(!s->used_ch_count) - s->used_ch_count= s->in.ch_count; + if (!av_channel_layout_check(&s->used_ch_layout)) + av_channel_layout_default(&s->used_ch_layout, s->in.ch_count); if(!s->out.ch_count) s->out.ch_count = s->out_ch_layout.nb_channels; @@ -410,23 +424,23 @@ av_cold int swr_init(struct SwrContext *s){ } #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); + if (s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_layout.nb_channels != 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_layout.nb_channels); ret = AVERROR(EINVAL); goto fail; } 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) { + || s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) && s->used_ch_layout.nb_channels != 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); goto fail; } -av_assert0(s->used_ch_count); +av_assert0(s->used_ch_layout.nb_channels); av_assert0(s->out.ch_count); - s->resample_first= RSC*s->out.ch_count/s->used_ch_count - RSC < s->out_sample_rate/(float)s-> in_sample_rate - 1.0; + s->resample_first= RSC*s->out.ch_count/s->used_ch_layout.nb_channels - RSC < s->out_sample_rate/(float)s-> in_sample_rate - 1.0; s->in_buffer= s->in; s->silence = s->in; @@ -442,7 +456,7 @@ av_assert0(s->out.ch_count); } s->in_convert = swri_audio_convert_alloc(s->int_sample_fmt, - s-> in_sample_fmt, s->used_ch_count, s->channel_map, 0); + s-> in_sample_fmt, s->used_ch_layout.nb_channels, s->channel_map, 0); s->out_convert= swri_audio_convert_alloc(s->out_sample_fmt, s->int_sample_fmt, s->out.ch_count, NULL, 0); @@ -457,9 +471,9 @@ av_assert0(s->out.ch_count); if(s->channel_map){ s->postin.ch_count= - s->midbuf.ch_count= s->used_ch_count; + s->midbuf.ch_count= s->used_ch_layout.nb_channels; if(s->resample) - s->in_buffer.ch_count= s->used_ch_count; + s->in_buffer.ch_count= s->used_ch_layout.nb_channels; } if(!s->resample_first){ s->midbuf.ch_count= s->out.ch_count; @@ -697,7 +711,7 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co if((ret=swri_realloc_audio(&s->postin, in_count))<0) return ret; if(s->resample_first){ - av_assert0(s->midbuf.ch_count == s->used_ch_count); + av_assert0(s->midbuf.ch_count == s->used_ch_layout.nb_channels); if((ret=swri_realloc_audio(&s->midbuf, out_count))<0) return ret; }else{ diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h index 262a0e2b8c..ad902d73fa 100644 --- a/libswresample/swresample_internal.h +++ b/libswresample/swresample_internal.h @@ -99,6 +99,7 @@ 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 + AVChannelLayout used_ch_layout; ///< number of used input channels (mapped channel count if channel_map, otherwise in.ch_count) AVChannelLayout in_ch_layout; ///< input channel layout AVChannelLayout out_ch_layout; ///< output channel layout int in_sample_rate; ///< input sample rate @@ -111,16 +112,16 @@ struct SwrContext { float rematrix_maxval; ///< maximum value for rematrixing output int matrix_encoding; /**< matrixed stereo encoding */ const int *channel_map; ///< channel index (or -1 if muted channel) map - 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_used_ch_count; ///< User set used channel count int user_in_ch_count; ///< User set input channel count int user_out_ch_count; ///< User set output 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_used_chlayout; ///< User set used channel layout 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 diff --git a/libswresample/x86/rematrix_init.c b/libswresample/x86/rematrix_init.c index b6ed38bf67..ce794eef90 100644 --- a/libswresample/x86/rematrix_init.c +++ b/libswresample/x86/rematrix_init.c @@ -33,7 +33,7 @@ D(int16, sse2) av_cold int swri_rematrix_init_x86(struct SwrContext *s){ #if HAVE_X86ASM int mm_flags = av_get_cpu_flags(); - int nb_in = s->used_ch_count; + int nb_in = s->used_ch_layout.nb_channels; int nb_out = s->out.ch_count; int num = nb_in * nb_out; int i,j;