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 :
73  av_get_channel_layout_nb_channels(s->user_in_ch_layout);
74  nb_out = (s->user_out_ch_count > 0) ? s->user_out_ch_count :
75  av_get_channel_layout_nb_channels(s->user_out_ch_layout);
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;
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;
373  } else if ( av_get_packed_sample_fmt(s->out_sample_fmt) < AV_SAMPLE_FMT_FLT
374  || av_get_packed_sample_fmt(s->int_sample_fmt) < AV_SAMPLE_FMT_FLT) {
375  maxval = 1.0;
376  } else
377  maxval = INT_MAX;
378 
379  memset(s->matrix, 0, sizeof(s->matrix));
380  ret = swr_build_matrix(s->in_ch_layout, s->out_ch_layout,
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);
503  av_freep(&s->native_simd_matrix);
504  av_freep(&s->native_simd_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 
522  av_assert0(!s->out_ch_layout || out->ch_count == av_get_channel_layout_nb_channels(s->out_ch_layout));
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:
555  if(s->int_sample_fmt == AV_SAMPLE_FMT_FLTP){
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 }
clean_layout
static int64_t clean_layout(void *s, int64_t layout)
Definition: rematrix.c:91
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
AV_SAMPLE_FMT_FLTP
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition: samplefmt.h:69
stride
int stride
Definition: mace.c:144
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:187
AV_CH_LAYOUT_7POINT1_WIDE_BACK
#define AV_CH_LAYOUT_7POINT1_WIDE_BACK
Definition: channel_layout.h:114
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
rematrix_template.c
av_get_channel_layout_string
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.
Definition: channel_layout.c:217
AV_SAMPLE_FMT_S32P
@ AV_SAMPLE_FMT_S32P
signed 32 bits, planar
Definition: samplefmt.h:68
swri_rematrix_init_x86
int swri_rematrix_init_x86(struct SwrContext *s)
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:197
SQRT3_2
#define SQRT3_2
Definition: swresample_internal.h:30
swr_set_matrix
int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride)
Set a customized remix matrix.
Definition: rematrix.c:64
AudioData
Definition: swresample_internal.h:45
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:53
AV_CH_LAYOUT_STEREO
#define AV_CH_LAYOUT_STEREO
Definition: channel_layout.h:91
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:181
even
static int even(int64_t layout)
Definition: rematrix.c:85
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:122
AV_CH_LOW_FREQUENCY
#define AV_CH_LOW_FREQUENCY
Definition: channel_layout.h:52
AV_CH_LAYOUT_22POINT2
#define AV_CH_LAYOUT_22POINT2
Definition: channel_layout.h:118
s
#define s(width, name)
Definition: cbs_vp9.c:257
AV_CH_LAYOUT_STEREO_DOWNMIX
#define AV_CH_LAYOUT_STEREO_DOWNMIX
Definition: channel_layout.h:117
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
av_get_channel_name
const char * av_get_channel_name(uint64_t channel)
Get the name of a given channel.
Definition: channel_layout.c:249
swri_rematrix
int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy)
Definition: rematrix.c:507
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:202
auto_matrix
static av_cold int auto_matrix(SwrContext *s)
Definition: rematrix.c:366
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:72
AVMatrixEncoding
AVMatrixEncoding
Definition: channel_layout.h:120
fabs
static __device__ float fabs(float a)
Definition: cuda_runtime.h:182
NULL
#define NULL
Definition: coverity.c:32
AV_CH_FRONT_CENTER
#define AV_CH_FRONT_CENTER
Definition: channel_layout.h:51
AV_CH_FRONT_LEFT_OF_CENTER
#define AV_CH_FRONT_LEFT_OF_CENTER
Definition: channel_layout.h:55
c
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
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:226
AudioData::ch_count
int ch_count
number of channels
Definition: swresample_internal.h:48
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
FFMAX
#define FFMAX(a, b)
Definition: common.h:103
BACK_RIGHT
#define BACK_RIGHT
Definition: rematrix.c:49
SIDE_LEFT
#define SIDE_LEFT
Definition: rematrix.c:53
swri_rematrix_free
av_cold void swri_rematrix_free(SwrContext *s)
Definition: rematrix.c:500
swresample_internal.h
AV_CH_FRONT_RIGHT_OF_CENTER
#define AV_CH_FRONT_RIGHT_OF_CENTER
Definition: channel_layout.h:56
FRONT_CENTER
#define FRONT_CENTER
Definition: rematrix.c:46
AV_SAMPLE_FMT_S16P
@ AV_SAMPLE_FMT_S16P
signed 16 bits, planar
Definition: samplefmt.h:67
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
i
int i
Definition: input.c:407
FRONT_RIGHT_OF_CENTER
#define FRONT_RIGHT_OF_CENTER
Definition: rematrix.c:51
lrintf
#define lrintf(x)
Definition: libm_mips.h:72
av_get_bytes_per_sample
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition: samplefmt.c:106
av_channel_layout_extract_channel
uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index)
Get the channel with the given index in channel_layout.
Definition: channel_layout.c:271
AV_CH_BACK_CENTER
#define AV_CH_BACK_CENTER
Definition: channel_layout.h:57
AV_CH_FRONT_LEFT
#define AV_CH_FRONT_LEFT
Definition: channel_layout.h:49
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:243
AV_CH_SIDE_RIGHT
#define AV_CH_SIDE_RIGHT
Definition: channel_layout.h:59
len
int len
Definition: vorbis_enc_data.h:452
FRONT_LEFT
#define FRONT_LEFT
Definition: rematrix.c:44
ret
ret
Definition: filter_design.txt:187
AV_CH_LAYOUT_SURROUND
#define AV_CH_LAYOUT_SURROUND
Definition: channel_layout.h:94
M_SQRT1_2
#define M_SQRT1_2
Definition: mathematics.h:58
SWR_CH_MAX
#define SWR_CH_MAX
Definition: af_amerge.c:35
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:251
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:75
AV_SAMPLE_FMT_DBLP
@ AV_SAMPLE_FMT_DBLP
double, planar
Definition: samplefmt.h:70
swri_rematrix_init
av_cold int swri_rematrix_init(SwrContext *s)
Definition: rematrix.c:395
AV_CH_FRONT_RIGHT
#define AV_CH_FRONT_RIGHT
Definition: channel_layout.h:50
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:35
SIDE_RIGHT
#define SIDE_RIGHT
Definition: rematrix.c:54
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AV_CH_BACK_RIGHT
#define AV_CH_BACK_RIGHT
Definition: channel_layout.h:54
swr_build_matrix
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
sane_layout
static int sane_layout(int64_t layout)
Definition: rematrix.c:102
AV_SAMPLE_FMT_FLT
@ AV_SAMPLE_FMT_FLT
float
Definition: samplefmt.h:63
AV_CH_SIDE_LEFT
#define AV_CH_SIDE_LEFT
Definition: channel_layout.h:58
AV_MATRIX_ENCODING_DPLII
@ AV_MATRIX_ENCODING_DPLII
Definition: channel_layout.h:123