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 <jamrial@gmail.com>
This commit is contained in:
James Almer 2023-02-17 15:41:56 -03:00
parent 1d14959f12
commit 223c70cf1d
6 changed files with 46 additions and 29 deletions

View File

@ -11,8 +11,8 @@ programmatic use.
@table @option @table @option
@item uch, used_channel_count @item uchl, used_chlayout
Set the number of used input channels. Default value is 0. This option is Set used input channel layout. Default is unset. This option is
only used for special remapping. only used for special remapping.
@item isr, in_sample_rate @item isr, in_sample_rate

View File

@ -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}, 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)", {"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}, 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 #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}, {"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}, {"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}, {"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"}, {"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"}, {"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"}, {"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}, {"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}, {"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}, {"slev" , "set surround mix level" , OFFSET(slev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM},

View File

@ -492,7 +492,7 @@ av_cold static int auto_matrix(SwrContext *s)
av_cold int swri_rematrix_init(SwrContext *s){ av_cold int swri_rematrix_init(SwrContext *s){
int i, j; 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; int nb_out = s->out.ch_count;
s->mix_any_f = NULL; s->mix_any_f = NULL;

View File

@ -161,6 +161,7 @@ static void clear_context(SwrContext *s){
free_temp(&s->dither.temp); free_temp(&s->dither.temp);
av_channel_layout_uninit(&s->in_ch_layout); av_channel_layout_uninit(&s->in_ch_layout);
av_channel_layout_uninit(&s->out_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-> in_convert);
swri_audio_convert_free(&s->out_convert); swri_audio_convert_free(&s->out_convert);
swri_audio_convert_free(&s->full_convert); swri_audio_convert_free(&s->full_convert);
@ -176,6 +177,7 @@ av_cold void swr_free(SwrContext **ss){
clear_context(s); clear_context(s);
av_channel_layout_uninit(&s->user_in_chlayout); av_channel_layout_uninit(&s->user_in_chlayout);
av_channel_layout_uninit(&s->user_out_chlayout); av_channel_layout_uninit(&s->user_out_chlayout);
av_channel_layout_uninit(&s->user_used_chlayout);
if (s->resampler) if (s->resampler)
s->resampler->free(&s->resample); 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); av_log(s, AV_LOG_ERROR, "Requested output sample rate %d is invalid\n", s->out_sample_rate);
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
s->used_ch_count = s->user_used_ch_count;
#if FF_API_OLD_CHANNEL_LAYOUT #if FF_API_OLD_CHANNEL_LAYOUT
s->out.ch_count = s-> user_out_ch_count; s->out.ch_count = s-> user_out_ch_count;
s-> in.ch_count = s-> user_in_ch_count; s-> in.ch_count = s-> user_in_ch_count;
// if the old/new fields are set inconsistently, prefer the old ones // 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) || 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_ch_layout && (s->user_in_chlayout.order != AV_CHANNEL_ORDER_NATIVE ||
s->user_in_chlayout.u.mask != s->user_in_ch_layout))) { 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)) } else if (av_channel_layout_check(&s->user_out_chlayout))
av_channel_layout_copy(&s->out_ch_layout, &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; 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; 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) { 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->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->out_ch_layout, &s->user_out_chlayout);
ret |= av_channel_layout_copy(&s->used_ch_layout, &s->user_used_chlayout);
if (ret < 0) if (ret < 0)
return ret; return ret;
#endif #endif
@ -299,16 +310,19 @@ av_cold int swr_init(struct SwrContext *s){
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
if(!s->used_ch_count) if (!av_channel_layout_check(&s->used_ch_layout))
s->used_ch_count= s->in.ch_count; 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) { if (s->used_ch_layout.nb_channels != 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");
av_channel_layout_uninit(&s->in_ch_layout); av_channel_layout_uninit(&s->in_ch_layout);
}
if (s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) if (s->used_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
av_channel_layout_default(&s->in_ch_layout, s->used_ch_count); 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) if (s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
av_channel_layout_default(&s->out_ch_layout, s->out.ch_count); 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 #define RSC 1 //FIXME finetune
if(!s-> in.ch_count) if(!s-> in.ch_count)
s-> in.ch_count = s->in_ch_layout.nb_channels; s-> in.ch_count = s->in_ch_layout.nb_channels;
if(!s->used_ch_count) if (!av_channel_layout_check(&s->used_ch_layout))
s->used_ch_count= s->in.ch_count; av_channel_layout_default(&s->used_ch_layout, s->in.ch_count);
if(!s->out.ch_count) if(!s->out.ch_count)
s->out.ch_count = s->out_ch_layout.nb_channels; s->out.ch_count = s->out_ch_layout.nb_channels;
@ -410,23 +424,23 @@ av_cold int swr_init(struct SwrContext *s){
} }
#endif #endif
av_channel_layout_describe(&s->in_ch_layout, l1, sizeof(l1)); 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) { 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_count); 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); ret = AVERROR(EINVAL);
goto fail; goto fail;
} }
if (( s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC 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 " 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); "but there is not enough information to do it\n", l1, l2);
ret = AVERROR(EINVAL); ret = AVERROR(EINVAL);
goto fail; goto fail;
} }
av_assert0(s->used_ch_count); av_assert0(s->used_ch_layout.nb_channels);
av_assert0(s->out.ch_count); 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->in_buffer= s->in;
s->silence = 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_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->out_convert= swri_audio_convert_alloc(s->out_sample_fmt,
s->int_sample_fmt, s->out.ch_count, NULL, 0); s->int_sample_fmt, s->out.ch_count, NULL, 0);
@ -457,9 +471,9 @@ av_assert0(s->out.ch_count);
if(s->channel_map){ if(s->channel_map){
s->postin.ch_count= 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) 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){ if(!s->resample_first){
s->midbuf.ch_count= s->out.ch_count; 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) if((ret=swri_realloc_audio(&s->postin, in_count))<0)
return ret; return ret;
if(s->resample_first){ 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) if((ret=swri_realloc_audio(&s->midbuf, out_count))<0)
return ret; return ret;
}else{ }else{

View File

@ -99,6 +99,7 @@ struct SwrContext {
enum AVSampleFormat in_sample_fmt; ///< input sample format 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 int_sample_fmt; ///< internal sample format (AV_SAMPLE_FMT_FLTP or AV_SAMPLE_FMT_S16P)
enum AVSampleFormat out_sample_fmt; ///< output sample format 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 in_ch_layout; ///< input channel layout
AVChannelLayout out_ch_layout; ///< output channel layout AVChannelLayout out_ch_layout; ///< output channel layout
int in_sample_rate; ///< input sample rate int in_sample_rate; ///< input sample rate
@ -111,16 +112,16 @@ struct SwrContext {
float rematrix_maxval; ///< maximum value for rematrixing output float rematrix_maxval; ///< maximum value for rematrixing output
int matrix_encoding; /**< matrixed stereo encoding */ int matrix_encoding; /**< matrixed stereo encoding */
const int *channel_map; ///< channel index (or -1 if muted channel) map 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 engine;
int user_used_ch_count; ///< User set used channel count
#if FF_API_OLD_CHANNEL_LAYOUT #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_in_ch_count; ///< User set input channel count
int user_out_ch_count; ///< User set output 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_in_ch_layout; ///< User set input channel layout
int64_t user_out_ch_layout; ///< User set output channel layout int64_t user_out_ch_layout; ///< User set output channel layout
#endif #endif
AVChannelLayout user_used_chlayout; ///< User set used channel layout
AVChannelLayout user_in_chlayout; ///< User set input channel layout AVChannelLayout user_in_chlayout; ///< User set input channel layout
AVChannelLayout user_out_chlayout; ///< User set output channel layout AVChannelLayout user_out_chlayout; ///< User set output channel layout
enum AVSampleFormat user_int_sample_fmt; ///< User set internal sample format enum AVSampleFormat user_int_sample_fmt; ///< User set internal sample format

View File

@ -33,7 +33,7 @@ D(int16, sse2)
av_cold int swri_rematrix_init_x86(struct SwrContext *s){ av_cold int swri_rematrix_init_x86(struct SwrContext *s){
#if HAVE_X86ASM #if HAVE_X86ASM
int mm_flags = av_get_cpu_flags(); 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 nb_out = s->out.ch_count;
int num = nb_in * nb_out; int num = nb_in * nb_out;
int i,j; int i,j;