diff --git a/libswresample/rematrix.c b/libswresample/rematrix.c index 3bec10360e..31b1078bcc 100644 --- a/libswresample/rematrix.c +++ b/libswresample/rematrix.c @@ -697,7 +697,8 @@ av_cold static int auto_matrix(SwrContext *s) if (s->rematrix_maxval > 0) { maxval = s->rematrix_maxval; } else if ( av_get_packed_sample_fmt(s->out_sample_fmt) < AV_SAMPLE_FMT_FLT - || av_get_packed_sample_fmt(s->int_sample_fmt) < AV_SAMPLE_FMT_FLT) { + || (s->user_int_sample_fmt != AV_SAMPLE_FMT_NONE && + av_get_packed_sample_fmt(s->user_int_sample_fmt) < AV_SAMPLE_FMT_FLT)) { maxval = 1.0; } else maxval = INT_MAX; @@ -709,13 +710,12 @@ av_cold static int auto_matrix(SwrContext *s) s->matrix[1] - s->matrix[0], s->matrix_encoding, s); } -av_cold int swri_rematrix_init(SwrContext *s){ +av_cold int swri_rematrix_build(SwrContext *s) +{ int i, j; int nb_in = s->used_ch_layout.nb_channels; int nb_out = s->out.ch_count; - s->mix_any_f = NULL; - if (!s->rematrix_custom) { int r = auto_matrix(s); if (r) @@ -735,6 +735,34 @@ av_cold int swri_rematrix_init(SwrContext *s){ av_log(s, AV_LOG_DEBUG, "\n"); } } + + /* a channel that is one channel of the input, or silent, is not mixed */ + for (i = 0; i < nb_out; i++) { + int sources = 0; + for (j = 0; j < nb_in; j++) { + if (s->matrix[i][j] == 0.0) + continue; + if (s->matrix[i][j] != 1.0 || sources++) + return 1; + } + } + + return 0; +} + +av_cold int swri_rematrix_init(SwrContext *s){ + int i, j; + int nb_in = s->used_ch_layout.nb_channels; + int nb_out = s->out.ch_count; + + s->mix_any_f = NULL; + + /* a matrix that is applied was built by swri_rematrix_build() */ + if (!s->rematrix) { + int r = auto_matrix(s); + if (r) + return r; + } if (s->midbuf.fmt == AV_SAMPLE_FMT_S16P){ int maxsum = 0; s->native_matrix = av_calloc(nb_in * nb_out, sizeof(int)); diff --git a/libswresample/swresample.c b/libswresample/swresample.c index 3fa2f3bf6c..cd84c731d9 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -154,7 +154,7 @@ av_cold void swr_close(SwrContext *s){ } av_cold int swr_init(struct SwrContext *s){ - int ret; + int ret, mixing; char l1[1024], l2[1024]; clear_context(s); @@ -232,6 +232,24 @@ av_cold int swr_init(struct SwrContext *s){ s->rematrix_volume!=1.0 || s->rematrix_custom; + av_channel_layout_describe(&s->out_ch_layout, l2, sizeof(l2)); + av_channel_layout_describe(&s->in_ch_layout, l1, sizeof(l1)); + if (( s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC + || 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); + return AVERROR(EINVAL); + } + + /* a matrix that only copies channels leaves the samples as they are, + * so the format in between is selected like without a matrix */ + mixing = 0; + if (s->rematrix) { + mixing = swri_rematrix_build(s); + if (mixing < 0) + return mixing; + } + if(s->int_sample_fmt == AV_SAMPLE_FMT_NONE){ // DSD to PCM conversion is done in floating point if( s->in_sample_fmt == AV_SAMPLE_FMT_DSD @@ -247,13 +265,13 @@ av_cold int swr_init(struct SwrContext *s){ +av_get_bytes_per_sample(s->out_sample_fmt) <= 3 ) { s->int_sample_fmt= AV_SAMPLE_FMT_S16P; }else if( av_get_bytes_per_sample(s-> in_sample_fmt) <= 2 - && !s->rematrix + && !mixing && s->out_sample_rate==s->in_sample_rate && !(s->flags & SWR_FLAG_RESAMPLE)){ s->int_sample_fmt= AV_SAMPLE_FMT_S16P; }else if( av_get_planar_sample_fmt(s-> in_sample_fmt) == AV_SAMPLE_FMT_S32P && av_get_planar_sample_fmt(s->out_sample_fmt) == AV_SAMPLE_FMT_S32P - && !s->rematrix + && !mixing && s->out_sample_rate == s->in_sample_rate && !(s->flags & SWR_FLAG_RESAMPLE) && s->engine != SWR_ENGINE_SOXR){ @@ -328,22 +346,12 @@ av_cold int swr_init(struct SwrContext *s){ goto fail; } - av_channel_layout_describe(&s->out_ch_layout, l2, sizeof(l2)); - av_channel_layout_describe(&s->in_ch_layout, l1, sizeof(l1)); 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_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_layout.nb_channels); av_assert0(s->out.ch_count); 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; diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h index 0cde2760bb..dcfb5335e7 100644 --- a/libswresample/swresample_internal.h +++ b/libswresample/swresample_internal.h @@ -207,6 +207,8 @@ void swri_noise_shaping_int32 (SwrContext *s, AudioData *dsts, const AudioData * void swri_noise_shaping_float (SwrContext *s, AudioData *dsts, const AudioData *srcs, const AudioData *noises, int count); void swri_noise_shaping_double(SwrContext *s, AudioData *dsts, const AudioData *srcs, const AudioData *noises, int count); +av_warn_unused_result +int swri_rematrix_build(SwrContext *s); av_warn_unused_result int swri_rematrix_init(SwrContext *s); void swri_rematrix_free(SwrContext *s); diff --git a/libswresample/version.h b/libswresample/version.h index d1795b5545..403be6227a 100644 --- a/libswresample/version.h +++ b/libswresample/version.h @@ -31,7 +31,7 @@ #include "version_major.h" #define LIBSWRESAMPLE_VERSION_MINOR 3 -#define LIBSWRESAMPLE_VERSION_MICRO 100 +#define LIBSWRESAMPLE_VERSION_MICRO 101 #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ LIBSWRESAMPLE_VERSION_MINOR, \ diff --git a/tests/fate/libswresample.mak b/tests/fate/libswresample.mak index 27a48a790b..19408e6567 100644 --- a/tests/fate/libswresample.mak +++ b/tests/fate/libswresample.mak @@ -1106,6 +1106,16 @@ fate-swr-custom-rematrix: REF = 2a14a44deb4ae26e3b474ddbfbc048f8 FATE_SWR += $(FATE_SWR_CUSTOM_REMATRIX-yes) +FATE_SWR_S32_SRC = mod(n*$(1)\,4294967296)/2147483648-1 +FATE_SWR_S32_7_1 = $(call FATE_SWR_S32_SRC,1103515245)|$(call FATE_SWR_S32_SRC,22695477)|$(call FATE_SWR_S32_SRC,214013)|$(call FATE_SWR_S32_SRC,1664525)|$(call FATE_SWR_S32_SRC,134775813)|$(call FATE_SWR_S32_SRC,69069)|$(call FATE_SWR_S32_SRC,1812433253)|$(call FATE_SWR_S32_SRC,2654435761) + +FATE_SWR_CUSTOM_REORDER-$(call ENCMUX, PCM_S32LE, PCM_S32LE, AEVALSRC_FILTER ARESAMPLE_FILTER AFORMAT_FILTER FILE_PROTOCOL) += fate-swr-custom-reorder +fate-swr-custom-reorder: CMD = md5 -filter_complex "aevalsrc=$(FATE_SWR_S32_7_1):c=7.1:d=0.5,aresample,aformat=f=s32:cl=7.1,aresample,aformat=f=s32:cl=FR+FL+FC+LFE+SL+SR+BL+BR[OUT]" -map [OUT] -f s32le +fate-swr-custom-reorder: CMP = oneline +fate-swr-custom-reorder: REF = 3621f90f05eb313858791b3915b9ca18 + +FATE_SWR += $(FATE_SWR_CUSTOM_REORDER-yes) + FATE_SWR_22_2_LAYOUTS = 9.1.6 9.1.4 7.2.3 7.1.6 7.1.4 7.1.2 5.1.6 5.1.4 5.1.2 7.1 5.1 stereo mono FATE_SWR_9_1_6_LAYOUTS = 9.1.4 7.2.3 7.1.6 7.1.4 7.1.2 5.1.6 5.1.4 5.1.2 7.1 5.1 stereo mono FATE_SWR_9_1_4_LAYOUTS = 7.2.3 7.1.4 7.1.2 5.1.4 5.1.2 7.1 5.1 stereo mono