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 int clean_layout(void *s, int64_t layout){
92  if(layout && layout != AV_CH_FRONT_CENTER && !(layout&(layout-1))) {
93  char buf[128];
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(!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;
363  } else if ( av_get_packed_sample_fmt(s->out_sample_fmt) < AV_SAMPLE_FMT_FLT
364  || av_get_packed_sample_fmt(s->int_sample_fmt) < AV_SAMPLE_FMT_FLT) {
365  maxval = 1.0;
366  } else
367  maxval = INT_MAX;
368 
369  memset(s->matrix, 0, sizeof(s->matrix));
370  ret = swr_build_matrix(s->in_ch_layout, s->out_ch_layout,
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);
493  av_freep(&s->native_simd_matrix);
494  av_freep(&s->native_simd_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 
512  av_assert0(!s->out_ch_layout || out->ch_count == av_get_channel_layout_nb_channels(s->out_ch_layout));
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:
545  if(s->int_sample_fmt == AV_SAMPLE_FMT_FLTP){
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 }
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
r
const char * r
Definition: vf_curves.c:114
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:211
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:192
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
Audio buffer used for intermediate storage between conversion phases.
Definition: audio_data.h:37
SQRT3_2
#define SQRT3_2
Definition: audio_mix_matrix.c:59
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:86
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
even
static int even(int64_t layout)
Definition: rematrix.c:85
buf
void * buf
Definition: avisynth_c.h:766
av_cold
#define av_cold
Definition: attributes.h:84
AV_MATRIX_ENCODING_DOLBY
@ AV_MATRIX_ENCODING_DOLBY
Definition: channel_layout.h:116
AV_CH_LOW_FREQUENCY
#define AV_CH_LOW_FREQUENCY
Definition: channel_layout.h:52
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:112
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:243
swri_rematrix
int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy)
Definition: rematrix.c:497
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
auto_matrix
static av_cold int auto_matrix(SwrContext *s)
Definition: rematrix.c:356
SwrContext
The libswresample context.
Definition: swresample_internal.h:95
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:114
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:220
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
clean_layout
static int clean_layout(void *s, int64_t layout)
Definition: rematrix.c:91
FFMAX
#define FFMAX(a, b)
Definition: common.h:94
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:490
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
in
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
Definition: audio_convert.c:326
FRONT_RIGHT_OF_CENTER
#define FRONT_RIGHT_OF_CENTER
Definition: rematrix.c:51
lrintf
#define lrintf(x)
Definition: libm_mips.h:70
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
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:265
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
uint8_t
uint8_t
Definition: audio_convert.c:194
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:236
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:89
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen_template.c:38
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:244
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:385
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:117