/src/ffmpeg/libswresample/rematrix.c
Line | Count | Source (jump to first uncovered line) |
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" |
23 | | #include "libavutil/channel_layout.h" |
24 | | #include "libavutil/mem.h" |
25 | | |
26 | | #define TEMPLATE_REMATRIX_FLT |
27 | | #include "rematrix_template.c" |
28 | | #undef TEMPLATE_REMATRIX_FLT |
29 | | |
30 | | #define TEMPLATE_REMATRIX_DBL |
31 | | #include "rematrix_template.c" |
32 | | #undef TEMPLATE_REMATRIX_DBL |
33 | | |
34 | | #define TEMPLATE_REMATRIX_S16 |
35 | | #include "rematrix_template.c" |
36 | | #define TEMPLATE_CLIP |
37 | | #include "rematrix_template.c" |
38 | | #undef TEMPLATE_CLIP |
39 | | #undef TEMPLATE_REMATRIX_S16 |
40 | | |
41 | | #define TEMPLATE_REMATRIX_S32 |
42 | | #include "rematrix_template.c" |
43 | | #undef TEMPLATE_REMATRIX_S32 |
44 | | |
45 | 13 | #define FRONT_LEFT 0 |
46 | 13 | #define FRONT_RIGHT 1 |
47 | 59 | #define FRONT_CENTER 2 |
48 | 5 | #define LOW_FREQUENCY 3 |
49 | 5 | #define BACK_LEFT 4 |
50 | 5 | #define BACK_RIGHT 5 |
51 | 4 | #define FRONT_LEFT_OF_CENTER 6 |
52 | 4 | #define FRONT_RIGHT_OF_CENTER 7 |
53 | 28 | #define BACK_CENTER 8 |
54 | 13 | #define SIDE_LEFT 9 |
55 | 13 | #define SIDE_RIGHT 10 |
56 | | #define TOP_CENTER 11 |
57 | 0 | #define TOP_FRONT_LEFT 12 |
58 | 0 | #define TOP_FRONT_CENTER 13 |
59 | 0 | #define TOP_FRONT_RIGHT 14 |
60 | | #define TOP_BACK_LEFT 15 |
61 | | #define TOP_BACK_CENTER 16 |
62 | | #define TOP_BACK_RIGHT 17 |
63 | | #define NUM_NAMED_CHANNELS 18 |
64 | | |
65 | | int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride) |
66 | 0 | { |
67 | 0 | int nb_in, nb_out, in, out; |
68 | |
|
69 | 0 | if (!s || s->in_convert) // s needs to be allocated but not initialized |
70 | 0 | return AVERROR(EINVAL); |
71 | 0 | memset(s->matrix, 0, sizeof(s->matrix)); |
72 | 0 | memset(s->matrix_flt, 0, sizeof(s->matrix_flt)); |
73 | |
|
74 | 0 | nb_in = s->user_in_chlayout.nb_channels; |
75 | 0 | nb_out = s->user_out_chlayout.nb_channels; |
76 | 0 | for (out = 0; out < nb_out; out++) { |
77 | 0 | for (in = 0; in < nb_in; in++) |
78 | 0 | s->matrix_flt[out][in] = s->matrix[out][in] = matrix[in]; |
79 | 0 | matrix += stride; |
80 | 0 | } |
81 | 0 | s->rematrix_custom = 1; |
82 | 0 | return 0; |
83 | 0 | } |
84 | | |
85 | 330 | static int even(int64_t layout){ |
86 | 330 | if(!layout) return 1; |
87 | 98 | if(layout&(layout-1)) return 1; |
88 | 0 | return 0; |
89 | 98 | } |
90 | | |
91 | | static int clean_layout(AVChannelLayout *out, const AVChannelLayout *in, void *s) |
92 | 66 | { |
93 | 66 | int ret = 0; |
94 | | |
95 | 66 | if (av_channel_layout_index_from_channel(in, AV_CHAN_FRONT_CENTER) < 0 && in->nb_channels == 1) { |
96 | 0 | char buf[128]; |
97 | 0 | av_channel_layout_describe(in, buf, sizeof(buf)); |
98 | 0 | av_log(s, AV_LOG_VERBOSE, "Treating %s as mono\n", buf); |
99 | 0 | *out = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; |
100 | 0 | } else |
101 | 66 | ret = av_channel_layout_copy(out, in); |
102 | | |
103 | 66 | return ret; |
104 | 66 | } |
105 | | |
106 | 66 | static int sane_layout(AVChannelLayout *ch_layout) { |
107 | 66 | if (ch_layout->order != AV_CHANNEL_ORDER_NATIVE) |
108 | 0 | return 0; |
109 | 66 | if(!av_channel_layout_subset(ch_layout, AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker |
110 | 0 | return 0; |
111 | 66 | if(!even(av_channel_layout_subset(ch_layout, (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)))) // no asymetric front |
112 | 0 | return 0; |
113 | 66 | if(!even(av_channel_layout_subset(ch_layout, (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)))) // no asymetric side |
114 | 0 | return 0; |
115 | 66 | if(!even(av_channel_layout_subset(ch_layout, (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)))) |
116 | 0 | return 0; |
117 | 66 | if(!even(av_channel_layout_subset(ch_layout, (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)))) |
118 | 0 | return 0; |
119 | 66 | if(!even(av_channel_layout_subset(ch_layout, (AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT)))) |
120 | 0 | return 0; |
121 | 66 | if(ch_layout->nb_channels >= SWR_CH_MAX) |
122 | 0 | return 0; |
123 | | |
124 | 66 | return 1; |
125 | 66 | } |
126 | | |
127 | | av_cold int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout, |
128 | | double center_mix_level, double surround_mix_level, |
129 | | double lfe_mix_level, double maxval, |
130 | | double rematrix_volume, double *matrix_param, |
131 | | ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding, void *log_context) |
132 | 33 | { |
133 | 33 | int i, j, out_i, ret; |
134 | 33 | AVChannelLayout in_ch_layout = { 0 }, out_ch_layout = { 0 }; |
135 | 33 | double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS]={{0}}; |
136 | 33 | int64_t unaccounted; |
137 | 33 | double maxcoef=0; |
138 | 33 | char buf[128]; |
139 | | |
140 | 33 | ret = clean_layout(&in_ch_layout, in_layout, log_context); |
141 | 33 | ret |= clean_layout(&out_ch_layout, out_layout, log_context); |
142 | 33 | if (ret < 0) |
143 | 0 | goto fail; |
144 | | |
145 | 33 | if( !av_channel_layout_compare(&out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO_DOWNMIX) |
146 | 33 | && !av_channel_layout_subset(&in_ch_layout, AV_CH_LAYOUT_STEREO_DOWNMIX) |
147 | 33 | ) { |
148 | 0 | av_channel_layout_uninit(&out_ch_layout); |
149 | 0 | out_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; |
150 | 0 | } |
151 | 33 | if( !av_channel_layout_compare(&in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO_DOWNMIX) |
152 | 33 | && !av_channel_layout_subset(&out_ch_layout, AV_CH_LAYOUT_STEREO_DOWNMIX) |
153 | 33 | ) { |
154 | 0 | av_channel_layout_uninit(&in_ch_layout); |
155 | 0 | in_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; |
156 | 0 | } |
157 | 33 | if (!av_channel_layout_compare(&in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_22POINT2) && |
158 | 33 | av_channel_layout_compare(&out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_22POINT2)) { |
159 | 4 | av_channel_layout_from_mask(&in_ch_layout, (AV_CH_LAYOUT_7POINT1_WIDE_BACK|AV_CH_BACK_CENTER)); |
160 | 4 | av_channel_layout_describe(&in_ch_layout, buf, sizeof(buf)); |
161 | 4 | av_log(log_context, AV_LOG_WARNING, |
162 | 4 | "Full-on remixing from 22.2 has not yet been implemented! " |
163 | 4 | "Processing the input as '%s'\n", |
164 | 4 | buf); |
165 | 4 | } |
166 | | |
167 | 33 | if(!av_channel_layout_check(&in_ch_layout)) { |
168 | 0 | av_log(log_context, AV_LOG_ERROR, "Input channel layout is invalid\n"); |
169 | 0 | ret = AVERROR(EINVAL); |
170 | 0 | goto fail; |
171 | 0 | } |
172 | 33 | if(!sane_layout(&in_ch_layout)) { |
173 | 0 | av_channel_layout_describe(&in_ch_layout, buf, sizeof(buf)); |
174 | 0 | av_log(log_context, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf); |
175 | 0 | ret = AVERROR(EINVAL); |
176 | 0 | goto fail; |
177 | 0 | } |
178 | | |
179 | 33 | if(!av_channel_layout_check(&out_ch_layout)) { |
180 | 0 | av_log(log_context, AV_LOG_ERROR, "Output channel layout is invalid\n"); |
181 | 0 | ret = AVERROR(EINVAL); |
182 | 0 | goto fail; |
183 | 0 | } |
184 | 33 | if(!sane_layout(&out_ch_layout)) { |
185 | 0 | av_channel_layout_describe(&out_ch_layout, buf, sizeof(buf)); |
186 | 0 | av_log(log_context, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf); |
187 | 0 | ret = AVERROR(EINVAL); |
188 | 0 | goto fail; |
189 | 0 | } |
190 | | |
191 | 627 | for(i=0; i<FF_ARRAY_ELEMS(matrix); i++){ |
192 | 594 | if( av_channel_layout_index_from_channel(&in_ch_layout, i) >= 0 |
193 | 594 | && av_channel_layout_index_from_channel(&out_ch_layout, i) >= 0) |
194 | 59 | matrix[i][i]= 1.0; |
195 | 594 | } |
196 | | |
197 | 33 | unaccounted = in_ch_layout.u.mask & ~out_ch_layout.u.mask; |
198 | | |
199 | | //FIXME implement dolby surround |
200 | | //FIXME implement full ac3 |
201 | | |
202 | | |
203 | 33 | if(unaccounted & AV_CH_FRONT_CENTER){ |
204 | 7 | if (av_channel_layout_subset(&out_ch_layout, AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO) { |
205 | 7 | if (av_channel_layout_subset(&in_ch_layout, AV_CH_LAYOUT_STEREO)) { |
206 | 0 | matrix[ FRONT_LEFT][FRONT_CENTER]+= center_mix_level; |
207 | 0 | matrix[FRONT_RIGHT][FRONT_CENTER]+= center_mix_level; |
208 | 7 | } else { |
209 | 7 | matrix[ FRONT_LEFT][FRONT_CENTER]+= M_SQRT1_2; |
210 | 7 | matrix[FRONT_RIGHT][FRONT_CENTER]+= M_SQRT1_2; |
211 | 7 | } |
212 | 7 | }else |
213 | 0 | av_assert0(0); |
214 | 7 | } |
215 | 33 | if(unaccounted & AV_CH_LAYOUT_STEREO){ |
216 | 5 | if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) { |
217 | 5 | matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2; |
218 | 5 | matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2; |
219 | 5 | if (av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) |
220 | 4 | matrix[FRONT_CENTER][ FRONT_CENTER] = center_mix_level*sqrt(2); |
221 | 5 | }else |
222 | 0 | av_assert0(0); |
223 | 5 | } |
224 | | |
225 | 33 | if(unaccounted & AV_CH_BACK_CENTER){ |
226 | 5 | if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_LEFT) >= 0) { |
227 | 0 | matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2; |
228 | 0 | matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2; |
229 | 5 | } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_SIDE_LEFT) >= 0) { |
230 | 0 | matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2; |
231 | 0 | matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2; |
232 | 5 | } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) { |
233 | 1 | if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY || |
234 | 1 | matrix_encoding == AV_MATRIX_ENCODING_DPLII) { |
235 | 0 | if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) { |
236 | 0 | matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level * M_SQRT1_2; |
237 | 0 | matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2; |
238 | 0 | } else { |
239 | 0 | matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level; |
240 | 0 | matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level; |
241 | 0 | } |
242 | 1 | } else { |
243 | 1 | matrix[ FRONT_LEFT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2; |
244 | 1 | matrix[FRONT_RIGHT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2; |
245 | 1 | } |
246 | 4 | } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) { |
247 | 4 | matrix[ FRONT_CENTER][BACK_CENTER]+= surround_mix_level * M_SQRT1_2; |
248 | 4 | }else |
249 | 0 | av_assert0(0); |
250 | 5 | } |
251 | 33 | if(unaccounted & AV_CH_BACK_LEFT){ |
252 | 4 | if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_CENTER) >= 0) { |
253 | 0 | matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2; |
254 | 0 | matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2; |
255 | 4 | } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_SIDE_LEFT) >= 0) { |
256 | 0 | if (av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_SIDE_LEFT) >= 0) { |
257 | 0 | matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2; |
258 | 0 | matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2; |
259 | 0 | }else{ |
260 | 0 | matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0; |
261 | 0 | matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0; |
262 | 0 | } |
263 | 4 | } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) { |
264 | 0 | if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) { |
265 | 0 | matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2; |
266 | 0 | matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2; |
267 | 0 | matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2; |
268 | 0 | matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * M_SQRT1_2; |
269 | 0 | } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) { |
270 | 0 | matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * SQRT3_2; |
271 | 0 | matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2; |
272 | 0 | matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2; |
273 | 0 | matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * SQRT3_2; |
274 | 0 | } else { |
275 | 0 | matrix[ FRONT_LEFT][ BACK_LEFT] += surround_mix_level; |
276 | 0 | matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level; |
277 | 0 | } |
278 | 4 | } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) { |
279 | 4 | matrix[ FRONT_CENTER][BACK_LEFT ]+= surround_mix_level*M_SQRT1_2; |
280 | 4 | matrix[ FRONT_CENTER][BACK_RIGHT]+= surround_mix_level*M_SQRT1_2; |
281 | 4 | }else |
282 | 0 | av_assert0(0); |
283 | 4 | } |
284 | | |
285 | 33 | if(unaccounted & AV_CH_SIDE_LEFT){ |
286 | 13 | if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_LEFT) >= 0) { |
287 | | /* if back channels do not exist in the input, just copy side |
288 | | channels to back channels, otherwise mix side into back */ |
289 | 1 | if (av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_BACK_LEFT) >= 0) { |
290 | 0 | matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2; |
291 | 0 | matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2; |
292 | 1 | } else { |
293 | 1 | matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0; |
294 | 1 | matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0; |
295 | 1 | } |
296 | 12 | } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_CENTER) >= 0) { |
297 | 11 | matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2; |
298 | 11 | matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2; |
299 | 11 | } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) { |
300 | 0 | if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) { |
301 | 0 | matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2; |
302 | 0 | matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2; |
303 | 0 | matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2; |
304 | 0 | matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2; |
305 | 0 | } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) { |
306 | 0 | matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * SQRT3_2; |
307 | 0 | matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2; |
308 | 0 | matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2; |
309 | 0 | matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * SQRT3_2; |
310 | 0 | } else { |
311 | 0 | matrix[ FRONT_LEFT][ SIDE_LEFT] += surround_mix_level; |
312 | 0 | matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level; |
313 | 0 | } |
314 | 1 | } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) { |
315 | 1 | matrix[ FRONT_CENTER][SIDE_LEFT ]+= surround_mix_level * M_SQRT1_2; |
316 | 1 | matrix[ FRONT_CENTER][SIDE_RIGHT]+= surround_mix_level * M_SQRT1_2; |
317 | 1 | }else |
318 | 0 | av_assert0(0); |
319 | 13 | } |
320 | | |
321 | 33 | if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){ |
322 | 4 | if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) { |
323 | 0 | matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0; |
324 | 0 | matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0; |
325 | 4 | } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) { |
326 | 4 | matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2; |
327 | 4 | matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2; |
328 | 4 | }else |
329 | 0 | av_assert0(0); |
330 | 4 | } |
331 | | |
332 | 33 | if (unaccounted & AV_CH_TOP_FRONT_LEFT) { |
333 | 0 | if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_TOP_FRONT_CENTER) >= 0) { |
334 | 0 | matrix[TOP_FRONT_CENTER][TOP_FRONT_LEFT ] += M_SQRT1_2; |
335 | 0 | matrix[TOP_FRONT_CENTER][TOP_FRONT_RIGHT] += M_SQRT1_2; |
336 | 0 | if (av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_TOP_FRONT_CENTER) >= 0) |
337 | 0 | matrix[TOP_FRONT_CENTER][TOP_FRONT_CENTER] = center_mix_level * sqrt(2); |
338 | 0 | } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) { |
339 | 0 | if (av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) { |
340 | 0 | matrix[FRONT_LEFT ][TOP_FRONT_LEFT ] += M_SQRT1_2; |
341 | 0 | matrix[FRONT_RIGHT][TOP_FRONT_RIGHT] += M_SQRT1_2; |
342 | 0 | } else { |
343 | 0 | matrix[FRONT_LEFT ][TOP_FRONT_LEFT ] += 1.0; |
344 | 0 | matrix[FRONT_RIGHT][TOP_FRONT_RIGHT] += 1.0; |
345 | 0 | } |
346 | 0 | } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) { |
347 | 0 | matrix[FRONT_CENTER][TOP_FRONT_LEFT ] += M_SQRT1_2; |
348 | 0 | matrix[FRONT_CENTER][TOP_FRONT_RIGHT] += M_SQRT1_2; |
349 | 0 | } else |
350 | 0 | av_assert0(0); |
351 | 0 | } |
352 | | |
353 | | /* mix LFE into front left/right or center */ |
354 | 33 | if (unaccounted & AV_CH_LOW_FREQUENCY) { |
355 | 5 | if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) { |
356 | 5 | matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level; |
357 | 5 | } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) { |
358 | 0 | matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2; |
359 | 0 | matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2; |
360 | 0 | } else |
361 | 0 | av_assert0(0); |
362 | 5 | } |
363 | | |
364 | 2.14k | for(out_i=i=0; i<64; i++){ |
365 | 2.11k | double sum=0; |
366 | 2.11k | int in_i=0; |
367 | 2.11k | if (av_channel_layout_index_from_channel(&out_ch_layout, i) < 0) |
368 | 1.92k | continue; |
369 | 12.1k | for(j=0; j<64; j++){ |
370 | 11.9k | if (av_channel_layout_index_from_channel(&in_ch_layout, j) < 0) |
371 | 11.4k | continue; |
372 | 549 | if (i < FF_ARRAY_ELEMS(matrix) && j < FF_ARRAY_ELEMS(matrix[0])) |
373 | 513 | matrix_param[stride*out_i + in_i] = matrix[i][j]; |
374 | 36 | else |
375 | 36 | matrix_param[stride*out_i + in_i] = i == j && |
376 | 36 | ( av_channel_layout_index_from_channel(&in_ch_layout, i) >= 0 |
377 | 0 | && av_channel_layout_index_from_channel(&out_ch_layout, i) >= 0); |
378 | 549 | sum += fabs(matrix_param[stride*out_i + in_i]); |
379 | 549 | in_i++; |
380 | 549 | } |
381 | 187 | maxcoef= FFMAX(maxcoef, sum); |
382 | 187 | out_i++; |
383 | 187 | } |
384 | 33 | if(rematrix_volume < 0) |
385 | 0 | maxcoef = -rematrix_volume; |
386 | | |
387 | 33 | if(maxcoef > maxval || rematrix_volume < 0){ |
388 | 16 | maxcoef /= maxval; |
389 | 1.04k | for(i=0; i<SWR_CH_MAX; i++) |
390 | 66.5k | for(j=0; j<SWR_CH_MAX; j++){ |
391 | 65.5k | matrix_param[stride*i + j] /= maxcoef; |
392 | 65.5k | } |
393 | 16 | } |
394 | | |
395 | 33 | if(rematrix_volume > 0){ |
396 | 2.14k | for(i=0; i<SWR_CH_MAX; i++) |
397 | 137k | for(j=0; j<SWR_CH_MAX; j++){ |
398 | 135k | matrix_param[stride*i + j] *= rematrix_volume; |
399 | 135k | } |
400 | 33 | } |
401 | | |
402 | 33 | av_log(log_context, AV_LOG_DEBUG, "Matrix coefficients:\n"); |
403 | 220 | for (i = 0; i < out_ch_layout.nb_channels; i++){ |
404 | 187 | av_channel_name(buf, sizeof(buf), av_channel_layout_channel_from_index(&out_ch_layout, i)); |
405 | 187 | av_log(log_context, AV_LOG_DEBUG, "%s: ", buf); |
406 | 736 | for (j = 0; j < in_ch_layout.nb_channels; j++){ |
407 | 549 | av_channel_name(buf, sizeof(buf), av_channel_layout_channel_from_index(&in_ch_layout, j)); |
408 | 549 | av_log(log_context, AV_LOG_DEBUG, "%s:%f ", buf, matrix_param[stride*i + j]); |
409 | 549 | } |
410 | 187 | av_log(log_context, AV_LOG_DEBUG, "\n"); |
411 | 187 | } |
412 | | |
413 | 33 | ret = 0; |
414 | 33 | fail: |
415 | 33 | av_channel_layout_uninit(&in_ch_layout); |
416 | 33 | av_channel_layout_uninit(&out_ch_layout); |
417 | | |
418 | 33 | return ret; |
419 | 33 | } |
420 | | |
421 | | av_cold static int auto_matrix(SwrContext *s) |
422 | 33 | { |
423 | 33 | double maxval; |
424 | 33 | int ret; |
425 | | |
426 | 33 | if (s->rematrix_maxval > 0) { |
427 | 0 | maxval = s->rematrix_maxval; |
428 | 33 | } else if ( av_get_packed_sample_fmt(s->out_sample_fmt) < AV_SAMPLE_FMT_FLT |
429 | 33 | || av_get_packed_sample_fmt(s->int_sample_fmt) < AV_SAMPLE_FMT_FLT) { |
430 | 32 | maxval = 1.0; |
431 | 32 | } else |
432 | 1 | maxval = INT_MAX; |
433 | | |
434 | 33 | memset(s->matrix, 0, sizeof(s->matrix)); |
435 | 33 | ret = swr_build_matrix2(&s->in_ch_layout, &s->out_ch_layout, |
436 | 33 | s->clev, s->slev, s->lfe_mix_level, |
437 | 33 | maxval, s->rematrix_volume, (double*)s->matrix, |
438 | 33 | s->matrix[1] - s->matrix[0], s->matrix_encoding, s); |
439 | | |
440 | 33 | if (ret >= 0 && s->int_sample_fmt == AV_SAMPLE_FMT_FLTP) { |
441 | 5 | int i, j; |
442 | 325 | for (i = 0; i < FF_ARRAY_ELEMS(s->matrix[0]); i++) |
443 | 20.8k | for (j = 0; j < FF_ARRAY_ELEMS(s->matrix[0]); j++) |
444 | 20.4k | s->matrix_flt[i][j] = s->matrix[i][j]; |
445 | 5 | } |
446 | | |
447 | 33 | return ret; |
448 | 33 | } |
449 | | |
450 | 33 | av_cold int swri_rematrix_init(SwrContext *s){ |
451 | 33 | int i, j; |
452 | 33 | int nb_in = s->used_ch_layout.nb_channels; |
453 | 33 | int nb_out = s->out.ch_count; |
454 | | |
455 | 33 | s->mix_any_f = NULL; |
456 | | |
457 | 33 | if (!s->rematrix_custom) { |
458 | 33 | int r = auto_matrix(s); |
459 | 33 | if (r) |
460 | 0 | return r; |
461 | 33 | } |
462 | 33 | if (s->midbuf.fmt == AV_SAMPLE_FMT_S16P){ |
463 | 10 | int maxsum = 0; |
464 | 10 | s->native_matrix = av_calloc(nb_in * nb_out, sizeof(int)); |
465 | 10 | s->native_one = av_mallocz(sizeof(int)); |
466 | 10 | if (!s->native_matrix || !s->native_one) |
467 | 0 | return AVERROR(ENOMEM); |
468 | 49 | for (i = 0; i < nb_out; i++) { |
469 | 39 | double rem = 0; |
470 | 39 | int sum = 0; |
471 | | |
472 | 103 | for (j = 0; j < nb_in; j++) { |
473 | 64 | double target = s->matrix[i][j] * 32768 + rem; |
474 | 64 | ((int*)s->native_matrix)[i * nb_in + j] = lrintf(target); |
475 | 64 | rem += target - ((int*)s->native_matrix)[i * nb_in + j]; |
476 | 64 | sum += FFABS(((int*)s->native_matrix)[i * nb_in + j]); |
477 | 64 | } |
478 | 39 | maxsum = FFMAX(maxsum, sum); |
479 | 39 | } |
480 | 10 | *((int*)s->native_one) = 32768; |
481 | 10 | if (maxsum <= 32768) { |
482 | 10 | s->mix_1_1_f = (mix_1_1_func_type*)copy_s16; |
483 | 10 | s->mix_2_1_f = (mix_2_1_func_type*)sum2_s16; |
484 | 10 | s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s16(s); |
485 | 10 | } else { |
486 | 0 | s->mix_1_1_f = (mix_1_1_func_type*)copy_clip_s16; |
487 | 0 | s->mix_2_1_f = (mix_2_1_func_type*)sum2_clip_s16; |
488 | 0 | s->mix_any_f = (mix_any_func_type*)get_mix_any_func_clip_s16(s); |
489 | 0 | } |
490 | 23 | }else if(s->midbuf.fmt == AV_SAMPLE_FMT_FLTP){ |
491 | 5 | s->native_matrix = av_calloc(nb_in * nb_out, sizeof(float)); |
492 | 5 | s->native_one = av_mallocz(sizeof(float)); |
493 | 5 | if (!s->native_matrix || !s->native_one) |
494 | 0 | return AVERROR(ENOMEM); |
495 | 86 | for (i = 0; i < nb_out; i++) |
496 | 237 | for (j = 0; j < nb_in; j++) |
497 | 156 | ((float*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j]; |
498 | 5 | *((float*)s->native_one) = 1.0; |
499 | 5 | s->mix_1_1_f = (mix_1_1_func_type*)copy_float; |
500 | 5 | s->mix_2_1_f = (mix_2_1_func_type*)sum2_float; |
501 | 5 | s->mix_any_f = (mix_any_func_type*)get_mix_any_func_float(s); |
502 | 18 | }else if(s->midbuf.fmt == AV_SAMPLE_FMT_DBLP){ |
503 | 18 | s->native_matrix = av_calloc(nb_in * nb_out, sizeof(double)); |
504 | 18 | s->native_one = av_mallocz(sizeof(double)); |
505 | 18 | if (!s->native_matrix || !s->native_one) |
506 | 0 | return AVERROR(ENOMEM); |
507 | 85 | for (i = 0; i < nb_out; i++) |
508 | 456 | for (j = 0; j < nb_in; j++) |
509 | 389 | ((double*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j]; |
510 | 18 | *((double*)s->native_one) = 1.0; |
511 | 18 | s->mix_1_1_f = (mix_1_1_func_type*)copy_double; |
512 | 18 | s->mix_2_1_f = (mix_2_1_func_type*)sum2_double; |
513 | 18 | s->mix_any_f = (mix_any_func_type*)get_mix_any_func_double(s); |
514 | 18 | }else if(s->midbuf.fmt == AV_SAMPLE_FMT_S32P){ |
515 | 0 | s->native_one = av_mallocz(sizeof(int)); |
516 | 0 | if (!s->native_one) |
517 | 0 | return AVERROR(ENOMEM); |
518 | 0 | s->native_matrix = av_calloc(nb_in * nb_out, sizeof(int)); |
519 | 0 | if (!s->native_matrix) { |
520 | 0 | av_freep(&s->native_one); |
521 | 0 | return AVERROR(ENOMEM); |
522 | 0 | } |
523 | 0 | for (i = 0; i < nb_out; i++) { |
524 | 0 | double rem = 0; |
525 | |
|
526 | 0 | for (j = 0; j < nb_in; j++) { |
527 | 0 | double target = s->matrix[i][j] * 32768 + rem; |
528 | 0 | ((int*)s->native_matrix)[i * nb_in + j] = lrintf(target); |
529 | 0 | rem += target - ((int*)s->native_matrix)[i * nb_in + j]; |
530 | 0 | } |
531 | 0 | } |
532 | 0 | *((int*)s->native_one) = 32768; |
533 | 0 | s->mix_1_1_f = (mix_1_1_func_type*)copy_s32; |
534 | 0 | s->mix_2_1_f = (mix_2_1_func_type*)sum2_s32; |
535 | 0 | s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s32(s); |
536 | 0 | }else |
537 | 0 | av_assert0(0); |
538 | | //FIXME quantize for integeres |
539 | 2.14k | for (i = 0; i < SWR_CH_MAX; i++) { |
540 | 2.11k | int ch_in=0; |
541 | 137k | for (j = 0; j < SWR_CH_MAX; j++) { |
542 | 135k | s->matrix32[i][j]= lrintf(s->matrix[i][j] * 32768); |
543 | 135k | if(s->matrix[i][j]) |
544 | 131 | s->matrix_ch[i][++ch_in]= j; |
545 | 135k | } |
546 | 2.11k | s->matrix_ch[i][0]= ch_in; |
547 | 2.11k | } |
548 | | |
549 | 33 | #if ARCH_X86 && HAVE_X86ASM && HAVE_MMX |
550 | 33 | return swri_rematrix_init_x86(s); |
551 | 0 | #endif |
552 | | |
553 | 0 | return 0; |
554 | 33 | } |
555 | | |
556 | 128 | av_cold void swri_rematrix_free(SwrContext *s){ |
557 | 128 | av_freep(&s->native_matrix); |
558 | 128 | av_freep(&s->native_one); |
559 | 128 | av_freep(&s->native_simd_matrix); |
560 | 128 | av_freep(&s->native_simd_one); |
561 | 128 | } |
562 | | |
563 | 32 | int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){ |
564 | 32 | int out_i, in_i, i, j; |
565 | 32 | int len1 = 0; |
566 | 32 | int off = 0; |
567 | | |
568 | 32 | if(s->mix_any_f) { |
569 | 0 | s->mix_any_f(out->ch, (const uint8_t **)in->ch, s->native_matrix, len); |
570 | 0 | return 0; |
571 | 0 | } |
572 | | |
573 | 32 | if(s->mix_2_1_simd || s->mix_1_1_simd){ |
574 | 0 | len1= len&~15; |
575 | 0 | off = len1 * out->bps; |
576 | 0 | } |
577 | | |
578 | 32 | av_assert0(s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC || out->ch_count == s->out_ch_layout.nb_channels); |
579 | 32 | av_assert0(s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC || in ->ch_count == s->in_ch_layout.nb_channels); |
580 | | |
581 | 215 | for(out_i=0; out_i<out->ch_count; out_i++){ |
582 | 183 | switch(s->matrix_ch[out_i][0]){ |
583 | 98 | case 0: |
584 | 98 | if(mustcopy) |
585 | 0 | memset(out->ch[out_i], 0, len * av_get_bytes_per_sample(s->int_sample_fmt)); |
586 | 98 | break; |
587 | 67 | case 1: |
588 | 67 | in_i= s->matrix_ch[out_i][1]; |
589 | 67 | if(s->matrix[out_i][in_i]!=1.0){ |
590 | 45 | if(s->mix_1_1_simd && len1) |
591 | 0 | 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); |
592 | 45 | if(len != len1) |
593 | 45 | 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); |
594 | 45 | }else if(mustcopy){ |
595 | 0 | memcpy(out->ch[out_i], in->ch[in_i], len*out->bps); |
596 | 22 | }else{ |
597 | 22 | out->ch[out_i]= in->ch[in_i]; |
598 | 22 | } |
599 | 67 | break; |
600 | 13 | case 2: { |
601 | 13 | int in_i1 = s->matrix_ch[out_i][1]; |
602 | 13 | int in_i2 = s->matrix_ch[out_i][2]; |
603 | 13 | if(s->mix_2_1_simd && len1) |
604 | 0 | 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); |
605 | 13 | else |
606 | 13 | 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); |
607 | 13 | if(len != len1) |
608 | 13 | 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); |
609 | 13 | break;} |
610 | 5 | default: |
611 | 5 | if(s->int_sample_fmt == AV_SAMPLE_FMT_FLTP){ |
612 | 14 | for(i=0; i<len; i++){ |
613 | 13 | float v=0; |
614 | 65 | for(j=0; j<s->matrix_ch[out_i][0]; j++){ |
615 | 52 | in_i= s->matrix_ch[out_i][1+j]; |
616 | 52 | v+= ((float*)in->ch[in_i])[i] * s->matrix_flt[out_i][in_i]; |
617 | 52 | } |
618 | 13 | ((float*)out->ch[out_i])[i]= v; |
619 | 13 | } |
620 | 4 | }else if(s->int_sample_fmt == AV_SAMPLE_FMT_DBLP){ |
621 | 4.41k | for(i=0; i<len; i++){ |
622 | 4.40k | double v=0; |
623 | 39.6k | for(j=0; j<s->matrix_ch[out_i][0]; j++){ |
624 | 35.2k | in_i= s->matrix_ch[out_i][1+j]; |
625 | 35.2k | v+= ((double*)in->ch[in_i])[i] * s->matrix[out_i][in_i]; |
626 | 35.2k | } |
627 | 4.40k | ((double*)out->ch[out_i])[i]= v; |
628 | 4.40k | } |
629 | 4 | }else{ |
630 | 0 | for(i=0; i<len; i++){ |
631 | 0 | int v=0; |
632 | 0 | for(j=0; j<s->matrix_ch[out_i][0]; j++){ |
633 | 0 | in_i= s->matrix_ch[out_i][1+j]; |
634 | 0 | v+= ((int16_t*)in->ch[in_i])[i] * s->matrix32[out_i][in_i]; |
635 | 0 | } |
636 | 0 | ((int16_t*)out->ch[out_i])[i]= (v + 16384)>>15; |
637 | 0 | } |
638 | 0 | } |
639 | 183 | } |
640 | 183 | } |
641 | 32 | return 0; |
642 | 32 | } |