Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Add libavresample

This is a new library for audio sample format, channel layout, and sample rate
conversion.
  • Loading branch information...
commit c8af852b97447491823ff9b91413e32415e2babf 1 parent c5671ae
Justin Ruggles justinruggles authored
1  Changelog
@@ -16,6 +16,7 @@ version <next>:
16 16 - RealAudio Lossless decoder
17 17 - ZeroCodec decoder
18 18 - drop support for avconv without libavfilter
  19 +- add libavresample audio conversion library
19 20
20 21
21 22 version 0.8:
3  Makefile
@@ -20,7 +20,7 @@ $(foreach VAR,$(SILENT),$(eval override $(VAR) = @$($(VAR))))
20 20 $(eval INSTALL = @$(call ECHO,INSTALL,$$(^:$(SRC_PATH)/%=%)); $(INSTALL))
21 21 endif
22 22
23   -ALLFFLIBS = avcodec avdevice avfilter avformat avutil swscale
  23 +ALLFFLIBS = avcodec avdevice avfilter avformat avresample avutil swscale
24 24
25 25 IFLAGS := -I. -I$(SRC_PATH)
26 26 CPPFLAGS := $(IFLAGS) $(CPPFLAGS)
@@ -71,6 +71,7 @@ ALLMANPAGES = $(BASENAMES:%=%.1)
71 71 FFLIBS-$(CONFIG_AVDEVICE) += avdevice
72 72 FFLIBS-$(CONFIG_AVFILTER) += avfilter
73 73 FFLIBS-$(CONFIG_AVFORMAT) += avformat
  74 +FFLIBS-$(CONFIG_AVRESAMPLE) += avresample
74 75 FFLIBS-$(CONFIG_AVCODEC) += avcodec
75 76 FFLIBS-$(CONFIG_SWSCALE) += swscale
76 77
7 configure
@@ -110,6 +110,7 @@ Component options:
110 110 --disable-avformat disable libavformat build
111 111 --disable-swscale disable libswscale build
112 112 --disable-avfilter disable video filter support [no]
  113 + --disable-avresample disable libavresample build [no]
113 114 --disable-pthreads disable pthreads [auto]
114 115 --disable-w32threads disable Win32 threads [auto]
115 116 --enable-x11grab enable X11 grabbing [no]
@@ -927,6 +928,7 @@ CONFIG_LIST="
927 928 avdevice
928 929 avfilter
929 930 avformat
  931 + avresample
930 932 avisynth
931 933 bzlib
932 934 dct
@@ -1536,7 +1538,7 @@ avdevice_deps="avcodec avformat"
1536 1538 avformat_deps="avcodec"
1537 1539
1538 1540 # programs
1539   -avconv_deps="avcodec avfilter avformat swscale"
  1541 +avconv_deps="avcodec avfilter avformat avresample swscale"
1540 1542 avplay_deps="avcodec avformat swscale sdl"
1541 1543 avplay_select="rdft"
1542 1544 avprobe_deps="avcodec avformat"
@@ -1684,6 +1686,7 @@ enable avcodec
1684 1686 enable avdevice
1685 1687 enable avfilter
1686 1688 enable avformat
  1689 +enable avresample
1687 1690 enable avutil
1688 1691 enable swscale
1689 1692
@@ -3385,6 +3388,7 @@ get_version LIBAVCODEC libavcodec/version.h
3385 3388 get_version LIBAVDEVICE libavdevice/avdevice.h
3386 3389 get_version LIBAVFILTER libavfilter/version.h
3387 3390 get_version LIBAVFORMAT libavformat/version.h
  3391 +get_version LIBAVRESAMPLE libavresample/version.h
3388 3392 get_version LIBAVUTIL libavutil/avutil.h
3389 3393 get_version LIBSWSCALE libswscale/swscale.h
3390 3394
@@ -3504,4 +3508,5 @@ pkgconfig_generate libavcodec "Libav codec library" "$LIBAVCODEC_VERSION" "$extr
3504 3508 pkgconfig_generate libavformat "Libav container format library" "$LIBAVFORMAT_VERSION" "$extralibs" "libavcodec = $LIBAVCODEC_VERSION"
3505 3509 pkgconfig_generate libavdevice "Libav device handling library" "$LIBAVDEVICE_VERSION" "$extralibs" "libavformat = $LIBAVFORMAT_VERSION"
3506 3510 pkgconfig_generate libavfilter "Libav video filtering library" "$LIBAVFILTER_VERSION" "$extralibs"
  3511 +pkgconfig_generate libavresample "Libav audio resampling library" "$LIBAVRESAMPLE_VERSION" "$extralibs"
3507 3512 pkgconfig_generate libswscale "Libav image rescaling library" "$LIBSWSCALE_VERSION" "$LIBM" "libavutil = $LIBAVUTIL_VERSION"
16 doc/APIchanges
@@ -2,16 +2,20 @@ Never assume the API of libav* to be stable unless at least 1 month has passed
2 2 since the last major version increase.
3 3
4 4 The last version increases were:
5   -libavcodec: 2012-01-27
6   -libavdevice: 2011-04-18
7   -libavfilter: 2011-04-18
8   -libavformat: 2012-01-27
9   -libswscale: 2011-06-20
10   -libavutil: 2011-04-18
  5 +libavcodec: 2012-01-27
  6 +libavdevice: 2011-04-18
  7 +libavfilter: 2011-04-18
  8 +libavformat: 2012-01-27
  9 +libavresample: 2012-xx-xx
  10 +libswscale: 2011-06-20
  11 +libavutil: 2011-04-18
11 12
12 13
13 14 API changes, most recent first:
14 15
  16 +2012-xx-xx - xxxxxxx - lavr 0.0.0
  17 + Add libavresample audio conversion library
  18 +
15 19 2012-xx-xx - xxxxxxx - lavu 51.28.0 - audio_fifo.h
16 20 Add audio FIFO functions:
17 21 av_audio_fifo_free()
15 libavresample/Makefile
... ... @@ -0,0 +1,15 @@
  1 +NAME = avresample
  2 +FFLIBS = avutil
  3 +
  4 +HEADERS = avresample.h \
  5 + version.h
  6 +
  7 +OBJS = audio_convert.o \
  8 + audio_data.o \
  9 + audio_mix.o \
  10 + audio_mix_matrix.o \
  11 + options.o \
  12 + resample.o \
  13 + utils.o
  14 +
  15 +TESTPROGS = avresample
334 libavresample/audio_convert.c
... ... @@ -0,0 +1,334 @@
  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 Libav.
  6 + *
  7 + * Libav 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 + * Libav 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 Libav; 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/libm.h"
  26 +#include "libavutil/log.h"
  27 +#include "libavutil/mem.h"
  28 +#include "libavutil/samplefmt.h"
  29 +#include "audio_convert.h"
  30 +#include "audio_data.h"
  31 +
  32 +enum ConvFuncType {
  33 + CONV_FUNC_TYPE_FLAT,
  34 + CONV_FUNC_TYPE_INTERLEAVE,
  35 + CONV_FUNC_TYPE_DEINTERLEAVE,
  36 +};
  37 +
  38 +typedef void (conv_func_flat)(uint8_t *out, const uint8_t *in, int len);
  39 +
  40 +typedef void (conv_func_interleave)(uint8_t *out, uint8_t *const *in,
  41 + int len, int channels);
  42 +
  43 +typedef void (conv_func_deinterleave)(uint8_t **out, const uint8_t *in, int len,
  44 + int channels);
  45 +
  46 +struct AudioConvert {
  47 + AVAudioResampleContext *avr;
  48 + enum AVSampleFormat in_fmt;
  49 + enum AVSampleFormat out_fmt;
  50 + int channels;
  51 + int planes;
  52 + int ptr_align;
  53 + int samples_align;
  54 + int has_optimized_func;
  55 + const char *func_descr;
  56 + const char *func_descr_generic;
  57 + enum ConvFuncType func_type;
  58 + conv_func_flat *conv_flat;
  59 + conv_func_flat *conv_flat_generic;
  60 + conv_func_interleave *conv_interleave;
  61 + conv_func_interleave *conv_interleave_generic;
  62 + conv_func_deinterleave *conv_deinterleave;
  63 + conv_func_deinterleave *conv_deinterleave_generic;
  64 +};
  65 +
  66 +void ff_audio_convert_set_func(AudioConvert *ac, enum AVSampleFormat out_fmt,
  67 + enum AVSampleFormat in_fmt, int channels,
  68 + int ptr_align, int samples_align,
  69 + const char *descr, void *conv)
  70 +{
  71 + int found = 0;
  72 +
  73 + switch (ac->func_type) {
  74 + case CONV_FUNC_TYPE_FLAT:
  75 + if (av_get_packed_sample_fmt(ac->in_fmt) == in_fmt &&
  76 + av_get_packed_sample_fmt(ac->out_fmt) == out_fmt) {
  77 + ac->conv_flat = conv;
  78 + ac->func_descr = descr;
  79 + ac->ptr_align = ptr_align;
  80 + ac->samples_align = samples_align;
  81 + if (ptr_align == 1 && samples_align == 1) {
  82 + ac->conv_flat_generic = conv;
  83 + ac->func_descr_generic = descr;
  84 + } else {
  85 + ac->has_optimized_func = 1;
  86 + }
  87 + found = 1;
  88 + }
  89 + break;
  90 + case CONV_FUNC_TYPE_INTERLEAVE:
  91 + if (ac->in_fmt == in_fmt && ac->out_fmt == out_fmt &&
  92 + (!channels || ac->channels == channels)) {
  93 + ac->conv_interleave = conv;
  94 + ac->func_descr = descr;
  95 + ac->ptr_align = ptr_align;
  96 + ac->samples_align = samples_align;
  97 + if (ptr_align == 1 && samples_align == 1) {
  98 + ac->conv_interleave_generic = conv;
  99 + ac->func_descr_generic = descr;
  100 + } else {
  101 + ac->has_optimized_func = 1;
  102 + }
  103 + found = 1;
  104 + }
  105 + break;
  106 + case CONV_FUNC_TYPE_DEINTERLEAVE:
  107 + if (ac->in_fmt == in_fmt && ac->out_fmt == out_fmt &&
  108 + (!channels || ac->channels == channels)) {
  109 + ac->conv_deinterleave = conv;
  110 + ac->func_descr = descr;
  111 + ac->ptr_align = ptr_align;
  112 + ac->samples_align = samples_align;
  113 + if (ptr_align == 1 && samples_align == 1) {
  114 + ac->conv_deinterleave_generic = conv;
  115 + ac->func_descr_generic = descr;
  116 + } else {
  117 + ac->has_optimized_func = 1;
  118 + }
  119 + found = 1;
  120 + }
  121 + break;
  122 + }
  123 + if (found) {
  124 + av_log(ac->avr, AV_LOG_DEBUG, "audio_convert: found function: %-4s "
  125 + "to %-4s (%s)\n", av_get_sample_fmt_name(ac->in_fmt),
  126 + av_get_sample_fmt_name(ac->out_fmt), descr);
  127 + }
  128 +}
  129 +
  130 +#define CONV_FUNC_NAME(dst_fmt, src_fmt) conv_ ## src_fmt ## _to_ ## dst_fmt
  131 +
  132 +#define CONV_LOOP(otype, expr) \
  133 + do { \
  134 + *(otype *)po = expr; \
  135 + pi += is; \
  136 + po += os; \
  137 + } while (po < end); \
  138 +
  139 +#define CONV_FUNC_FLAT(ofmt, otype, ifmt, itype, expr) \
  140 +static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *out, const uint8_t *in, \
  141 + int len) \
  142 +{ \
  143 + int is = sizeof(itype); \
  144 + int os = sizeof(otype); \
  145 + const uint8_t *pi = in; \
  146 + uint8_t *po = out; \
  147 + uint8_t *end = out + os * len; \
  148 + CONV_LOOP(otype, expr) \
  149 +}
  150 +
  151 +#define CONV_FUNC_INTERLEAVE(ofmt, otype, ifmt, itype, expr) \
  152 +static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *out, const uint8_t **in, \
  153 + int len, int channels) \
  154 +{ \
  155 + int ch; \
  156 + int out_bps = sizeof(otype); \
  157 + int is = sizeof(itype); \
  158 + int os = channels * out_bps; \
  159 + for (ch = 0; ch < channels; ch++) { \
  160 + const uint8_t *pi = in[ch]; \
  161 + uint8_t *po = out + ch * out_bps; \
  162 + uint8_t *end = po + os * len; \
  163 + CONV_LOOP(otype, expr) \
  164 + } \
  165 +}
  166 +
  167 +#define CONV_FUNC_DEINTERLEAVE(ofmt, otype, ifmt, itype, expr) \
  168 +static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t **out, const uint8_t *in, \
  169 + int len, int channels) \
  170 +{ \
  171 + int ch; \
  172 + int in_bps = sizeof(itype); \
  173 + int is = channels * in_bps; \
  174 + int os = sizeof(otype); \
  175 + for (ch = 0; ch < channels; ch++) { \
  176 + const uint8_t *pi = in + ch * in_bps; \
  177 + uint8_t *po = out[ch]; \
  178 + uint8_t *end = po + os * len; \
  179 + CONV_LOOP(otype, expr) \
  180 + } \
  181 +}
  182 +
  183 +#define CONV_FUNC_GROUP(ofmt, otype, ifmt, itype, expr) \
  184 +CONV_FUNC_FLAT( ofmt, otype, ifmt, itype, expr) \
  185 +CONV_FUNC_INTERLEAVE( ofmt, otype, ifmt ## P, itype, expr) \
  186 +CONV_FUNC_DEINTERLEAVE(ofmt ## P, otype, ifmt, itype, expr)
  187 +
  188 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_U8, uint8_t, *(const uint8_t *)pi)
  189 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) << 8)
  190 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) << 24)
  191 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) * (1.0f / (1 << 7)))
  192 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) * (1.0 / (1 << 7)))
  193 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t, (*(const int16_t *)pi >> 8) + 0x80)
  194 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi)
  195 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi << 16)
  196 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi * (1.0f / (1 << 15)))
  197 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi * (1.0 / (1 << 15)))
  198 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t, (*(const int32_t *)pi >> 24) + 0x80)
  199 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi >> 16)
  200 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi)
  201 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi * (1.0f / (1U << 31)))
  202 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi * (1.0 / (1U << 31)))
  203 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8( lrintf(*(const float *)pi * (1 << 7)) + 0x80))
  204 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16( lrintf(*(const float *)pi * (1 << 15))))
  205 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *)pi * (1U << 31))))
  206 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_FLT, float, *(const float *)pi)
  207 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_FLT, float, *(const float *)pi)
  208 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8( lrint(*(const double *)pi * (1 << 7)) + 0x80))
  209 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16( lrint(*(const double *)pi * (1 << 15))))
  210 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *)pi * (1U << 31))))
  211 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_DBL, double, *(const double *)pi)
  212 +CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_DBL, double, *(const double *)pi)
  213 +
  214 +#define SET_CONV_FUNC_GROUP(ofmt, ifmt) \
  215 +ff_audio_convert_set_func(ac, ofmt, ifmt, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt, ifmt)); \
  216 +ff_audio_convert_set_func(ac, ofmt ## P, ifmt, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt ## P, ifmt)); \
  217 +ff_audio_convert_set_func(ac, ofmt, ifmt ## P, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt, ifmt ## P));
  218 +
  219 +static void set_generic_function(AudioConvert *ac)
  220 +{
  221 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8)
  222 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8)
  223 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8)
  224 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8)
  225 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8)
  226 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16)
  227 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16)
  228 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16)
  229 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16)
  230 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16)
  231 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32)
  232 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32)
  233 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32)
  234 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32)
  235 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32)
  236 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT)
  237 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT)
  238 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT)
  239 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT)
  240 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT)
  241 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL)
  242 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL)
  243 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL)
  244 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL)
  245 + SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL)
  246 +}
  247 +
  248 +AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr,
  249 + enum AVSampleFormat out_fmt,
  250 + enum AVSampleFormat in_fmt,
  251 + int channels)
  252 +{
  253 + AudioConvert *ac;
  254 + int in_planar, out_planar;
  255 +
  256 + ac = av_mallocz(sizeof(*ac));
  257 + if (!ac)
  258 + return NULL;
  259 +
  260 + ac->avr = avr;
  261 + ac->out_fmt = out_fmt;
  262 + ac->in_fmt = in_fmt;
  263 + ac->channels = channels;
  264 +
  265 + in_planar = av_sample_fmt_is_planar(in_fmt);
  266 + out_planar = av_sample_fmt_is_planar(out_fmt);
  267 +
  268 + if (in_planar == out_planar) {
  269 + ac->func_type = CONV_FUNC_TYPE_FLAT;
  270 + ac->planes = in_planar ? ac->channels : 1;
  271 + } else if (in_planar)
  272 + ac->func_type = CONV_FUNC_TYPE_INTERLEAVE;
  273 + else
  274 + ac->func_type = CONV_FUNC_TYPE_DEINTERLEAVE;
  275 +
  276 + set_generic_function(ac);
  277 +
  278 + if (ARCH_X86)
  279 + ff_audio_convert_init_x86(ac);
  280 +
  281 + return ac;
  282 +}
  283 +
  284 +int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in, int len)
  285 +{
  286 + int use_generic = 1;
  287 +
  288 + /* determine whether to use the optimized function based on pointer and
  289 + samples alignment in both the input and output */
  290 + if (ac->has_optimized_func) {
  291 + int ptr_align = FFMIN(in->ptr_align, out->ptr_align);
  292 + int samples_align = FFMIN(in->samples_align, out->samples_align);
  293 + int aligned_len = FFALIGN(len, ac->samples_align);
  294 + if (!(ptr_align % ac->ptr_align) && samples_align >= aligned_len) {
  295 + len = aligned_len;
  296 + use_generic = 0;
  297 + }
  298 + }
  299 + av_dlog(ac->avr, "%d samples - audio_convert: %s to %s (%s)\n", len,
  300 + av_get_sample_fmt_name(ac->in_fmt),
  301 + av_get_sample_fmt_name(ac->out_fmt),
  302 + use_generic ? ac->func_descr_generic : ac->func_descr);
  303 +
  304 + switch (ac->func_type) {
  305 + case CONV_FUNC_TYPE_FLAT: {
  306 + int p;
  307 + if (!in->is_planar)
  308 + len *= in->channels;
  309 + if (use_generic) {
  310 + for (p = 0; p < ac->planes; p++)
  311 + ac->conv_flat_generic(out->data[p], in->data[p], len);
  312 + } else {
  313 + for (p = 0; p < ac->planes; p++)
  314 + ac->conv_flat(out->data[p], in->data[p], len);
  315 + }
  316 + break;
  317 + }
  318 + case CONV_FUNC_TYPE_INTERLEAVE:
  319 + if (use_generic)
  320 + ac->conv_interleave_generic(out->data[0], in->data, len, ac->channels);
  321 + else
  322 + ac->conv_interleave(out->data[0], in->data, len, ac->channels);
  323 + break;
  324 + case CONV_FUNC_TYPE_DEINTERLEAVE:
  325 + if (use_generic)
  326 + ac->conv_deinterleave_generic(out->data, in->data[0], len, ac->channels);
  327 + else
  328 + ac->conv_deinterleave(out->data, in->data[0], len, ac->channels);
  329 + break;
  330 + }
  331 +
  332 + out->nb_samples = in->nb_samples;
  333 + return 0;
  334 +}
87 libavresample/audio_convert.h
... ... @@ -0,0 +1,87 @@
  1 +/*
  2 + * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
  3 + *
  4 + * This file is part of Libav.
  5 + *
  6 + * Libav 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 + * Libav 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 Libav; if not, write to the Free Software
  18 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19 + */
  20 +
  21 +#ifndef AVRESAMPLE_AUDIO_CONVERT_H
  22 +#define AVRESAMPLE_AUDIO_CONVERT_H
  23 +
  24 +#include "libavutil/samplefmt.h"
  25 +#include "avresample.h"
  26 +#include "audio_data.h"
  27 +
  28 +typedef struct AudioConvert AudioConvert;
  29 +
  30 +/**
  31 + * Set conversion function if the parameters match.
  32 + *
  33 + * This compares the parameters of the conversion function to the parameters
  34 + * in the AudioConvert context. If the parameters do not match, no changes are
  35 + * made to the active functions. If the parameters do match and the alignment
  36 + * is not constrained, the function is set as the generic conversion function.
  37 + * If the parameters match and the alignment is constrained, the function is
  38 + * set as the optimized conversion function.
  39 + *
  40 + * @param ac AudioConvert context
  41 + * @param out_fmt output sample format
  42 + * @param in_fmt input sample format
  43 + * @param channels number of channels, or 0 for any number of channels
  44 + * @param ptr_align buffer pointer alignment, in bytes
  45 + * @param sample_align buffer size alignment, in samples
  46 + * @param descr function type description (e.g. "C" or "SSE")
  47 + * @param conv conversion function pointer
  48 + */
  49 +void ff_audio_convert_set_func(AudioConvert *ac, enum AVSampleFormat out_fmt,
  50 + enum AVSampleFormat in_fmt, int channels,
  51 + int ptr_align, int samples_align,
  52 + const char *descr, void *conv);
  53 +
  54 +/**
  55 + * Allocate and initialize AudioConvert context for sample format conversion.
  56 + *
  57 + * @param avr AVAudioResampleContext
  58 + * @param out_fmt output sample format
  59 + * @param in_fmt input sample format
  60 + * @param channels number of channels
  61 + * @return newly-allocated AudioConvert context
  62 + */
  63 +AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr,
  64 + enum AVSampleFormat out_fmt,
  65 + enum AVSampleFormat in_fmt,
  66 + int channels);
  67 +
  68 +/**
  69 + * Convert audio data from one sample format to another.
  70 + *
  71 + * For each call, the alignment of the input and output AudioData buffers are
  72 + * examined to determine whether to use the generic or optimized conversion
  73 + * function (when available).
  74 + *
  75 + * @param ac AudioConvert context
  76 + * @param out output audio data
  77 + * @param in input audio data
  78 + * @param len number of samples to convert
  79 + * @return 0 on success, negative AVERROR code on failure
  80 + */
  81 +int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in, int len);
  82 +
  83 +/* arch-specific initialization functions */
  84 +
  85 +void ff_audio_convert_init_x86(AudioConvert *ac);
  86 +
  87 +#endif /* AVRESAMPLE_AUDIO_CONVERT_H */
345 libavresample/audio_data.c
... ... @@ -0,0 +1,345 @@
  1 +/*
  2 + * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
  3 + *
  4 + * This file is part of Libav.
  5 + *
  6 + * Libav 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 + * Libav 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 Libav; 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/mem.h"
  24 +#include "audio_data.h"
  25 +
  26 +static const AVClass audio_data_class = {
  27 + .class_name = "AudioData",
  28 + .item_name = av_default_item_name,
  29 + .version = LIBAVUTIL_VERSION_INT,
  30 +};
  31 +
  32 +/*
  33 + * Calculate alignment for data pointers.
  34 + */
  35 +static void calc_ptr_alignment(AudioData *a)
  36 +{
  37 + int p;
  38 + int min_align = 128;
  39 +
  40 + for (p = 0; p < a->planes; p++) {
  41 + int cur_align = 128;
  42 + while ((intptr_t)a->data[p] % cur_align)
  43 + cur_align >>= 1;
  44 + if (cur_align < min_align)
  45 + min_align = cur_align;
  46 + }
  47 + a->ptr_align = min_align;
  48 +}
  49 +
  50 +int ff_audio_data_set_channels(AudioData *a, int channels)
  51 +{
  52 + if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS ||
  53 + channels > a->allocated_channels)
  54 + return AVERROR(EINVAL);
  55 +
  56 + a->channels = channels;
  57 + a->planes = a->is_planar ? channels : 1;
  58 +
  59 + calc_ptr_alignment(a);
  60 +
  61 + return 0;
  62 +}
  63 +
  64 +int ff_audio_data_init(AudioData *a, void **src, int plane_size, int channels,
  65 + int nb_samples, enum AVSampleFormat sample_fmt,
  66 + int read_only, const char *name)
  67 +{
  68 + int p;
  69 +
  70 + memset(a, 0, sizeof(*a));
  71 + a->class = &audio_data_class;
  72 +
  73 + if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS) {
  74 + av_log(a, AV_LOG_ERROR, "invalid channel count: %d\n", channels);
  75 + return AVERROR(EINVAL);
  76 + }
  77 +
  78 + a->sample_size = av_get_bytes_per_sample(sample_fmt);
  79 + if (!a->sample_size) {
  80 + av_log(a, AV_LOG_ERROR, "invalid sample format\n");
  81 + return AVERROR(EINVAL);
  82 + }
  83 + a->is_planar = av_sample_fmt_is_planar(sample_fmt);
  84 + a->planes = a->is_planar ? channels : 1;
  85 + a->stride = a->sample_size * (a->is_planar ? 1 : channels);
  86 +
  87 + for (p = 0; p < (a->is_planar ? channels : 1); p++) {
  88 + if (!src[p]) {
  89 + av_log(a, AV_LOG_ERROR, "invalid NULL pointer for src[%d]\n", p);
  90 + return AVERROR(EINVAL);
  91 + }
  92 + a->data[p] = src[p];
  93 + }
  94 + a->allocated_samples = nb_samples * !read_only;
  95 + a->nb_samples = nb_samples;
  96 + a->sample_fmt = sample_fmt;
  97 + a->channels = channels;
  98 + a->allocated_channels = channels;
  99 + a->read_only = read_only;
  100 + a->allow_realloc = 0;
  101 + a->name = name ? name : "{no name}";
  102 +
  103 + calc_ptr_alignment(a);
  104 + a->samples_align = plane_size / a->stride;
  105 +
  106 + return 0;
  107 +}
  108 +
  109 +AudioData *ff_audio_data_alloc(int channels, int nb_samples,
  110 + enum AVSampleFormat sample_fmt, const char *name)
  111 +{
  112 + AudioData *a;
  113 + int ret;
  114 +
  115 + if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS)
  116 + return NULL;
  117 +
  118 + a = av_mallocz(sizeof(*a));
  119 + if (!a)
  120 + return NULL;
  121 +
  122 + a->sample_size = av_get_bytes_per_sample(sample_fmt);
  123 + if (!a->sample_size) {
  124 + av_free(a);
  125 + return NULL;
  126 + }
  127 + a->is_planar = av_sample_fmt_is_planar(sample_fmt);
  128 + a->planes = a->is_planar ? channels : 1;
  129 + a->stride = a->sample_size * (a->is_planar ? 1 : channels);
  130 +
  131 + a->class = &audio_data_class;
  132 + a->sample_fmt = sample_fmt;
  133 + a->channels = channels;
  134 + a->allocated_channels = channels;
  135 + a->read_only = 0;
  136 + a->allow_realloc = 1;
  137 + a->name = name ? name : "{no name}";
  138 +
  139 + if (nb_samples > 0) {
  140 + ret = ff_audio_data_realloc(a, nb_samples);
  141 + if (ret < 0) {
  142 + av_free(a);
  143 + return NULL;
  144 + }
  145 + return a;
  146 + } else {
  147 + calc_ptr_alignment(a);
  148 + return a;
  149 + }
  150 +}
  151 +
  152 +int ff_audio_data_realloc(AudioData *a, int nb_samples)
  153 +{
  154 + int ret, new_buf_size, plane_size, p;
  155 +
  156 + /* check if buffer is already large enough */
  157 + if (a->allocated_samples >= nb_samples)
  158 + return 0;
  159 +
  160 + /* validate that the output is not read-only and realloc is allowed */
  161 + if (a->read_only || !a->allow_realloc)
  162 + return AVERROR(EINVAL);
  163 +
  164 + new_buf_size = av_samples_get_buffer_size(&plane_size,
  165 + a->allocated_channels, nb_samples,
  166 + a->sample_fmt, 0);
  167 + if (new_buf_size < 0)
  168 + return new_buf_size;
  169 +
  170 + /* if there is already data in the buffer and the sample format is planar,
  171 + allocate a new buffer and copy the data, otherwise just realloc the
  172 + internal buffer and set new data pointers */
  173 + if (a->nb_samples > 0 && a->is_planar) {
  174 + uint8_t *new_data[AVRESAMPLE_MAX_CHANNELS] = { NULL };
  175 +
  176 + ret = av_samples_alloc(new_data, &plane_size, a->allocated_channels,
  177 + nb_samples, a->sample_fmt, 0);
  178 + if (ret < 0)
  179 + return ret;
  180 +
  181 + for (p = 0; p < a->planes; p++)
  182 + memcpy(new_data[p], a->data[p], a->nb_samples * a->stride);
  183 +
  184 + av_freep(&a->buffer);
  185 + memcpy(a->data, new_data, sizeof(new_data));
  186 + a->buffer = a->data[0];
  187 + } else {
  188 + av_freep(&a->buffer);
  189 + a->buffer = av_malloc(new_buf_size);
  190 + if (!a->buffer)
  191 + return AVERROR(ENOMEM);
  192 + ret = av_samples_fill_arrays(a->data, &plane_size, a->buffer,
  193 + a->allocated_channels, nb_samples,
  194 + a->sample_fmt, 0);
  195 + if (ret < 0)
  196 + return ret;
  197 + }
  198 + a->buffer_size = new_buf_size;
  199 + a->allocated_samples = nb_samples;
  200 +
  201 + calc_ptr_alignment(a);
  202 + a->samples_align = plane_size / a->stride;
  203 +
  204 + return 0;
  205 +}
  206 +
  207 +void ff_audio_data_free(AudioData **a)
  208 +{
  209 + if (!*a)
  210 + return;
  211 + av_free((*a)->buffer);
  212 + av_freep(a);
  213 +}
  214 +
  215 +int ff_audio_data_copy(AudioData *dst, AudioData *src)
  216 +{
  217 + int ret, p;
  218 +
  219 + /* validate input/output compatibility */
  220 + if (dst->sample_fmt != src->sample_fmt || dst->channels < src->channels)
  221 + return AVERROR(EINVAL);
  222 +
  223 + /* if the input is empty, just empty the output */
  224 + if (!src->nb_samples) {
  225 + dst->nb_samples = 0;
  226 + return 0;
  227 + }
  228 +
  229 + /* reallocate output if necessary */
  230 + ret = ff_audio_data_realloc(dst, src->nb_samples);
  231 + if (ret < 0)
  232 + return ret;
  233 +
  234 + /* copy data */
  235 + for (p = 0; p < src->planes; p++)
  236 + memcpy(dst->data[p], src->data[p], src->nb_samples * src->stride);
  237 + dst->nb_samples = src->nb_samples;
  238 +
  239 + return 0;
  240 +}
  241 +
  242 +int ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src,
  243 + int src_offset, int nb_samples)
  244 +{
  245 + int ret, p, dst_offset2, dst_move_size;
  246 +
  247 + /* validate input/output compatibility */
  248 + if (dst->sample_fmt != src->sample_fmt || dst->channels != src->channels) {
  249 + av_log(src, AV_LOG_ERROR, "sample format mismatch\n");
  250 + return AVERROR(EINVAL);
  251 + }
  252 +
  253 + /* validate offsets are within the buffer bounds */
  254 + if (dst_offset < 0 || dst_offset > dst->nb_samples ||
  255 + src_offset < 0 || src_offset > src->nb_samples) {
  256 + av_log(src, AV_LOG_ERROR, "offset out-of-bounds: src=%d dst=%d\n",
  257 + src_offset, dst_offset);
  258 + return AVERROR(EINVAL);
  259 + }
  260 +
  261 + /* check offsets and sizes to see if we can just do nothing and return */
  262 + if (nb_samples > src->nb_samples - src_offset)
  263 + nb_samples = src->nb_samples - src_offset;
  264 + if (nb_samples <= 0)
  265 + return 0;
  266 +
  267 + /* validate that the output is not read-only */
  268 + if (dst->read_only) {
  269 + av_log(dst, AV_LOG_ERROR, "dst is read-only\n");
  270 + return AVERROR(EINVAL);
  271 + }
  272 +
  273 + /* reallocate output if necessary */
  274 + ret = ff_audio_data_realloc(dst, dst->nb_samples + nb_samples);
  275 + if (ret < 0) {
  276 + av_log(dst, AV_LOG_ERROR, "error reallocating dst\n");
  277 + return ret;
  278 + }
  279 +
  280 + dst_offset2 = dst_offset + nb_samples;
  281 + dst_move_size = dst->nb_samples - dst_offset;
  282 +
  283 + for (p = 0; p < src->planes; p++) {
  284 + if (dst_move_size > 0) {
  285 + memmove(dst->data[p] + dst_offset2 * dst->stride,
  286 + dst->data[p] + dst_offset * dst->stride,
  287 + dst_move_size * dst->stride);
  288 + }
  289 + memcpy(dst->data[p] + dst_offset * dst->stride,
  290 + src->data[p] + src_offset * src->stride,
  291 + nb_samples * src->stride);
  292 + }
  293 + dst->nb_samples += nb_samples;
  294 +
  295 + return 0;
  296 +}
  297 +
  298 +void ff_audio_data_drain(AudioData *a, int nb_samples)
  299 +{
  300 + if (a->nb_samples <= nb_samples) {
  301 + /* drain the whole buffer */
  302 + a->nb_samples = 0;
  303 + } else {
  304 + int p;
  305 + int move_offset = a->stride * nb_samples;
  306 + int move_size = a->stride * (a->nb_samples - nb_samples);
  307 +
  308 + for (p = 0; p < a->planes; p++)
  309 + memmove(a->data[p], a->data[p] + move_offset, move_size);
  310 +
  311 + a->nb_samples -= nb_samples;
  312 + }
  313 +}
  314 +
  315 +int ff_audio_data_add_to_fifo(AVAudioFifo *af, AudioData *a, int offset,
  316 + int nb_samples)
  317 +{
  318 + uint8_t *offset_data[AVRESAMPLE_MAX_CHANNELS];
  319 + int offset_size, p;
  320 +
  321 + if (offset >= a->nb_samples)
  322 + return 0;
  323 + offset_size = offset * a->stride;
  324 + for (p = 0; p < a->planes; p++)
  325 + offset_data[p] = a->data[p] + offset_size;
  326 +
  327 + return av_audio_fifo_write(af, (void **)offset_data, nb_samples);
  328 +}
  329 +
  330 +int ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples)
  331 +{
  332 + int ret;
  333 +
  334 + if (a->read_only)
  335 + return AVERROR(EINVAL);
  336 +
  337 + ret = ff_audio_data_realloc(a, nb_samples);
  338 + if (ret < 0)
  339 + return ret;
  340 +
  341 + ret = av_audio_fifo_read(af, (void **)a->data, nb_samples);
  342 + if (ret >= 0)
  343 + a->nb_samples = ret;
  344 + return ret;
  345 +}
173 libavresample/audio_data.h
... ... @@ -0,0 +1,173 @@
  1 +/*
  2 + * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
  3 + *
  4 + * This file is part of Libav.
  5 + *
  6 + * Libav 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 + * Libav 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 Libav; if not, write to the Free Software
  18 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19 + */
  20 +
  21 +#ifndef AVRESAMPLE_AUDIO_DATA_H
  22 +#define AVRESAMPLE_AUDIO_DATA_H
  23 +
  24 +#include <stdint.h>
  25 +
  26 +#include "libavutil/audio_fifo.h"
  27 +#include "libavutil/log.h"
  28 +#include "libavutil/samplefmt.h"
  29 +#include "avresample.h"
  30 +
  31 +/**
  32 + * Audio buffer used for intermediate storage between conversion phases.
  33 + */
  34 +typedef struct AudioData {
  35 + const AVClass *class; /**< AVClass for logging */
  36 + uint8_t *data[AVRESAMPLE_MAX_CHANNELS]; /**< data plane pointers */
  37 + uint8_t *buffer; /**< data buffer */
  38 + unsigned int buffer_size; /**< allocated buffer size */
  39 + int allocated_samples; /**< number of samples the buffer can hold */
  40 + int nb_samples; /**< current number of samples */
  41 + enum AVSampleFormat sample_fmt; /**< sample format */
  42 + int channels; /**< channel count */
  43 + int allocated_channels; /**< allocated channel count */
  44 + int is_planar; /**< sample format is planar */
  45 + int planes; /**< number of data planes */
  46 + int sample_size; /**< bytes per sample */
  47 + int stride; /**< sample byte offset within a plane */
  48 + int read_only; /**< data is read-only */
  49 + int allow_realloc; /**< realloc is allowed */
  50 + int ptr_align; /**< minimum data pointer alignment */
  51 + int samples_align; /**< allocated samples alignment */
  52 + const char *name; /**< name for debug logging */
  53 +} AudioData;
  54 +
  55 +int ff_audio_data_set_channels(AudioData *a, int channels);
  56 +
  57 +/**
  58 + * Initialize AudioData using a given source.
  59 + *
  60 + * This does not allocate an internal buffer. It only sets the data pointers
  61 + * and audio parameters.
  62 + *
  63 + * @param a AudioData struct
  64 + * @param src source data pointers
  65 + * @param plane_size plane size, in bytes.
  66 + * This can be 0 if unknown, but that will lead to
  67 + * optimized functions not being used in many cases,
  68 + * which could slow down some conversions.
  69 + * @param channels channel count
  70 + * @param nb_samples number of samples in the source data
  71 + * @param sample_fmt sample format
  72 + * @param read_only indicates if buffer is read only or read/write
  73 + * @param name name for debug logging (can be NULL)
  74 + * @return 0 on success, negative AVERROR value on error
  75 + */
  76 +int ff_audio_data_init(AudioData *a, void **src, int plane_size, int channels,
  77 + int nb_samples, enum AVSampleFormat sample_fmt,
  78 + int read_only, const char *name);
  79 +
  80 +/**
  81 + * Allocate AudioData.
  82 + *
  83 + * This allocates an internal buffer and sets audio parameters.
  84 + *
  85 + * @param channels channel count
  86 + * @param nb_samples number of samples to allocate space for
  87 + * @param sample_fmt sample format
  88 + * @param name name for debug logging (can be NULL)
  89 + * @return newly allocated AudioData struct, or NULL on error
  90 + */
  91 +AudioData *ff_audio_data_alloc(int channels, int nb_samples,
  92 + enum AVSampleFormat sample_fmt,
  93 + const char *name);
  94 +
  95 +/**
  96 + * Reallocate AudioData.
  97 + *
  98 + * The AudioData must have been previously allocated with ff_audio_data_alloc().
  99 + *
  100 + * @param a AudioData struct
  101 + * @param nb_samples number of samples to allocate space for
  102 + * @return 0 on success, negative AVERROR value on error
  103 + */
  104 +int ff_audio_data_realloc(AudioData *a, int nb_samples);
  105 +
  106 +/**
  107 + * Free AudioData.
  108 + *
  109 + * The AudioData must have been previously allocated with ff_audio_data_alloc().
  110 + *
  111 + * @param a AudioData struct
  112 + */
  113 +void ff_audio_data_free(AudioData **a);
  114 +
  115 +/**
  116 + * Copy data from one AudioData to another.
  117 + *
  118 + * @param out output AudioData
  119 + * @param in input AudioData
  120 + * @return 0 on success, negative AVERROR value on error
  121 + */
  122 +int ff_audio_data_copy(AudioData *out, AudioData *in);
  123 +
  124 +/**
  125 + * Append data from one AudioData to the end of another.
  126 + *
  127 + * @param dst destination AudioData
  128 + * @param dst_offset offset, in samples, to start writing, relative to the
  129 + * start of dst
  130 + * @param src source AudioData
  131 + * @param src_offset offset, in samples, to start copying, relative to the
  132 + * start of the src
  133 + * @param nb_samples number of samples to copy
  134 + * @return 0 on success, negative AVERROR value on error
  135 + */
  136 +int ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src,
  137 + int src_offset, int nb_samples);
  138 +
  139 +/**
  140 + * Drain samples from the start of the AudioData.
  141 + *
  142 + * Remaining samples are shifted to the start of the AudioData.
  143 + *
  144 + * @param a AudioData struct
  145 + * @param nb_samples number of samples to drain
  146 + */
  147 +void ff_audio_data_drain(AudioData *a, int nb_samples);
  148 +
  149 +/**
  150 + * Add samples in AudioData to an AVAudioFifo.
  151 + *
  152 + * @param af Audio FIFO Buffer
  153 + * @param a AudioData struct
  154 + * @param offset number of samples to skip from the start of the data
  155 + * @param nb_samples number of samples to add to the FIFO
  156 + * @return number of samples actually added to the FIFO, or
  157 + * negative AVERROR code on error
  158 + */
  159 +int ff_audio_data_add_to_fifo(AVAudioFifo *af, AudioData *a, int offset,
  160 + int nb_samples);
  161 +
  162 +/**
  163 + * Read samples from an AVAudioFifo to AudioData.
  164 + *
  165 + * @param af Audio FIFO Buffer
  166 + * @param a AudioData struct
  167 + * @param nb_samples number of samples to read from the FIFO
  168 + * @return number of samples actually read from the FIFO, or
  169 + * negative AVERROR code on error
  170 + */
  171 +int ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples);
  172 +
  173 +#endif /* AVRESAMPLE_AUDIO_DATA_H */
356 libavresample/audio_mix.c
... ... @@ -0,0 +1,356 @@
  1 +/*
  2 + * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
  3 + *
  4 + * This file is part of Libav.
  5 + *
  6 + * Libav 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 + * Libav 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 Libav; 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/libm.h"
  24 +#include "libavutil/samplefmt.h"
  25 +#include "avresample.h"
  26 +#include "internal.h"
  27 +#include "audio_data.h"
  28 +#include "audio_mix.h"
  29 +
  30 +static const char *coeff_type_names[] = { "q6", "q15", "flt" };
  31 +
  32 +void ff_audio_mix_set_func(AudioMix *am, enum AVSampleFormat fmt,
  33 + enum AVMixCoeffType coeff_type, int in_channels,
  34 + int out_channels, int ptr_align, int samples_align,
  35 + const char *descr, void *mix_func)
  36 +{
  37 + if (fmt == am->fmt && coeff_type == am->coeff_type &&
  38 + ( in_channels == am->in_channels || in_channels == 0) &&
  39 + (out_channels == am->out_channels || out_channels == 0)) {
  40 + char chan_str[16];
  41 + am->mix = mix_func;
  42 + am->func_descr = descr;
  43 + am->ptr_align = ptr_align;
  44 + am->samples_align = samples_align;
  45 + if (ptr_align == 1 && samples_align == 1) {
  46 + am->mix_generic = mix_func;
  47 + am->func_descr_generic = descr;
  48 + } else {
  49 + am->has_optimized_func = 1;
  50 + }
  51 + if (in_channels) {
  52 + if (out_channels)
  53 + snprintf(chan_str, sizeof(chan_str), "[%d to %d] ",
  54 + in_channels, out_channels);
  55 + else
  56 + snprintf(chan_str, sizeof(chan_str), "[%d to any] ",
  57 + in_channels);
  58 + } else if (out_channels) {
  59 + snprintf(chan_str, sizeof(chan_str), "[any to %d] ",
  60 + out_channels);
  61 + }
  62 + av_log(am->avr, AV_LOG_DEBUG, "audio_mix: found function: [fmt=%s] "
  63 + "[c=%s] %s(%s)\n", av_get_sample_fmt_name(fmt),
  64 + coeff_type_names[coeff_type],
  65 + (in_channels || out_channels) ? chan_str : "", descr);
  66 + }
  67 +}
  68 +
  69 +#define MIX_FUNC_NAME(fmt, cfmt) mix_any_ ## fmt ##_## cfmt ##_c
  70 +
  71 +#define MIX_FUNC_GENERIC(fmt, cfmt, stype, ctype, sumtype, expr) \
  72 +static void MIX_FUNC_NAME(fmt, cfmt)(stype **samples, ctype **matrix, \
  73 + int len, int out_ch, int in_ch) \
  74 +{ \
  75 + int i, in, out; \
  76 + stype temp[AVRESAMPLE_MAX_CHANNELS]; \
  77 + for (i = 0; i < len; i++) { \
  78 + for (out = 0; out < out_ch; out++) { \
  79 + sumtype sum = 0; \
  80 + for (in = 0; in < in_ch; in++) \
  81 + sum += samples[in][i] * matrix[out][in]; \
  82 + temp[out] = expr; \
  83 + } \
  84 + for (out = 0; out < out_ch; out++) \
  85 + samples[out][i] = temp[out]; \
  86 + } \
  87 +}
  88 +
  89 +MIX_FUNC_GENERIC(FLTP, FLT, float, float, float, sum)
  90 +MIX_FUNC_GENERIC(S16P, FLT, int16_t, float, float, av_clip_int16(lrintf(sum)))
  91 +MIX_FUNC_GENERIC(S16P, Q15, int16_t, int32_t, int64_t, av_clip_int16(sum >> 15))
  92 +MIX_FUNC_GENERIC(S16P, Q6, int16_t, int16_t, int32_t, av_clip_int16(sum >> 6))
  93 +
  94 +/* TODO: templatize the channel-specific C functions */
  95 +
  96 +static void mix_2_to_1_fltp_flt_c(float **samples, float **matrix, int len,
  97 + int out_ch, int in_ch)
  98 +{
  99 + float *src0 = samples[0];
  100 + float *src1 = samples[1];
  101 + float *dst = src0;
  102 + float m0 = matrix[0][0];
  103 + float m1 = matrix[0][1];
  104 +
  105 + while (len > 4) {
  106 + *dst++ = *src0++ * m0 + *src1++ * m1;
  107 + *dst++ = *src0++ * m0 + *src1++ * m1;
  108 + *dst++ = *src0++ * m0 + *src1++ * m1;