FFmpeg
rematrix.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2011-2012 Michael Niedermayer (michaelni@gmx.at)
3  *
4  * This file is part of libswresample
5  *
6  * libswresample is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * libswresample is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with libswresample; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "swresample_internal.h"
22 #include "libavutil/avassert.h"
24 
25 #define TEMPLATE_REMATRIX_FLT
26 #include "rematrix_template.c"
27 #undef TEMPLATE_REMATRIX_FLT
28 
29 #define TEMPLATE_REMATRIX_DBL
30 #include "rematrix_template.c"
31 #undef TEMPLATE_REMATRIX_DBL
32 
33 #define TEMPLATE_REMATRIX_S16
34 #include "rematrix_template.c"
35 #define TEMPLATE_CLIP
36 #include "rematrix_template.c"
37 #undef TEMPLATE_CLIP
38 #undef TEMPLATE_REMATRIX_S16
39 
40 #define TEMPLATE_REMATRIX_S32
41 #include "rematrix_template.c"
42 #undef TEMPLATE_REMATRIX_S32
43 
44 #define FRONT_LEFT 0
45 #define FRONT_RIGHT 1
46 #define FRONT_CENTER 2
47 #define LOW_FREQUENCY 3
48 #define BACK_LEFT 4
49 #define BACK_RIGHT 5
50 #define FRONT_LEFT_OF_CENTER 6
51 #define FRONT_RIGHT_OF_CENTER 7
52 #define BACK_CENTER 8
53 #define SIDE_LEFT 9
54 #define SIDE_RIGHT 10
55 #define TOP_CENTER 11
56 #define TOP_FRONT_LEFT 12
57 #define TOP_FRONT_CENTER 13
58 #define TOP_FRONT_RIGHT 14
59 #define TOP_BACK_LEFT 15
60 #define TOP_BACK_CENTER 16
61 #define TOP_BACK_RIGHT 17
62 #define NUM_NAMED_CHANNELS 18
63 
64 int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride)
65 {
66  int nb_in, nb_out, in, out;
67  int user_in_chlayout_nb_channels, user_out_chlayout_nb_channels;
68 
69  if (!s || s->in_convert) // s needs to be allocated but not initialized
70  return AVERROR(EINVAL);
71  memset(s->matrix, 0, sizeof(s->matrix));
72  memset(s->matrix_flt, 0, sizeof(s->matrix_flt));
73 
74 #if FF_API_OLD_CHANNEL_LAYOUT
76  user_in_chlayout_nb_channels = av_get_channel_layout_nb_channels(s->user_in_ch_layout);
78  if (!user_in_chlayout_nb_channels)
79 #endif
80  user_in_chlayout_nb_channels = s->user_in_chlayout.nb_channels;
81  nb_in =
82 #if FF_API_OLD_CHANNEL_LAYOUT
83  (s->user_in_ch_count > 0) ? s->user_in_ch_count :
84 #endif
85  user_in_chlayout_nb_channels;
88  user_out_chlayout_nb_channels = av_get_channel_layout_nb_channels(s->user_out_ch_layout);
90  if (!user_out_chlayout_nb_channels)
91 #endif
92  user_out_chlayout_nb_channels = s->user_out_chlayout.nb_channels;
93  nb_out =
94 #if FF_API_OLD_CHANNEL_LAYOUT
95  (s->user_out_ch_count > 0) ? s->user_out_ch_count :
96 #endif
97  user_out_chlayout_nb_channels;
98  for (out = 0; out < nb_out; out++) {
99  for (in = 0; in < nb_in; in++)
100  s->matrix_flt[out][in] = s->matrix[out][in] = matrix[in];
101  matrix += stride;
102  }
103  s->rematrix_custom = 1;
104  return 0;
105 }
106 
107 static int even(int64_t layout){
108  if(!layout) return 1;
109  if(layout&(layout-1)) return 1;
110  return 0;
111 }
112 
113 static int clean_layout(AVChannelLayout *out, const AVChannelLayout *in, void *s)
114 {
115  int ret = 0;
116 
118  char buf[128];
119  av_channel_layout_describe(in, buf, sizeof(buf));
120  av_log(s, AV_LOG_VERBOSE, "Treating %s as mono\n", buf);
122  } else
124 
125  return ret;
126 }
127 
128 static int sane_layout(AVChannelLayout *ch_layout) {
129  if (ch_layout->order != AV_CHANNEL_ORDER_NATIVE)
130  return 0;
131  if(!av_channel_layout_subset(ch_layout, AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker
132  return 0;
133  if(!even(av_channel_layout_subset(ch_layout, (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)))) // no asymetric front
134  return 0;
135  if(!even(av_channel_layout_subset(ch_layout, (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)))) // no asymetric side
136  return 0;
138  return 0;
140  return 0;
141  if(ch_layout->nb_channels >= SWR_CH_MAX)
142  return 0;
143 
144  return 1;
145 }
146 
147 #if FF_API_OLD_CHANNEL_LAYOUT
148 av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout_param,
149  double center_mix_level, double surround_mix_level,
150  double lfe_mix_level, double maxval,
151  double rematrix_volume, double *matrix_param,
152  int stride, enum AVMatrixEncoding matrix_encoding, void *log_context)
153 {
154  AVChannelLayout in_ch_layout = { 0 }, out_ch_layout = { 0 };
155  int ret;
156 
157  ret = av_channel_layout_from_mask(&in_ch_layout, in_ch_layout_param);
158  ret |= av_channel_layout_from_mask(&out_ch_layout, out_ch_layout_param);
159  if (ret < 0)
160  return ret;
161 
162  return swr_build_matrix2(&in_ch_layout, &out_ch_layout, center_mix_level, surround_mix_level,
163  lfe_mix_level, maxval, rematrix_volume, matrix_param,
164  stride, matrix_encoding, log_context);
165 }
166 #endif
167 
168 av_cold int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout,
169  double center_mix_level, double surround_mix_level,
170  double lfe_mix_level, double maxval,
171  double rematrix_volume, double *matrix_param,
172  ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding, void *log_context)
173 {
174  int i, j, out_i, ret;
175  AVChannelLayout in_ch_layout = { 0 }, out_ch_layout = { 0 };
177  int64_t unaccounted;
178  double maxcoef=0;
179  char buf[128];
180 
181  ret = clean_layout(&in_ch_layout, in_layout, log_context);
182  ret |= clean_layout(&out_ch_layout, out_layout, log_context);
183  if (ret < 0)
184  goto fail;
185 
188  ) {
189  av_channel_layout_uninit(&out_ch_layout);
190  out_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
191  }
194  ) {
195  av_channel_layout_uninit(&in_ch_layout);
197  }
201  av_channel_layout_describe(&in_ch_layout, buf, sizeof(buf));
202  av_log(log_context, AV_LOG_WARNING,
203  "Full-on remixing from 22.2 has not yet been implemented! "
204  "Processing the input as '%s'\n",
205  buf);
206  }
207 
208  if(!av_channel_layout_check(&in_ch_layout)) {
209  av_log(log_context, AV_LOG_ERROR, "Input channel layout is invalid\n");
210  ret = AVERROR(EINVAL);
211  goto fail;
212  }
213  if(!sane_layout(&in_ch_layout)) {
214  av_channel_layout_describe(&in_ch_layout, buf, sizeof(buf));
215  av_log(log_context, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf);
216  ret = AVERROR(EINVAL);
217  goto fail;
218  }
219 
220  if(!av_channel_layout_check(&out_ch_layout)) {
221  av_log(log_context, AV_LOG_ERROR, "Output channel layout is invalid\n");
222  ret = AVERROR(EINVAL);
223  goto fail;
224  }
225  if(!sane_layout(&out_ch_layout)) {
226  av_channel_layout_describe(&out_ch_layout, buf, sizeof(buf));
227  av_log(log_context, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf);
228  ret = AVERROR(EINVAL);
229  goto fail;
230  }
231 
232  for(i=0; i<FF_ARRAY_ELEMS(matrix); i++){
233  if( av_channel_layout_index_from_channel(&in_ch_layout, i) >= 0
234  && av_channel_layout_index_from_channel(&out_ch_layout, i) >= 0)
235  matrix[i][i]= 1.0;
236  }
237 
238  unaccounted = in_ch_layout.u.mask & ~out_ch_layout.u.mask;
239 
240 //FIXME implement dolby surround
241 //FIXME implement full ac3
242 
243 
244  if(unaccounted & AV_CH_FRONT_CENTER){
246  if (av_channel_layout_subset(&in_ch_layout, AV_CH_LAYOUT_STEREO)) {
247  matrix[ FRONT_LEFT][FRONT_CENTER]+= center_mix_level;
248  matrix[FRONT_RIGHT][FRONT_CENTER]+= center_mix_level;
249  } else {
252  }
253  }else
254  av_assert0(0);
255  }
256  if(unaccounted & AV_CH_LAYOUT_STEREO){
261  matrix[FRONT_CENTER][ FRONT_CENTER] = center_mix_level*sqrt(2);
262  }else
263  av_assert0(0);
264  }
265 
266  if(unaccounted & AV_CH_BACK_CENTER){
267  if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_LEFT) >= 0) {
270  } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_SIDE_LEFT) >= 0) {
273  } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) {
274  if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
275  matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
276  if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
277  matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level * M_SQRT1_2;
278  matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
279  } else {
280  matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level;
281  matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level;
282  }
283  } else {
284  matrix[ FRONT_LEFT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
285  matrix[FRONT_RIGHT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
286  }
287  } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) {
288  matrix[ FRONT_CENTER][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
289  }else
290  av_assert0(0);
291  }
292  if(unaccounted & AV_CH_BACK_LEFT){
293  if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_CENTER) >= 0) {
296  } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_SIDE_LEFT) >= 0) {
297  if (av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_SIDE_LEFT) >= 0) {
300  }else{
301  matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0;
302  matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0;
303  }
304  } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) {
305  if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
306  matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2;
307  matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
308  matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
309  matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
310  } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
311  matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * SQRT3_2;
312  matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
313  matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
314  matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * SQRT3_2;
315  } else {
316  matrix[ FRONT_LEFT][ BACK_LEFT] += surround_mix_level;
317  matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
318  }
319  } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) {
320  matrix[ FRONT_CENTER][BACK_LEFT ]+= surround_mix_level*M_SQRT1_2;
321  matrix[ FRONT_CENTER][BACK_RIGHT]+= surround_mix_level*M_SQRT1_2;
322  }else
323  av_assert0(0);
324  }
325 
326  if(unaccounted & AV_CH_SIDE_LEFT){
327  if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_LEFT) >= 0) {
328  /* if back channels do not exist in the input, just copy side
329  channels to back channels, otherwise mix side into back */
330  if (av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_BACK_LEFT) >= 0) {
333  } else {
334  matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
335  matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
336  }
337  } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_CENTER) >= 0) {
340  } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) {
341  if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
342  matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2;
343  matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
344  matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
345  matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
346  } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
347  matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * SQRT3_2;
348  matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
349  matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
350  matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * SQRT3_2;
351  } else {
352  matrix[ FRONT_LEFT][ SIDE_LEFT] += surround_mix_level;
353  matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
354  }
355  } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) {
356  matrix[ FRONT_CENTER][SIDE_LEFT ]+= surround_mix_level * M_SQRT1_2;
357  matrix[ FRONT_CENTER][SIDE_RIGHT]+= surround_mix_level * M_SQRT1_2;
358  }else
359  av_assert0(0);
360  }
361 
362  if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){
363  if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) {
366  } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) {
369  }else
370  av_assert0(0);
371  }
372  /* mix LFE into front left/right or center */
373  if (unaccounted & AV_CH_LOW_FREQUENCY) {
375  matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level;
376  } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) {
377  matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
378  matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
379  } else
380  av_assert0(0);
381  }
382 
383  for(out_i=i=0; i<64; i++){
384  double sum=0;
385  int in_i=0;
386  if (av_channel_layout_index_from_channel(&out_ch_layout, i) < 0)
387  continue;
388  for(j=0; j<64; j++){
389  if (av_channel_layout_index_from_channel(&in_ch_layout, j) < 0)
390  continue;
391  if (i < FF_ARRAY_ELEMS(matrix) && j < FF_ARRAY_ELEMS(matrix[0]))
392  matrix_param[stride*out_i + in_i] = matrix[i][j];
393  else
394  matrix_param[stride*out_i + in_i] = i == j &&
395  ( av_channel_layout_index_from_channel(&in_ch_layout, i) >= 0
396  && av_channel_layout_index_from_channel(&out_ch_layout, i) >= 0);
397  sum += fabs(matrix_param[stride*out_i + in_i]);
398  in_i++;
399  }
400  maxcoef= FFMAX(maxcoef, sum);
401  out_i++;
402  }
403  if(rematrix_volume < 0)
404  maxcoef = -rematrix_volume;
405 
406  if(maxcoef > maxval || rematrix_volume < 0){
407  maxcoef /= maxval;
408  for(i=0; i<SWR_CH_MAX; i++)
409  for(j=0; j<SWR_CH_MAX; j++){
410  matrix_param[stride*i + j] /= maxcoef;
411  }
412  }
413 
414  if(rematrix_volume > 0){
415  for(i=0; i<SWR_CH_MAX; i++)
416  for(j=0; j<SWR_CH_MAX; j++){
417  matrix_param[stride*i + j] *= rematrix_volume;
418  }
419  }
420 
421  av_log(log_context, AV_LOG_DEBUG, "Matrix coefficients:\n");
422  for (i = 0; i < out_ch_layout.nb_channels; i++){
423  av_channel_name(buf, sizeof(buf), av_channel_layout_channel_from_index(&out_ch_layout, i));
424  av_log(log_context, AV_LOG_DEBUG, "%s: ", buf);
425  for (j = 0; j < in_ch_layout.nb_channels; j++){
426  av_channel_name(buf, sizeof(buf), av_channel_layout_channel_from_index(&in_ch_layout, j));
427  av_log(log_context, AV_LOG_DEBUG, "%s:%f ", buf, matrix_param[stride*i + j]);
428  }
429  av_log(log_context, AV_LOG_DEBUG, "\n");
430  }
431 
432  ret = 0;
433 fail:
434  av_channel_layout_uninit(&in_ch_layout);
435  av_channel_layout_uninit(&out_ch_layout);
436 
437  return ret;
438 }
439 
441 {
442  double maxval;
443  int ret;
444 
445  if (s->rematrix_maxval > 0) {
446  maxval = s->rematrix_maxval;
447  } else if ( av_get_packed_sample_fmt(s->out_sample_fmt) < AV_SAMPLE_FMT_FLT
448  || av_get_packed_sample_fmt(s->int_sample_fmt) < AV_SAMPLE_FMT_FLT) {
449  maxval = 1.0;
450  } else
451  maxval = INT_MAX;
452 
453  memset(s->matrix, 0, sizeof(s->matrix));
454  ret = swr_build_matrix2(&s->in_ch_layout, &s->out_ch_layout,
455  s->clev, s->slev, s->lfe_mix_level,
456  maxval, s->rematrix_volume, (double*)s->matrix,
457  s->matrix[1] - s->matrix[0], s->matrix_encoding, s);
458 
459  if (ret >= 0 && s->int_sample_fmt == AV_SAMPLE_FMT_FLTP) {
460  int i, j;
461  for (i = 0; i < FF_ARRAY_ELEMS(s->matrix[0]); i++)
462  for (j = 0; j < FF_ARRAY_ELEMS(s->matrix[0]); j++)
463  s->matrix_flt[i][j] = s->matrix[i][j];
464  }
465 
466  return ret;
467 }
468 
470  int i, j;
471  int nb_in = s->used_ch_count;
472  int nb_out = s->out.ch_count;
473 
474  s->mix_any_f = NULL;
475 
476  if (!s->rematrix_custom) {
477  int r = auto_matrix(s);
478  if (r)
479  return r;
480  }
481  if (s->midbuf.fmt == AV_SAMPLE_FMT_S16P){
482  int maxsum = 0;
483  s->native_matrix = av_calloc(nb_in * nb_out, sizeof(int));
484  s->native_one = av_mallocz(sizeof(int));
485  if (!s->native_matrix || !s->native_one)
486  return AVERROR(ENOMEM);
487  for (i = 0; i < nb_out; i++) {
488  double rem = 0;
489  int sum = 0;
490 
491  for (j = 0; j < nb_in; j++) {
492  double target = s->matrix[i][j] * 32768 + rem;
493  ((int*)s->native_matrix)[i * nb_in + j] = lrintf(target);
494  rem += target - ((int*)s->native_matrix)[i * nb_in + j];
495  sum += FFABS(((int*)s->native_matrix)[i * nb_in + j]);
496  }
497  maxsum = FFMAX(maxsum, sum);
498  }
499  *((int*)s->native_one) = 32768;
500  if (maxsum <= 32768) {
501  s->mix_1_1_f = (mix_1_1_func_type*)copy_s16;
502  s->mix_2_1_f = (mix_2_1_func_type*)sum2_s16;
503  s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s16(s);
504  } else {
505  s->mix_1_1_f = (mix_1_1_func_type*)copy_clip_s16;
506  s->mix_2_1_f = (mix_2_1_func_type*)sum2_clip_s16;
507  s->mix_any_f = (mix_any_func_type*)get_mix_any_func_clip_s16(s);
508  }
509  }else if(s->midbuf.fmt == AV_SAMPLE_FMT_FLTP){
510  s->native_matrix = av_calloc(nb_in * nb_out, sizeof(float));
511  s->native_one = av_mallocz(sizeof(float));
512  if (!s->native_matrix || !s->native_one)
513  return AVERROR(ENOMEM);
514  for (i = 0; i < nb_out; i++)
515  for (j = 0; j < nb_in; j++)
516  ((float*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
517  *((float*)s->native_one) = 1.0;
518  s->mix_1_1_f = (mix_1_1_func_type*)copy_float;
519  s->mix_2_1_f = (mix_2_1_func_type*)sum2_float;
520  s->mix_any_f = (mix_any_func_type*)get_mix_any_func_float(s);
521  }else if(s->midbuf.fmt == AV_SAMPLE_FMT_DBLP){
522  s->native_matrix = av_calloc(nb_in * nb_out, sizeof(double));
523  s->native_one = av_mallocz(sizeof(double));
524  if (!s->native_matrix || !s->native_one)
525  return AVERROR(ENOMEM);
526  for (i = 0; i < nb_out; i++)
527  for (j = 0; j < nb_in; j++)
528  ((double*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
529  *((double*)s->native_one) = 1.0;
530  s->mix_1_1_f = (mix_1_1_func_type*)copy_double;
531  s->mix_2_1_f = (mix_2_1_func_type*)sum2_double;
532  s->mix_any_f = (mix_any_func_type*)get_mix_any_func_double(s);
533  }else if(s->midbuf.fmt == AV_SAMPLE_FMT_S32P){
534  s->native_one = av_mallocz(sizeof(int));
535  if (!s->native_one)
536  return AVERROR(ENOMEM);
537  s->native_matrix = av_calloc(nb_in * nb_out, sizeof(int));
538  if (!s->native_matrix) {
539  av_freep(&s->native_one);
540  return AVERROR(ENOMEM);
541  }
542  for (i = 0; i < nb_out; i++) {
543  double rem = 0;
544 
545  for (j = 0; j < nb_in; j++) {
546  double target = s->matrix[i][j] * 32768 + rem;
547  ((int*)s->native_matrix)[i * nb_in + j] = lrintf(target);
548  rem += target - ((int*)s->native_matrix)[i * nb_in + j];
549  }
550  }
551  *((int*)s->native_one) = 32768;
552  s->mix_1_1_f = (mix_1_1_func_type*)copy_s32;
553  s->mix_2_1_f = (mix_2_1_func_type*)sum2_s32;
554  s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s32(s);
555  }else
556  av_assert0(0);
557  //FIXME quantize for integeres
558  for (i = 0; i < SWR_CH_MAX; i++) {
559  int ch_in=0;
560  for (j = 0; j < SWR_CH_MAX; j++) {
561  s->matrix32[i][j]= lrintf(s->matrix[i][j] * 32768);
562  if(s->matrix[i][j])
563  s->matrix_ch[i][++ch_in]= j;
564  }
565  s->matrix_ch[i][0]= ch_in;
566  }
567 
568 #if ARCH_X86 && HAVE_X86ASM && HAVE_MMX
569  return swri_rematrix_init_x86(s);
570 #endif
571 
572  return 0;
573 }
574 
576  av_freep(&s->native_matrix);
577  av_freep(&s->native_one);
578  av_freep(&s->native_simd_matrix);
579  av_freep(&s->native_simd_one);
580 }
581 
582 int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){
583  int out_i, in_i, i, j;
584  int len1 = 0;
585  int off = 0;
586 
587  if(s->mix_any_f) {
588  s->mix_any_f(out->ch, (const uint8_t **)in->ch, s->native_matrix, len);
589  return 0;
590  }
591 
592  if(s->mix_2_1_simd || s->mix_1_1_simd){
593  len1= len&~15;
594  off = len1 * out->bps;
595  }
596 
597  av_assert0(s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC || out->ch_count == s->out_ch_layout.nb_channels);
598  av_assert0(s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC || in ->ch_count == s->in_ch_layout.nb_channels);
599 
600  for(out_i=0; out_i<out->ch_count; out_i++){
601  switch(s->matrix_ch[out_i][0]){
602  case 0:
603  if(mustcopy)
604  memset(out->ch[out_i], 0, len * av_get_bytes_per_sample(s->int_sample_fmt));
605  break;
606  case 1:
607  in_i= s->matrix_ch[out_i][1];
608  if(s->matrix[out_i][in_i]!=1.0){
609  if(s->mix_1_1_simd && len1)
610  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);
611  if(len != len1)
612  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);
613  }else if(mustcopy){
614  memcpy(out->ch[out_i], in->ch[in_i], len*out->bps);
615  }else{
616  out->ch[out_i]= in->ch[in_i];
617  }
618  break;
619  case 2: {
620  int in_i1 = s->matrix_ch[out_i][1];
621  int in_i2 = s->matrix_ch[out_i][2];
622  if(s->mix_2_1_simd && len1)
623  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);
624  else
625  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);
626  if(len != len1)
627  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);
628  break;}
629  default:
630  if(s->int_sample_fmt == AV_SAMPLE_FMT_FLTP){
631  for(i=0; i<len; i++){
632  float v=0;
633  for(j=0; j<s->matrix_ch[out_i][0]; j++){
634  in_i= s->matrix_ch[out_i][1+j];
635  v+= ((float*)in->ch[in_i])[i] * s->matrix_flt[out_i][in_i];
636  }
637  ((float*)out->ch[out_i])[i]= v;
638  }
639  }else if(s->int_sample_fmt == AV_SAMPLE_FMT_DBLP){
640  for(i=0; i<len; i++){
641  double v=0;
642  for(j=0; j<s->matrix_ch[out_i][0]; j++){
643  in_i= s->matrix_ch[out_i][1+j];
644  v+= ((double*)in->ch[in_i])[i] * s->matrix[out_i][in_i];
645  }
646  ((double*)out->ch[out_i])[i]= v;
647  }
648  }else{
649  for(i=0; i<len; i++){
650  int v=0;
651  for(j=0; j<s->matrix_ch[out_i][0]; j++){
652  in_i= s->matrix_ch[out_i][1+j];
653  v+= ((int16_t*)in->ch[in_i])[i] * s->matrix32[out_i][in_i];
654  }
655  ((int16_t*)out->ch[out_i])[i]= (v + 16384)>>15;
656  }
657  }
658  }
659  }
660  return 0;
661 }
mix_any_func_type
void() mix_any_func_type(uint8_t **out, const uint8_t **in1, void *coeffp, integer len)
Definition: swresample_internal.h:43
FF_ENABLE_DEPRECATION_WARNINGS
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:83
AV_SAMPLE_FMT_FLTP
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition: samplefmt.h:66
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
AV_CH_LAYOUT_7POINT1_WIDE_BACK
#define AV_CH_LAYOUT_7POINT1_WIDE_BACK
Definition: channel_layout.h:228
r
const char * r
Definition: vf_curves.c:116
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
out
FILE * out
Definition: movenc.c:54
NUM_NAMED_CHANNELS
#define NUM_NAMED_CHANNELS
Definition: rematrix.c:62
matrix
Definition: vc1dsp.c:42
rematrix_template.c
AV_CHANNEL_LAYOUT_STEREO_DOWNMIX
#define AV_CHANNEL_LAYOUT_STEREO_DOWNMIX
Definition: channel_layout.h:380
AV_SAMPLE_FMT_S32P
@ AV_SAMPLE_FMT_S32P
signed 32 bits, planar
Definition: samplefmt.h:65
swri_rematrix_init_x86
int swri_rematrix_init_x86(struct SwrContext *s)
AV_CHANNEL_LAYOUT_MONO
#define AV_CHANNEL_LAYOUT_MONO
Definition: channel_layout.h:353
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
sane_layout
static int sane_layout(AVChannelLayout *ch_layout)
Definition: rematrix.c:128
av_channel_layout_subset
uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout, uint64_t mask)
Find out what channels from a given set are present in a channel layout, without regard for their pos...
Definition: channel_layout.c:986
AV_CHANNEL_LAYOUT_STEREO
#define AV_CHANNEL_LAYOUT_STEREO
Definition: channel_layout.h:354
SQRT3_2
#define SQRT3_2
Definition: swresample_internal.h:30
AVChannelLayout::order
enum AVChannelOrder order
Channel order used in this layout.
Definition: channel_layout.h:295
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVChannelLayout::mask
uint64_t mask
This member must be used for AV_CHANNEL_ORDER_NATIVE, and may be used for AV_CHANNEL_ORDER_AMBISONIC ...
Definition: channel_layout.h:322
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:300
swr_set_matrix
int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride)
Set a customized remix matrix.
Definition: rematrix.c:64
av_channel_layout_copy
int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src)
Make a copy of a channel layout.
Definition: channel_layout.c:637
AudioData
Definition: swresample_internal.h:45
fail
#define fail()
Definition: checkasm.h:131
FRONT_LEFT_OF_CENTER
#define FRONT_LEFT_OF_CENTER
Definition: rematrix.c:50
AV_CH_BACK_LEFT
#define AV_CH_BACK_LEFT
Definition: channel_layout.h:162
AV_CH_LAYOUT_STEREO
#define AV_CH_LAYOUT_STEREO
Definition: channel_layout.h:205
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
even
static int even(int64_t layout)
Definition: rematrix.c:107
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
AV_MATRIX_ENCODING_DOLBY
@ AV_MATRIX_ENCODING_DOLBY
Definition: channel_layout.h:236
AV_CHANNEL_ORDER_NATIVE
@ AV_CHANNEL_ORDER_NATIVE
The native channel order, i.e.
Definition: channel_layout.h:112
AV_CH_LOW_FREQUENCY
#define AV_CH_LOW_FREQUENCY
Definition: channel_layout.h:161
s
#define s(width, name)
Definition: cbs_vp9.c:256
AV_CHANNEL_ORDER_UNSPEC
@ AV_CHANNEL_ORDER_UNSPEC
Only the channel count is specified, without any further information about the channel order.
Definition: channel_layout.h:106
AV_CH_LAYOUT_STEREO_DOWNMIX
#define AV_CH_LAYOUT_STEREO_DOWNMIX
Definition: channel_layout.h:231
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
swri_rematrix
int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy)
Definition: rematrix.c:582
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
auto_matrix
static av_cold int auto_matrix(SwrContext *s)
Definition: rematrix.c:440
SwrContext
The libswresample context.
Definition: swresample_internal.h:95
AudioData::ch
uint8_t * ch[SWR_CH_MAX]
samples buffer per channel
Definition: swresample_internal.h:46
FRONT_RIGHT
#define FRONT_RIGHT
Definition: rematrix.c:45
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:64
swr_build_matrix2
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)
Generate a channel mixing matrix.
Definition: rematrix.c:168
AVMatrixEncoding
AVMatrixEncoding
Definition: channel_layout.h:234
AVChannelLayout::u
union AVChannelLayout::@296 u
Details about which channels are present in this layout.
fabs
static __device__ float fabs(float a)
Definition: cuda_runtime.h:182
NULL
#define NULL
Definition: coverity.c:32
AV_CHAN_FRONT_LEFT
@ AV_CHAN_FRONT_LEFT
Definition: channel_layout.h:44
av_channel_layout_compare
int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1)
Check whether two channel layouts are semantically the same, i.e.
Definition: channel_layout.c:930
AV_CH_FRONT_CENTER
#define AV_CH_FRONT_CENTER
Definition: channel_layout.h:160
AV_CH_FRONT_LEFT_OF_CENTER
#define AV_CH_FRONT_LEFT_OF_CENTER
Definition: channel_layout.h:164
av_channel_layout_uninit
void av_channel_layout_uninit(AVChannelLayout *channel_layout)
Free any allocated data in the channel layout and reset the channel count to 0.
Definition: channel_layout.c:630
AudioData::ch_count
int ch_count
number of channels
Definition: swresample_internal.h:48
copy_double
static void copy_double(SilenceRemoveContext *s, AVFrame *out, AVFrame *in, int ch, int out_offset, int in_offset)
Definition: af_silenceremove.c:135
mix_2_1_func_type
void() mix_2_1_func_type(void *out, const void *in1, const void *in2, void *coeffp, integer index1, integer index2, integer len)
Definition: swresample_internal.h:41
BACK_LEFT
#define BACK_LEFT
Definition: rematrix.c:48
AV_CHAN_BACK_LEFT
@ AV_CHAN_BACK_LEFT
Definition: channel_layout.h:48
AVChannelLayout
An AVChannelLayout holds information about the channel layout of audio data.
Definition: channel_layout.h:290
av_get_channel_layout_nb_channels
int av_get_channel_layout_nb_channels(uint64_t channel_layout)
Return the number of channels in the channel layout.
Definition: channel_layout.c:318
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:425
FF_API_OLD_CHANNEL_LAYOUT
#define FF_API_OLD_CHANNEL_LAYOUT
Definition: version.h:115
BACK_RIGHT
#define BACK_RIGHT
Definition: rematrix.c:49
AV_CHAN_BACK_CENTER
@ AV_CHAN_BACK_CENTER
Definition: channel_layout.h:52
SIDE_LEFT
#define SIDE_LEFT
Definition: rematrix.c:53
swri_rematrix_free
av_cold void swri_rematrix_free(SwrContext *s)
Definition: rematrix.c:575
AV_CHAN_SIDE_LEFT
@ AV_CHAN_SIDE_LEFT
Definition: channel_layout.h:53
swresample_internal.h
AV_CH_FRONT_RIGHT_OF_CENTER
#define AV_CH_FRONT_RIGHT_OF_CENTER
Definition: channel_layout.h:165
FRONT_CENTER
#define FRONT_CENTER
Definition: rematrix.c:46
AV_SAMPLE_FMT_S16P
@ AV_SAMPLE_FMT_S16P
signed 16 bits, planar
Definition: samplefmt.h:64
av_channel_name
int av_channel_name(char *buf, size_t buf_size, enum AVChannel channel_id)
Get a human readable string in an abbreviated form describing a given channel.
Definition: channel_layout.c:101
layout
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel layout
Definition: filter_design.txt:18
mix_1_1_func_type
void() mix_1_1_func_type(void *out, const void *in, void *coeffp, integer index, integer len)
Definition: swresample_internal.h:40
FRONT_RIGHT_OF_CENTER
#define FRONT_RIGHT_OF_CENTER
Definition: rematrix.c:51
lrintf
#define lrintf(x)
Definition: libm_mips.h:72
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
av_get_bytes_per_sample
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition: samplefmt.c:108
av_channel_layout_check
int av_channel_layout_check(const AVChannelLayout *channel_layout)
Check whether a channel layout is valid, i.e.
Definition: channel_layout.c:904
AV_CHAN_FRONT_CENTER
@ AV_CHAN_FRONT_CENTER
Definition: channel_layout.h:46
AV_CH_BACK_CENTER
#define AV_CH_BACK_CENTER
Definition: channel_layout.h:166
AV_CH_FRONT_LEFT
#define AV_CH_FRONT_LEFT
Definition: channel_layout.h:158
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:264
AV_CH_SIDE_RIGHT
#define AV_CH_SIDE_RIGHT
Definition: channel_layout.h:168
len
int len
Definition: vorbis_enc_data.h:426
av_channel_layout_index_from_channel
int av_channel_layout_index_from_channel(const AVChannelLayout *channel_layout, enum AVChannel channel)
Get the index of a given channel in a channel layout.
Definition: channel_layout.c:834
FRONT_LEFT
#define FRONT_LEFT
Definition: rematrix.c:44
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:272
av_channel_layout_channel_from_index
enum AVChannel av_channel_layout_channel_from_index(const AVChannelLayout *channel_layout, unsigned int idx)
Get the channel with the given index in a channel layout.
Definition: channel_layout.c:794
stride
#define stride
Definition: h264pred_template.c:537
av_channel_layout_from_mask
FF_ENABLE_DEPRECATION_WARNINGS int av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask)
Initialize a native channel layout from a bitmask indicating which channels are present.
Definition: channel_layout.c:389
ret
ret
Definition: filter_design.txt:187
AV_CH_LAYOUT_SURROUND
#define AV_CH_LAYOUT_SURROUND
Definition: channel_layout.h:208
M_SQRT1_2
#define M_SQRT1_2
Definition: mathematics.h:58
SWR_CH_MAX
#define SWR_CH_MAX
Definition: af_amerge.c:35
channel_layout.h
av_get_packed_sample_fmt
enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt)
Get the packed alternative form of the given sample format.
Definition: samplefmt.c:77
AV_SAMPLE_FMT_DBLP
@ AV_SAMPLE_FMT_DBLP
double, planar
Definition: samplefmt.h:67
av_channel_layout_describe
int av_channel_layout_describe(const AVChannelLayout *channel_layout, char *buf, size_t buf_size)
Get a human-readable string describing the channel layout properties.
Definition: channel_layout.c:776
swri_rematrix_init
av_cold int swri_rematrix_init(SwrContext *s)
Definition: rematrix.c:469
AV_CH_FRONT_RIGHT
#define AV_CH_FRONT_RIGHT
Definition: channel_layout.h:159
FF_DISABLE_DEPRECATION_WARNINGS
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:82
LOW_FREQUENCY
#define LOW_FREQUENCY
Definition: rematrix.c:47
BACK_CENTER
#define BACK_CENTER
Definition: rematrix.c:52
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
SIDE_RIGHT
#define SIDE_RIGHT
Definition: rematrix.c:54
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
copy_float
static void copy_float(SilenceRemoveContext *s, AVFrame *out, AVFrame *in, int ch, int out_offset, int in_offset)
Definition: af_silenceremove.c:155
AV_CH_BACK_RIGHT
#define AV_CH_BACK_RIGHT
Definition: channel_layout.h:163
AV_CHANNEL_LAYOUT_22POINT2
#define AV_CHANNEL_LAYOUT_22POINT2
Definition: channel_layout.h:381
AV_SAMPLE_FMT_FLT
@ AV_SAMPLE_FMT_FLT
float
Definition: samplefmt.h:60
AV_CH_SIDE_LEFT
#define AV_CH_SIDE_LEFT
Definition: channel_layout.h:167
AV_MATRIX_ENCODING_DPLII
@ AV_MATRIX_ENCODING_DPLII
Definition: channel_layout.h:237
clean_layout
static int clean_layout(AVChannelLayout *out, const AVChannelLayout *in, void *s)
Definition: rematrix.c:113