Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/*
2
 * Copyright (c) 2012 Justin Ruggles 
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg 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
 * FFmpeg 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 FFmpeg; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
 
21
#include 
22
 
23
#include "libavutil/common.h"
24
#include "libavutil/libm.h"
25
#include "libavutil/samplefmt.h"
26
#include "avresample.h"
27
#include "internal.h"
28
#include "audio_data.h"
29
#include "audio_mix.h"
30
 
31
static const char *coeff_type_names[] = { "q8", "q15", "flt" };
32
 
33
struct AudioMix {
34
    AVAudioResampleContext *avr;
35
    enum AVSampleFormat fmt;
36
    enum AVMixCoeffType coeff_type;
37
    uint64_t in_layout;
38
    uint64_t out_layout;
39
    int in_channels;
40
    int out_channels;
41
 
42
    int ptr_align;
43
    int samples_align;
44
    int has_optimized_func;
45
    const char *func_descr;
46
    const char *func_descr_generic;
47
    mix_func *mix;
48
    mix_func *mix_generic;
49
 
50
    int in_matrix_channels;
51
    int out_matrix_channels;
52
    int output_zero[AVRESAMPLE_MAX_CHANNELS];
53
    int input_skip[AVRESAMPLE_MAX_CHANNELS];
54
    int output_skip[AVRESAMPLE_MAX_CHANNELS];
55
    int16_t *matrix_q8[AVRESAMPLE_MAX_CHANNELS];
56
    int32_t *matrix_q15[AVRESAMPLE_MAX_CHANNELS];
57
    float   *matrix_flt[AVRESAMPLE_MAX_CHANNELS];
58
    void   **matrix;
59
};
60
 
61
void ff_audio_mix_set_func(AudioMix *am, enum AVSampleFormat fmt,
62
                           enum AVMixCoeffType coeff_type, int in_channels,
63
                           int out_channels, int ptr_align, int samples_align,
64
                           const char *descr, void *mix_func)
65
{
66
    if (fmt == am->fmt && coeff_type == am->coeff_type &&
67
        ( in_channels ==  am->in_matrix_channels ||  in_channels == 0) &&
68
        (out_channels == am->out_matrix_channels || out_channels == 0)) {
69
        char chan_str[16];
70
        am->mix           = mix_func;
71
        am->func_descr    = descr;
72
        am->ptr_align     = ptr_align;
73
        am->samples_align = samples_align;
74
        if (ptr_align == 1 && samples_align == 1) {
75
            am->mix_generic        = mix_func;
76
            am->func_descr_generic = descr;
77
        } else {
78
            am->has_optimized_func = 1;
79
        }
80
        if (in_channels) {
81
            if (out_channels)
82
                snprintf(chan_str, sizeof(chan_str), "[%d to %d] ",
83
                         in_channels, out_channels);
84
            else
85
                snprintf(chan_str, sizeof(chan_str), "[%d to any] ",
86
                         in_channels);
87
        } else if (out_channels) {
88
                snprintf(chan_str, sizeof(chan_str), "[any to %d] ",
89
                         out_channels);
90
        } else {
91
            snprintf(chan_str, sizeof(chan_str), "[any to any] ");
92
        }
93
        av_log(am->avr, AV_LOG_DEBUG, "audio_mix: found function: [fmt=%s] "
94
               "[c=%s] %s(%s)\n", av_get_sample_fmt_name(fmt),
95
               coeff_type_names[coeff_type], chan_str, descr);
96
    }
97
}
98
 
99
#define MIX_FUNC_NAME(fmt, cfmt) mix_any_ ## fmt ##_## cfmt ##_c
100
 
101
#define MIX_FUNC_GENERIC(fmt, cfmt, stype, ctype, sumtype, expr)            \
102
static void MIX_FUNC_NAME(fmt, cfmt)(stype **samples, ctype **matrix,       \
103
                                     int len, int out_ch, int in_ch)        \
104
{                                                                           \
105
    int i, in, out;                                                         \
106
    stype temp[AVRESAMPLE_MAX_CHANNELS];                                    \
107
    for (i = 0; i < len; i++) {                                             \
108
        for (out = 0; out < out_ch; out++) {                                \
109
            sumtype sum = 0;                                                \
110
            for (in = 0; in < in_ch; in++)                                  \
111
                sum += samples[in][i] * matrix[out][in];                    \
112
            temp[out] = expr;                                               \
113
        }                                                                   \
114
        for (out = 0; out < out_ch; out++)                                  \
115
            samples[out][i] = temp[out];                                    \
116
    }                                                                       \
117
}
118
 
119
MIX_FUNC_GENERIC(FLTP, FLT, float,   float,   float,   sum)
120
MIX_FUNC_GENERIC(S16P, FLT, int16_t, float,   float,   av_clip_int16(lrintf(sum)))
121
MIX_FUNC_GENERIC(S16P, Q15, int16_t, int32_t, int64_t, av_clip_int16(sum >> 15))
122
MIX_FUNC_GENERIC(S16P, Q8,  int16_t, int16_t, int32_t, av_clip_int16(sum >>  8))
123
 
124
/* TODO: templatize the channel-specific C functions */
125
 
126
static void mix_2_to_1_fltp_flt_c(float **samples, float **matrix, int len,
127
                                  int out_ch, int in_ch)
128
{
129
    float *src0 = samples[0];
130
    float *src1 = samples[1];
131
    float *dst  = src0;
132
    float m0    = matrix[0][0];
133
    float m1    = matrix[0][1];
134
 
135
    while (len > 4) {
136
        *dst++ = *src0++ * m0 + *src1++ * m1;
137
        *dst++ = *src0++ * m0 + *src1++ * m1;
138
        *dst++ = *src0++ * m0 + *src1++ * m1;
139
        *dst++ = *src0++ * m0 + *src1++ * m1;
140
        len -= 4;
141
    }
142
    while (len > 0) {
143
        *dst++ = *src0++ * m0 + *src1++ * m1;
144
        len--;
145
    }
146
}
147
 
148
static void mix_2_to_1_s16p_flt_c(int16_t **samples, float **matrix, int len,
149
                                  int out_ch, int in_ch)
150
{
151
    int16_t *src0 = samples[0];
152
    int16_t *src1 = samples[1];
153
    int16_t *dst  = src0;
154
    float m0      = matrix[0][0];
155
    float m1      = matrix[0][1];
156
 
157
    while (len > 4) {
158
        *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
159
        *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
160
        *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
161
        *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
162
        len -= 4;
163
    }
164
    while (len > 0) {
165
        *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
166
        len--;
167
    }
168
}
169
 
170
static void mix_2_to_1_s16p_q8_c(int16_t **samples, int16_t **matrix, int len,
171
                                 int out_ch, int in_ch)
172
{
173
    int16_t *src0 = samples[0];
174
    int16_t *src1 = samples[1];
175
    int16_t *dst  = src0;
176
    int16_t m0    = matrix[0][0];
177
    int16_t m1    = matrix[0][1];
178
 
179
    while (len > 4) {
180
        *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
181
        *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
182
        *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
183
        *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
184
        len -= 4;
185
    }
186
    while (len > 0) {
187
        *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
188
        len--;
189
    }
190
}
191
 
192
static void mix_1_to_2_fltp_flt_c(float **samples, float **matrix, int len,
193
                                  int out_ch, int in_ch)
194
{
195
    float v;
196
    float *dst0 = samples[0];
197
    float *dst1 = samples[1];
198
    float *src  = dst0;
199
    float m0    = matrix[0][0];
200
    float m1    = matrix[1][0];
201
 
202
    while (len > 4) {
203
        v = *src++;
204
        *dst0++ = v * m0;
205
        *dst1++ = v * m1;
206
        v = *src++;
207
        *dst0++ = v * m0;
208
        *dst1++ = v * m1;
209
        v = *src++;
210
        *dst0++ = v * m0;
211
        *dst1++ = v * m1;
212
        v = *src++;
213
        *dst0++ = v * m0;
214
        *dst1++ = v * m1;
215
        len -= 4;
216
    }
217
    while (len > 0) {
218
        v = *src++;
219
        *dst0++ = v * m0;
220
        *dst1++ = v * m1;
221
        len--;
222
    }
223
}
224
 
225
static void mix_6_to_2_fltp_flt_c(float **samples, float **matrix, int len,
226
                                  int out_ch, int in_ch)
227
{
228
    float v0, v1;
229
    float *src0 = samples[0];
230
    float *src1 = samples[1];
231
    float *src2 = samples[2];
232
    float *src3 = samples[3];
233
    float *src4 = samples[4];
234
    float *src5 = samples[5];
235
    float *dst0 = src0;
236
    float *dst1 = src1;
237
    float *m0   = matrix[0];
238
    float *m1   = matrix[1];
239
 
240
    while (len > 0) {
241
        v0 = *src0++;
242
        v1 = *src1++;
243
        *dst0++ = v0      * m0[0] +
244
                  v1      * m0[1] +
245
                  *src2   * m0[2] +
246
                  *src3   * m0[3] +
247
                  *src4   * m0[4] +
248
                  *src5   * m0[5];
249
        *dst1++ = v0      * m1[0] +
250
                  v1      * m1[1] +
251
                  *src2++ * m1[2] +
252
                  *src3++ * m1[3] +
253
                  *src4++ * m1[4] +
254
                  *src5++ * m1[5];
255
        len--;
256
    }
257
}
258
 
259
static void mix_2_to_6_fltp_flt_c(float **samples, float **matrix, int len,
260
                                  int out_ch, int in_ch)
261
{
262
    float v0, v1;
263
    float *dst0 = samples[0];
264
    float *dst1 = samples[1];
265
    float *dst2 = samples[2];
266
    float *dst3 = samples[3];
267
    float *dst4 = samples[4];
268
    float *dst5 = samples[5];
269
    float *src0 = dst0;
270
    float *src1 = dst1;
271
 
272
    while (len > 0) {
273
        v0 = *src0++;
274
        v1 = *src1++;
275
        *dst0++ = v0 * matrix[0][0] + v1 * matrix[0][1];
276
        *dst1++ = v0 * matrix[1][0] + v1 * matrix[1][1];
277
        *dst2++ = v0 * matrix[2][0] + v1 * matrix[2][1];
278
        *dst3++ = v0 * matrix[3][0] + v1 * matrix[3][1];
279
        *dst4++ = v0 * matrix[4][0] + v1 * matrix[4][1];
280
        *dst5++ = v0 * matrix[5][0] + v1 * matrix[5][1];
281
        len--;
282
    }
283
}
284
 
285
static av_cold int mix_function_init(AudioMix *am)
286
{
287
    am->func_descr = am->func_descr_generic = "n/a";
288
    am->mix = am->mix_generic = NULL;
289
 
290
    /* no need to set a mix function when we're skipping mixing */
291
    if (!am->in_matrix_channels || !am->out_matrix_channels)
292
        return 0;
293
 
294
    /* any-to-any C versions */
295
 
296
    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
297
                          0, 0, 1, 1, "C", MIX_FUNC_NAME(FLTP, FLT));
298
 
299
    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
300
                          0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, FLT));
301
 
302
    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q15,
303
                          0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q15));
304
 
305
    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q8,
306
                          0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q8));
307
 
308
    /* channel-specific C versions */
309
 
310
    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
311
                          2, 1, 1, 1, "C", mix_2_to_1_fltp_flt_c);
312
 
313
    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
314
                          2, 1, 1, 1, "C", mix_2_to_1_s16p_flt_c);
315
 
316
    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q8,
317
                          2, 1, 1, 1, "C", mix_2_to_1_s16p_q8_c);
318
 
319
    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
320
                          1, 2, 1, 1, "C", mix_1_to_2_fltp_flt_c);
321
 
322
    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
323
                          6, 2, 1, 1, "C", mix_6_to_2_fltp_flt_c);
324
 
325
    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
326
                          2, 6, 1, 1, "C", mix_2_to_6_fltp_flt_c);
327
 
328
    if (ARCH_X86)
329
        ff_audio_mix_init_x86(am);
330
 
331
    if (!am->mix) {
332
        av_log(am->avr, AV_LOG_ERROR, "audio_mix: NO FUNCTION FOUND: [fmt=%s] "
333
               "[c=%s] [%d to %d]\n", av_get_sample_fmt_name(am->fmt),
334
               coeff_type_names[am->coeff_type], am->in_channels,
335
               am->out_channels);
336
        return AVERROR_PATCHWELCOME;
337
    }
338
    return 0;
339
}
340
 
341
AudioMix *ff_audio_mix_alloc(AVAudioResampleContext *avr)
342
{
343
    AudioMix *am;
344
    int ret;
345
 
346
    am = av_mallocz(sizeof(*am));
347
    if (!am)
348
        return NULL;
349
    am->avr = avr;
350
 
351
    if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P &&
352
        avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP) {
353
        av_log(avr, AV_LOG_ERROR, "Unsupported internal format for "
354
               "mixing: %s\n",
355
               av_get_sample_fmt_name(avr->internal_sample_fmt));
356
        goto error;
357
    }
358
 
359
    am->fmt          = avr->internal_sample_fmt;
360
    am->coeff_type   = avr->mix_coeff_type;
361
    am->in_layout    = avr->in_channel_layout;
362
    am->out_layout   = avr->out_channel_layout;
363
    am->in_channels  = avr->in_channels;
364
    am->out_channels = avr->out_channels;
365
 
366
    /* build matrix if the user did not already set one */
367
    if (avr->mix_matrix) {
368
        ret = ff_audio_mix_set_matrix(am, avr->mix_matrix, avr->in_channels);
369
        if (ret < 0)
370
            goto error;
371
        av_freep(&avr->mix_matrix);
372
    } else {
373
        double *matrix_dbl = av_mallocz(avr->out_channels * avr->in_channels *
374
                                        sizeof(*matrix_dbl));
375
        if (!matrix_dbl)
376
            goto error;
377
 
378
        ret = avresample_build_matrix(avr->in_channel_layout,
379
                                      avr->out_channel_layout,
380
                                      avr->center_mix_level,
381
                                      avr->surround_mix_level,
382
                                      avr->lfe_mix_level,
383
                                      avr->normalize_mix_level,
384
                                      matrix_dbl,
385
                                      avr->in_channels,
386
                                      avr->matrix_encoding);
387
        if (ret < 0) {
388
            av_free(matrix_dbl);
389
            goto error;
390
        }
391
 
392
        ret = ff_audio_mix_set_matrix(am, matrix_dbl, avr->in_channels);
393
        if (ret < 0) {
394
            av_log(avr, AV_LOG_ERROR, "error setting mix matrix\n");
395
            av_free(matrix_dbl);
396
            goto error;
397
        }
398
 
399
        av_free(matrix_dbl);
400
    }
401
 
402
    return am;
403
 
404
error:
405
    av_free(am);
406
    return NULL;
407
}
408
 
409
void ff_audio_mix_free(AudioMix **am_p)
410
{
411
    AudioMix *am;
412
 
413
    if (!*am_p)
414
        return;
415
    am = *am_p;
416
 
417
    if (am->matrix) {
418
        av_free(am->matrix[0]);
419
        am->matrix = NULL;
420
    }
421
    memset(am->matrix_q8,  0, sizeof(am->matrix_q8 ));
422
    memset(am->matrix_q15, 0, sizeof(am->matrix_q15));
423
    memset(am->matrix_flt, 0, sizeof(am->matrix_flt));
424
 
425
    av_freep(am_p);
426
}
427
 
428
int ff_audio_mix(AudioMix *am, AudioData *src)
429
{
430
    int use_generic = 1;
431
    int len = src->nb_samples;
432
    int i, j;
433
 
434
    /* determine whether to use the optimized function based on pointer and
435
       samples alignment in both the input and output */
436
    if (am->has_optimized_func) {
437
        int aligned_len = FFALIGN(len, am->samples_align);
438
        if (!(src->ptr_align % am->ptr_align) &&
439
            src->samples_align >= aligned_len) {
440
            len = aligned_len;
441
            use_generic = 0;
442
        }
443
    }
444
    av_dlog(am->avr, "audio_mix: %d samples - %d to %d channels (%s)\n",
445
            src->nb_samples, am->in_channels, am->out_channels,
446
            use_generic ? am->func_descr_generic : am->func_descr);
447
 
448
    if (am->in_matrix_channels && am->out_matrix_channels) {
449
        uint8_t **data;
450
        uint8_t *data0[AVRESAMPLE_MAX_CHANNELS];
451
 
452
        if (am->out_matrix_channels < am->out_channels ||
453
             am->in_matrix_channels <  am->in_channels) {
454
            for (i = 0, j = 0; i < FFMAX(am->in_channels, am->out_channels); i++) {
455
                if (am->input_skip[i] || am->output_skip[i] || am->output_zero[i])
456
                    continue;
457
                data0[j++] = src->data[i];
458
            }
459
            data = data0;
460
        } else {
461
            data = src->data;
462
        }
463
 
464
        if (use_generic)
465
            am->mix_generic(data, am->matrix, len, am->out_matrix_channels,
466
                            am->in_matrix_channels);
467
        else
468
            am->mix(data, am->matrix, len, am->out_matrix_channels,
469
                    am->in_matrix_channels);
470
    }
471
 
472
    if (am->out_matrix_channels < am->out_channels) {
473
        for (i = 0; i < am->out_channels; i++)
474
            if (am->output_zero[i])
475
                av_samples_set_silence(&src->data[i], 0, len, 1, am->fmt);
476
    }
477
 
478
    ff_audio_data_set_channels(src, am->out_channels);
479
 
480
    return 0;
481
}
482
 
483
int ff_audio_mix_get_matrix(AudioMix *am, double *matrix, int stride)
484
{
485
    int i, o, i0, o0;
486
 
487
    if ( am->in_channels <= 0 ||  am->in_channels > AVRESAMPLE_MAX_CHANNELS ||
488
        am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {
489
        av_log(am->avr, AV_LOG_ERROR, "Invalid channel counts\n");
490
        return AVERROR(EINVAL);
491
    }
492
 
493
#define GET_MATRIX_CONVERT(suffix, scale)                                   \
494
    if (!am->matrix_ ## suffix[0]) {                                        \
495
        av_log(am->avr, AV_LOG_ERROR, "matrix is not set\n");               \
496
        return AVERROR(EINVAL);                                             \
497
    }                                                                       \
498
    for (o = 0, o0 = 0; o < am->out_channels; o++) {                        \
499
        for (i = 0, i0 = 0; i < am->in_channels; i++) {                     \
500
            if (am->input_skip[i] || am->output_zero[o])                    \
501
                matrix[o * stride + i] = 0.0;                               \
502
            else                                                            \
503
                matrix[o * stride + i] = am->matrix_ ## suffix[o0][i0] *    \
504
                                         (scale);                           \
505
            if (!am->input_skip[i])                                         \
506
                i0++;                                                       \
507
        }                                                                   \
508
        if (!am->output_zero[o])                                            \
509
            o0++;                                                           \
510
    }
511
 
512
    switch (am->coeff_type) {
513
    case AV_MIX_COEFF_TYPE_Q8:
514
        GET_MATRIX_CONVERT(q8, 1.0 / 256.0);
515
        break;
516
    case AV_MIX_COEFF_TYPE_Q15:
517
        GET_MATRIX_CONVERT(q15, 1.0 / 32768.0);
518
        break;
519
    case AV_MIX_COEFF_TYPE_FLT:
520
        GET_MATRIX_CONVERT(flt, 1.0);
521
        break;
522
    default:
523
        av_log(am->avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
524
        return AVERROR(EINVAL);
525
    }
526
 
527
    return 0;
528
}
529
 
530
static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
531
{
532
    int i, o;
533
 
534
    memset(am->output_zero, 0, sizeof(am->output_zero));
535
    memset(am->input_skip,  0, sizeof(am->input_skip));
536
    memset(am->output_skip, 0, sizeof(am->output_skip));
537
 
538
    /* exclude output channels if they can be zeroed instead of mixed */
539
    for (o = 0; o < am->out_channels; o++) {
540
        int zero = 1;
541
 
542
        /* check if the output is always silent */
543
        for (i = 0; i < am->in_channels; i++) {
544
            if (matrix[o * stride + i] != 0.0) {
545
                zero = 0;
546
                break;
547
            }
548
        }
549
        /* check if the corresponding input channel makes a contribution to
550
           any output channel */
551
        if (o < am->in_channels) {
552
            for (i = 0; i < am->out_channels; i++) {
553
                if (matrix[i * stride + o] != 0.0) {
554
                    zero = 0;
555
                    break;
556
                }
557
            }
558
        }
559
        if (zero) {
560
            am->output_zero[o] = 1;
561
            am->out_matrix_channels--;
562
        }
563
    }
564
    if (am->out_matrix_channels == 0) {
565
        am->in_matrix_channels = 0;
566
        return;
567
    }
568
 
569
    /* skip input channels that contribute fully only to the corresponding
570
       output channel */
571
    for (i = 0; i < FFMIN(am->in_channels, am->out_channels); i++) {
572
        int skip = 1;
573
 
574
        for (o = 0; o < am->out_channels; o++) {
575
            int i0;
576
            if ((o != i && matrix[o * stride + i] != 0.0) ||
577
                (o == i && matrix[o * stride + i] != 1.0)) {
578
                skip = 0;
579
                break;
580
            }
581
            /* if the input contributes fully to the output, also check that no
582
               other inputs contribute to this output */
583
            if (o == i) {
584
                for (i0 = 0; i0 < am->in_channels; i0++) {
585
                    if (i0 != i && matrix[o * stride + i0] != 0.0) {
586
                        skip = 0;
587
                        break;
588
                    }
589
                }
590
            }
591
        }
592
        if (skip) {
593
            am->input_skip[i] = 1;
594
            am->in_matrix_channels--;
595
        }
596
    }
597
    /* skip input channels that do not contribute to any output channel */
598
    for (; i < am->in_channels; i++) {
599
        int contrib = 0;
600
 
601
        for (o = 0; o < am->out_channels; o++) {
602
            if (matrix[o * stride + i] != 0.0) {
603
                contrib = 1;
604
                break;
605
            }
606
        }
607
        if (!contrib) {
608
            am->input_skip[i] = 1;
609
            am->in_matrix_channels--;
610
        }
611
    }
612
    if (am->in_matrix_channels == 0) {
613
        am->out_matrix_channels = 0;
614
        return;
615
    }
616
 
617
    /* skip output channels that only get full contribution from the
618
       corresponding input channel */
619
    for (o = 0; o < FFMIN(am->in_channels, am->out_channels); o++) {
620
        int skip = 1;
621
        int o0;
622
 
623
        for (i = 0; i < am->in_channels; i++) {
624
            if ((o != i && matrix[o * stride + i] != 0.0) ||
625
                (o == i && matrix[o * stride + i] != 1.0)) {
626
                skip = 0;
627
                break;
628
            }
629
        }
630
        /* check if the corresponding input channel makes a contribution to
631
           any other output channel */
632
        i = o;
633
        for (o0 = 0; o0 < am->out_channels; o0++) {
634
            if (o0 != i && matrix[o0 * stride + i] != 0.0) {
635
                skip = 0;
636
                break;
637
            }
638
        }
639
        if (skip) {
640
            am->output_skip[o] = 1;
641
            am->out_matrix_channels--;
642
        }
643
    }
644
    if (am->out_matrix_channels == 0) {
645
        am->in_matrix_channels = 0;
646
        return;
647
    }
648
}
649
 
650
int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride)
651
{
652
    int i, o, i0, o0, ret;
653
    char in_layout_name[128];
654
    char out_layout_name[128];
655
 
656
    if ( am->in_channels <= 0 ||  am->in_channels > AVRESAMPLE_MAX_CHANNELS ||
657
        am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {
658
        av_log(am->avr, AV_LOG_ERROR, "Invalid channel counts\n");
659
        return AVERROR(EINVAL);
660
    }
661
 
662
    if (am->matrix) {
663
        av_free(am->matrix[0]);
664
        am->matrix = NULL;
665
    }
666
 
667
    am->in_matrix_channels  = am->in_channels;
668
    am->out_matrix_channels = am->out_channels;
669
 
670
    reduce_matrix(am, matrix, stride);
671
 
672
#define CONVERT_MATRIX(type, expr)                                          \
673
    am->matrix_## type[0] = av_mallocz(am->out_matrix_channels *            \
674
                                       am->in_matrix_channels  *            \
675
                                       sizeof(*am->matrix_## type[0]));     \
676
    if (!am->matrix_## type[0])                                             \
677
        return AVERROR(ENOMEM);                                             \
678
    for (o = 0, o0 = 0; o < am->out_channels; o++) {                        \
679
        if (am->output_zero[o] || am->output_skip[o])                       \
680
            continue;                                                       \
681
        if (o0 > 0)                                                         \
682
            am->matrix_## type[o0] = am->matrix_## type[o0 - 1] +           \
683
                                     am->in_matrix_channels;                \
684
        for (i = 0, i0 = 0; i < am->in_channels; i++) {                     \
685
            double v;                                                       \
686
            if (am->input_skip[i])                                          \
687
                continue;                                                   \
688
            v = matrix[o * stride + i];                                     \
689
            am->matrix_## type[o0][i0] = expr;                              \
690
            i0++;                                                           \
691
        }                                                                   \
692
        o0++;                                                               \
693
    }                                                                       \
694
    am->matrix = (void **)am->matrix_## type;
695
 
696
    if (am->in_matrix_channels && am->out_matrix_channels) {
697
        switch (am->coeff_type) {
698
        case AV_MIX_COEFF_TYPE_Q8:
699
            CONVERT_MATRIX(q8, av_clip_int16(lrint(256.0 * v)))
700
            break;
701
        case AV_MIX_COEFF_TYPE_Q15:
702
            CONVERT_MATRIX(q15, av_clipl_int32(llrint(32768.0 * v)))
703
            break;
704
        case AV_MIX_COEFF_TYPE_FLT:
705
            CONVERT_MATRIX(flt, v)
706
            break;
707
        default:
708
            av_log(am->avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
709
            return AVERROR(EINVAL);
710
        }
711
    }
712
 
713
    ret = mix_function_init(am);
714
    if (ret < 0)
715
        return ret;
716
 
717
    av_get_channel_layout_string(in_layout_name, sizeof(in_layout_name),
718
                                 am->in_channels, am->in_layout);
719
    av_get_channel_layout_string(out_layout_name, sizeof(out_layout_name),
720
                                 am->out_channels, am->out_layout);
721
    av_log(am->avr, AV_LOG_DEBUG, "audio_mix: %s to %s\n",
722
           in_layout_name, out_layout_name);
723
    av_log(am->avr, AV_LOG_DEBUG, "matrix size: %d x %d\n",
724
           am->in_matrix_channels, am->out_matrix_channels);
725
    for (o = 0; o < am->out_channels; o++) {
726
        for (i = 0; i < am->in_channels; i++) {
727
            if (am->output_zero[o])
728
                av_log(am->avr, AV_LOG_DEBUG, "  (ZERO)");
729
            else if (am->input_skip[i] || am->output_skip[o])
730
                av_log(am->avr, AV_LOG_DEBUG, "  (SKIP)");
731
            else
732
                av_log(am->avr, AV_LOG_DEBUG, "  %0.3f ",
733
                       matrix[o * am->in_channels + i]);
734
        }
735
        av_log(am->avr, AV_LOG_DEBUG, "\n");
736
    }
737
 
738
    return 0;
739
}