1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
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 <stdint.h>
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
31static const char * const coeff_type_names[] = { "q8", "q15", "flt" };
32
33struct 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
61void 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)            \
102static 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
119MIX_FUNC_GENERIC(FLTP, FLT, float,   float,   float,   sum)
120MIX_FUNC_GENERIC(S16P, FLT, int16_t, float,   float,   av_clip_int16(lrintf(sum)))
121MIX_FUNC_GENERIC(S16P, Q15, int16_t, int32_t, int64_t, av_clip_int16(sum >> 15))
122MIX_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
126static 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
148static 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
170static 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
192static 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
225static 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
259static 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
285static 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
341AudioMix *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
404error:
405    av_free(am);
406    return NULL;
407}
408
409void 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
428int 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_log(am->avr, AV_LOG_TRACE, "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] = { NULL };
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
483int 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
530static 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            if (o < am->in_channels)
563                am->in_matrix_channels--;
564        }
565    }
566    if (am->out_matrix_channels == 0 || am->in_matrix_channels == 0) {
567        am->out_matrix_channels = 0;
568        am->in_matrix_channels = 0;
569        return;
570    }
571
572    /* skip input channels that contribute fully only to the corresponding
573       output channel */
574    for (i = 0; i < FFMIN(am->in_channels, am->out_channels); i++) {
575        int skip = 1;
576
577        for (o = 0; o < am->out_channels; o++) {
578            int i0;
579            if ((o != i && matrix[o * stride + i] != 0.0) ||
580                (o == i && matrix[o * stride + i] != 1.0)) {
581                skip = 0;
582                break;
583            }
584            /* if the input contributes fully to the output, also check that no
585               other inputs contribute to this output */
586            if (o == i) {
587                for (i0 = 0; i0 < am->in_channels; i0++) {
588                    if (i0 != i && matrix[o * stride + i0] != 0.0) {
589                        skip = 0;
590                        break;
591                    }
592                }
593            }
594        }
595        if (skip) {
596            am->input_skip[i] = 1;
597            am->in_matrix_channels--;
598        }
599    }
600    /* skip input channels that do not contribute to any output channel */
601    for (; i < am->in_channels; i++) {
602        int contrib = 0;
603
604        for (o = 0; o < am->out_channels; o++) {
605            if (matrix[o * stride + i] != 0.0) {
606                contrib = 1;
607                break;
608            }
609        }
610        if (!contrib) {
611            am->input_skip[i] = 1;
612            am->in_matrix_channels--;
613        }
614    }
615    if (am->in_matrix_channels == 0) {
616        am->out_matrix_channels = 0;
617        return;
618    }
619
620    /* skip output channels that only get full contribution from the
621       corresponding input channel */
622    for (o = 0; o < FFMIN(am->in_channels, am->out_channels); o++) {
623        int skip = 1;
624        int o0;
625
626        for (i = 0; i < am->in_channels; i++) {
627            if ((o != i && matrix[o * stride + i] != 0.0) ||
628                (o == i && matrix[o * stride + i] != 1.0)) {
629                skip = 0;
630                break;
631            }
632        }
633        /* check if the corresponding input channel makes a contribution to
634           any other output channel */
635        i = o;
636        for (o0 = 0; o0 < am->out_channels; o0++) {
637            if (o0 != i && matrix[o0 * stride + i] != 0.0) {
638                skip = 0;
639                break;
640            }
641        }
642        if (skip) {
643            am->output_skip[o] = 1;
644            am->out_matrix_channels--;
645        }
646    }
647    if (am->out_matrix_channels == 0) {
648        am->in_matrix_channels = 0;
649        return;
650    }
651}
652
653int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride)
654{
655    int i, o, i0, o0, ret;
656    char in_layout_name[128];
657    char out_layout_name[128];
658
659    if ( am->in_channels <= 0 ||  am->in_channels > AVRESAMPLE_MAX_CHANNELS ||
660        am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {
661        av_log(am->avr, AV_LOG_ERROR, "Invalid channel counts\n");
662        return AVERROR(EINVAL);
663    }
664
665    if (am->matrix) {
666        av_free(am->matrix[0]);
667        am->matrix = NULL;
668    }
669
670    am->in_matrix_channels  = am->in_channels;
671    am->out_matrix_channels = am->out_channels;
672
673    reduce_matrix(am, matrix, stride);
674
675#define CONVERT_MATRIX(type, expr)                                          \
676    am->matrix_## type[0] = av_mallocz(am->out_matrix_channels *            \
677                                       am->in_matrix_channels  *            \
678                                       sizeof(*am->matrix_## type[0]));     \
679    if (!am->matrix_## type[0])                                             \
680        return AVERROR(ENOMEM);                                             \
681    for (o = 0, o0 = 0; o < am->out_channels; o++) {                        \
682        if (am->output_zero[o] || am->output_skip[o])                       \
683            continue;                                                       \
684        if (o0 > 0)                                                         \
685            am->matrix_## type[o0] = am->matrix_## type[o0 - 1] +           \
686                                     am->in_matrix_channels;                \
687        for (i = 0, i0 = 0; i < am->in_channels; i++) {                     \
688            double v;                                                       \
689            if (am->input_skip[i] || am->output_zero[i])                    \
690                continue;                                                   \
691            v = matrix[o * stride + i];                                     \
692            am->matrix_## type[o0][i0] = expr;                              \
693            i0++;                                                           \
694        }                                                                   \
695        o0++;                                                               \
696    }                                                                       \
697    am->matrix = (void **)am->matrix_## type;
698
699    if (am->in_matrix_channels && am->out_matrix_channels) {
700        switch (am->coeff_type) {
701        case AV_MIX_COEFF_TYPE_Q8:
702            CONVERT_MATRIX(q8, av_clip_int16(lrint(256.0 * v)))
703            break;
704        case AV_MIX_COEFF_TYPE_Q15:
705            CONVERT_MATRIX(q15, av_clipl_int32(llrint(32768.0 * v)))
706            break;
707        case AV_MIX_COEFF_TYPE_FLT:
708            CONVERT_MATRIX(flt, v)
709            break;
710        default:
711            av_log(am->avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
712            return AVERROR(EINVAL);
713        }
714    }
715
716    ret = mix_function_init(am);
717    if (ret < 0)
718        return ret;
719
720    av_get_channel_layout_string(in_layout_name, sizeof(in_layout_name),
721                                 am->in_channels, am->in_layout);
722    av_get_channel_layout_string(out_layout_name, sizeof(out_layout_name),
723                                 am->out_channels, am->out_layout);
724    av_log(am->avr, AV_LOG_DEBUG, "audio_mix: %s to %s\n",
725           in_layout_name, out_layout_name);
726    av_log(am->avr, AV_LOG_DEBUG, "matrix size: %d x %d\n",
727           am->in_matrix_channels, am->out_matrix_channels);
728    for (o = 0; o < am->out_channels; o++) {
729        for (i = 0; i < am->in_channels; i++) {
730            if (am->output_zero[o])
731                av_log(am->avr, AV_LOG_DEBUG, "  (ZERO)");
732            else if (am->input_skip[i] || am->output_zero[i] || am->output_skip[o])
733                av_log(am->avr, AV_LOG_DEBUG, "  (SKIP)");
734            else
735                av_log(am->avr, AV_LOG_DEBUG, "  %0.3f ",
736                       matrix[o * am->in_channels + i]);
737        }
738        av_log(am->avr, AV_LOG_DEBUG, "\n");
739    }
740
741    return 0;
742}
743