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 int 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(!sane_layout(in_ch_layout)){
145  av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout_param);
146  av_log(log_context, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf);
147  return AVERROR(EINVAL);
148  }
149 
150  if(!sane_layout(out_ch_layout)){
151  av_get_channel_layout_string(buf, sizeof(buf), -1, out_ch_layout_param);
152  av_log(log_context, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf);
153  return AVERROR(EINVAL);
154  }
155 
156  for(i=0; i<FF_ARRAY_ELEMS(matrix); i++){
157  if(in_ch_layout & out_ch_layout & (1ULL<<i))
158  matrix[i][i]= 1.0;
159  }
160 
161  unaccounted= in_ch_layout & ~out_ch_layout;
162 
163 //FIXME implement dolby surround
164 //FIXME implement full ac3
165 
166 
167  if(unaccounted & AV_CH_FRONT_CENTER){
168  if((out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){
169  if(in_ch_layout & AV_CH_LAYOUT_STEREO) {
170  matrix[ FRONT_LEFT][FRONT_CENTER]+= center_mix_level;
171  matrix[FRONT_RIGHT][FRONT_CENTER]+= center_mix_level;
172  } else {
173  matrix[ FRONT_LEFT][FRONT_CENTER]+= M_SQRT1_2;
175  }
176  }else
177  av_assert0(0);
178  }
179  if(unaccounted & AV_CH_LAYOUT_STEREO){
180  if(out_ch_layout & AV_CH_FRONT_CENTER){
181  matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2;
183  if(in_ch_layout & AV_CH_FRONT_CENTER)
184  matrix[FRONT_CENTER][ FRONT_CENTER] = center_mix_level*sqrt(2);
185  }else
186  av_assert0(0);
187  }
188 
189  if(unaccounted & AV_CH_BACK_CENTER){
190  if(out_ch_layout & AV_CH_BACK_LEFT){
191  matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2;
192  matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2;
193  }else if(out_ch_layout & AV_CH_SIDE_LEFT){
194  matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2;
195  matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2;
196  }else if(out_ch_layout & AV_CH_FRONT_LEFT){
197  if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
198  matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
199  if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
200  matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level * M_SQRT1_2;
201  matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
202  } else {
203  matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level;
204  matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level;
205  }
206  } else {
207  matrix[ FRONT_LEFT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
208  matrix[FRONT_RIGHT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
209  }
210  }else if(out_ch_layout & AV_CH_FRONT_CENTER){
211  matrix[ FRONT_CENTER][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
212  }else
213  av_assert0(0);
214  }
215  if(unaccounted & AV_CH_BACK_LEFT){
216  if(out_ch_layout & AV_CH_BACK_CENTER){
217  matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2;
218  matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2;
219  }else if(out_ch_layout & AV_CH_SIDE_LEFT){
220  if(in_ch_layout & AV_CH_SIDE_LEFT){
221  matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2;
222  matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2;
223  }else{
224  matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0;
225  matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0;
226  }
227  }else if(out_ch_layout & AV_CH_FRONT_LEFT){
228  if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
229  matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2;
230  matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
231  matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
232  matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
233  } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
234  matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * SQRT3_2;
235  matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
236  matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
237  matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * SQRT3_2;
238  } else {
239  matrix[ FRONT_LEFT][ BACK_LEFT] += surround_mix_level;
240  matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
241  }
242  }else if(out_ch_layout & AV_CH_FRONT_CENTER){
243  matrix[ FRONT_CENTER][BACK_LEFT ]+= surround_mix_level*M_SQRT1_2;
244  matrix[ FRONT_CENTER][BACK_RIGHT]+= surround_mix_level*M_SQRT1_2;
245  }else
246  av_assert0(0);
247  }
248 
249  if(unaccounted & AV_CH_SIDE_LEFT){
250  if(out_ch_layout & AV_CH_BACK_LEFT){
251  /* if back channels do not exist in the input, just copy side
252  channels to back channels, otherwise mix side into back */
253  if (in_ch_layout & AV_CH_BACK_LEFT) {
254  matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
255  matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
256  } else {
257  matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
258  matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
259  }
260  }else if(out_ch_layout & AV_CH_BACK_CENTER){
261  matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2;
262  matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2;
263  }else if(out_ch_layout & AV_CH_FRONT_LEFT){
264  if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
265  matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2;
266  matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
267  matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
268  matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
269  } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
270  matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * SQRT3_2;
271  matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
272  matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
273  matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * SQRT3_2;
274  } else {
275  matrix[ FRONT_LEFT][ SIDE_LEFT] += surround_mix_level;
276  matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
277  }
278  }else if(out_ch_layout & AV_CH_FRONT_CENTER){
279  matrix[ FRONT_CENTER][SIDE_LEFT ]+= surround_mix_level * M_SQRT1_2;
280  matrix[ FRONT_CENTER][SIDE_RIGHT]+= surround_mix_level * M_SQRT1_2;
281  }else
282  av_assert0(0);
283  }
284 
285  if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){
286  if(out_ch_layout & AV_CH_FRONT_LEFT){
287  matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0;
288  matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0;
289  }else if(out_ch_layout & AV_CH_FRONT_CENTER){
292  }else
293  av_assert0(0);
294  }
295  /* mix LFE into front left/right or center */
296  if (unaccounted & AV_CH_LOW_FREQUENCY) {
297  if (out_ch_layout & AV_CH_FRONT_CENTER) {
298  matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level;
299  } else if (out_ch_layout & AV_CH_FRONT_LEFT) {
300  matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
301  matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
302  } else
303  av_assert0(0);
304  }
305 
306  for(out_i=i=0; i<64; i++){
307  double sum=0;
308  int in_i=0;
309  if((out_ch_layout & (1ULL<<i)) == 0)
310  continue;
311  for(j=0; j<64; j++){
312  if((in_ch_layout & (1ULL<<j)) == 0)
313  continue;
314  if (i < FF_ARRAY_ELEMS(matrix) && j < FF_ARRAY_ELEMS(matrix[0]))
315  matrix_param[stride*out_i + in_i] = matrix[i][j];
316  else
317  matrix_param[stride*out_i + in_i] = i == j && (in_ch_layout & out_ch_layout & (1ULL<<i));
318  sum += fabs(matrix_param[stride*out_i + in_i]);
319  in_i++;
320  }
321  maxcoef= FFMAX(maxcoef, sum);
322  out_i++;
323  }
324  if(rematrix_volume < 0)
325  maxcoef = -rematrix_volume;
326 
327  if(maxcoef > maxval || rematrix_volume < 0){
328  maxcoef /= maxval;
329  for(i=0; i<SWR_CH_MAX; i++)
330  for(j=0; j<SWR_CH_MAX; j++){
331  matrix_param[stride*i + j] /= maxcoef;
332  }
333  }
334 
335  if(rematrix_volume > 0){
336  for(i=0; i<SWR_CH_MAX; i++)
337  for(j=0; j<SWR_CH_MAX; j++){
338  matrix_param[stride*i + j] *= rematrix_volume;
339  }
340  }
341 
342  av_log(log_context, AV_LOG_DEBUG, "Matrix coefficients:\n");
343  for(i=0; i<av_get_channel_layout_nb_channels(out_ch_layout); i++){
344  const char *c =
346  av_log(log_context, AV_LOG_DEBUG, "%s: ", c ? c : "?");
347  for(j=0; j<av_get_channel_layout_nb_channels(in_ch_layout); j++){
349  av_log(log_context, AV_LOG_DEBUG, "%s:%f ", c ? c : "?", matrix_param[stride*i + j]);
350  }
351  av_log(log_context, AV_LOG_DEBUG, "\n");
352  }
353  return 0;
354 }
355 
357 {
358  double maxval;
359  int ret;
360 
361  if (s->rematrix_maxval > 0) {
362  maxval = s->rematrix_maxval;
365  maxval = 1.0;
366  } else
367  maxval = INT_MAX;
368 
369  memset(s->matrix, 0, sizeof(s->matrix));
371  s->clev, s->slev, s->lfe_mix_level,
372  maxval, s->rematrix_volume, (double*)s->matrix,
373  s->matrix[1] - s->matrix[0], s->matrix_encoding, s);
374 
375  if (ret >= 0 && s->int_sample_fmt == AV_SAMPLE_FMT_FLTP) {
376  int i, j;
377  for (i = 0; i < FF_ARRAY_ELEMS(s->matrix[0]); i++)
378  for (j = 0; j < FF_ARRAY_ELEMS(s->matrix[0]); j++)
379  s->matrix_flt[i][j] = s->matrix[i][j];
380  }
381 
382  return ret;
383 }
384 
386  int i, j;
387  int nb_in = s->used_ch_count;
388  int nb_out = s->out.ch_count;
389 
390  s->mix_any_f = NULL;
391 
392  if (!s->rematrix_custom) {
393  int r = auto_matrix(s);
394  if (r)
395  return r;
396  }
397  if (s->midbuf.fmt == AV_SAMPLE_FMT_S16P){
398  int maxsum = 0;
399  s->native_matrix = av_calloc(nb_in * nb_out, sizeof(int));
400  s->native_one = av_mallocz(sizeof(int));
401  if (!s->native_matrix || !s->native_one)
402  return AVERROR(ENOMEM);
403  for (i = 0; i < nb_out; i++) {
404  double rem = 0;
405  int sum = 0;
406 
407  for (j = 0; j < nb_in; j++) {
408  double target = s->matrix[i][j] * 32768 + rem;
409  ((int*)s->native_matrix)[i * nb_in + j] = lrintf(target);
410  rem += target - ((int*)s->native_matrix)[i * nb_in + j];
411  sum += FFABS(((int*)s->native_matrix)[i * nb_in + j]);
412  }
413  maxsum = FFMAX(maxsum, sum);
414  }
415  *((int*)s->native_one) = 32768;
416  if (maxsum <= 32768) {
417  s->mix_1_1_f = (mix_1_1_func_type*)copy_s16;
418  s->mix_2_1_f = (mix_2_1_func_type*)sum2_s16;
419  s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s16(s);
420  } else {
421  s->mix_1_1_f = (mix_1_1_func_type*)copy_clip_s16;
422  s->mix_2_1_f = (mix_2_1_func_type*)sum2_clip_s16;
423  s->mix_any_f = (mix_any_func_type*)get_mix_any_func_clip_s16(s);
424  }
425  }else if(s->midbuf.fmt == AV_SAMPLE_FMT_FLTP){
426  s->native_matrix = av_calloc(nb_in * nb_out, sizeof(float));
427  s->native_one = av_mallocz(sizeof(float));
428  if (!s->native_matrix || !s->native_one)
429  return AVERROR(ENOMEM);
430  for (i = 0; i < nb_out; i++)
431  for (j = 0; j < nb_in; j++)
432  ((float*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
433  *((float*)s->native_one) = 1.0;
434  s->mix_1_1_f = (mix_1_1_func_type*)copy_float;
435  s->mix_2_1_f = (mix_2_1_func_type*)sum2_float;
436  s->mix_any_f = (mix_any_func_type*)get_mix_any_func_float(s);
437  }else if(s->midbuf.fmt == AV_SAMPLE_FMT_DBLP){
438  s->native_matrix = av_calloc(nb_in * nb_out, sizeof(double));
439  s->native_one = av_mallocz(sizeof(double));
440  if (!s->native_matrix || !s->native_one)
441  return AVERROR(ENOMEM);
442  for (i = 0; i < nb_out; i++)
443  for (j = 0; j < nb_in; j++)
444  ((double*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
445  *((double*)s->native_one) = 1.0;
446  s->mix_1_1_f = (mix_1_1_func_type*)copy_double;
447  s->mix_2_1_f = (mix_2_1_func_type*)sum2_double;
448  s->mix_any_f = (mix_any_func_type*)get_mix_any_func_double(s);
449  }else if(s->midbuf.fmt == AV_SAMPLE_FMT_S32P){
450  s->native_one = av_mallocz(sizeof(int));
451  if (!s->native_one)
452  return AVERROR(ENOMEM);
453  s->native_matrix = av_calloc(nb_in * nb_out, sizeof(int));
454  if (!s->native_matrix) {
455  av_freep(&s->native_one);
456  return AVERROR(ENOMEM);
457  }
458  for (i = 0; i < nb_out; i++) {
459  double rem = 0;
460 
461  for (j = 0; j < nb_in; j++) {
462  double target = s->matrix[i][j] * 32768 + rem;
463  ((int*)s->native_matrix)[i * nb_in + j] = lrintf(target);
464  rem += target - ((int*)s->native_matrix)[i * nb_in + j];
465  }
466  }
467  *((int*)s->native_one) = 32768;
468  s->mix_1_1_f = (mix_1_1_func_type*)copy_s32;
469  s->mix_2_1_f = (mix_2_1_func_type*)sum2_s32;
470  s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s32(s);
471  }else
472  av_assert0(0);
473  //FIXME quantize for integeres
474  for (i = 0; i < SWR_CH_MAX; i++) {
475  int ch_in=0;
476  for (j = 0; j < SWR_CH_MAX; j++) {
477  s->matrix32[i][j]= lrintf(s->matrix[i][j] * 32768);
478  if(s->matrix[i][j])
479  s->matrix_ch[i][++ch_in]= j;
480  }
481  s->matrix_ch[i][0]= ch_in;
482  }
483 
484  if(HAVE_X86ASM && HAVE_MMX)
485  return swri_rematrix_init_x86(s);
486 
487  return 0;
488 }
489 
491  av_freep(&s->native_matrix);
492  av_freep(&s->native_one);
495 }
496 
497 int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){
498  int out_i, in_i, i, j;
499  int len1 = 0;
500  int off = 0;
501 
502  if(s->mix_any_f) {
503  s->mix_any_f(out->ch, (const uint8_t **)in->ch, s->native_matrix, len);
504  return 0;
505  }
506 
507  if(s->mix_2_1_simd || s->mix_1_1_simd){
508  len1= len&~15;
509  off = len1 * out->bps;
510  }
511 
513  av_assert0(!s-> in_ch_layout || in ->ch_count == av_get_channel_layout_nb_channels(s-> in_ch_layout));
514 
515  for(out_i=0; out_i<out->ch_count; out_i++){
516  switch(s->matrix_ch[out_i][0]){
517  case 0:
518  if(mustcopy)
519  memset(out->ch[out_i], 0, len * av_get_bytes_per_sample(s->int_sample_fmt));
520  break;
521  case 1:
522  in_i= s->matrix_ch[out_i][1];
523  if(s->matrix[out_i][in_i]!=1.0){
524  if(s->mix_1_1_simd && len1)
525  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);
526  if(len != len1)
527  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);
528  }else if(mustcopy){
529  memcpy(out->ch[out_i], in->ch[in_i], len*out->bps);
530  }else{
531  out->ch[out_i]= in->ch[in_i];
532  }
533  break;
534  case 2: {
535  int in_i1 = s->matrix_ch[out_i][1];
536  int in_i2 = s->matrix_ch[out_i][2];
537  if(s->mix_2_1_simd && len1)
538  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);
539  else
540  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);
541  if(len != len1)
542  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);
543  break;}
544  default:
546  for(i=0; i<len; i++){
547  float v=0;
548  for(j=0; j<s->matrix_ch[out_i][0]; j++){
549  in_i= s->matrix_ch[out_i][1+j];
550  v+= ((float*)in->ch[in_i])[i] * s->matrix_flt[out_i][in_i];
551  }
552  ((float*)out->ch[out_i])[i]= v;
553  }
554  }else if(s->int_sample_fmt == AV_SAMPLE_FMT_DBLP){
555  for(i=0; i<len; i++){
556  double v=0;
557  for(j=0; j<s->matrix_ch[out_i][0]; j++){
558  in_i= s->matrix_ch[out_i][1+j];
559  v+= ((double*)in->ch[in_i])[i] * s->matrix[out_i][in_i];
560  }
561  ((double*)out->ch[out_i])[i]= v;
562  }
563  }else{
564  for(i=0; i<len; i++){
565  int v=0;
566  for(j=0; j<s->matrix_ch[out_i][0]; j++){
567  in_i= s->matrix_ch[out_i][1+j];
568  v+= ((int16_t*)in->ch[in_i])[i] * s->matrix32[out_i][in_i];
569  }
570  ((int16_t*)out->ch[out_i])[i]= (v + 16384)>>15;
571  }
572  }
573  }
574  }
575  return 0;
576 }
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_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:497
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:236
#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
static int clean_layout(void *s, int64_t layout)
Definition: rematrix.c:91
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:244
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:385
uint8_t
#define av_cold
Definition: attributes.h:82
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:192
#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 i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
int matrix_encoding
matrixed stereo encoding
float slev
surround mixing level
#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:197
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)
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:356
#define AV_CH_FRONT_LEFT
void * buf
Definition: avisynth_c.h:766
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
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:490
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
#define AV_CH_BACK_RIGHT