1/*
2 * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
3 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <stdint.h>
23
24#include "config.h"
25#include "libavutil/common.h"
26#include "libavutil/libm.h"
27#include "libavutil/log.h"
28#include "libavutil/mem.h"
29#include "libavutil/samplefmt.h"
30#include "audio_convert.h"
31#include "audio_data.h"
32#include "dither.h"
33
34enum ConvFuncType {
35    CONV_FUNC_TYPE_FLAT,
36    CONV_FUNC_TYPE_INTERLEAVE,
37    CONV_FUNC_TYPE_DEINTERLEAVE,
38};
39
40typedef void (conv_func_flat)(uint8_t *out, const uint8_t *in, int len);
41
42typedef void (conv_func_interleave)(uint8_t *out, uint8_t *const *in,
43                                    int len, int channels);
44
45typedef void (conv_func_deinterleave)(uint8_t **out, const uint8_t *in, int len,
46                                      int channels);
47
48struct AudioConvert {
49    AVAudioResampleContext *avr;
50    DitherContext *dc;
51    enum AVSampleFormat in_fmt;
52    enum AVSampleFormat out_fmt;
53    int apply_map;
54    int channels;
55    int planes;
56    int ptr_align;
57    int samples_align;
58    int has_optimized_func;
59    const char *func_descr;
60    const char *func_descr_generic;
61    enum ConvFuncType func_type;
62    conv_func_flat         *conv_flat;
63    conv_func_flat         *conv_flat_generic;
64    conv_func_interleave   *conv_interleave;
65    conv_func_interleave   *conv_interleave_generic;
66    conv_func_deinterleave *conv_deinterleave;
67    conv_func_deinterleave *conv_deinterleave_generic;
68};
69
70void ff_audio_convert_set_func(AudioConvert *ac, enum AVSampleFormat out_fmt,
71                               enum AVSampleFormat in_fmt, int channels,
72                               int ptr_align, int samples_align,
73                               const char *descr, void *conv)
74{
75    int found = 0;
76
77    switch (ac->func_type) {
78    case CONV_FUNC_TYPE_FLAT:
79        if (av_get_packed_sample_fmt(ac->in_fmt)  == in_fmt &&
80            av_get_packed_sample_fmt(ac->out_fmt) == out_fmt) {
81            ac->conv_flat     = conv;
82            ac->func_descr    = descr;
83            ac->ptr_align     = ptr_align;
84            ac->samples_align = samples_align;
85            if (ptr_align == 1 && samples_align == 1) {
86                ac->conv_flat_generic  = conv;
87                ac->func_descr_generic = descr;
88            } else {
89                ac->has_optimized_func = 1;
90            }
91            found = 1;
92        }
93        break;
94    case CONV_FUNC_TYPE_INTERLEAVE:
95        if (ac->in_fmt == in_fmt && ac->out_fmt == out_fmt &&
96            (!channels || ac->channels == channels)) {
97            ac->conv_interleave = conv;
98            ac->func_descr      = descr;
99            ac->ptr_align       = ptr_align;
100            ac->samples_align   = samples_align;
101            if (ptr_align == 1 && samples_align == 1) {
102                ac->conv_interleave_generic = conv;
103                ac->func_descr_generic      = descr;
104            } else {
105                ac->has_optimized_func = 1;
106            }
107            found = 1;
108        }
109        break;
110    case CONV_FUNC_TYPE_DEINTERLEAVE:
111        if (ac->in_fmt == in_fmt && ac->out_fmt == out_fmt &&
112            (!channels || ac->channels == channels)) {
113            ac->conv_deinterleave = conv;
114            ac->func_descr        = descr;
115            ac->ptr_align         = ptr_align;
116            ac->samples_align     = samples_align;
117            if (ptr_align == 1 && samples_align == 1) {
118                ac->conv_deinterleave_generic = conv;
119                ac->func_descr_generic        = descr;
120            } else {
121                ac->has_optimized_func = 1;
122            }
123            found = 1;
124        }
125        break;
126    }
127    if (found) {
128        av_log(ac->avr, AV_LOG_DEBUG, "audio_convert: found function: %-4s "
129               "to %-4s (%s)\n", av_get_sample_fmt_name(ac->in_fmt),
130               av_get_sample_fmt_name(ac->out_fmt), descr);
131    }
132}
133
134#define CONV_FUNC_NAME(dst_fmt, src_fmt) conv_ ## src_fmt ## _to_ ## dst_fmt
135
136#define CONV_LOOP(otype, expr)                                              \
137    do {                                                                    \
138        *(otype *)po = expr;                                                \
139        pi += is;                                                           \
140        po += os;                                                           \
141    } while (po < end);                                                     \
142
143#define CONV_FUNC_FLAT(ofmt, otype, ifmt, itype, expr)                      \
144static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *out, const uint8_t *in,     \
145                                       int len)                             \
146{                                                                           \
147    int is       = sizeof(itype);                                           \
148    int os       = sizeof(otype);                                           \
149    const uint8_t *pi = in;                                                 \
150    uint8_t       *po = out;                                                \
151    uint8_t *end = out + os * len;                                          \
152    CONV_LOOP(otype, expr)                                                  \
153}
154
155#define CONV_FUNC_INTERLEAVE(ofmt, otype, ifmt, itype, expr)                \
156static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *out, const uint8_t **in,    \
157                                       int len, int channels)               \
158{                                                                           \
159    int ch;                                                                 \
160    int out_bps = sizeof(otype);                                            \
161    int is      = sizeof(itype);                                            \
162    int os      = channels * out_bps;                                       \
163    for (ch = 0; ch < channels; ch++) {                                     \
164        const uint8_t *pi = in[ch];                                         \
165        uint8_t       *po = out + ch * out_bps;                             \
166        uint8_t      *end = po + os * len;                                  \
167        CONV_LOOP(otype, expr)                                              \
168    }                                                                       \
169}
170
171#define CONV_FUNC_DEINTERLEAVE(ofmt, otype, ifmt, itype, expr)              \
172static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t **out, const uint8_t *in,    \
173                                       int len, int channels)               \
174{                                                                           \
175    int ch;                                                                 \
176    int in_bps = sizeof(itype);                                             \
177    int is     = channels * in_bps;                                         \
178    int os     = sizeof(otype);                                             \
179    for (ch = 0; ch < channels; ch++) {                                     \
180        const uint8_t *pi = in  + ch * in_bps;                              \
181        uint8_t       *po = out[ch];                                        \
182        uint8_t      *end = po + os * len;                                  \
183        CONV_LOOP(otype, expr)                                              \
184    }                                                                       \
185}
186
187#define CONV_FUNC_GROUP(ofmt, otype, ifmt, itype, expr) \
188CONV_FUNC_FLAT(        ofmt,      otype, ifmt,      itype, expr) \
189CONV_FUNC_INTERLEAVE(  ofmt,      otype, ifmt ## P, itype, expr) \
190CONV_FUNC_DEINTERLEAVE(ofmt ## P, otype, ifmt,      itype, expr)
191
192CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  uint8_t, AV_SAMPLE_FMT_U8,  uint8_t,  *(const uint8_t *)pi)
193CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_U8,  uint8_t, (*(const uint8_t *)pi - 0x80) <<  8)
194CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_U8,  uint8_t, (*(const uint8_t *)pi - 0x80) << 24)
195CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float,   AV_SAMPLE_FMT_U8,  uint8_t, (*(const uint8_t *)pi - 0x80) * (1.0f / (1 << 7)))
196CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double,  AV_SAMPLE_FMT_U8,  uint8_t, (*(const uint8_t *)pi - 0x80) * (1.0  / (1 << 7)))
197CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  uint8_t, AV_SAMPLE_FMT_S16, int16_t, (*(const int16_t *)pi >> 8) + 0x80)
198CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S16, int16_t,  *(const int16_t *)pi)
199CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, int16_t,  *(const int16_t *)pi << 16)
200CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float,   AV_SAMPLE_FMT_S16, int16_t,  *(const int16_t *)pi * (1.0f / (1 << 15)))
201CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double,  AV_SAMPLE_FMT_S16, int16_t,  *(const int16_t *)pi * (1.0  / (1 << 15)))
202CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  uint8_t, AV_SAMPLE_FMT_S32, int32_t, (*(const int32_t *)pi >> 24) + 0x80)
203CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S32, int32_t,  *(const int32_t *)pi >> 16)
204CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S32, int32_t,  *(const int32_t *)pi)
205CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float,   AV_SAMPLE_FMT_S32, int32_t,  *(const int32_t *)pi * (1.0f / (1U << 31)))
206CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double,  AV_SAMPLE_FMT_S32, int32_t,  *(const int32_t *)pi * (1.0  / (1U << 31)))
207CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  uint8_t, AV_SAMPLE_FMT_FLT, float,   av_clip_uint8(  lrintf(*(const float *)pi * (1  <<  7)) + 0x80))
208CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float,   av_clip_int16(  lrintf(*(const float *)pi * (1  << 15))))
209CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float,   av_clipl_int32(llrintf(*(const float *)pi * (1U << 31))))
210CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float,   AV_SAMPLE_FMT_FLT, float,   *(const float *)pi)
211CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double,  AV_SAMPLE_FMT_FLT, float,   *(const float *)pi)
212CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  uint8_t, AV_SAMPLE_FMT_DBL, double,  av_clip_uint8(  lrint(*(const double *)pi * (1  <<  7)) + 0x80))
213CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double,  av_clip_int16(  lrint(*(const double *)pi * (1  << 15))))
214CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double,  av_clipl_int32(llrint(*(const double *)pi * (1U << 31))))
215CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float,   AV_SAMPLE_FMT_DBL, double,  *(const double *)pi)
216CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double,  AV_SAMPLE_FMT_DBL, double,  *(const double *)pi)
217
218#define SET_CONV_FUNC_GROUP(ofmt, ifmt)                                                             \
219ff_audio_convert_set_func(ac, ofmt,      ifmt,      0, 1, 1, "C", CONV_FUNC_NAME(ofmt,      ifmt)); \
220ff_audio_convert_set_func(ac, ofmt ## P, ifmt,      0, 1, 1, "C", CONV_FUNC_NAME(ofmt ## P, ifmt)); \
221ff_audio_convert_set_func(ac, ofmt,      ifmt ## P, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt,      ifmt ## P));
222
223static void set_generic_function(AudioConvert *ac)
224{
225    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  AV_SAMPLE_FMT_U8)
226    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8)
227    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8)
228    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8)
229    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8)
230    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  AV_SAMPLE_FMT_S16)
231    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16)
232    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16)
233    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16)
234    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16)
235    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  AV_SAMPLE_FMT_S32)
236    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32)
237    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32)
238    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32)
239    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32)
240    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  AV_SAMPLE_FMT_FLT)
241    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT)
242    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT)
243    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT)
244    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT)
245    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  AV_SAMPLE_FMT_DBL)
246    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL)
247    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL)
248    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL)
249    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL)
250}
251
252void ff_audio_convert_free(AudioConvert **ac)
253{
254    if (!*ac)
255        return;
256    ff_dither_free(&(*ac)->dc);
257    av_freep(ac);
258}
259
260AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr,
261                                     enum AVSampleFormat out_fmt,
262                                     enum AVSampleFormat in_fmt,
263                                     int channels, int sample_rate,
264                                     int apply_map)
265{
266    AudioConvert *ac;
267    int in_planar, out_planar;
268
269    ac = av_mallocz(sizeof(*ac));
270    if (!ac)
271        return NULL;
272
273    ac->avr      = avr;
274    ac->out_fmt  = out_fmt;
275    ac->in_fmt   = in_fmt;
276    ac->channels = channels;
277    ac->apply_map = apply_map;
278
279    if (avr->dither_method != AV_RESAMPLE_DITHER_NONE          &&
280        av_get_packed_sample_fmt(out_fmt) == AV_SAMPLE_FMT_S16 &&
281        av_get_bytes_per_sample(in_fmt) > 2) {
282        ac->dc = ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate,
283                                 apply_map);
284        if (!ac->dc) {
285            av_free(ac);
286            return NULL;
287        }
288        return ac;
289    }
290
291    in_planar  = av_sample_fmt_is_planar(in_fmt);
292    out_planar = av_sample_fmt_is_planar(out_fmt);
293
294    if (in_planar == out_planar) {
295        ac->func_type = CONV_FUNC_TYPE_FLAT;
296        ac->planes    = in_planar ? ac->channels : 1;
297    } else if (in_planar)
298        ac->func_type = CONV_FUNC_TYPE_INTERLEAVE;
299    else
300        ac->func_type = CONV_FUNC_TYPE_DEINTERLEAVE;
301
302    set_generic_function(ac);
303
304    if (ARCH_AARCH64)
305        ff_audio_convert_init_aarch64(ac);
306    if (ARCH_ARM)
307        ff_audio_convert_init_arm(ac);
308    if (ARCH_X86)
309        ff_audio_convert_init_x86(ac);
310
311    return ac;
312}
313
314int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in)
315{
316    int use_generic = 1;
317    int len         = in->nb_samples;
318    int p;
319
320    if (ac->dc) {
321        /* dithered conversion */
322        av_dlog(ac->avr, "%d samples - audio_convert: %s to %s (dithered)\n",
323                len, av_get_sample_fmt_name(ac->in_fmt),
324                av_get_sample_fmt_name(ac->out_fmt));
325
326        return ff_convert_dither(ac->dc, out, in);
327    }
328
329    /* determine whether to use the optimized function based on pointer and
330       samples alignment in both the input and output */
331    if (ac->has_optimized_func) {
332        int ptr_align     = FFMIN(in->ptr_align,     out->ptr_align);
333        int samples_align = FFMIN(in->samples_align, out->samples_align);
334        int aligned_len   = FFALIGN(len, ac->samples_align);
335        if (!(ptr_align % ac->ptr_align) && samples_align >= aligned_len) {
336            len = aligned_len;
337            use_generic = 0;
338        }
339    }
340    av_dlog(ac->avr, "%d samples - audio_convert: %s to %s (%s)\n", len,
341            av_get_sample_fmt_name(ac->in_fmt),
342            av_get_sample_fmt_name(ac->out_fmt),
343            use_generic ? ac->func_descr_generic : ac->func_descr);
344
345    if (ac->apply_map) {
346        ChannelMapInfo *map = &ac->avr->ch_map_info;
347
348        if (!av_sample_fmt_is_planar(ac->out_fmt)) {
349            av_log(ac->avr, AV_LOG_ERROR, "cannot remap packed format during conversion\n");
350            return AVERROR(EINVAL);
351        }
352
353        if (map->do_remap) {
354            if (av_sample_fmt_is_planar(ac->in_fmt)) {
355                conv_func_flat *convert = use_generic ? ac->conv_flat_generic :
356                                                        ac->conv_flat;
357
358                for (p = 0; p < ac->planes; p++)
359                    if (map->channel_map[p] >= 0)
360                        convert(out->data[p], in->data[map->channel_map[p]], len);
361            } else {
362                uint8_t *data[AVRESAMPLE_MAX_CHANNELS];
363                conv_func_deinterleave *convert = use_generic ?
364                                                  ac->conv_deinterleave_generic :
365                                                  ac->conv_deinterleave;
366
367                for (p = 0; p < ac->channels; p++)
368                    data[map->input_map[p]] = out->data[p];
369
370                convert(data, in->data[0], len, ac->channels);
371            }
372        }
373        if (map->do_copy || map->do_zero) {
374            for (p = 0; p < ac->planes; p++) {
375                if (map->channel_copy[p])
376                    memcpy(out->data[p], out->data[map->channel_copy[p]],
377                           len * out->stride);
378                else if (map->channel_zero[p])
379                    av_samples_set_silence(&out->data[p], 0, len, 1, ac->out_fmt);
380            }
381        }
382    } else {
383        switch (ac->func_type) {
384        case CONV_FUNC_TYPE_FLAT: {
385            if (!in->is_planar)
386                len *= in->channels;
387            if (use_generic) {
388                for (p = 0; p < ac->planes; p++)
389                    ac->conv_flat_generic(out->data[p], in->data[p], len);
390            } else {
391                for (p = 0; p < ac->planes; p++)
392                    ac->conv_flat(out->data[p], in->data[p], len);
393            }
394            break;
395        }
396        case CONV_FUNC_TYPE_INTERLEAVE:
397            if (use_generic)
398                ac->conv_interleave_generic(out->data[0], in->data, len,
399                                            ac->channels);
400            else
401                ac->conv_interleave(out->data[0], in->data, len, ac->channels);
402            break;
403        case CONV_FUNC_TYPE_DEINTERLEAVE:
404            if (use_generic)
405                ac->conv_deinterleave_generic(out->data, in->data[0], len,
406                                              ac->channels);
407            else
408                ac->conv_deinterleave(out->data, in->data[0], len,
409                                      ac->channels);
410            break;
411        }
412    }
413
414    out->nb_samples = in->nb_samples;
415    return 0;
416}
417