Coverage Report

Created: 2024-09-06 07:53

/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
}