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 
68  if (!s || s->in_convert) // s needs to be allocated but not initialized
69  return AVERROR(EINVAL);
70  memset(s->matrix, 0, sizeof(s->matrix));
71  memset(s->matrix_flt, 0, sizeof(s->matrix_flt));
72  nb_in = (s->user_in_ch_count > 0) ? s->user_in_ch_count :
74  nb_out = (s->user_out_ch_count > 0) ? s->user_out_ch_count :
76  for (out = 0; out < nb_out; out++) {
77  for (in = 0; in < nb_in; in++)
78  s->matrix_flt[out][in] = s->matrix[out][in] = matrix[in];
79  matrix += stride;
80  }
81  s->rematrix_custom = 1;
82  return 0;
83 }
84 
85 static int even(int64_t layout){
86  if(!layout) return 1;
87  if(layout&(layout-1)) return 1;
88  return 0;
89 }
90 
91 static int64_t clean_layout(void *s, int64_t layout){
92  if(layout && layout != AV_CH_FRONT_CENTER && !(layout&(layout-1))) {
93  char buf[128];
94  av_get_channel_layout_string(buf, sizeof(buf), -1, layout);
95  av_log(s, AV_LOG_VERBOSE, "Treating %s as mono\n", buf);
96  return AV_CH_FRONT_CENTER;
97  }
98 
99  return layout;
100 }
101 
102 static int sane_layout(int64_t layout){
103  if(!(layout & AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker
104  return 0;
105  if(!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT))) // no asymetric front
106  return 0;
107  if(!even(layout & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT))) // no asymetric side
108  return 0;
109  if(!even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)))
110  return 0;
112  return 0;
114  return 0;
115 
116  return 1;
117 }
118 
119 av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout_param,
120  double center_mix_level, double surround_mix_level,
121  double lfe_mix_level, double maxval,
122  double rematrix_volume, double *matrix_param,
123  int stride, enum AVMatrixEncoding matrix_encoding, void *log_context)
124 {
125  int i, j, out_i;
126  double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS]={{0}};
127  int64_t unaccounted, in_ch_layout, out_ch_layout;
128  double maxcoef=0;
129  char buf[128];
130 
131  in_ch_layout = clean_layout(log_context, in_ch_layout_param);
132  out_ch_layout = clean_layout(log_context, out_ch_layout_param);
133 
134  if( out_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX
135  && (in_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0
136  )
137  out_ch_layout = AV_CH_LAYOUT_STEREO;
138 
139  if( in_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX
140  && (out_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0
141  )
142  in_ch_layout = AV_CH_LAYOUT_STEREO;
143 
144  if (in_ch_layout == AV_CH_LAYOUT_22POINT2 &&
145  out_ch_layout != AV_CH_LAYOUT_22POINT2) {
147  av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout);
148  av_log(log_context, AV_LOG_WARNING,
149  "Full-on remixing from 22.2 has not yet been implemented! "
150  "Processing the input as '%s'\n",
151  buf);
152  }
153 
154  if(!sane_layout(in_ch_layout)){
155  av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout_param);
156  av_log(log_context, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf);
157  return AVERROR(EINVAL);
158  }
159 
160  if(!sane_layout(out_ch_layout)){
161  av_get_channel_layout_string(buf, sizeof(buf), -1, out_ch_layout_param);
162  av_log(log_context, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf);
163  return AVERROR(EINVAL);
164  }
165 
166  for(i=0; i<FF_ARRAY_ELEMS(matrix); i++){
167  if(in_ch_layout & out_ch_layout & (1ULL<<i))
168  matrix[i][i]= 1.0;
169  }
170 
171  unaccounted= in_ch_layout & ~out_ch_layout;
172 
173 //FIXME implement dolby surround
174 //FIXME implement full ac3
175 
176 
177  if(unaccounted & AV_CH_FRONT_CENTER){
178  if((out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){
179  if(in_ch_layout & AV_CH_LAYOUT_STEREO) {
180  matrix[ FRONT_LEFT][FRONT_CENTER]+= center_mix_level;
181  matrix[FRONT_RIGHT][FRONT_CENTER]+= center_mix_level;
182  } else {
183  matrix[ FRONT_LEFT][FRONT_CENTER]+= M_SQRT1_2;
185  }
186  }else
187  av_assert0(0);
188  }
189  if(unaccounted & AV_CH_LAYOUT_STEREO){
190  if(out_ch_layout & AV_CH_FRONT_CENTER){
191  matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2;
193  if(in_ch_layout & AV_CH_FRONT_CENTER)
194  matrix[FRONT_CENTER][ FRONT_CENTER] = center_mix_level*sqrt(2);
195  }else
196  av_assert0(0);
197  }
198 
199  if(unaccounted & AV_CH_BACK_CENTER){
200  if(out_ch_layout & AV_CH_BACK_LEFT){
201  matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2;
202  matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2;
203  }else if(out_ch_layout & AV_CH_SIDE_LEFT){
204  matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2;
205  matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2;
206  }else if(out_ch_layout & AV_CH_FRONT_LEFT){
207  if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
208  matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
209  if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
210  matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level * M_SQRT1_2;
211  matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
212  } else {
213  matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level;
214  matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level;
215  }
216  } else {
217  matrix[ FRONT_LEFT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
218  matrix[FRONT_RIGHT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
219  }
220  }else if(out_ch_layout & AV_CH_FRONT_CENTER){
221  matrix[ FRONT_CENTER][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
222  }else
223  av_assert0(0);
224  }
225  if(unaccounted & AV_CH_BACK_LEFT){
226  if(out_ch_layout & AV_CH_BACK_CENTER){
227  matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2;
228  matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2;
229  }else if(out_ch_layout & AV_CH_SIDE_LEFT){
230  if(in_ch_layout & AV_CH_SIDE_LEFT){
231  matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2;
232  matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2;
233  }else{
234  matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0;
235  matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0;
236  }
237  }else if(out_ch_layout & AV_CH_FRONT_LEFT){
238  if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
239  matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2;
240  matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
241  matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
242  matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
243  } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
244  matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * SQRT3_2;
245  matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
246  matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
247  matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * SQRT3_2;
248  } else {
249  matrix[ FRONT_LEFT][ BACK_LEFT] += surround_mix_level;
250  matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
251  }
252  }else if(out_ch_layout & AV_CH_FRONT_CENTER){
253  matrix[ FRONT_CENTER][BACK_LEFT ]+= surround_mix_level*M_SQRT1_2;
254  matrix[ FRONT_CENTER][BACK_RIGHT]+= surround_mix_level*M_SQRT1_2;
255  }else
256  av_assert0(0);
257  }
258 
259  if(unaccounted & AV_CH_SIDE_LEFT){
260  if(out_ch_layout & AV_CH_BACK_LEFT){
261  /* if back channels do not exist in the input, just copy side
262  channels to back channels, otherwise mix side into back */
263  if (in_ch_layout & AV_CH_BACK_LEFT) {
264  matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
265  matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
266  } else {
267  matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
268  matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
269  }
270  }else if(out_ch_layout & AV_CH_BACK_CENTER){
271  matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2;
272  matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2;
273  }else if(out_ch_layout & AV_CH_FRONT_LEFT){
274  if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
275  matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2;
276  matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
277  matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
278  matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
279  } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
280  matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * SQRT3_2;
281  matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
282  matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
283  matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * SQRT3_2;
284  } else {
285  matrix[ FRONT_LEFT][ SIDE_LEFT] += surround_mix_level;
286  matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
287  }
288  }else if(out_ch_layout & AV_CH_FRONT_CENTER){
289  matrix[ FRONT_CENTER][SIDE_LEFT ]+= surround_mix_level * M_SQRT1_2;
290  matrix[ FRONT_CENTER][SIDE_RIGHT]+= surround_mix_level * M_SQRT1_2;
291  }else
292  av_assert0(0);
293  }
294 
295  if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){
296  if(out_ch_layout & AV_CH_FRONT_LEFT){
297  matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0;
298  matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0;
299  }else if(out_ch_layout & AV_CH_FRONT_CENTER){
302  }else
303  av_assert0(0);
304  }
305  /* mix LFE into front left/right or center */
306  if (unaccounted & AV_CH_LOW_FREQUENCY) {
307  if (out_ch_layout & AV_CH_FRONT_CENTER) {
308  matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level;
309  } else if (out_ch_layout & AV_CH_FRONT_LEFT) {
310  matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
311  matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
312  } else
313  av_assert0(0);
314  }
315 
316  for(out_i=i=0; i<64; i++){
317  double sum=0;
318  int in_i=0;
319  if((out_ch_layout & (1ULL<<i)) == 0)
320  continue;
321  for(j=0; j<64; j++){
322  if((in_ch_layout & (1ULL<<j)) == 0)
323  continue;
324  if (i < FF_ARRAY_ELEMS(matrix) && j < FF_ARRAY_ELEMS(matrix[0]))
325  matrix_param[stride*out_i + in_i] = matrix[i][j];
326  else
327  matrix_param[stride*out_i + in_i] = i == j && (in_ch_layout & out_ch_layout & (1ULL<<i));
328  sum += fabs(matrix_param[stride*out_i + in_i]);
329  in_i++;
330  }
331  maxcoef= FFMAX(maxcoef, sum);
332  out_i++;
333  }
334  if(rematrix_volume < 0)
335  maxcoef = -rematrix_volume;
336 
337  if(maxcoef > maxval || rematrix_volume < 0){
338  maxcoef /= maxval;
339  for(i=0; i<SWR_CH_MAX; i++)
340  for(j=0; j<SWR_CH_MAX; j++){
341  matrix_param[stride*i + j] /= maxcoef;
342  }
343  }
344 
345  if(rematrix_volume > 0){
346  for(i=0; i<SWR_CH_MAX; i++)
347  for(j=0; j<SWR_CH_MAX; j++){
348  matrix_param[stride*i + j] *= rematrix_volume;
349  }
350  }
351 
352  av_log(log_context, AV_LOG_DEBUG, "Matrix coefficients:\n");
353  for(i=0; i<av_get_channel_layout_nb_channels(out_ch_layout); i++){
354  const char *c =
356  av_log(log_context, AV_LOG_DEBUG, "%s: ", c ? c : "?");
357  for(j=0; j<av_get_channel_layout_nb_channels(in_ch_layout); j++){
359  av_log(log_context, AV_LOG_DEBUG, "%s:%f ", c ? c : "?", matrix_param[stride*i + j]);
360  }
361  av_log(log_context, AV_LOG_DEBUG, "\n");
362  }
363  return 0;
364 }
365 
367 {
368  double maxval;
369  int ret;
370 
371  if (s->rematrix_maxval > 0) {
372  maxval = s->rematrix_maxval;
375  maxval = 1.0;
376  } else
377  maxval = INT_MAX;
378 
379  memset(s->matrix, 0, sizeof(s->matrix));
381  s->clev, s->slev, s->lfe_mix_level,
382  maxval, s->rematrix_volume, (double*)s->matrix,
383  s->matrix[1] - s->matrix[0], s->matrix_encoding, s);
384 
385  if (ret >= 0 && s->int_sample_fmt == AV_SAMPLE_FMT_FLTP) {
386  int i, j;
387  for (i = 0; i < FF_ARRAY_ELEMS(s->matrix[0]); i++)
388  for (j = 0; j < FF_ARRAY_ELEMS(s->matrix[0]); j++)
389  s->matrix_flt[i][j] = s->matrix[i][j];
390  }
391 
392  return ret;
393 }
394 
396  int i, j;
397  int nb_in = s->used_ch_count;
398  int nb_out = s->out.ch_count;
399 
400  s->mix_any_f = NULL;
401 
402  if (!s->rematrix_custom) {
403  int r = auto_matrix(s);
404  if (r)
405  return r;
406  }
407  if (s->midbuf.fmt == AV_SAMPLE_FMT_S16P){
408  int maxsum = 0;
409  s->native_matrix = av_calloc(nb_in * nb_out, sizeof(int));
410  s->native_one = av_mallocz(sizeof(int));
411  if (!s->native_matrix || !s->native_one)
412  return AVERROR(ENOMEM);
413  for (i = 0; i < nb_out; i++) {
414  double rem = 0;
415  int sum = 0;
416 
417  for (j = 0; j < nb_in; j++) {
418  double target = s->matrix[i][j] * 32768 + rem;
419  ((int*)s->native_matrix)[i * nb_in + j] = lrintf(target);
420  rem += target - ((int*)s->native_matrix)[i * nb_in + j];
421  sum += FFABS(((int*)s->native_matrix)[i * nb_in + j]);
422  }
423  maxsum = FFMAX(maxsum, sum);
424  }
425  *((int*)s->native_one) = 32768;
426  if (maxsum <= 32768) {
427  s->mix_1_1_f = (mix_1_1_func_type*)copy_s16;
428  s->mix_2_1_f = (mix_2_1_func_type*)sum2_s16;
429  s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s16(s);
430  } else {
431  s->mix_1_1_f = (mix_1_1_func_type*)copy_clip_s16;
432  s->mix_2_1_f = (mix_2_1_func_type*)sum2_clip_s16;
433  s->mix_any_f = (mix_any_func_type*)get_mix_any_func_clip_s16(s);
434  }
435  }else if(s->midbuf.fmt == AV_SAMPLE_FMT_FLTP){
436  s->native_matrix = av_calloc(nb_in * nb_out, sizeof(float));
437  s->native_one = av_mallocz(sizeof(float));
438  if (!s->native_matrix || !s->native_one)
439  return AVERROR(ENOMEM);
440  for (i = 0; i < nb_out; i++)
441  for (j = 0; j < nb_in; j++)
442  ((float*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
443  *((float*)s->native_one) = 1.0;
444  s->mix_1_1_f = (mix_1_1_func_type*)copy_float;
445  s->mix_2_1_f = (mix_2_1_func_type*)sum2_float;
446  s->mix_any_f = (mix_any_func_type*)get_mix_any_func_float(s);
447  }else if(s->midbuf.fmt == AV_SAMPLE_FMT_DBLP){
448  s->native_matrix = av_calloc(nb_in * nb_out, sizeof(double));
449  s->native_one = av_mallocz(sizeof(double));
450  if (!s->native_matrix || !s->native_one)
451  return AVERROR(ENOMEM);
452  for (i = 0; i < nb_out; i++)
453  for (j = 0; j < nb_in; j++)
454  ((double*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
455  *((double*)s->native_one) = 1.0;
456  s->mix_1_1_f = (mix_1_1_func_type*)copy_double;
457  s->mix_2_1_f = (mix_2_1_func_type*)sum2_double;
458  s->mix_any_f = (mix_any_func_type*)get_mix_any_func_double(s);
459  }else if(s->midbuf.fmt == AV_SAMPLE_FMT_S32P){
460  s->native_one = av_mallocz(sizeof(int));
461  if (!s->native_one)
462  return AVERROR(ENOMEM);
463  s->native_matrix = av_calloc(nb_in * nb_out, sizeof(int));
464  if (!s->native_matrix) {
465  av_freep(&s->native_one);
466  return AVERROR(ENOMEM);
467  }
468  for (i = 0; i < nb_out; i++) {
469  double rem = 0;
470 
471  for (j = 0; j < nb_in; j++) {
472  double target = s->matrix[i][j] * 32768 + rem;
473  ((int*)s->native_matrix)[i * nb_in + j] = lrintf(target);
474  rem += target - ((int*)s->native_matrix)[i * nb_in + j];
475  }
476  }
477  *((int*)s->native_one) = 32768;
478  s->mix_1_1_f = (mix_1_1_func_type*)copy_s32;
479  s->mix_2_1_f = (mix_2_1_func_type*)sum2_s32;
480  s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s32(s);
481  }else
482  av_assert0(0);
483  //FIXME quantize for integeres
484  for (i = 0; i < SWR_CH_MAX; i++) {
485  int ch_in=0;
486  for (j = 0; j < SWR_CH_MAX; j++) {
487  s->matrix32[i][j]= lrintf(s->matrix[i][j] * 32768);
488  if(s->matrix[i][j])
489  s->matrix_ch[i][++ch_in]= j;
490  }
491  s->matrix_ch[i][0]= ch_in;
492  }
493 
494  if(HAVE_X86ASM && HAVE_MMX)
495  return swri_rematrix_init_x86(s);
496 
497  return 0;
498 }
499 
501  av_freep(&s->native_matrix);
502  av_freep(&s->native_one);
505 }
506 
507 int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){
508  int out_i, in_i, i, j;
509  int len1 = 0;
510  int off = 0;
511 
512  if(s->mix_any_f) {
513  s->mix_any_f(out->ch, (const uint8_t **)in->ch, s->native_matrix, len);
514  return 0;
515  }
516 
517  if(s->mix_2_1_simd || s->mix_1_1_simd){
518  len1= len&~15;
519  off = len1 * out->bps;
520  }
521 
523  av_assert0(!s-> in_ch_layout || in ->ch_count == av_get_channel_layout_nb_channels(s-> in_ch_layout));
524 
525  for(out_i=0; out_i<out->ch_count; out_i++){
526  switch(s->matrix_ch[out_i][0]){
527  case 0:
528  if(mustcopy)
529  memset(out->ch[out_i], 0, len * av_get_bytes_per_sample(s->int_sample_fmt));
530  break;
531  case 1:
532  in_i= s->matrix_ch[out_i][1];
533  if(s->matrix[out_i][in_i]!=1.0){
534  if(s->mix_1_1_simd && len1)
535  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);
536  if(len != len1)
537  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);
538  }else if(mustcopy){
539  memcpy(out->ch[out_i], in->ch[in_i], len*out->bps);
540  }else{
541  out->ch[out_i]= in->ch[in_i];
542  }
543  break;
544  case 2: {
545  int in_i1 = s->matrix_ch[out_i][1];
546  int in_i2 = s->matrix_ch[out_i][2];
547  if(s->mix_2_1_simd && len1)
548  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);
549  else
550  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);
551  if(len != len1)
552  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);
553  break;}
554  default:
556  for(i=0; i<len; i++){
557  float v=0;
558  for(j=0; j<s->matrix_ch[out_i][0]; j++){
559  in_i= s->matrix_ch[out_i][1+j];
560  v+= ((float*)in->ch[in_i])[i] * s->matrix_flt[out_i][in_i];
561  }
562  ((float*)out->ch[out_i])[i]= v;
563  }
564  }else if(s->int_sample_fmt == AV_SAMPLE_FMT_DBLP){
565  for(i=0; i<len; i++){
566  double v=0;
567  for(j=0; j<s->matrix_ch[out_i][0]; j++){
568  in_i= s->matrix_ch[out_i][1+j];
569  v+= ((double*)in->ch[in_i])[i] * s->matrix[out_i][in_i];
570  }
571  ((double*)out->ch[out_i])[i]= v;
572  }
573  }else{
574  for(i=0; i<len; i++){
575  int v=0;
576  for(j=0; j<s->matrix_ch[out_i][0]; j++){
577  in_i= s->matrix_ch[out_i][1+j];
578  v+= ((int16_t*)in->ch[in_i])[i] * s->matrix32[out_i][in_i];
579  }
580  ((int16_t*)out->ch[out_i])[i]= (v + 16384)>>15;
581  }
582  }
583  }
584  }
585  return 0;
586 }
float, planar
Definition: samplefmt.h:69
struct AudioConvert * in_convert
input conversion context
#define NULL
Definition: coverity.c:32
#define BACK_RIGHT
Definition: rematrix.c:49
#define FRONT_RIGHT
Definition: rematrix.c:45
enum AVSampleFormat int_sample_fmt
internal sample format (AV_SAMPLE_FMT_FLTP or AV_SAMPLE_FMT_S16P)
Audio buffer used for intermediate storage between conversion phases.
Definition: audio_data.h:37
#define FRONT_RIGHT_OF_CENTER
Definition: rematrix.c:51
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
#define AV_CH_LAYOUT_SURROUND
int ch_count
number of channels
#define SWR_CH_MAX
Definition: af_amerge.c:35
#define M_SQRT1_2
Definition: mathematics.h:58
int rematrix_custom
flag to indicate that a custom matrix has been defined
int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy)
Definition: rematrix.c:507
double, planar
Definition: samplefmt.h:70
#define LOW_FREQUENCY
Definition: rematrix.c:47
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:237
#define AV_CH_LAYOUT_STEREO
#define SQRT3_2
#define SIDE_RIGHT
Definition: rematrix.c:54
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)
Generate a channel mixing matrix.
Definition: rematrix.c:119
void( mix_2_1_func_type)(void *out, const void *in1, const void *in2, void *coeffp, integer index1, integer index2, integer len)
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:245
int av_get_channel_layout_nb_channels(uint64_t channel_layout)
Return the number of channels in the channel layout.
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
av_cold int swri_rematrix_init(SwrContext *s)
Definition: rematrix.c:395
uint8_t
#define av_cold
Definition: attributes.h:88
int user_out_ch_count
User set output channel count.
enum AVSampleFormat fmt
sample format
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
#define BACK_CENTER
Definition: rematrix.c:52
AudioData out
converted output audio data
#define AV_CH_LOW_FREQUENCY
uint8_t * native_simd_one
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:210
#define lrintf(x)
Definition: libm_mips.h:70
#define AV_CH_BACK_LEFT
enum AVSampleFormat out_sample_fmt
output sample format
#define av_log(a,...)
#define AV_CH_LAYOUT_22POINT2
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
int matrix_encoding
matrixed stereo encoding
float slev
surround mixing level
static __device__ float fabs(float a)
Definition: cuda_runtime.h:182
#define FRONT_CENTER
Definition: rematrix.c:46
int64_t user_in_ch_layout
User set input channel layout.
The libswresample context.
#define SIDE_LEFT
Definition: rematrix.c:53
int swri_rematrix_init_x86(struct SwrContext *s)
const char * r
Definition: vf_curves.c:114
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
float clev
center mixing level
simple assert() macros that are a bit more flexible than ISO C assert().
void( mix_any_func_type)(uint8_t **out, const uint8_t **in1, void *coeffp, integer len)
static int64_t clean_layout(void *s, int64_t layout)
Definition: rematrix.c:91
mix_2_1_func_type * mix_2_1_simd
#define FFMAX(a, b)
Definition: common.h:94
#define NUM_NAMED_CHANNELS
Definition: rematrix.c:62
int32_t matrix32[SWR_CH_MAX][SWR_CH_MAX]
17.15 fixed point rematrixing coefficients
AudioData midbuf
intermediate audio data (postin/preout)
audio channel layout utility functions
#define AV_CH_LAYOUT_STEREO_DOWNMIX
#define FRONT_LEFT_OF_CENTER
Definition: rematrix.c:50
signed 32 bits, planar
Definition: samplefmt.h:68
int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride)
Set a customized remix matrix.
Definition: rematrix.c:64
mix_1_1_func_type * mix_1_1_f
mix_1_1_func_type * mix_1_1_simd
int64_t out_ch_layout
output channel layout
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:72
#define s(width, name)
Definition: cbs_vp9.c:257
int bps
bytes per sample
#define AV_CH_FRONT_LEFT_OF_CENTER
uint8_t * native_matrix
mix_any_func_type * mix_any_f
#define AV_CH_FRONT_CENTER
#define FF_ARRAY_ELEMS(a)
#define AV_CH_FRONT_RIGHT_OF_CENTER
void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout)
Return a description of a channel layout.
int user_in_ch_count
User set input channel count.
static av_cold int auto_matrix(SwrContext *s)
Definition: rematrix.c:366
#define AV_CH_FRONT_LEFT
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
#define AV_CH_LAYOUT_7POINT1_WIDE_BACK
float matrix_flt[SWR_CH_MAX][SWR_CH_MAX]
single precision floating point rematrixing coefficients
static int sane_layout(int64_t layout)
Definition: rematrix.c:102
#define BACK_LEFT
Definition: rematrix.c:48
#define AV_CH_BACK_CENTER
double matrix[SWR_CH_MAX][SWR_CH_MAX]
floating point rematrixing coefficients
uint8_t * native_one
#define AV_CH_SIDE_RIGHT
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition: samplefmt.c:106
void( mix_1_1_func_type)(void *out, const void *in, void *coeffp, integer index, integer len)
int64_t in_ch_layout
input channel layout
GLint GLenum GLboolean GLsizei stride
Definition: opengl_enc.c:104
enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt)
Get the packed alternative form of the given sample format.
Definition: samplefmt.c:75
uint8_t * native_simd_matrix
uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index)
Get the channel with the given index in channel_layout.
float lfe_mix_level
LFE mixing level.
const char * av_get_channel_name(uint64_t channel)
Get the name of a given channel.
av_cold void swri_rematrix_free(SwrContext *s)
Definition: rematrix.c:500
int len
float rematrix_maxval
maximum value for rematrixing output
float rematrix_volume
rematrixing volume coefficient
mix_2_1_func_type * mix_2_1_f
#define AV_CH_FRONT_RIGHT
FILE * out
Definition: movenc.c:54
#define av_freep(p)
signed 16 bits, planar
Definition: samplefmt.h:67
static int even(int64_t layout)
Definition: rematrix.c:85
AVMatrixEncoding
#define AV_CH_SIDE_LEFT
#define FRONT_LEFT
Definition: rematrix.c:44
uint8_t matrix_ch[SWR_CH_MAX][SWR_CH_MAX+1]
Lists of input channels per output channel that have non zero rematrixing coefficients.
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
uint8_t * ch[SWR_CH_MAX]
samples buffer per channel
int used_ch_count
number of used input channels (mapped channel count if channel_map, otherwise in.ch_count) ...
int64_t user_out_ch_layout
User set output channel 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
int i
Definition: input.c:407
#define AV_CH_BACK_RIGHT