You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	swresample: convert to new channel layout API
Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
		| @@ -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}, | ||||
|   | ||||
| @@ -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))) { | ||||
|         char buf[128]; | ||||
|         av_get_channel_layout_string(buf, sizeof(buf), -1, layout); | ||||
|         av_log(s, AV_LOG_VERBOSE, "Treating %s as mono\n", buf); | ||||
|         return AV_CH_FRONT_CENTER; | ||||
|     } | ||||
| static int clean_layout(AVChannelLayout *out, const AVChannelLayout *in, void *s) | ||||
| { | ||||
|     int ret = 0; | ||||
|  | ||||
|     return layout; | ||||
|     if(av_channel_layout_index_from_channel(in, AV_CH_FRONT_CENTER) < 0 && in->nb_channels == 1) { | ||||
|         char buf[128]; | ||||
|         av_channel_layout_describe(in, buf, sizeof(buf)); | ||||
|         av_log(s, AV_LOG_VERBOSE, "Treating %s as mono\n", buf); | ||||
|         *out = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; | ||||
|     } else | ||||
|         ret = av_channel_layout_copy(out, in); | ||||
|  | ||||
|     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(!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT))) // no asymetric front | ||||
|     if(!av_channel_layout_subset(ch_layout, AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker | ||||
|         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_FRONT_LEFT | AV_CH_FRONT_RIGHT)))) // no asymetric front | ||||
|         return 0; | ||||
|     if(!even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT))) | ||||
|     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_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER))) | ||||
|     if(!even(av_channel_layout_subset(ch_layout, (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)))) | ||||
|         return 0; | ||||
|     if(av_get_channel_layout_nb_channels(layout) >= SWR_CH_MAX) | ||||
|     if(!even(av_channel_layout_subset(ch_layout, (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)))) | ||||
|         return 0; | ||||
|     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<FF_ARRAY_ELEMS(matrix); i++){ | ||||
|         if(in_ch_layout & out_ch_layout & (1ULL<<i)) | ||||
|         if(   av_channel_layout_index_from_channel(&in_ch_layout, 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<<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)); | ||||
|                 matrix_param[stride*out_i + in_i] = i == j && | ||||
|                 (   av_channel_layout_index_from_channel(&in_ch_layout, i) >= 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; 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 +451,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 +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_i<out->ch_count; out_i++){ | ||||
|         switch(s->matrix_ch[out_i][0]){ | ||||
|   | ||||
| @@ -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] | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|     *ps = s; | ||||
|  | ||||
|     s->log_level_offset = log_offset; | ||||
|     s->log_ctx = log_ctx; | ||||
|  | ||||
|     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 | ||||
|  | ||||
|     return 0; | ||||
| fail: | ||||
|     av_log(s, AV_LOG_ERROR, "Failed to set option\n"); | ||||
|     swr_free(ps); | ||||
|     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); | ||||
|   | ||||
| @@ -34,11 +34,11 @@ | ||||
|  * Audio resampling, sample format conversion and mixing library. | ||||
|  * | ||||
|  * Interaction with lswr is done through SwrContext, which is | ||||
|  * allocated with swr_alloc() or swr_alloc_set_opts(). It is opaque, so all parameters | ||||
|  * allocated with swr_alloc() or swr_alloc_set_opts2(). It is opaque, so all parameters | ||||
|  * must be set with the @ref avoptions API. | ||||
|  * | ||||
|  * The first thing you will need to do in order to use lswr is to allocate | ||||
|  * SwrContext. This can be done with swr_alloc() or swr_alloc_set_opts(). If you | ||||
|  * SwrContext. This can be done with swr_alloc() or swr_alloc_set_opts2(). If you | ||||
|  * are using the former, you must set options through the @ref avoptions API. | ||||
|  * The latter function provides the same feature, but it allows you to set some | ||||
|  * common options in the same statement. | ||||
| @@ -57,13 +57,14 @@ | ||||
|  * av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16,  0); | ||||
|  * @endcode | ||||
|  * | ||||
|  * The same job can be done using swr_alloc_set_opts() as well: | ||||
|  * The same job can be done using swr_alloc_set_opts2() as well: | ||||
|  * @code | ||||
|  * SwrContext *swr = swr_alloc_set_opts(NULL,  // we're allocating a new context | ||||
|  *                       AV_CH_LAYOUT_STEREO,  // out_ch_layout | ||||
|  * SwrContext *swr = NULL; | ||||
|  * int ret = swr_alloc_set_opts2(&swr,         // we're allocating a new context | ||||
|  *                       &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO, // out_ch_layout | ||||
|  *                       AV_SAMPLE_FMT_S16,    // out_sample_fmt | ||||
|  *                       44100,                // out_sample_rate | ||||
|  *                       AV_CH_LAYOUT_5POINT1, // in_ch_layout | ||||
|  *                       &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1, // in_ch_layout | ||||
|  *                       AV_SAMPLE_FMT_FLTP,   // in_sample_fmt | ||||
|  *                       48000,                // in_sample_rate | ||||
|  *                       0,                    // log_offset | ||||
| @@ -73,7 +74,7 @@ | ||||
|  * Once all values have been set, it must be initialized with swr_init(). If | ||||
|  * you need to change the conversion parameters, you can change the parameters | ||||
|  * using @ref AVOptions, as described above in the first example; or by using | ||||
|  * swr_alloc_set_opts(), but with the first argument the allocated context. | ||||
|  * swr_alloc_set_opts2(), but with the first argument the allocated context. | ||||
|  * You must then call swr_init() again. | ||||
|  * | ||||
|  * The conversion itself is done by repeatedly calling swr_convert(). | ||||
| @@ -199,9 +200,9 @@ const AVClass *swr_get_class(void); | ||||
|  * Allocate SwrContext. | ||||
|  * | ||||
|  * If you use this function you will need to set the parameters (manually or | ||||
|  * with swr_alloc_set_opts()) before calling swr_init(). | ||||
|  * with swr_alloc_set_opts2()) before calling swr_init(). | ||||
|  * | ||||
|  * @see swr_alloc_set_opts(), swr_init(), swr_free() | ||||
|  * @see swr_alloc_set_opts2(), swr_init(), swr_free() | ||||
|  * @return NULL on error, allocated context otherwise | ||||
|  */ | ||||
| struct SwrContext *swr_alloc(void); | ||||
| @@ -227,6 +228,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 +248,41 @@ 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 *ps to be allocated with swr_alloc(). On the | ||||
|  * other hand, swr_alloc() can use swr_alloc_set_opts2() 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 to the allocated context. | ||||
|  * @param out_ch_layout   output channel layout (e.g. AV_CHANNEL_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 (e.g. AV_CHANNEL_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. | ||||
|  *         On error, the Swr context is freed and *ps set to NULL. | ||||
|  */ | ||||
| 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 +393,40 @@ 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. | ||||
|  * | ||||
|  * 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. | ||||
|  * @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 | ||||
|  * @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. | ||||
|  * | ||||
| @@ -385,12 +450,12 @@ int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map); | ||||
|  * @param log_ctx             parent logging context, can be NULL | ||||
|  * @return                    0 on success, negative AVERROR code on failure | ||||
|  */ | ||||
| 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); | ||||
| 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, | ||||
|                       ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding, | ||||
|                       void *log_context); | ||||
|  | ||||
| /** | ||||
|  * Set a customized remix matrix. | ||||
|   | ||||
| @@ -26,39 +26,79 @@ | ||||
|  | ||||
| int swr_config_frame(SwrContext *s, const AVFrame *out, const AVFrame *in) | ||||
| { | ||||
|     AVChannelLayout ch_layout = { 0 }; | ||||
|     int ret; | ||||
|  | ||||
|     swr_close(s); | ||||
|  | ||||
|     if (in) { | ||||
|         if (av_opt_set_int(s, "icl", in->channel_layout, 0) < 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(&ch_layout, in->channel_layout); | ||||
| FF_ENABLE_DEPRECATION_WARNINGS | ||||
|         } else | ||||
| #endif | ||||
|         if ((ret = av_channel_layout_copy(&ch_layout, &in->ch_layout)) < 0) | ||||
|             goto fail; | ||||
|         if (av_opt_set_int(s, "isf", in->format, 0) < 0) | ||||
|         if ((ret = av_opt_set_chlayout(s, "ichl", &ch_layout, 0)) < 0) | ||||
|             goto fail; | ||||
|         if (av_opt_set_int(s, "isr", in->sample_rate, 0) < 0) | ||||
|         if ((ret = av_opt_set_int(s, "isf", in->format, 0)) < 0) | ||||
|             goto fail; | ||||
|         if ((ret = av_opt_set_int(s, "isr", in->sample_rate, 0)) < 0) | ||||
|             goto fail; | ||||
|     } | ||||
|  | ||||
|     if (out) { | ||||
|         if (av_opt_set_int(s, "ocl", out->channel_layout, 0) < 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_uninit(&ch_layout); | ||||
|             av_channel_layout_from_mask(&ch_layout, out->channel_layout); | ||||
| FF_ENABLE_DEPRECATION_WARNINGS | ||||
|         } else | ||||
| #endif | ||||
|         if ((ret = av_channel_layout_copy(&ch_layout, &out->ch_layout)) < 0) | ||||
|             goto fail; | ||||
|         if (av_opt_set_int(s, "osf", out->format,  0) < 0) | ||||
|         if ((ret = av_opt_set_chlayout(s, "ochl", &ch_layout, 0)) < 0) | ||||
|             goto fail; | ||||
|         if (av_opt_set_int(s, "osr", out->sample_rate, 0) < 0) | ||||
|         if ((ret = av_opt_set_int(s, "osf", out->format,  0)) < 0) | ||||
|             goto fail; | ||||
|         if ((ret = av_opt_set_int(s, "osr", out->sample_rate, 0)) < 0) | ||||
|             goto fail; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
|     ret = 0; | ||||
| fail: | ||||
|     av_log(s, AV_LOG_ERROR, "Failed to set option\n"); | ||||
|     return AVERROR(EINVAL); | ||||
|     if (ret < 0) | ||||
|         av_log(s, AV_LOG_ERROR, "Failed to set option\n"); | ||||
|     av_channel_layout_uninit(&ch_layout); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int config_changed(SwrContext *s, | ||||
|                           const AVFrame *out, const AVFrame *in) | ||||
| { | ||||
|     AVChannelLayout ch_layout = { 0 }; | ||||
|     int ret = 0; | ||||
|  | ||||
|     if (in) { | ||||
|         if (s->in_ch_layout   != in->channel_layout || | ||||
| #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(&ch_layout, in->channel_layout); | ||||
| FF_ENABLE_DEPRECATION_WARNINGS | ||||
|         } else | ||||
| #endif | ||||
|         if ((ret = av_channel_layout_copy(&ch_layout, &in->ch_layout)) < 0) | ||||
|             return ret; | ||||
|         if (av_channel_layout_compare(&s->in_ch_layout, &ch_layout) || | ||||
|             s->in_sample_rate != in->sample_rate || | ||||
|             s->in_sample_fmt  != in->format) { | ||||
|             ret |= AVERROR_INPUT_CHANGED; | ||||
| @@ -66,12 +106,25 @@ static int config_changed(SwrContext *s, | ||||
|     } | ||||
|  | ||||
|     if (out) { | ||||
|         if (s->out_ch_layout   != out->channel_layout || | ||||
| #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_uninit(&ch_layout); | ||||
|             av_channel_layout_from_mask(&ch_layout, out->channel_layout); | ||||
| FF_ENABLE_DEPRECATION_WARNINGS | ||||
|         } else | ||||
| #endif | ||||
|         if ((ret = av_channel_layout_copy(&ch_layout, &out->ch_layout)) < 0) | ||||
|             return ret; | ||||
|         if (av_channel_layout_compare(&s->out_ch_layout, &ch_layout) || | ||||
|             s->out_sample_rate != out->sample_rate || | ||||
|             s->out_sample_fmt  != out->format) { | ||||
|             ret |= AVERROR_OUTPUT_CHANGED; | ||||
|         } | ||||
|     } | ||||
|     av_channel_layout_uninit(&ch_layout); | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
| @@ -116,7 +169,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; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -109,21 +109,21 @@ static const int rates[] = { | ||||
|     48000, | ||||
| }; | ||||
|  | ||||
| static const uint64_t layouts[]={ | ||||
|     AV_CH_LAYOUT_MONO                    , | ||||
|     AV_CH_LAYOUT_STEREO                  , | ||||
|     AV_CH_LAYOUT_2_1                     , | ||||
|     AV_CH_LAYOUT_SURROUND                , | ||||
|     AV_CH_LAYOUT_4POINT0                 , | ||||
|     AV_CH_LAYOUT_2_2                     , | ||||
|     AV_CH_LAYOUT_QUAD                    , | ||||
|     AV_CH_LAYOUT_5POINT0                 , | ||||
|     AV_CH_LAYOUT_5POINT1                 , | ||||
|     AV_CH_LAYOUT_5POINT0_BACK            , | ||||
|     AV_CH_LAYOUT_5POINT1_BACK            , | ||||
|     AV_CH_LAYOUT_7POINT0                 , | ||||
|     AV_CH_LAYOUT_7POINT1                 , | ||||
|     AV_CH_LAYOUT_7POINT1_WIDE            , | ||||
| static const AVChannelLayout layouts[]={ | ||||
|     AV_CHANNEL_LAYOUT_MONO               , | ||||
|     AV_CHANNEL_LAYOUT_STEREO             , | ||||
|     AV_CHANNEL_LAYOUT_2_1                , | ||||
|     AV_CHANNEL_LAYOUT_SURROUND           , | ||||
|     AV_CHANNEL_LAYOUT_4POINT0            , | ||||
|     AV_CHANNEL_LAYOUT_2_2                , | ||||
|     AV_CHANNEL_LAYOUT_QUAD               , | ||||
|     AV_CHANNEL_LAYOUT_5POINT0            , | ||||
|     AV_CHANNEL_LAYOUT_5POINT1            , | ||||
|     AV_CHANNEL_LAYOUT_5POINT0_BACK       , | ||||
|     AV_CHANNEL_LAYOUT_5POINT1_BACK       , | ||||
|     AV_CHANNEL_LAYOUT_7POINT0            , | ||||
|     AV_CHANNEL_LAYOUT_7POINT1            , | ||||
|     AV_CHANNEL_LAYOUT_7POINT1_WIDE       , | ||||
| }; | ||||
|  | ||||
| static void setup_array(uint8_t *out[SWR_CH_MAX], uint8_t *in, enum AVSampleFormat format, int samples){ | ||||
| @@ -224,7 +224,7 @@ static void audiogen(void *data, enum AVSampleFormat sample_fmt, | ||||
|  | ||||
| int main(int argc, char **argv){ | ||||
|     int in_sample_rate, out_sample_rate, ch ,i, flush_count; | ||||
|     uint64_t in_ch_layout, out_ch_layout; | ||||
|     AVChannelLayout in_ch_layout = { 0 }, out_ch_layout = { 0 }; | ||||
|     enum AVSampleFormat in_sample_fmt, out_sample_fmt; | ||||
|     uint8_t array_in[SAMPLES*8*8]; | ||||
|     uint8_t array_mid[SAMPLES*8*8*3]; | ||||
| @@ -281,44 +281,38 @@ int main(int argc, char **argv){ | ||||
|         int in_ch_count; | ||||
|         int out_count, mid_count, out_ch_count; | ||||
|  | ||||
|         in_ch_layout    = layouts[vector % FF_ARRAY_ELEMS(layouts)]; vector /= FF_ARRAY_ELEMS(layouts); | ||||
|         out_ch_layout   = layouts[vector % FF_ARRAY_ELEMS(layouts)]; vector /= FF_ARRAY_ELEMS(layouts); | ||||
|         av_channel_layout_copy(&in_ch_layout,  &layouts[vector % FF_ARRAY_ELEMS(layouts)]); vector /= FF_ARRAY_ELEMS(layouts); | ||||
|         av_channel_layout_copy(&out_ch_layout, &layouts[vector % FF_ARRAY_ELEMS(layouts)]); vector /= FF_ARRAY_ELEMS(layouts); | ||||
|         in_sample_fmt   = formats[vector % FF_ARRAY_ELEMS(formats)]; vector /= FF_ARRAY_ELEMS(formats); | ||||
|         out_sample_fmt  = formats[vector % FF_ARRAY_ELEMS(formats)]; vector /= FF_ARRAY_ELEMS(formats); | ||||
|         out_sample_rate = rates  [vector % FF_ARRAY_ELEMS(rates  )]; vector /= FF_ARRAY_ELEMS(rates); | ||||
|         av_assert0(!vector); | ||||
|  | ||||
|         if(specific_test == 0){ | ||||
|             if(out_sample_rate != in_sample_rate || in_ch_layout != out_ch_layout) | ||||
|             if(out_sample_rate != in_sample_rate || av_channel_layout_compare(&in_ch_layout, &out_ch_layout)) | ||||
|                 continue; | ||||
|         } | ||||
|  | ||||
|         in_ch_count= av_get_channel_layout_nb_channels(in_ch_layout); | ||||
|         out_ch_count= av_get_channel_layout_nb_channels(out_ch_layout); | ||||
|         av_get_channel_layout_string( in_layout_string, sizeof( in_layout_string),  in_ch_count,  in_ch_layout); | ||||
|         av_get_channel_layout_string(out_layout_string, sizeof(out_layout_string), out_ch_count, out_ch_layout); | ||||
|         in_ch_count= in_ch_layout.nb_channels; | ||||
|         out_ch_count= out_ch_layout.nb_channels; | ||||
|         av_channel_layout_describe(&in_ch_layout,   in_layout_string, sizeof( in_layout_string)); | ||||
|         av_channel_layout_describe(&out_ch_layout, out_layout_string, sizeof(out_layout_string)); | ||||
|         fprintf(stderr, "TEST: %s->%s, rate:%5d->%5d, fmt:%s->%s\n", | ||||
|                 in_layout_string, out_layout_string, | ||||
|                 in_sample_rate, out_sample_rate, | ||||
|                 av_get_sample_fmt_name(in_sample_fmt), av_get_sample_fmt_name(out_sample_fmt)); | ||||
|         forw_ctx  = swr_alloc_set_opts(forw_ctx, out_ch_layout, out_sample_fmt,  out_sample_rate, | ||||
|                                                     in_ch_layout,  in_sample_fmt,  in_sample_rate, | ||||
|                                         0, 0); | ||||
|         backw_ctx = swr_alloc_set_opts(backw_ctx, in_ch_layout,  in_sample_fmt,             in_sample_rate, | ||||
|                                                     out_ch_layout, out_sample_fmt, out_sample_rate, | ||||
|                                         0, 0); | ||||
|         if(!forw_ctx) { | ||||
|         if (swr_alloc_set_opts2(&forw_ctx, &out_ch_layout, out_sample_fmt, out_sample_rate, | ||||
|                                            &in_ch_layout,   in_sample_fmt,  in_sample_rate, | ||||
|                                            0, 0) < 0) { | ||||
|             fprintf(stderr, "Failed to init forw_cts\n"); | ||||
|             return 1; | ||||
|         } | ||||
|         if(!backw_ctx) { | ||||
|         if (swr_alloc_set_opts2(&backw_ctx, &in_ch_layout,   in_sample_fmt,  in_sample_rate, | ||||
|                                             &out_ch_layout, out_sample_fmt, out_sample_rate, | ||||
|                                             0, 0) < 0) { | ||||
|             fprintf(stderr, "Failed to init backw_ctx\n"); | ||||
|             return 1; | ||||
|         } | ||||
|         if (uint_rand(rand_seed) % 3 == 0) | ||||
|             av_opt_set_int(forw_ctx, "ich", 0, 0); | ||||
|         if (uint_rand(rand_seed) % 3 == 0) | ||||
|             av_opt_set_int(forw_ctx, "och", 0, 0); | ||||
|  | ||||
|         if(swr_init( forw_ctx) < 0) | ||||
|             fprintf(stderr, "swr_init(->) failed\n"); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user