00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "swresample_internal.h"
00022 #include "libavutil/avassert.h"
00023 #include "libavutil/channel_layout.h"
00024
00025 #define TEMPLATE_REMATRIX_FLT
00026 #include "rematrix_template.c"
00027 #undef TEMPLATE_REMATRIX_FLT
00028
00029 #define TEMPLATE_REMATRIX_DBL
00030 #include "rematrix_template.c"
00031 #undef TEMPLATE_REMATRIX_DBL
00032
00033 #define TEMPLATE_REMATRIX_S16
00034 #include "rematrix_template.c"
00035 #undef TEMPLATE_REMATRIX_S16
00036
00037 #define FRONT_LEFT 0
00038 #define FRONT_RIGHT 1
00039 #define FRONT_CENTER 2
00040 #define LOW_FREQUENCY 3
00041 #define BACK_LEFT 4
00042 #define BACK_RIGHT 5
00043 #define FRONT_LEFT_OF_CENTER 6
00044 #define FRONT_RIGHT_OF_CENTER 7
00045 #define BACK_CENTER 8
00046 #define SIDE_LEFT 9
00047 #define SIDE_RIGHT 10
00048 #define TOP_CENTER 11
00049 #define TOP_FRONT_LEFT 12
00050 #define TOP_FRONT_CENTER 13
00051 #define TOP_FRONT_RIGHT 14
00052 #define TOP_BACK_LEFT 15
00053 #define TOP_BACK_CENTER 16
00054 #define TOP_BACK_RIGHT 17
00055
00056 int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride)
00057 {
00058 int nb_in, nb_out, in, out;
00059
00060 if (!s || s->in_convert)
00061 return AVERROR(EINVAL);
00062 memset(s->matrix, 0, sizeof(s->matrix));
00063 nb_in = av_get_channel_layout_nb_channels(s->in_ch_layout);
00064 nb_out = av_get_channel_layout_nb_channels(s->out_ch_layout);
00065 for (out = 0; out < nb_out; out++) {
00066 for (in = 0; in < nb_in; in++)
00067 s->matrix[out][in] = matrix[in];
00068 matrix += stride;
00069 }
00070 s->rematrix_custom = 1;
00071 return 0;
00072 }
00073
00074 static int even(int64_t layout){
00075 if(!layout) return 1;
00076 if(layout&(layout-1)) return 1;
00077 return 0;
00078 }
00079
00080 static int clean_layout(SwrContext *s, int64_t layout){
00081 if((layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == AV_CH_LAYOUT_STEREO_DOWNMIX)
00082 return AV_CH_LAYOUT_STEREO;
00083
00084 if(layout && layout != AV_CH_FRONT_CENTER && !(layout&(layout-1))) {
00085 char buf[128];
00086 av_get_channel_layout_string(buf, sizeof(buf), -1, layout);
00087 av_log(s, AV_LOG_VERBOSE, "Treating %s as mono\n", buf);
00088 return AV_CH_FRONT_CENTER;
00089 }
00090
00091 return layout;
00092 }
00093
00094 static int sane_layout(int64_t layout){
00095 if(!(layout & AV_CH_LAYOUT_SURROUND))
00096 return 0;
00097 if(!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)))
00098 return 0;
00099 if(!even(layout & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)))
00100 return 0;
00101 if(!even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)))
00102 return 0;
00103 if(!even(layout & (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)))
00104 return 0;
00105 if(av_get_channel_layout_nb_channels(layout) >= SWR_CH_MAX)
00106 return 0;
00107
00108 return 1;
00109 }
00110
00111 av_cold static int auto_matrix(SwrContext *s)
00112 {
00113 int i, j, out_i;
00114 double matrix[64][64]={{0}};
00115 int64_t unaccounted, in_ch_layout, out_ch_layout;
00116 double maxcoef=0;
00117 char buf[128];
00118 const int matrix_encoding = s->matrix_encoding;
00119
00120 in_ch_layout = clean_layout(s, s->in_ch_layout);
00121 if(!sane_layout(in_ch_layout)){
00122 av_get_channel_layout_string(buf, sizeof(buf), -1, s->in_ch_layout);
00123 av_log(s, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf);
00124 return AVERROR(EINVAL);
00125 }
00126
00127 out_ch_layout = clean_layout(s, s->out_ch_layout);
00128 if(!sane_layout(out_ch_layout)){
00129 av_get_channel_layout_string(buf, sizeof(buf), -1, s->out_ch_layout);
00130 av_log(s, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf);
00131 return AVERROR(EINVAL);
00132 }
00133
00134 memset(s->matrix, 0, sizeof(s->matrix));
00135 for(i=0; i<64; i++){
00136 if(in_ch_layout & out_ch_layout & (1ULL<<i))
00137 matrix[i][i]= 1.0;
00138 }
00139
00140 unaccounted= in_ch_layout & ~out_ch_layout;
00141
00142
00143
00144
00145
00146 if(unaccounted & AV_CH_FRONT_CENTER){
00147 if((out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){
00148 if(in_ch_layout & AV_CH_LAYOUT_STEREO) {
00149 matrix[ FRONT_LEFT][FRONT_CENTER]+= s->clev;
00150 matrix[FRONT_RIGHT][FRONT_CENTER]+= s->clev;
00151 } else {
00152 matrix[ FRONT_LEFT][FRONT_CENTER]+= M_SQRT1_2;
00153 matrix[FRONT_RIGHT][FRONT_CENTER]+= M_SQRT1_2;
00154 }
00155 }else
00156 av_assert0(0);
00157 }
00158 if(unaccounted & AV_CH_LAYOUT_STEREO){
00159 if(out_ch_layout & AV_CH_FRONT_CENTER){
00160 matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2;
00161 matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2;
00162 if(in_ch_layout & AV_CH_FRONT_CENTER)
00163 matrix[FRONT_CENTER][ FRONT_CENTER] = s->clev*sqrt(2);
00164 }else
00165 av_assert0(0);
00166 }
00167
00168 if(unaccounted & AV_CH_BACK_CENTER){
00169 if(out_ch_layout & AV_CH_BACK_LEFT){
00170 matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2;
00171 matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2;
00172 }else if(out_ch_layout & AV_CH_SIDE_LEFT){
00173 matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2;
00174 matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2;
00175 }else if(out_ch_layout & AV_CH_FRONT_LEFT){
00176 if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
00177 matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
00178 if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
00179 matrix[FRONT_LEFT ][BACK_CENTER] -= s->slev * M_SQRT1_2;
00180 matrix[FRONT_RIGHT][BACK_CENTER] += s->slev * M_SQRT1_2;
00181 } else {
00182 matrix[FRONT_LEFT ][BACK_CENTER] -= s->slev;
00183 matrix[FRONT_RIGHT][BACK_CENTER] += s->slev;
00184 }
00185 } else {
00186 matrix[ FRONT_LEFT][BACK_CENTER]+= s->slev*M_SQRT1_2;
00187 matrix[FRONT_RIGHT][BACK_CENTER]+= s->slev*M_SQRT1_2;
00188 }
00189 }else if(out_ch_layout & AV_CH_FRONT_CENTER){
00190 matrix[ FRONT_CENTER][BACK_CENTER]+= s->slev*M_SQRT1_2;
00191 }else
00192 av_assert0(0);
00193 }
00194 if(unaccounted & AV_CH_BACK_LEFT){
00195 if(out_ch_layout & AV_CH_BACK_CENTER){
00196 matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2;
00197 matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2;
00198 }else if(out_ch_layout & AV_CH_SIDE_LEFT){
00199 if(in_ch_layout & AV_CH_SIDE_LEFT){
00200 matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2;
00201 matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2;
00202 }else{
00203 matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0;
00204 matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0;
00205 }
00206 }else if(out_ch_layout & AV_CH_FRONT_LEFT){
00207 if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
00208 matrix[FRONT_LEFT ][BACK_LEFT ] -= s->slev * M_SQRT1_2;
00209 matrix[FRONT_LEFT ][BACK_RIGHT] -= s->slev * M_SQRT1_2;
00210 matrix[FRONT_RIGHT][BACK_LEFT ] += s->slev * M_SQRT1_2;
00211 matrix[FRONT_RIGHT][BACK_RIGHT] += s->slev * M_SQRT1_2;
00212 } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
00213 matrix[FRONT_LEFT ][BACK_LEFT ] -= s->slev * SQRT3_2;
00214 matrix[FRONT_LEFT ][BACK_RIGHT] -= s->slev * M_SQRT1_2;
00215 matrix[FRONT_RIGHT][BACK_LEFT ] += s->slev * M_SQRT1_2;
00216 matrix[FRONT_RIGHT][BACK_RIGHT] += s->slev * SQRT3_2;
00217 } else {
00218 matrix[ FRONT_LEFT][ BACK_LEFT] += s->slev;
00219 matrix[FRONT_RIGHT][BACK_RIGHT] += s->slev;
00220 }
00221 }else if(out_ch_layout & AV_CH_FRONT_CENTER){
00222 matrix[ FRONT_CENTER][BACK_LEFT ]+= s->slev*M_SQRT1_2;
00223 matrix[ FRONT_CENTER][BACK_RIGHT]+= s->slev*M_SQRT1_2;
00224 }else
00225 av_assert0(0);
00226 }
00227
00228 if(unaccounted & AV_CH_SIDE_LEFT){
00229 if(out_ch_layout & AV_CH_BACK_LEFT){
00230
00231
00232 if (in_ch_layout & AV_CH_BACK_LEFT) {
00233 matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
00234 matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
00235 } else {
00236 matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
00237 matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
00238 }
00239 }else if(out_ch_layout & AV_CH_BACK_CENTER){
00240 matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2;
00241 matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2;
00242 }else if(out_ch_layout & AV_CH_FRONT_LEFT){
00243 if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
00244 matrix[FRONT_LEFT ][SIDE_LEFT ] -= s->slev * M_SQRT1_2;
00245 matrix[FRONT_LEFT ][SIDE_RIGHT] -= s->slev * M_SQRT1_2;
00246 matrix[FRONT_RIGHT][SIDE_LEFT ] += s->slev * M_SQRT1_2;
00247 matrix[FRONT_RIGHT][SIDE_RIGHT] += s->slev * M_SQRT1_2;
00248 } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
00249 matrix[FRONT_LEFT ][SIDE_LEFT ] -= s->slev * SQRT3_2;
00250 matrix[FRONT_LEFT ][SIDE_RIGHT] -= s->slev * M_SQRT1_2;
00251 matrix[FRONT_RIGHT][SIDE_LEFT ] += s->slev * M_SQRT1_2;
00252 matrix[FRONT_RIGHT][SIDE_RIGHT] += s->slev * SQRT3_2;
00253 } else {
00254 matrix[ FRONT_LEFT][ SIDE_LEFT] += s->slev;
00255 matrix[FRONT_RIGHT][SIDE_RIGHT] += s->slev;
00256 }
00257 }else if(out_ch_layout & AV_CH_FRONT_CENTER){
00258 matrix[ FRONT_CENTER][SIDE_LEFT ]+= s->slev*M_SQRT1_2;
00259 matrix[ FRONT_CENTER][SIDE_RIGHT]+= s->slev*M_SQRT1_2;
00260 }else
00261 av_assert0(0);
00262 }
00263
00264 if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){
00265 if(out_ch_layout & AV_CH_FRONT_LEFT){
00266 matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0;
00267 matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0;
00268 }else if(out_ch_layout & AV_CH_FRONT_CENTER){
00269 matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2;
00270 matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2;
00271 }else
00272 av_assert0(0);
00273 }
00274
00275 if (unaccounted & AV_CH_LOW_FREQUENCY) {
00276 if (out_ch_layout & AV_CH_FRONT_CENTER) {
00277 matrix[FRONT_CENTER][LOW_FREQUENCY] += s->lfe_mix_level;
00278 } else if (out_ch_layout & AV_CH_FRONT_LEFT) {
00279 matrix[FRONT_LEFT ][LOW_FREQUENCY] += s->lfe_mix_level * M_SQRT1_2;
00280 matrix[FRONT_RIGHT][LOW_FREQUENCY] += s->lfe_mix_level * M_SQRT1_2;
00281 } else
00282 av_assert0(0);
00283 }
00284
00285 for(out_i=i=0; i<64; i++){
00286 double sum=0;
00287 int in_i=0;
00288 for(j=0; j<64; j++){
00289 s->matrix[out_i][in_i]= matrix[i][j];
00290 if(matrix[i][j]){
00291 sum += fabs(matrix[i][j]);
00292 }
00293 if(in_ch_layout & (1ULL<<j))
00294 in_i++;
00295 }
00296 maxcoef= FFMAX(maxcoef, sum);
00297 if(out_ch_layout & (1ULL<<i))
00298 out_i++;
00299 }
00300 if(s->rematrix_volume < 0)
00301 maxcoef = -s->rematrix_volume;
00302
00303 if(( av_get_packed_sample_fmt(s->out_sample_fmt) < AV_SAMPLE_FMT_FLT
00304 || av_get_packed_sample_fmt(s->int_sample_fmt) < AV_SAMPLE_FMT_FLT) && maxcoef > 1.0){
00305 for(i=0; i<SWR_CH_MAX; i++)
00306 for(j=0; j<SWR_CH_MAX; j++){
00307 s->matrix[i][j] /= maxcoef;
00308 }
00309 }
00310
00311 if(s->rematrix_volume > 0){
00312 for(i=0; i<SWR_CH_MAX; i++)
00313 for(j=0; j<SWR_CH_MAX; j++){
00314 s->matrix[i][j] *= s->rematrix_volume;
00315 }
00316 }
00317
00318 for(i=0; i<av_get_channel_layout_nb_channels(out_ch_layout); i++){
00319 for(j=0; j<av_get_channel_layout_nb_channels(in_ch_layout); j++){
00320 av_log(NULL, AV_LOG_DEBUG, "%f ", s->matrix[i][j]);
00321 }
00322 av_log(NULL, AV_LOG_DEBUG, "\n");
00323 }
00324 return 0;
00325 }
00326
00327 av_cold int swri_rematrix_init(SwrContext *s){
00328 int i, j;
00329 int nb_in = av_get_channel_layout_nb_channels(s->in_ch_layout);
00330 int nb_out = av_get_channel_layout_nb_channels(s->out_ch_layout);
00331
00332 s->mix_any_f = NULL;
00333
00334 if (!s->rematrix_custom) {
00335 int r = auto_matrix(s);
00336 if (r)
00337 return r;
00338 }
00339 if (s->midbuf.fmt == AV_SAMPLE_FMT_S16P){
00340 s->native_matrix = av_mallocz(nb_in * nb_out * sizeof(int));
00341 s->native_one = av_mallocz(sizeof(int));
00342 for (i = 0; i < nb_out; i++)
00343 for (j = 0; j < nb_in; j++)
00344 ((int*)s->native_matrix)[i * nb_in + j] = lrintf(s->matrix[i][j] * 32768);
00345 *((int*)s->native_one) = 32768;
00346 s->mix_1_1_f = (mix_1_1_func_type*)copy_s16;
00347 s->mix_2_1_f = (mix_2_1_func_type*)sum2_s16;
00348 s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s16(s);
00349 }else if(s->midbuf.fmt == AV_SAMPLE_FMT_FLTP){
00350 s->native_matrix = av_mallocz(nb_in * nb_out * sizeof(float));
00351 s->native_one = av_mallocz(sizeof(float));
00352 for (i = 0; i < nb_out; i++)
00353 for (j = 0; j < nb_in; j++)
00354 ((float*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
00355 *((float*)s->native_one) = 1.0;
00356 s->mix_1_1_f = (mix_1_1_func_type*)copy_float;
00357 s->mix_2_1_f = (mix_2_1_func_type*)sum2_float;
00358 s->mix_any_f = (mix_any_func_type*)get_mix_any_func_float(s);
00359 }else if(s->midbuf.fmt == AV_SAMPLE_FMT_DBLP){
00360 s->native_matrix = av_mallocz(nb_in * nb_out * sizeof(double));
00361 s->native_one = av_mallocz(sizeof(double));
00362 for (i = 0; i < nb_out; i++)
00363 for (j = 0; j < nb_in; j++)
00364 ((double*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
00365 *((double*)s->native_one) = 1.0;
00366 s->mix_1_1_f = (mix_1_1_func_type*)copy_double;
00367 s->mix_2_1_f = (mix_2_1_func_type*)sum2_double;
00368 s->mix_any_f = (mix_any_func_type*)get_mix_any_func_double(s);
00369 }else
00370 av_assert0(0);
00371
00372 for (i = 0; i < SWR_CH_MAX; i++) {
00373 int ch_in=0;
00374 for (j = 0; j < SWR_CH_MAX; j++) {
00375 s->matrix32[i][j]= lrintf(s->matrix[i][j] * 32768);
00376 if(s->matrix[i][j])
00377 s->matrix_ch[i][++ch_in]= j;
00378 }
00379 s->matrix_ch[i][0]= ch_in;
00380 }
00381
00382 if(HAVE_YASM && HAVE_MMX) swri_rematrix_init_x86(s);
00383
00384 return 0;
00385 }
00386
00387 av_cold void swri_rematrix_free(SwrContext *s){
00388 av_freep(&s->native_matrix);
00389 av_freep(&s->native_one);
00390 av_freep(&s->native_simd_matrix);
00391 }
00392
00393 int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){
00394 int out_i, in_i, i, j;
00395 int len1 = 0;
00396 int off = 0;
00397
00398 if(s->mix_any_f) {
00399 s->mix_any_f(out->ch, (const uint8_t **)in->ch, s->native_matrix, len);
00400 return 0;
00401 }
00402
00403 if(s->mix_2_1_simd || s->mix_1_1_simd){
00404 len1= len&~15;
00405 off = len1 * out->bps;
00406 }
00407
00408 av_assert0(out->ch_count == av_get_channel_layout_nb_channels(s->out_ch_layout));
00409 av_assert0(in ->ch_count == av_get_channel_layout_nb_channels(s-> in_ch_layout));
00410
00411 for(out_i=0; out_i<out->ch_count; out_i++){
00412 switch(s->matrix_ch[out_i][0]){
00413 case 0:
00414 if(mustcopy)
00415 memset(out->ch[out_i], 0, len * av_get_bytes_per_sample(s->int_sample_fmt));
00416 break;
00417 case 1:
00418 in_i= s->matrix_ch[out_i][1];
00419 if(s->matrix[out_i][in_i]!=1.0){
00420 if(s->mix_1_1_simd && len1)
00421 s->mix_1_1_simd(out->ch[out_i] , in->ch[in_i] , s->native_simd_matrix, in->ch_count*out_i + in_i, len1);
00422 if(len != len1)
00423 s->mix_1_1_f (out->ch[out_i]+off, in->ch[in_i]+off, s->native_matrix, in->ch_count*out_i + in_i, len-len1);
00424 }else if(mustcopy){
00425 memcpy(out->ch[out_i], in->ch[in_i], len*out->bps);
00426 }else{
00427 out->ch[out_i]= in->ch[in_i];
00428 }
00429 break;
00430 case 2: {
00431 int in_i1 = s->matrix_ch[out_i][1];
00432 int in_i2 = s->matrix_ch[out_i][2];
00433 if(s->mix_2_1_simd && len1)
00434 s->mix_2_1_simd(out->ch[out_i] , in->ch[in_i1] , in->ch[in_i2] , s->native_simd_matrix, in->ch_count*out_i + in_i1, in->ch_count*out_i + in_i2, len1);
00435 else
00436 s->mix_2_1_f (out->ch[out_i] , in->ch[in_i1] , in->ch[in_i2] , s->native_matrix, in->ch_count*out_i + in_i1, in->ch_count*out_i + in_i2, len1);
00437 if(len != len1)
00438 s->mix_2_1_f (out->ch[out_i]+off, in->ch[in_i1]+off, in->ch[in_i2]+off, s->native_matrix, in->ch_count*out_i + in_i1, in->ch_count*out_i + in_i2, len-len1);
00439 break;}
00440 default:
00441 if(s->int_sample_fmt == AV_SAMPLE_FMT_FLTP){
00442 for(i=0; i<len; i++){
00443 float v=0;
00444 for(j=0; j<s->matrix_ch[out_i][0]; j++){
00445 in_i= s->matrix_ch[out_i][1+j];
00446 v+= ((float*)in->ch[in_i])[i] * s->matrix[out_i][in_i];
00447 }
00448 ((float*)out->ch[out_i])[i]= v;
00449 }
00450 }else if(s->int_sample_fmt == AV_SAMPLE_FMT_DBLP){
00451 for(i=0; i<len; i++){
00452 double v=0;
00453 for(j=0; j<s->matrix_ch[out_i][0]; j++){
00454 in_i= s->matrix_ch[out_i][1+j];
00455 v+= ((double*)in->ch[in_i])[i] * s->matrix[out_i][in_i];
00456 }
00457 ((double*)out->ch[out_i])[i]= v;
00458 }
00459 }else{
00460 for(i=0; i<len; i++){
00461 int v=0;
00462 for(j=0; j<s->matrix_ch[out_i][0]; j++){
00463 in_i= s->matrix_ch[out_i][1+j];
00464 v+= ((int16_t*)in->ch[in_i])[i] * s->matrix32[out_i][in_i];
00465 }
00466 ((int16_t*)out->ch[out_i])[i]= (v + 16384)>>15;
00467 }
00468 }
00469 }
00470 }
00471 return 0;
00472 }