History

Merge remote-tracking branch 'qatar/master'

* qatar/master: FATE: use updated reference for aac-latm_stereo_to_51 avconv: use libavresample Add libavresample FATE: avoid channel mixing in lavf-dv_fmt Conflicts: Changelog Makefile cmdutils.c configure doc/APIchanges ffmpeg.c tests/lavf-regression.sh tests/ref/lavf/dv_fmt tests/ref/seek/lavf_dv

Michael Niedermayer committed 14 years ago

Commit 3ead79e2 parents cab15f9 394dbde33 files · +3875 −27Browse files

Unified · Split

33 files
  1. Changelog +1 −0
  2. Makefile +1 −0
  3. cmdutils.c +4 −1
  4. common.mak +1 −1
  5. configure +5 −0
  6. doc/APIchanges +4 −0
  7. ffmpeg.c +35 −20
  8. libavresample/Makefile +15 −0
  9. libavresample/audio_convert.c +334 −0
  10. libavresample/audio_convert.h +87 −0
  11. libavresample/audio_data.c +345 −0
  12. libavresample/audio_data.h +173 −0
  13. libavresample/audio_mix.c +356 −0
  14. libavresample/audio_mix.h +108 −0
  15. libavresample/audio_mix_matrix.c +346 −0
  16. libavresample/avresample-test.c +340 −0
  17. libavresample/avresample.h +283 −0
  18. libavresample/internal.h +75 −0
  19. libavresample/libavresample.v +4 −0
  20. libavresample/options.c +89 −0
  21. libavresample/resample.c +480 −0
  22. libavresample/resample.h +70 −0
  23. libavresample/utils.c +405 −0
  24. libavresample/version.h +41 −0
  25. libavresample/x86/Makefile +5 −0
  26. libavresample/x86/audio_convert.asm +104 −0
  27. libavresample/x86/audio_convert_init.c +42 −0
  28. libavresample/x86/audio_mix.asm +64 −0
  29. libavresample/x86/audio_mix_init.c +44 −0
  30. libavutil/x86/x86util.asm +9 −0
  31. tests/fate/aac.mak +2 −2
  32. tests/lavf-regression.sh +1 −1
  33. tests/ref/lavf/dv_fmt +2 −2
Changelog+1−0
@@ -26,6 +26,7 @@ version next: · 25 unmodified lines
2626 - drawtext video filter: fontconfig support
2727 - ffmpeg -benchmark_all option
2828 - super2xsai filter ported from libmpcodecs
29+- add libavresample audio conversion library for compatibility
2930
3031
3132 version 0.10:
Makefile+1−0
@@ -31,6 +31,7 @@ ALLMANPAGES = $(BASENAMES:%=%.1) · 30 unmodified lines
3131 FFLIBS-$(CONFIG_AVDEVICE) += avdevice
3232 FFLIBS-$(CONFIG_AVFILTER) += avfilter
3333 FFLIBS-$(CONFIG_AVFORMAT) += avformat
34+FFLIBS-$(CONFIG_AVRESAMPLE) += avresample
3435 FFLIBS-$(CONFIG_AVCODEC) += avcodec
3536 FFLIBS-$(CONFIG_POSTPROC) += postproc
3637 FFLIBS-$(CONFIG_SWRESAMPLE)+= swresample
cmdutils.c+4−1
@@ -32,6 +32,7 @@ · 31 unmodified lines
3232 #include "libavformat/avformat.h"
3333 #include "libavfilter/avfilter.h"
3434 #include "libavdevice/avdevice.h"
35+#include "libavresample/avresample.h"
3536 #include "libswscale/swscale.h"
3637 #include "libswresample/swresample.h"
3738 #if CONFIG_POSTPROC
@@ -633,7 +634,8 @@ static int warned_cfg = 0; · 595 unmodified lines
633634 const char *indent = flags & INDENT? " " : ""; \
634635 if (flags & SHOW_VERSION) { \
635636 unsigned int version = libname##_version(); \
636− av_log(NULL, level, "%slib%-11s %2d.%3d.%3d / %2d.%3d.%3d\n",\
637+ av_log(NULL, level, \
638+ "%slib%-11s %2d.%3d.%3d / %2d.%3d.%3d\n", \
637639 indent, #libname, \
638640 LIB##LIBNAME##_VERSION_MAJOR, \
639641 LIB##LIBNAME##_VERSION_MINOR, \
@@ -662,6 +664,7 @@ static void print_all_libs_info(int flags, int level) · 22 unmodified lines
662664 PRINT_LIB_INFO(avformat, AVFORMAT, flags, level);
663665 PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level);
664666 PRINT_LIB_INFO(avfilter, AVFILTER, flags, level);
667+// PRINT_LIB_INFO(avresample, AVRESAMPLE, flags, level);
665668 PRINT_LIB_INFO(swscale, SWSCALE, flags, level);
666669 PRINT_LIB_INFO(swresample,SWRESAMPLE, flags, level);
667670 #if CONFIG_POSTPROC
common.mak+1−1
@@ -20,7 +20,7 @@ $(foreach VAR,$(SILENT),$(eval override $(VAR) = @$($(VAR)))) · 19 unmodified lines
2020 $(eval INSTALL = @$(call ECHO,INSTALL,$$(^:$(SRC_DIR)/%=%)); $(INSTALL))
2121 endif
2222
23−ALLFFLIBS = avcodec avdevice avfilter avformat avutil postproc swscale swresample
23+ALLFFLIBS = avcodec avdevice avfilter avformat avresample avutil postproc swscale swresample
2424
2525 # NASM requires -I path terminated with /
2626 IFLAGS := -I. -I$(SRC_PATH)/
configure+5−0
@@ -112,6 +112,7 @@ Component options: · 111 unmodified lines
112112 --disable-swscale disable libswscale build
113113 --disable-postproc disable libpostproc build
114114 --disable-avfilter disable video filter support [no]
115+ --disable-avresample disable libavresample build [no]
115116 --disable-pthreads disable pthreads [auto]
116117 --disable-w32threads disable Win32 threads [auto]
117118 --disable-os2threads disable OS/2 threads [auto]
@@ -1013,6 +1014,7 @@ CONFIG_LIST=" · 895 unmodified lines
10131014 avdevice
10141015 avfilter
10151016 avformat
1017+ avresample
10161018 avisynth
10171019 bzlib
10181020 crystalhd
@@ -1870,6 +1872,7 @@ enable avcodec · 851 unmodified lines
18701872 enable avdevice
18711873 enable avfilter
18721874 enable avformat
1875+enable avresample
18731876 enable avutil
18741877 enable postproc
18751878 enable stripping
@@ -3724,6 +3727,7 @@ get_version LIBAVCODEC libavcodec/version.h · 1848 unmodified lines
37243727 get_version LIBAVDEVICE libavdevice/avdevice.h
37253728 get_version LIBAVFILTER libavfilter/version.h
37263729 get_version LIBAVFORMAT libavformat/version.h
3730+get_version LIBAVRESAMPLE libavresample/version.h
37273731 get_version LIBAVUTIL libavutil/avutil.h
37283732 get_version LIBPOSTPROC libpostproc/postprocess.h
37293733 get_version LIBSWRESAMPLE libswresample/swresample.h
@@ -3869,5 +3873,6 @@ pkgconfig_generate libavformat "FFmpeg container format library" "$LIBAVFORMAT_V · 139 unmodified lines
38693873 pkgconfig_generate libavdevice "FFmpeg device handling library" "$LIBAVDEVICE_VERSION" "$extralibs" "$libavdevice_pc_deps"
38703874 pkgconfig_generate libavfilter "FFmpeg video filtering library" "$LIBAVFILTER_VERSION" "$extralibs" "$libavfilter_pc_deps"
38713875 pkgconfig_generate libpostproc "FFmpeg postprocessing library" "$LIBPOSTPROC_VERSION" "" "libavutil = $LIBAVUTIL_VERSION"
3876+pkgconfig_generate libavresample "Libav audio resampling library" "$LIBAVRESAMPLE_VERSION" "$extralibs"
38723877 pkgconfig_generate libswscale "FFmpeg image rescaling library" "$LIBSWSCALE_VERSION" "$LIBM" "libavutil = $LIBAVUTIL_VERSION"
38733878 pkgconfig_generate libswresample "FFmpeg audio rescaling library" "$LIBSWRESAMPLE_VERSION" "$LIBM" "libavutil = $LIBAVUTIL_VERSION"
doc/APIchanges+4−0
@@ -6,6 +6,7 @@ libavcodec: 2012-01-27 · 5 unmodified lines
66 libavdevice: 2011-04-18
77 libavfilter: 2011-04-18
88 libavformat: 2012-01-27
9+libavresample: 2012-xx-xx
910 libpostproc: 2011-04-18
1011 libswscale: 2011-06-20
1112 libavutil: 2011-04-18
@@ -22,6 +23,9 @@ API changes, most recent first: · 10 unmodified lines
2223 2012-03-26 - a67d9cf - lavfi 2.66.100
2324 Add avfilter_fill_frame_from_{audio_,}buffer_ref() functions.
2425
26+2012-xx-xx - xxxxxxx - lavr 0.0.0
27+ Add libavresample audio conversion library
28+
2529 2012-xx-xx - xxxxxxx - lavu 51.28.0 - audio_fifo.h
2630 Add audio FIFO functions:
2731 av_audio_fifo_free()
ffmpeg.c+35−20
@@ -36,7 +36,6 @@ · 35 unmodified lines
3636 #include "libavdevice/avdevice.h"
3737 #include "libswscale/swscale.h"
3838 #include "libavutil/opt.h"
39−#include "libavcodec/audioconvert.h"
4039 #include "libavutil/audioconvert.h"
4140 #include "libavutil/parseutils.h"
4241 #include "libavutil/samplefmt.h"
@@ -300,6 +299,7 @@ typedef struct OutputStream { · 257 unmodified lines
300299 int audio_channels_mapped; ///< number of channels in audio_channels_map
301300 int resample_sample_fmt;
302301 int resample_channels;
302+ uint64_t resample_channel_layout;
303303 int resample_sample_rate;
304304 float rematrix_volume;
305305 AVFifoBuffer *fifo; /* for compression: one audio fifo per codec */
@@ -1525,7 +1525,7 @@ static int encode_audio_frame(AVFormatContext *s, OutputStream *ost, · 1219 unmodified lines
15251525 }
15261526
15271527 static int alloc_audio_output_buf(AVCodecContext *dec, AVCodecContext *enc,
1528− int nb_samples)
1528+ int nb_samples, int *buf_linesize)
15291529 {
15301530 int64_t audio_buf_samples;
15311531 int audio_buf_size;
@@ -1538,7 +1538,7 @@ static int alloc_audio_output_buf(AVCodecContext *dec, AVCodecContext *enc, · 6 unmodified lines
15381538 if (audio_buf_samples > INT_MAX)
15391539 return AVERROR(EINVAL);
15401540
1541− audio_buf_size = av_samples_get_buffer_size(NULL, enc->channels,
1541+ audio_buf_size = av_samples_get_buffer_size(buf_linesize, enc->channels,
15421542 audio_buf_samples,
15431543 enc->sample_fmt, 0);
15441544 if (audio_buf_size < 0)
@@ -1557,7 +1557,7 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, · 12 unmodified lines
15571557 uint8_t *buftmp;
15581558 int64_t size_out;
15591559
1560− int frame_bytes, resample_changed;
1560+ int frame_bytes, resample_changed, ret;
15611561 AVCodecContext *enc = ost->st->codec;
15621562 AVCodecContext *dec = ist->st->codec;
15631563 int osize = av_get_bytes_per_sample(enc->sample_fmt);
@@ -1566,37 +1566,46 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, · 2 unmodified lines
15661566 int size = decoded_frame->nb_samples * dec->channels * isize;
15671567 int planes = av_sample_fmt_is_planar(dec->sample_fmt) ? dec->channels : 1;
15681568 int i;
1569+ int out_linesize = 0;
1570+ int buf_linesize = decoded_frame->linesize[0];
15691571
15701572 av_assert0(planes <= AV_NUM_DATA_POINTERS);
15711573
15721574 for(i=0; i<planes; i++)
15731575 buf[i]= decoded_frame->data[i];
15741576
1577+
15751578 get_default_channel_layouts(ost, ist);
15761579
1577− if (alloc_audio_output_buf(dec, enc, decoded_frame->nb_samples) < 0) {
1580+ if (alloc_audio_output_buf(dec, enc, decoded_frame->nb_samples, &out_linesize) < 0) {
15781581 av_log(NULL, AV_LOG_FATAL, "Error allocating audio buffer\n");
15791582 exit_program(1);
15801583 }
15811584
1582− if (enc->channels != dec->channels
1583− || enc->sample_fmt != dec->sample_fmt
1584− || enc->sample_rate!= dec->sample_rate
1585− )
1585+ if (audio_sync_method > 1 ||
1586+ enc->channels != dec->channels ||
1587+ enc->channel_layout != dec->channel_layout ||
1588+ enc->sample_rate != dec->sample_rate ||
1589+ dec->sample_fmt != enc->sample_fmt)
15861590 ost->audio_resample = 1;
15871591
15881592 resample_changed = ost->resample_sample_fmt != dec->sample_fmt ||
15891593 ost->resample_channels != dec->channels ||
1594+ ost->resample_channel_layout != dec->channel_layout ||
15901595 ost->resample_sample_rate != dec->sample_rate;
15911596
15921597 if ((ost->audio_resample && !ost->swr) || resample_changed || ost->audio_channels_mapped) {
1598+
15931599 if (resample_changed) {
1594− av_log(NULL, AV_LOG_INFO, "Input stream #%d:%d frame changed from rate:%d fmt:%s ch:%d to rate:%d fmt:%s ch:%d\n",
1600+ av_log(NULL, AV_LOG_INFO, "Input stream #%d:%d frame changed from rate:%d fmt:%s ch:%d chl:0x%"PRIx64" to rate:%d fmt:%s ch:%d chl:0x%"PRIx64"\n",
15951601 ist->file_index, ist->st->index,
1596− ost->resample_sample_rate, av_get_sample_fmt_name(ost->resample_sample_fmt), ost->resample_channels,
1597− dec->sample_rate, av_get_sample_fmt_name(dec->sample_fmt), dec->channels);
1602+ ost->resample_sample_rate, av_get_sample_fmt_name(ost->resample_sample_fmt),
1603+ ost->resample_channels, ost->resample_channel_layout,
1604+ dec->sample_rate, av_get_sample_fmt_name(dec->sample_fmt),
1605+ dec->channels, dec->channel_layout);
15981606 ost->resample_sample_fmt = dec->sample_fmt;
15991607 ost->resample_channels = dec->channels;
1608+ ost->resample_channel_layout = dec->channel_layout;
16001609 ost->resample_sample_rate = dec->sample_rate;
16011610 swr_free(&ost->swr);
16021611 }
@@ -1604,6 +1613,7 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, · 1 unmodified line
16041613 if (audio_sync_method <= 1 && !ost->audio_channels_mapped &&
16051614 ost->resample_sample_fmt == enc->sample_fmt &&
16061615 ost->resample_channels == enc->channels &&
1616+ ost->resample_channel_layout == enc->channel_layout &&
16071617 ost->resample_sample_rate == enc->sample_rate) {
16081618 //ost->swr = NULL;
16091619 ost->audio_resample = 0;
@@ -1673,7 +1683,7 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, · 63 unmodified lines
16731683 exit_program(1);
16741684 }
16751685
1676− if (alloc_audio_output_buf(dec, enc, decoded_frame->nb_samples + idelta) < 0) {
1686+ if (alloc_audio_output_buf(dec, enc, decoded_frame->nb_samples + idelta, &out_linesize) < 0) {
16771687 av_log(NULL, AV_LOG_FATAL, "Error allocating audio buffer\n");
16781688 exit_program(1);
16791689 }
@@ -1686,11 +1696,11 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, · 6 unmodified lines
16861696 buf[i] = t;
16871697 }
16881698 size += byte_delta;
1699+ buf_linesize = allocated_async_buf_size;
16891700 av_log(NULL, AV_LOG_VERBOSE, "adding %d audio samples of silence\n", idelta);
16901701 }
16911702 } else if (audio_sync_method > 1) {
16921703 int comp = av_clip(delta, -audio_sync_method, audio_sync_method);
1693− av_assert0(ost->audio_resample);
16941704 av_log(NULL, AV_LOG_VERBOSE, "compensating audio timestamp drift:%f compensation:%d in:%d\n",
16951705 delta, comp, enc->sample_rate);
16961706 // fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2));
@@ -1703,8 +1713,10 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, · 6 unmodified lines
17031713
17041714 if (ost->audio_resample || ost->audio_channels_mapped) {
17051715 buftmp = audio_buf;
1706− size_out = swr_convert(ost->swr, ( uint8_t*[]){buftmp}, allocated_audio_buf_size / (enc->channels * osize),
1707− buf, size / (dec->channels * isize));
1716+ size_out = swr_convert(ost->swr, ( uint8_t*[]){buftmp},
1717+ allocated_audio_buf_size / (enc->channels * osize),
1718+ buf,
1719+ size / (dec->channels * isize));
17081720 if (size_out < 0) {
17091721 av_log(NULL, AV_LOG_FATAL, "swr_convert failed\n");
17101722 exit_program(1);
@@ -3078,6 +3090,7 @@ static int transcode_init(void) · 1367 unmodified lines
30783090 if (!ost->fifo) {
30793091 return AVERROR(ENOMEM);
30803092 }
3093+
30813094 if (!codec->sample_rate)
30823095 codec->sample_rate = icodec->sample_rate;
30833096 choose_sample_rate(ost->st, ost->enc);
@@ -3110,13 +3123,15 @@ static int transcode_init(void) · 26 unmodified lines
31103123 if (av_get_channel_layout_nb_channels(codec->channel_layout) != codec->channels)
31113124 codec->channel_layout = 0;
31123125
3113− ost->audio_resample = codec->sample_rate != icodec->sample_rate || audio_sync_method > 1;
3114− ost->audio_resample |= codec->sample_fmt != icodec->sample_fmt
3115− || codec->channel_layout != icodec->channel_layout;
3116− icodec->request_channels = codec->channels;
3126+
3127+// ost->audio_resample = codec->sample_rate != icodec->sample_rate || audio_sync_method > 1;
3128+// ost->audio_resample |= codec->sample_fmt != icodec->sample_fmt
3129+// || codec->channel_layout != icodec->channel_layout;
3130+ icodec->request_channels = codec-> channels;
31173131 ost->resample_sample_fmt = icodec->sample_fmt;
31183132 ost->resample_sample_rate = icodec->sample_rate;
31193133 ost->resample_channels = icodec->channels;
3134+ ost->resample_channel_layout = icodec->channel_layout;
31203135 break;
31213136 case AVMEDIA_TYPE_VIDEO:
31223137 if (!ost->filter) {
libavresample/Makefile+15−0
@@ -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
libavresample/audio_convert.c+334−0
@@ -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+}
libavresample/audio_convert.h+87−0
@@ -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 */
libavresample/audio_data.c+345−0
@@ -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+}
libavresample/audio_data.h+173−0
@@ -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 */
libavresample/audio_mix.c+356−0
@@ -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;
109+ *dst++ = *src0++ * m0 + *src1++ * m1;
110+ len -= 4;
111+ }
112+ while (len > 0) {
113+ *dst++ = *src0++ * m0 + *src1++ * m1;
114+ len--;
115+ }
116+}
117+
118+static void mix_1_to_2_fltp_flt_c(float **samples, float **matrix, int len,
119+ int out_ch, int in_ch)
120+{
121+ float v;
122+ float *dst0 = samples[0];
123+ float *dst1 = samples[1];
124+ float *src = dst0;
125+ float m0 = matrix[0][0];
126+ float m1 = matrix[1][0];
127+
128+ while (len > 4) {
129+ v = *src++;
130+ *dst0++ = v * m1;
131+ *dst1++ = v * m0;
132+ v = *src++;
133+ *dst0++ = v * m1;
134+ *dst1++ = v * m0;
135+ v = *src++;
136+ *dst0++ = v * m1;
137+ *dst1++ = v * m0;
138+ v = *src++;
139+ *dst0++ = v * m1;
140+ *dst1++ = v * m0;
141+ len -= 4;
142+ }
143+ while (len > 0) {
144+ v = *src++;
145+ *dst0++ = v * m1;
146+ *dst1++ = v * m0;
147+ len--;
148+ }
149+}
150+
151+static void mix_6_to_2_fltp_flt_c(float **samples, float **matrix, int len,
152+ int out_ch, int in_ch)
153+{
154+ float v0, v1;
155+ float *src0 = samples[0];
156+ float *src1 = samples[1];
157+ float *src2 = samples[2];
158+ float *src3 = samples[3];
159+ float *src4 = samples[4];
160+ float *src5 = samples[5];
161+ float *dst0 = src0;
162+ float *dst1 = src1;
163+ float *m0 = matrix[0];
164+ float *m1 = matrix[1];
165+
166+ while (len > 0) {
167+ v0 = *src0++;
168+ v1 = *src1++;
169+ *dst0++ = v0 * m0[0] +
170+ v1 * m0[1] +
171+ *src2 * m0[2] +
172+ *src3 * m0[3] +
173+ *src4 * m0[4] +
174+ *src5 * m0[5];
175+ *dst1++ = v0 * m1[0] +
176+ v1 * m1[1] +
177+ *src2++ * m1[2] +
178+ *src3++ * m1[3] +
179+ *src4++ * m1[4] +
180+ *src5++ * m1[5];
181+ len--;
182+ }
183+}
184+
185+static void mix_2_to_6_fltp_flt_c(float **samples, float **matrix, int len,
186+ int out_ch, int in_ch)
187+{
188+ float v0, v1;
189+ float *dst0 = samples[0];
190+ float *dst1 = samples[1];
191+ float *dst2 = samples[2];
192+ float *dst3 = samples[3];
193+ float *dst4 = samples[4];
194+ float *dst5 = samples[5];
195+ float *src0 = dst0;
196+ float *src1 = dst1;
197+
198+ while (len > 0) {
199+ v0 = *src0++;
200+ v1 = *src1++;
201+ *dst0++ = v0 * matrix[0][0] + v1 * matrix[0][1];
202+ *dst1++ = v0 * matrix[1][0] + v1 * matrix[1][1];
203+ *dst2++ = v0 * matrix[2][0] + v1 * matrix[2][1];
204+ *dst3++ = v0 * matrix[3][0] + v1 * matrix[3][1];
205+ *dst4++ = v0 * matrix[4][0] + v1 * matrix[4][1];
206+ *dst5++ = v0 * matrix[5][0] + v1 * matrix[5][1];
207+ len--;
208+ }
209+}
210+
211+static int mix_function_init(AudioMix *am)
212+{
213+ /* any-to-any C versions */
214+
215+ ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
216+ 0, 0, 1, 1, "C", MIX_FUNC_NAME(FLTP, FLT));
217+
218+ ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
219+ 0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, FLT));
220+
221+ ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q15,
222+ 0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q15));
223+
224+ ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q6,
225+ 0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q6));
226+
227+ /* channel-specific C versions */
228+
229+ ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
230+ 2, 1, 1, 1, "C", mix_2_to_1_fltp_flt_c);
231+
232+ ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
233+ 1, 2, 1, 1, "C", mix_1_to_2_fltp_flt_c);
234+
235+ ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
236+ 6, 2, 1, 1, "C", mix_6_to_2_fltp_flt_c);
237+
238+ ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
239+ 2, 6, 1, 1, "C", mix_2_to_6_fltp_flt_c);
240+
241+ if (ARCH_X86)
242+ ff_audio_mix_init_x86(am);
243+
244+ if (!am->mix) {
245+ av_log(am->avr, AV_LOG_ERROR, "audio_mix: NO FUNCTION FOUND: [fmt=%s] "
246+ "[c=%s] [%d to %d]\n", av_get_sample_fmt_name(am->fmt),
247+ coeff_type_names[am->coeff_type], am->in_channels,
248+ am->out_channels);
249+ return AVERROR_PATCHWELCOME;
250+ }
251+ return 0;
252+}
253+
254+int ff_audio_mix_init(AVAudioResampleContext *avr)
255+{
256+ int ret;
257+
258+ /* build matrix if the user did not already set one */
259+ if (!avr->am->matrix) {
260+ int i, j;
261+ char in_layout_name[128];
262+ char out_layout_name[128];
263+ double *matrix_dbl = av_mallocz(avr->out_channels * avr->in_channels *
264+ sizeof(*matrix_dbl));
265+ if (!matrix_dbl)
266+ return AVERROR(ENOMEM);
267+
268+ ret = avresample_build_matrix(avr->in_channel_layout,
269+ avr->out_channel_layout,
270+ avr->center_mix_level,
271+ avr->surround_mix_level,
272+ avr->lfe_mix_level, 1, matrix_dbl,
273+ avr->in_channels);
274+ if (ret < 0) {
275+ av_free(matrix_dbl);
276+ return ret;
277+ }
278+
279+ av_get_channel_layout_string(in_layout_name, sizeof(in_layout_name),
280+ avr->in_channels, avr->in_channel_layout);
281+ av_get_channel_layout_string(out_layout_name, sizeof(out_layout_name),
282+ avr->out_channels, avr->out_channel_layout);
283+ av_log(avr, AV_LOG_DEBUG, "audio_mix: %s to %s\n",
284+ in_layout_name, out_layout_name);
285+ for (i = 0; i < avr->out_channels; i++) {
286+ for (j = 0; j < avr->in_channels; j++) {
287+ av_log(avr, AV_LOG_DEBUG, " %0.3f ",
288+ matrix_dbl[i * avr->in_channels + j]);
289+ }
290+ av_log(avr, AV_LOG_DEBUG, "\n");
291+ }
292+
293+ ret = avresample_set_matrix(avr, matrix_dbl, avr->in_channels);
294+ if (ret < 0) {
295+ av_free(matrix_dbl);
296+ return ret;
297+ }
298+ av_free(matrix_dbl);
299+ }
300+
301+ avr->am->fmt = avr->internal_sample_fmt;
302+ avr->am->coeff_type = avr->mix_coeff_type;
303+ avr->am->in_layout = avr->in_channel_layout;
304+ avr->am->out_layout = avr->out_channel_layout;
305+ avr->am->in_channels = avr->in_channels;
306+ avr->am->out_channels = avr->out_channels;
307+
308+ ret = mix_function_init(avr->am);
309+ if (ret < 0)
310+ return ret;
311+
312+ return 0;
313+}
314+
315+void ff_audio_mix_close(AudioMix *am)
316+{
317+ if (!am)
318+ return;
319+ if (am->matrix) {
320+ av_free(am->matrix[0]);
321+ am->matrix = NULL;
322+ }
323+ memset(am->matrix_q6, 0, sizeof(am->matrix_q6 ));
324+ memset(am->matrix_q15, 0, sizeof(am->matrix_q15));
325+ memset(am->matrix_flt, 0, sizeof(am->matrix_flt));
326+}
327+
328+int ff_audio_mix(AudioMix *am, AudioData *src)
329+{
330+ int use_generic = 1;
331+ int len = src->nb_samples;
332+
333+ /* determine whether to use the optimized function based on pointer and
334+ samples alignment in both the input and output */
335+ if (am->has_optimized_func) {
336+ int aligned_len = FFALIGN(len, am->samples_align);
337+ if (!(src->ptr_align % am->ptr_align) &&
338+ src->samples_align >= aligned_len) {
339+ len = aligned_len;
340+ use_generic = 0;
341+ }
342+ }
343+ av_dlog(am->avr, "audio_mix: %d samples - %d to %d channels (%s)\n",
344+ src->nb_samples, am->in_channels, am->out_channels,
345+ use_generic ? am->func_descr_generic : am->func_descr);
346+
347+ if (use_generic)
348+ am->mix_generic(src->data, am->matrix, len, am->out_channels,
349+ am->in_channels);
350+ else
351+ am->mix(src->data, am->matrix, len, am->out_channels, am->in_channels);
352+
353+ ff_audio_data_set_channels(src, am->out_channels);
354+
355+ return 0;
356+}
libavresample/audio_mix.h+108−0
@@ -0,0 +1,108 @@
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_MIX_H
22+#define AVRESAMPLE_AUDIO_MIX_H
23+
24+#include <stdint.h>
25+
26+#include "libavutil/samplefmt.h"
27+#include "avresample.h"
28+#include "audio_data.h"
29+
30+typedef void (mix_func)(uint8_t **src, void **matrix, int len, int out_ch,
31+ int in_ch);
32+
33+typedef struct AudioMix {
34+ AVAudioResampleContext *avr;
35+ enum AVSampleFormat fmt;
36+ enum AVMixCoeffType coeff_type;
37+ uint64_t in_layout;
38+ uint64_t out_layout;
39+ int in_channels;
40+ int out_channels;
41+
42+ int ptr_align;
43+ int samples_align;
44+ int has_optimized_func;
45+ const char *func_descr;
46+ const char *func_descr_generic;
47+ mix_func *mix;
48+ mix_func *mix_generic;
49+
50+ int16_t *matrix_q6[AVRESAMPLE_MAX_CHANNELS];
51+ int32_t *matrix_q15[AVRESAMPLE_MAX_CHANNELS];
52+ float *matrix_flt[AVRESAMPLE_MAX_CHANNELS];
53+ void **matrix;
54+} AudioMix;
55+
56+/**
57+ * Set mixing function if the parameters match.
58+ *
59+ * This compares the parameters of the mixing function to the parameters in the
60+ * AudioMix context. If the parameters do not match, no changes are made to the
61+ * active functions. If the parameters do match and the alignment is not
62+ * constrained, the function is set as the generic mixing function. If the
63+ * parameters match and the alignment is constrained, the function is set as
64+ * the optimized mixing function.
65+ *
66+ * @param am AudioMix context
67+ * @param fmt input/output sample format
68+ * @param coeff_type mixing coefficient type
69+ * @param in_channels number of input channels, or 0 for any number of channels
70+ * @param out_channels number of output channels, or 0 for any number of channels
71+ * @param ptr_align buffer pointer alignment, in bytes
72+ * @param sample_align buffer size alignment, in samples
73+ * @param descr function type description (e.g. "C" or "SSE")
74+ * @param mix_func mixing function pointer
75+ */
76+void ff_audio_mix_set_func(AudioMix *am, enum AVSampleFormat fmt,
77+ enum AVMixCoeffType coeff_type, int in_channels,
78+ int out_channels, int ptr_align, int samples_align,
79+ const char *descr, void *mix_func);
80+
81+/**
82+ * Initialize the AudioMix context in the AVAudioResampleContext.
83+ *
84+ * The parameters in the AVAudioResampleContext are used to initialize the
85+ * AudioMix context and set the mixing matrix.
86+ *
87+ * @param avr AVAudioResampleContext
88+ * @return 0 on success, negative AVERROR code on failure
89+ */
90+int ff_audio_mix_init(AVAudioResampleContext *avr);
91+
92+/**
93+ * Close an AudioMix context.
94+ *
95+ * This clears and frees the mixing matrix arrays.
96+ */
97+void ff_audio_mix_close(AudioMix *am);
98+
99+/**
100+ * Apply channel mixing to audio data using the current mixing matrix.
101+ */
102+int ff_audio_mix(AudioMix *am, AudioData *src);
103+
104+/* arch-specific initialization functions */
105+
106+void ff_audio_mix_init_x86(AudioMix *am);
107+
108+#endif /* AVRESAMPLE_AUDIO_MIX_H */
libavresample/audio_mix_matrix.c+346−0
@@ -0,0 +1,346 @@
1+/*
2+ * Copyright (C) 2011 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 "libavutil/libm.h"
25+#include "libavutil/samplefmt.h"
26+#include "avresample.h"
27+#include "internal.h"
28+#include "audio_data.h"
29+#include "audio_mix.h"
30+
31+/* channel positions */
32+#define FRONT_LEFT 0
33+#define FRONT_RIGHT 1
34+#define FRONT_CENTER 2
35+#define LOW_FREQUENCY 3
36+#define BACK_LEFT 4
37+#define BACK_RIGHT 5
38+#define FRONT_LEFT_OF_CENTER 6
39+#define FRONT_RIGHT_OF_CENTER 7
40+#define BACK_CENTER 8
41+#define SIDE_LEFT 9
42+#define SIDE_RIGHT 10
43+#define TOP_CENTER 11
44+#define TOP_FRONT_LEFT 12
45+#define TOP_FRONT_CENTER 13
46+#define TOP_FRONT_RIGHT 14
47+#define TOP_BACK_LEFT 15
48+#define TOP_BACK_CENTER 16
49+#define TOP_BACK_RIGHT 17
50+#define STEREO_LEFT 29
51+#define STEREO_RIGHT 30
52+#define WIDE_LEFT 31
53+#define WIDE_RIGHT 32
54+#define SURROUND_DIRECT_LEFT 33
55+#define SURROUND_DIRECT_RIGHT 34
56+
57+static av_always_inline int even(uint64_t layout)
58+{
59+ return (!layout || (layout & (layout - 1)));
60+}
61+
62+static int sane_layout(uint64_t layout)
63+{
64+ /* check that there is at least 1 front speaker */
65+ if (!(layout & AV_CH_LAYOUT_SURROUND))
66+ return 0;
67+
68+ /* check for left/right symmetry */
69+ if (!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)) ||
70+ !even(layout & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)) ||
71+ !even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)) ||
72+ !even(layout & (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)) ||
73+ !even(layout & (AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT)) ||
74+ !even(layout & (AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT)) ||
75+ !even(layout & (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT)) ||
76+ !even(layout & (AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT)) ||
77+ !even(layout & (AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT)))
78+ return 0;
79+
80+ return 1;
81+}
82+
83+int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
84+ double center_mix_level, double surround_mix_level,
85+ double lfe_mix_level, int normalize,
86+ double *matrix_out, int stride)
87+{
88+ int i, j, out_i, out_j;
89+ double matrix[64][64] = {{0}};
90+ int64_t unaccounted = in_layout & ~out_layout;
91+ double maxcoef = 0;
92+ int in_channels, out_channels;
93+
94+ in_channels = av_get_channel_layout_nb_channels( in_layout);
95+ out_channels = av_get_channel_layout_nb_channels(out_layout);
96+
97+ memset(matrix_out, 0, out_channels * stride * sizeof(*matrix_out));
98+
99+ /* check if layouts are supported */
100+ if (!in_layout || in_channels > AVRESAMPLE_MAX_CHANNELS)
101+ return AVERROR(EINVAL);
102+ if (!out_layout || out_channels > AVRESAMPLE_MAX_CHANNELS)
103+ return AVERROR(EINVAL);
104+
105+ /* check if layouts are unbalanced or abnormal */
106+ if (!sane_layout(in_layout) || !sane_layout(out_layout))
107+ return AVERROR_PATCHWELCOME;
108+
109+ /* route matching input/output channels */
110+ for (i = 0; i < 64; i++) {
111+ if (in_layout & out_layout & (1ULL << i))
112+ matrix[i][i] = 1.0;
113+ }
114+
115+ /* mix front center to front left/right */
116+ if (unaccounted & AV_CH_FRONT_CENTER) {
117+ if ((out_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO) {
118+ matrix[FRONT_LEFT ][FRONT_CENTER] += M_SQRT1_2;
119+ matrix[FRONT_RIGHT][FRONT_CENTER] += M_SQRT1_2;
120+ } else
121+ return AVERROR_PATCHWELCOME;
122+ }
123+ /* mix front left/right to center */
124+ if (unaccounted & AV_CH_LAYOUT_STEREO) {
125+ if (out_layout & AV_CH_FRONT_CENTER) {
126+ matrix[FRONT_CENTER][FRONT_LEFT ] += M_SQRT1_2;
127+ matrix[FRONT_CENTER][FRONT_RIGHT] += M_SQRT1_2;
128+ /* mix left/right/center to center */
129+ if (in_layout & AV_CH_FRONT_CENTER)
130+ matrix[FRONT_CENTER][FRONT_CENTER] = center_mix_level * M_SQRT2;
131+ } else
132+ return AVERROR_PATCHWELCOME;
133+ }
134+ /* mix back center to back, side, or front */
135+ if (unaccounted & AV_CH_BACK_CENTER) {
136+ if (out_layout & AV_CH_BACK_LEFT) {
137+ matrix[BACK_LEFT ][BACK_CENTER] += M_SQRT1_2;
138+ matrix[BACK_RIGHT][BACK_CENTER] += M_SQRT1_2;
139+ } else if (out_layout & AV_CH_SIDE_LEFT) {
140+ matrix[SIDE_LEFT ][BACK_CENTER] += M_SQRT1_2;
141+ matrix[SIDE_RIGHT][BACK_CENTER] += M_SQRT1_2;
142+ } else if (out_layout & AV_CH_FRONT_LEFT) {
143+ matrix[FRONT_LEFT ][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
144+ matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
145+ } else if (out_layout & AV_CH_FRONT_CENTER) {
146+ matrix[FRONT_CENTER][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
147+ } else
148+ return AVERROR_PATCHWELCOME;
149+ }
150+ /* mix back left/right to back center, side, or front */
151+ if (unaccounted & AV_CH_BACK_LEFT) {
152+ if (out_layout & AV_CH_BACK_CENTER) {
153+ matrix[BACK_CENTER][BACK_LEFT ] += M_SQRT1_2;
154+ matrix[BACK_CENTER][BACK_RIGHT] += M_SQRT1_2;
155+ } else if (out_layout & AV_CH_SIDE_LEFT) {
156+ /* if side channels do not exist in the input, just copy back
157+ channels to side channels, otherwise mix back into side */
158+ if (in_layout & AV_CH_SIDE_LEFT) {
159+ matrix[SIDE_LEFT ][BACK_LEFT ] += M_SQRT1_2;
160+ matrix[SIDE_RIGHT][BACK_RIGHT] += M_SQRT1_2;
161+ } else {
162+ matrix[SIDE_LEFT ][BACK_LEFT ] += 1.0;
163+ matrix[SIDE_RIGHT][BACK_RIGHT] += 1.0;
164+ }
165+ } else if (out_layout & AV_CH_FRONT_LEFT) {
166+ matrix[FRONT_LEFT ][BACK_LEFT ] += surround_mix_level;
167+ matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
168+ } else if (out_layout & AV_CH_FRONT_CENTER) {
169+ matrix[FRONT_CENTER][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
170+ matrix[FRONT_CENTER][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
171+ } else
172+ return AVERROR_PATCHWELCOME;
173+ }
174+ /* mix side left/right into back or front */
175+ if (unaccounted & AV_CH_SIDE_LEFT) {
176+ if (out_layout & AV_CH_BACK_LEFT) {
177+ /* if back channels do not exist in the input, just copy side
178+ channels to back channels, otherwise mix side into back */
179+ if (in_layout & AV_CH_BACK_LEFT) {
180+ matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
181+ matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
182+ } else {
183+ matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
184+ matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
185+ }
186+ } else if (out_layout & AV_CH_BACK_CENTER) {
187+ matrix[BACK_CENTER][SIDE_LEFT ] += M_SQRT1_2;
188+ matrix[BACK_CENTER][SIDE_RIGHT] += M_SQRT1_2;
189+ } else if (out_layout & AV_CH_FRONT_LEFT) {
190+ matrix[FRONT_LEFT ][SIDE_LEFT ] += surround_mix_level;
191+ matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
192+ } else if (out_layout & AV_CH_FRONT_CENTER) {
193+ matrix[FRONT_CENTER][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
194+ matrix[FRONT_CENTER][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
195+ } else
196+ return AVERROR_PATCHWELCOME;
197+ }
198+ /* mix left-of-center/right-of-center into front left/right or center */
199+ if (unaccounted & AV_CH_FRONT_LEFT_OF_CENTER) {
200+ if (out_layout & AV_CH_FRONT_LEFT) {
201+ matrix[FRONT_LEFT ][FRONT_LEFT_OF_CENTER ] += 1.0;
202+ matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER] += 1.0;
203+ } else if (out_layout & AV_CH_FRONT_CENTER) {
204+ matrix[FRONT_CENTER][FRONT_LEFT_OF_CENTER ] += M_SQRT1_2;
205+ matrix[FRONT_CENTER][FRONT_RIGHT_OF_CENTER] += M_SQRT1_2;
206+ } else
207+ return AVERROR_PATCHWELCOME;
208+ }
209+ /* mix LFE into front left/right or center */
210+ if (unaccounted & AV_CH_LOW_FREQUENCY) {
211+ if (out_layout & AV_CH_FRONT_CENTER) {
212+ matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level;
213+ } else if (out_layout & AV_CH_FRONT_LEFT) {
214+ matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
215+ matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
216+ } else
217+ return AVERROR_PATCHWELCOME;
218+ }
219+
220+ /* transfer internal matrix to output matrix and calculate maximum
221+ per-channel coefficient sum */
222+ for (out_i = i = 0; out_i < out_channels && i < 64; i++) {
223+ double sum = 0;
224+ for (out_j = j = 0; out_j < in_channels && j < 64; j++) {
225+ matrix_out[out_i * stride + out_j] = matrix[i][j];
226+ sum += fabs(matrix[i][j]);
227+ if (in_layout & (1ULL << j))
228+ out_j++;
229+ }
230+ maxcoef = FFMAX(maxcoef, sum);
231+ if (out_layout & (1ULL << i))
232+ out_i++;
233+ }
234+
235+ /* normalize */
236+ if (normalize && maxcoef > 1.0) {
237+ for (i = 0; i < out_channels; i++)
238+ for (j = 0; j < in_channels; j++)
239+ matrix_out[i * stride + j] /= maxcoef;
240+ }
241+
242+ return 0;
243+}
244+
245+int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix,
246+ int stride)
247+{
248+ int in_channels, out_channels, i, o;
249+
250+ in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
251+ out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
252+
253+ if ( in_channels < 0 || in_channels > AVRESAMPLE_MAX_CHANNELS ||
254+ out_channels < 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
255+ av_log(avr, AV_LOG_ERROR, "Invalid channel layouts\n");
256+ return AVERROR(EINVAL);
257+ }
258+
259+ switch (avr->mix_coeff_type) {
260+ case AV_MIX_COEFF_TYPE_Q6:
261+ if (!avr->am->matrix_q6[0]) {
262+ av_log(avr, AV_LOG_ERROR, "matrix is not set\n");
263+ return AVERROR(EINVAL);
264+ }
265+ for (o = 0; o < out_channels; o++)
266+ for (i = 0; i < in_channels; i++)
267+ matrix[o * stride + i] = avr->am->matrix_q6[o][i] / 64.0;
268+ break;
269+ case AV_MIX_COEFF_TYPE_Q15:
270+ if (!avr->am->matrix_q15[0]) {
271+ av_log(avr, AV_LOG_ERROR, "matrix is not set\n");
272+ return AVERROR(EINVAL);
273+ }
274+ for (o = 0; o < out_channels; o++)
275+ for (i = 0; i < in_channels; i++)
276+ matrix[o * stride + i] = avr->am->matrix_q15[o][i] / 32768.0;
277+ break;
278+ case AV_MIX_COEFF_TYPE_FLT:
279+ if (!avr->am->matrix_flt[0]) {
280+ av_log(avr, AV_LOG_ERROR, "matrix is not set\n");
281+ return AVERROR(EINVAL);
282+ }
283+ for (o = 0; o < out_channels; o++)
284+ for (i = 0; i < in_channels; i++)
285+ matrix[o * stride + i] = avr->am->matrix_flt[o][i];
286+ break;
287+ default:
288+ av_log(avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
289+ return AVERROR(EINVAL);
290+ }
291+ return 0;
292+}
293+
294+int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix,
295+ int stride)
296+{
297+ int in_channels, out_channels, i, o;
298+
299+ in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
300+ out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
301+
302+ if ( in_channels < 0 || in_channels > AVRESAMPLE_MAX_CHANNELS ||
303+ out_channels < 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
304+ av_log(avr, AV_LOG_ERROR, "Invalid channel layouts\n");
305+ return AVERROR(EINVAL);
306+ }
307+
308+ if (avr->am->matrix)
309+ av_freep(avr->am->matrix);
310+
311+#define CONVERT_MATRIX(type, expr) \
312+ avr->am->matrix_## type[0] = av_mallocz(out_channels * in_channels * \
313+ sizeof(*avr->am->matrix_## type[0])); \
314+ if (!avr->am->matrix_## type[0]) \
315+ return AVERROR(ENOMEM); \
316+ for (o = 0; o < out_channels; o++) { \
317+ if (o > 0) \
318+ avr->am->matrix_## type[o] = avr->am->matrix_## type[o - 1] + \
319+ in_channels; \
320+ for (i = 0; i < in_channels; i++) { \
321+ double v = matrix[o * stride + i]; \
322+ avr->am->matrix_## type[o][i] = expr; \
323+ } \
324+ } \
325+ avr->am->matrix = (void **)avr->am->matrix_## type;
326+
327+ switch (avr->mix_coeff_type) {
328+ case AV_MIX_COEFF_TYPE_Q6:
329+ CONVERT_MATRIX(q6, av_clip_int16(lrint(64.0 * v)))
330+ break;
331+ case AV_MIX_COEFF_TYPE_Q15:
332+ CONVERT_MATRIX(q15, av_clipl_int32(llrint(32768.0 * v)))
333+ break;
334+ case AV_MIX_COEFF_TYPE_FLT:
335+ CONVERT_MATRIX(flt, v)
336+ break;
337+ default:
338+ av_log(avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
339+ return AVERROR(EINVAL);
340+ }
341+
342+ /* TODO: detect situations where we can just swap around pointers
343+ instead of doing matrix multiplications with 0.0 and 1.0 */
344+
345+ return 0;
346+}
libavresample/avresample-test.c+340−0
@@ -0,0 +1,340 @@
1+/*
2+ * Copyright (c) 2002 Fabrice Bellard
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+#include <stdio.h>
24+
25+#include "libavutil/avstring.h"
26+#include "libavutil/lfg.h"
27+#include "libavutil/libm.h"
28+#include "libavutil/log.h"
29+#include "libavutil/mem.h"
30+#include "libavutil/opt.h"
31+#include "libavutil/samplefmt.h"
32+#include "avresample.h"
33+
34+static double dbl_rand(AVLFG *lfg)
35+{
36+ return 2.0 * (av_lfg_get(lfg) / (double)UINT_MAX) - 1.0;
37+}
38+
39+#define PUT_FUNC(name, fmt, type, expr) \
40+static void put_sample_ ## name(void **data, enum AVSampleFormat sample_fmt,\
41+ int channels, int sample, int ch, \
42+ double v_dbl) \
43+{ \
44+ type v = expr; \
45+ type **out = (type **)data; \
46+ if (av_sample_fmt_is_planar(sample_fmt)) \
47+ out[ch][sample] = v; \
48+ else \
49+ out[0][sample * channels + ch] = v; \
50+}
51+
52+PUT_FUNC(u8, AV_SAMPLE_FMT_U8, uint8_t, av_clip_uint8 ( lrint(v_dbl * (1 << 7)) + 128))
53+PUT_FUNC(s16, AV_SAMPLE_FMT_S16, int16_t, av_clip_int16 ( lrint(v_dbl * (1 << 15))))
54+PUT_FUNC(s32, AV_SAMPLE_FMT_S32, int32_t, av_clipl_int32(llrint(v_dbl * (1U << 31))))
55+PUT_FUNC(flt, AV_SAMPLE_FMT_FLT, float, v_dbl)
56+PUT_FUNC(dbl, AV_SAMPLE_FMT_DBL, double, v_dbl)
57+
58+static void put_sample(void **data, enum AVSampleFormat sample_fmt,
59+ int channels, int sample, int ch, double v_dbl)
60+{
61+ switch (av_get_packed_sample_fmt(sample_fmt)) {
62+ case AV_SAMPLE_FMT_U8:
63+ put_sample_u8(data, sample_fmt, channels, sample, ch, v_dbl);
64+ break;
65+ case AV_SAMPLE_FMT_S16:
66+ put_sample_s16(data, sample_fmt, channels, sample, ch, v_dbl);
67+ break;
68+ case AV_SAMPLE_FMT_S32:
69+ put_sample_s32(data, sample_fmt, channels, sample, ch, v_dbl);
70+ break;
71+ case AV_SAMPLE_FMT_FLT:
72+ put_sample_flt(data, sample_fmt, channels, sample, ch, v_dbl);
73+ break;
74+ case AV_SAMPLE_FMT_DBL:
75+ put_sample_dbl(data, sample_fmt, channels, sample, ch, v_dbl);
76+ break;
77+ }
78+}
79+
80+static void audiogen(AVLFG *rnd, void **data, enum AVSampleFormat sample_fmt,
81+ int channels, int sample_rate, int nb_samples)
82+{
83+ int i, ch, k;
84+ double v, f, a, ampa;
85+ double tabf1[AVRESAMPLE_MAX_CHANNELS];
86+ double tabf2[AVRESAMPLE_MAX_CHANNELS];
87+ double taba[AVRESAMPLE_MAX_CHANNELS];
88+
89+#define PUT_SAMPLE put_sample(data, sample_fmt, channels, k, ch, v);
90+
91+ k = 0;
92+
93+ /* 1 second of single freq sinus at 1000 Hz */
94+ a = 0;
95+ for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
96+ v = sin(a) * 0.30;
97+ for (ch = 0; ch < channels; ch++)
98+ PUT_SAMPLE
99+ a += M_PI * 1000.0 * 2.0 / sample_rate;
100+ }
101+
102+ /* 1 second of varing frequency between 100 and 10000 Hz */
103+ a = 0;
104+ for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
105+ v = sin(a) * 0.30;
106+ for (ch = 0; ch < channels; ch++)
107+ PUT_SAMPLE
108+ f = 100.0 + (((10000.0 - 100.0) * i) / sample_rate);
109+ a += M_PI * f * 2.0 / sample_rate;
110+ }
111+
112+ /* 0.5 second of low amplitude white noise */
113+ for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
114+ v = dbl_rand(rnd) * 0.30;
115+ for (ch = 0; ch < channels; ch++)
116+ PUT_SAMPLE
117+ }
118+
119+ /* 0.5 second of high amplitude white noise */
120+ for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
121+ v = dbl_rand(rnd);
122+ for (ch = 0; ch < channels; ch++)
123+ PUT_SAMPLE
124+ }
125+
126+ /* 1 second of unrelated ramps for each channel */
127+ for (ch = 0; ch < channels; ch++) {
128+ taba[ch] = 0;
129+ tabf1[ch] = 100 + av_lfg_get(rnd) % 5000;
130+ tabf2[ch] = 100 + av_lfg_get(rnd) % 5000;
131+ }
132+ for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
133+ for (ch = 0; ch < channels; ch++) {
134+ v = sin(taba[ch]) * 0.30;
135+ PUT_SAMPLE
136+ f = tabf1[ch] + (((tabf2[ch] - tabf1[ch]) * i) / sample_rate);
137+ taba[ch] += M_PI * f * 2.0 / sample_rate;
138+ }
139+ }
140+
141+ /* 2 seconds of 500 Hz with varying volume */
142+ a = 0;
143+ ampa = 0;
144+ for (i = 0; i < 2 * sample_rate && k < nb_samples; i++, k++) {
145+ for (ch = 0; ch < channels; ch++) {
146+ double amp = (1.0 + sin(ampa)) * 0.15;
147+ if (ch & 1)
148+ amp = 0.30 - amp;
149+ v = sin(a) * amp;
150+ PUT_SAMPLE
151+ a += M_PI * 500.0 * 2.0 / sample_rate;
152+ ampa += M_PI * 2.0 / sample_rate;
153+ }
154+ }
155+}
156+
157+/* formats, rates, and layouts are ordered for priority in testing.
158+ e.g. 'avresample-test 4 2 2' will test all input/output combinations of
159+ S16/FLTP/S16P/FLT, 48000/44100, and stereo/mono */
160+
161+static const enum AVSampleFormat formats[] = {
162+ AV_SAMPLE_FMT_S16,
163+ AV_SAMPLE_FMT_FLTP,
164+ AV_SAMPLE_FMT_S16P,
165+ AV_SAMPLE_FMT_FLT,
166+ AV_SAMPLE_FMT_S32P,
167+ AV_SAMPLE_FMT_S32,
168+ AV_SAMPLE_FMT_U8P,
169+ AV_SAMPLE_FMT_U8,
170+ AV_SAMPLE_FMT_DBLP,
171+ AV_SAMPLE_FMT_DBL,
172+};
173+
174+static const int rates[] = {
175+ 48000,
176+ 44100,
177+ 16000
178+};
179+
180+static const uint64_t layouts[] = {
181+ AV_CH_LAYOUT_STEREO,
182+ AV_CH_LAYOUT_MONO,
183+ AV_CH_LAYOUT_5POINT1,
184+ AV_CH_LAYOUT_7POINT1,
185+};
186+
187+int main(int argc, char **argv)
188+{
189+ AVAudioResampleContext *s;
190+ AVLFG rnd;
191+ int ret = 0;
192+ uint8_t *in_buf = NULL;
193+ uint8_t *out_buf = NULL;
194+ unsigned int in_buf_size;
195+ unsigned int out_buf_size;
196+ uint8_t *in_data[AVRESAMPLE_MAX_CHANNELS] = { 0 };
197+ uint8_t *out_data[AVRESAMPLE_MAX_CHANNELS] = { 0 };
198+ int in_linesize;
199+ int out_linesize;
200+ uint64_t in_ch_layout;
201+ int in_channels;
202+ enum AVSampleFormat in_fmt;
203+ int in_rate;
204+ uint64_t out_ch_layout;
205+ int out_channels;
206+ enum AVSampleFormat out_fmt;
207+ int out_rate;
208+ int num_formats, num_rates, num_layouts;
209+ int i, j, k, l, m, n;
210+
211+ num_formats = 2;
212+ num_rates = 2;
213+ num_layouts = 2;
214+ if (argc > 1) {
215+ if (!av_strncasecmp(argv[1], "-h", 3)) {
216+ av_log(NULL, AV_LOG_INFO, "Usage: avresample-test [<num formats> "
217+ "[<num sample rates> [<num channel layouts>]]]\n"
218+ "Default is 2 2 2\n");
219+ return 0;
220+ }
221+ num_formats = strtol(argv[1], NULL, 0);
222+ num_formats = av_clip(num_formats, 1, FF_ARRAY_ELEMS(formats));
223+ }
224+ if (argc > 2) {
225+ num_rates = strtol(argv[2], NULL, 0);
226+ num_rates = av_clip(num_rates, 1, FF_ARRAY_ELEMS(rates));
227+ }
228+ if (argc > 3) {
229+ num_layouts = strtol(argv[3], NULL, 0);
230+ num_layouts = av_clip(num_layouts, 1, FF_ARRAY_ELEMS(layouts));
231+ }
232+
233+ av_log_set_level(AV_LOG_DEBUG);
234+
235+ av_lfg_init(&rnd, 0xC0FFEE);
236+
237+ in_buf_size = av_samples_get_buffer_size(&in_linesize, 8, 48000 * 6,
238+ AV_SAMPLE_FMT_DBLP, 0);
239+ out_buf_size = in_buf_size;
240+
241+ in_buf = av_malloc(in_buf_size);
242+ if (!in_buf)
243+ goto end;
244+ out_buf = av_malloc(out_buf_size);
245+ if (!out_buf)
246+ goto end;
247+
248+ s = avresample_alloc_context();
249+ if (!s) {
250+ av_log(NULL, AV_LOG_ERROR, "Error allocating AVAudioResampleContext\n");
251+ ret = 1;
252+ goto end;
253+ }
254+
255+ for (i = 0; i < num_formats; i++) {
256+ in_fmt = formats[i];
257+ for (k = 0; k < num_layouts; k++) {
258+ in_ch_layout = layouts[k];
259+ in_channels = av_get_channel_layout_nb_channels(in_ch_layout);
260+ for (m = 0; m < num_rates; m++) {
261+ in_rate = rates[m];
262+
263+ ret = av_samples_fill_arrays(in_data, &in_linesize, in_buf,
264+ in_channels, in_rate * 6,
265+ in_fmt, 0);
266+ if (ret < 0) {
267+ av_log(s, AV_LOG_ERROR, "failed in_data fill arrays\n");
268+ goto end;
269+ }
270+ audiogen(&rnd, (void **)in_data, in_fmt, in_channels, in_rate, in_rate * 6);
271+
272+ for (j = 0; j < num_formats; j++) {
273+ out_fmt = formats[j];
274+ for (l = 0; l < num_layouts; l++) {
275+ out_ch_layout = layouts[l];
276+ out_channels = av_get_channel_layout_nb_channels(out_ch_layout);
277+ for (n = 0; n < num_rates; n++) {
278+ out_rate = rates[n];
279+
280+ av_log(NULL, AV_LOG_INFO, "%s to %s, %d to %d channels, %d Hz to %d Hz\n",
281+ av_get_sample_fmt_name(in_fmt), av_get_sample_fmt_name(out_fmt),
282+ in_channels, out_channels, in_rate, out_rate);
283+
284+ ret = av_samples_fill_arrays(out_data, &out_linesize,
285+ out_buf, out_channels,
286+ out_rate * 6, out_fmt, 0);
287+ if (ret < 0) {
288+ av_log(s, AV_LOG_ERROR, "failed out_data fill arrays\n");
289+ goto end;
290+ }
291+
292+ av_opt_set_int(s, "in_channel_layout", in_ch_layout, 0);
293+ av_opt_set_int(s, "in_sample_fmt", in_fmt, 0);
294+ av_opt_set_int(s, "in_sample_rate", in_rate, 0);
295+ av_opt_set_int(s, "out_channel_layout", out_ch_layout, 0);
296+ av_opt_set_int(s, "out_sample_fmt", out_fmt, 0);
297+ av_opt_set_int(s, "out_sample_rate", out_rate, 0);
298+
299+ av_opt_set_int(s, "internal_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
300+
301+ ret = avresample_open(s);
302+ if (ret < 0) {
303+ av_log(s, AV_LOG_ERROR, "Error opening context\n");
304+ goto end;
305+ }
306+
307+ ret = avresample_convert(s, (void **)out_data, out_linesize, out_rate * 6,
308+ (void **) in_data, in_linesize, in_rate * 6);
309+ if (ret < 0) {
310+ char errbuf[256];
311+ av_strerror(ret, errbuf, sizeof(errbuf));
312+ av_log(NULL, AV_LOG_ERROR, "%s\n", errbuf);
313+ goto end;
314+ }
315+ av_log(NULL, AV_LOG_INFO, "Converted %d samples to %d samples\n",
316+ in_rate * 6, ret);
317+ if (avresample_get_delay(s) > 0)
318+ av_log(NULL, AV_LOG_INFO, "%d delay samples not converted\n",
319+ avresample_get_delay(s));
320+ if (avresample_available(s) > 0)
321+ av_log(NULL, AV_LOG_INFO, "%d samples available for output\n",
322+ avresample_available(s));
323+ av_log(NULL, AV_LOG_INFO, "\n");
324+
325+ avresample_close(s);
326+ }
327+ }
328+ }
329+ }
330+ }
331+ }
332+
333+ ret = 0;
334+
335+end:
336+ av_freep(&in_buf);
337+ av_freep(&out_buf);
338+ avresample_free(&s);
339+ return ret;
340+}
libavresample/avresample.h+283−0
@@ -0,0 +1,283 @@
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_AVRESAMPLE_H
22+#define AVRESAMPLE_AVRESAMPLE_H
23+
24+/**
25+ * @file
26+ * external API header
27+ */
28+
29+#include "libavutil/audioconvert.h"
30+#include "libavutil/avutil.h"
31+#include "libavutil/dict.h"
32+#include "libavutil/log.h"
33+
34+#include "libavresample/version.h"
35+
36+#define AVRESAMPLE_MAX_CHANNELS 32
37+
38+typedef struct AVAudioResampleContext AVAudioResampleContext;
39+
40+/** Mixing Coefficient Types */
41+enum AVMixCoeffType {
42+ AV_MIX_COEFF_TYPE_Q6, /** 16-bit 10.6 fixed-point */
43+ AV_MIX_COEFF_TYPE_Q15, /** 32-bit 17.15 fixed-point */
44+ AV_MIX_COEFF_TYPE_FLT, /** floating-point */
45+ AV_MIX_COEFF_TYPE_NB, /** Number of coeff types. Not part of ABI */
46+};
47+
48+/**
49+ * Return the LIBAVRESAMPLE_VERSION_INT constant.
50+ */
51+unsigned avresample_version(void);
52+
53+/**
54+ * Return the libavresample build-time configuration.
55+ * @return configure string
56+ */
57+const char *avresample_configuration(void);
58+
59+/**
60+ * Return the libavresample license.
61+ */
62+const char *avresample_license(void);
63+
64+/**
65+ * Get the AVClass for AVAudioResampleContext.
66+ *
67+ * Can be used in combination with AV_OPT_SEARCH_FAKE_OBJ for examining options
68+ * without allocating a context.
69+ *
70+ * @see av_opt_find().
71+ *
72+ * @return AVClass for AVAudioResampleContext
73+ */
74+const AVClass *avresample_get_class(void);
75+
76+/**
77+ * Allocate AVAudioResampleContext and set options.
78+ *
79+ * @return allocated audio resample context, or NULL on failure
80+ */
81+AVAudioResampleContext *avresample_alloc_context(void);
82+
83+/**
84+ * Initialize AVAudioResampleContext.
85+ *
86+ * @param avr audio resample context
87+ * @return 0 on success, negative AVERROR code on failure
88+ */
89+int avresample_open(AVAudioResampleContext *avr);
90+
91+/**
92+ * Close AVAudioResampleContext.
93+ *
94+ * This closes the context, but it does not change the parameters. The context
95+ * can be reopened with avresample_open(). It does, however, clear the output
96+ * FIFO and any remaining leftover samples in the resampling delay buffer. If
97+ * there was a custom matrix being used, that is also cleared.
98+ *
99+ * @see avresample_convert()
100+ * @see avresample_set_matrix()
101+ *
102+ * @param avr audio resample context
103+ */
104+void avresample_close(AVAudioResampleContext *avr);
105+
106+/**
107+ * Free AVAudioResampleContext and associated AVOption values.
108+ *
109+ * This also calls avresample_close() before freeing.
110+ *
111+ * @param avr audio resample context
112+ */
113+void avresample_free(AVAudioResampleContext **avr);
114+
115+/**
116+ * Generate a channel mixing matrix.
117+ *
118+ * This function is the one used internally by libavresample for building the
119+ * default mixing matrix. It is made public just as a utility function for
120+ * building custom matrices.
121+ *
122+ * @param in_layout input channel layout
123+ * @param out_layout output channel layout
124+ * @param center_mix_level mix level for the center channel
125+ * @param surround_mix_level mix level for the surround channel(s)
126+ * @param lfe_mix_level mix level for the low-frequency effects channel
127+ * @param normalize if 1, coefficients will be normalized to prevent
128+ * overflow. if 0, coefficients will not be
129+ * normalized.
130+ * @param[out] matrix mixing coefficients; matrix[i + stride * o] is
131+ * the weight of input channel i in output channel o.
132+ * @param stride distance between adjacent input channels in the
133+ * matrix array
134+ * @return 0 on success, negative AVERROR code on failure
135+ */
136+int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
137+ double center_mix_level, double surround_mix_level,
138+ double lfe_mix_level, int normalize, double *matrix,
139+ int stride);
140+
141+/**
142+ * Get the current channel mixing matrix.
143+ *
144+ * @param avr audio resample context
145+ * @param matrix mixing coefficients; matrix[i + stride * o] is the weight of
146+ * input channel i in output channel o.
147+ * @param stride distance between adjacent input channels in the matrix array
148+ * @return 0 on success, negative AVERROR code on failure
149+ */
150+int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix,
151+ int stride);
152+
153+/**
154+ * Set channel mixing matrix.
155+ *
156+ * Allows for setting a custom mixing matrix, overriding the default matrix
157+ * generated internally during avresample_open(). This function can be called
158+ * anytime on an allocated context, either before or after calling
159+ * avresample_open(). avresample_convert() always uses the current matrix.
160+ * Calling avresample_close() on the context will clear the current matrix.
161+ *
162+ * @see avresample_close()
163+ *
164+ * @param avr audio resample context
165+ * @param matrix mixing coefficients; matrix[i + stride * o] is the weight of
166+ * input channel i in output channel o.
167+ * @param stride distance between adjacent input channels in the matrix array
168+ * @return 0 on success, negative AVERROR code on failure
169+ */
170+int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix,
171+ int stride);
172+
173+/**
174+ * Set compensation for resampling.
175+ *
176+ * This can be called anytime after avresample_open(). If resampling was not
177+ * being done previously, the AVAudioResampleContext is closed and reopened
178+ * with resampling enabled. In this case, any samples remaining in the output
179+ * FIFO and the current channel mixing matrix will be restored after reopening
180+ * the context.
181+ *
182+ * @param avr audio resample context
183+ * @param sample_delta compensation delta, in samples
184+ * @param compensation_distance compensation distance, in samples
185+ * @return 0 on success, negative AVERROR code on failure
186+ */
187+int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta,
188+ int compensation_distance);
189+
190+/**
191+ * Convert input samples and write them to the output FIFO.
192+ *
193+ * The output data can be NULL or have fewer allocated samples than required.
194+ * In this case, any remaining samples not written to the output will be added
195+ * to an internal FIFO buffer, to be returned at the next call to this function
196+ * or to avresample_read().
197+ *
198+ * If converting sample rate, there may be data remaining in the internal
199+ * resampling delay buffer. avresample_get_delay() tells the number of remaining
200+ * samples. To get this data as output, call avresample_convert() with NULL
201+ * input.
202+ *
203+ * At the end of the conversion process, there may be data remaining in the
204+ * internal FIFO buffer. avresample_available() tells the number of remaining
205+ * samples. To get this data as output, either call avresample_convert() with
206+ * NULL input or call avresample_read().
207+ *
208+ * @see avresample_available()
209+ * @see avresample_read()
210+ * @see avresample_get_delay()
211+ *
212+ * @param avr audio resample context
213+ * @param output output data pointers
214+ * @param out_plane_size output plane size, in bytes.
215+ * This can be 0 if unknown, but that will lead to
216+ * optimized functions not being used directly on the
217+ * output, which could slow down some conversions.
218+ * @param out_samples maximum number of samples that the output buffer can hold
219+ * @param input input data pointers
220+ * @param in_plane_size input plane size, in bytes
221+ * This can be 0 if unknown, but that will lead to
222+ * optimized functions not being used directly on the
223+ * input, which could slow down some conversions.
224+ * @param in_samples number of input samples to convert
225+ * @return number of samples written to the output buffer,
226+ * not including converted samples added to the internal
227+ * output FIFO
228+ */
229+int avresample_convert(AVAudioResampleContext *avr, void **output,
230+ int out_plane_size, int out_samples, void **input,
231+ int in_plane_size, int in_samples);
232+
233+/**
234+ * Return the number of samples currently in the resampling delay buffer.
235+ *
236+ * When resampling, there may be a delay between the input and output. Any
237+ * unconverted samples in each call are stored internally in a delay buffer.
238+ * This function allows the user to determine the current number of samples in
239+ * the delay buffer, which can be useful for synchronization.
240+ *
241+ * @see avresample_convert()
242+ *
243+ * @param avr audio resample context
244+ * @return number of samples currently in the resampling delay buffer
245+ */
246+int avresample_get_delay(AVAudioResampleContext *avr);
247+
248+/**
249+ * Return the number of available samples in the output FIFO.
250+ *
251+ * During conversion, if the user does not specify an output buffer or
252+ * specifies an output buffer that is smaller than what is needed, remaining
253+ * samples that are not written to the output are stored to an internal FIFO
254+ * buffer. The samples in the FIFO can be read with avresample_read() or
255+ * avresample_convert().
256+ *
257+ * @see avresample_read()
258+ * @see avresample_convert()
259+ *
260+ * @param avr audio resample context
261+ * @return number of samples available for reading
262+ */
263+int avresample_available(AVAudioResampleContext *avr);
264+
265+/**
266+ * Read samples from the output FIFO.
267+ *
268+ * During conversion, if the user does not specify an output buffer or
269+ * specifies an output buffer that is smaller than what is needed, remaining
270+ * samples that are not written to the output are stored to an internal FIFO
271+ * buffer. This function can be used to read samples from that internal FIFO.
272+ *
273+ * @see avresample_available()
274+ * @see avresample_convert()
275+ *
276+ * @param avr audio resample context
277+ * @param output output data pointers
278+ * @param nb_samples number of samples to read from the FIFO
279+ * @return the number of samples written to output
280+ */
281+int avresample_read(AVAudioResampleContext *avr, void **output, int nb_samples);
282+
283+#endif /* AVRESAMPLE_AVRESAMPLE_H */
libavresample/internal.h+75−0
@@ -0,0 +1,75 @@
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_INTERNAL_H
22+#define AVRESAMPLE_INTERNAL_H
23+
24+#include "libavutil/audio_fifo.h"
25+#include "libavutil/log.h"
26+#include "libavutil/opt.h"
27+#include "libavutil/samplefmt.h"
28+#include "avresample.h"
29+#include "audio_convert.h"
30+#include "audio_data.h"
31+#include "audio_mix.h"
32+#include "resample.h"
33+
34+struct AVAudioResampleContext {
35+ const AVClass *av_class; /**< AVClass for logging and AVOptions */
36+
37+ uint64_t in_channel_layout; /**< input channel layout */
38+ enum AVSampleFormat in_sample_fmt; /**< input sample format */
39+ int in_sample_rate; /**< input sample rate */
40+ uint64_t out_channel_layout; /**< output channel layout */
41+ enum AVSampleFormat out_sample_fmt; /**< output sample format */
42+ int out_sample_rate; /**< output sample rate */
43+ enum AVSampleFormat internal_sample_fmt; /**< internal sample format */
44+ enum AVMixCoeffType mix_coeff_type; /**< mixing coefficient type */
45+ double center_mix_level; /**< center mix level */
46+ double surround_mix_level; /**< surround mix level */
47+ double lfe_mix_level; /**< lfe mix level */
48+ int force_resampling; /**< force resampling */
49+ int filter_size; /**< length of each FIR filter in the resampling filterbank relative to the cutoff frequency */
50+ int phase_shift; /**< log2 of the number of entries in the resampling polyphase filterbank */
51+ int linear_interp; /**< if 1 then the resampling FIR filter will be linearly interpolated */
52+ double cutoff; /**< resampling cutoff frequency. 1.0 corresponds to half the output sample rate */
53+
54+ int in_channels; /**< number of input channels */
55+ int out_channels; /**< number of output channels */
56+ int resample_channels; /**< number of channels used for resampling */
57+ int downmix_needed; /**< downmixing is needed */
58+ int upmix_needed; /**< upmixing is needed */
59+ int mixing_needed; /**< either upmixing or downmixing is needed */
60+ int resample_needed; /**< resampling is needed */
61+ int in_convert_needed; /**< input sample format conversion is needed */
62+ int out_convert_needed; /**< output sample format conversion is needed */
63+
64+ AudioData *in_buffer; /**< buffer for converted input */
65+ AudioData *resample_out_buffer; /**< buffer for output from resampler */
66+ AudioData *out_buffer; /**< buffer for converted output */
67+ AVAudioFifo *out_fifo; /**< FIFO for output samples */
68+
69+ AudioConvert *ac_in; /**< input sample format conversion context */
70+ AudioConvert *ac_out; /**< output sample format conversion context */
71+ ResampleContext *resample; /**< resampling context */
72+ AudioMix *am; /**< channel mixing context */
73+};
74+
75+#endif /* AVRESAMPLE_INTERNAL_H */
libavresample/libavresample.v+4−0
@@ -0,0 +1,4 @@
1+LIBAVRESAMPLE_$MAJOR {
2+ global: av*;
3+ local: *;
4+};
libavresample/options.c+89−0
@@ -0,0 +1,89 @@
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 "libavutil/mathematics.h"
22+#include "libavutil/opt.h"
23+#include "avresample.h"
24+#include "internal.h"
25+#include "audio_mix.h"
26+
27+/**
28+ * @file
29+ * Options definition for AVAudioResampleContext.
30+ */
31+
32+#define OFFSET(x) offsetof(AVAudioResampleContext, x)
33+#define PARAM AV_OPT_FLAG_AUDIO_PARAM
34+
35+static const AVOption options[] = {
36+ { "in_channel_layout", "Input Channel Layout", OFFSET(in_channel_layout), AV_OPT_TYPE_INT64, { 0 }, INT64_MIN, INT64_MAX, PARAM },
37+ { "in_sample_fmt", "Input Sample Format", OFFSET(in_sample_fmt), AV_OPT_TYPE_INT, { AV_SAMPLE_FMT_S16 }, AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NB-1, PARAM },
38+ { "in_sample_rate", "Input Sample Rate", OFFSET(in_sample_rate), AV_OPT_TYPE_INT, { 48000 }, 1, INT_MAX, PARAM },
39+ { "out_channel_layout", "Output Channel Layout", OFFSET(out_channel_layout), AV_OPT_TYPE_INT64, { 0 }, INT64_MIN, INT64_MAX, PARAM },
40+ { "out_sample_fmt", "Output Sample Format", OFFSET(out_sample_fmt), AV_OPT_TYPE_INT, { AV_SAMPLE_FMT_S16 }, AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NB-1, PARAM },
41+ { "out_sample_rate", "Output Sample Rate", OFFSET(out_sample_rate), AV_OPT_TYPE_INT, { 48000 }, 1, INT_MAX, PARAM },
42+ { "internal_sample_fmt", "Internal Sample Format", OFFSET(internal_sample_fmt), AV_OPT_TYPE_INT, { AV_SAMPLE_FMT_FLTP }, AV_SAMPLE_FMT_NONE, AV_SAMPLE_FMT_NB-1, PARAM },
43+ { "mix_coeff_type", "Mixing Coefficient Type", OFFSET(mix_coeff_type), AV_OPT_TYPE_INT, { AV_MIX_COEFF_TYPE_FLT }, AV_MIX_COEFF_TYPE_Q6, AV_MIX_COEFF_TYPE_NB-1, PARAM, "mix_coeff_type" },
44+ { "q6", "16-bit 10.6 Fixed-Point", 0, AV_OPT_TYPE_CONST, { AV_MIX_COEFF_TYPE_Q6 }, INT_MIN, INT_MAX, PARAM, "mix_coeff_type" },
45+ { "q15", "32-bit 17.15 Fixed-Point", 0, AV_OPT_TYPE_CONST, { AV_MIX_COEFF_TYPE_Q15 }, INT_MIN, INT_MAX, PARAM, "mix_coeff_type" },
46+ { "flt", "Floating-Point", 0, AV_OPT_TYPE_CONST, { AV_MIX_COEFF_TYPE_FLT }, INT_MIN, INT_MAX, PARAM, "mix_coeff_type" },
47+ { "center_mix_level", "Center Mix Level", OFFSET(center_mix_level), AV_OPT_TYPE_DOUBLE, { M_SQRT1_2 }, -32.0, 32.0, PARAM },
48+ { "surround_mix_level", "Surround Mix Level", OFFSET(surround_mix_level), AV_OPT_TYPE_DOUBLE, { M_SQRT1_2 }, -32.0, 32.0, PARAM },
49+ { "lfe_mix_level", "LFE Mix Level", OFFSET(lfe_mix_level), AV_OPT_TYPE_DOUBLE, { 0.0 }, -32.0, 32.0, PARAM },
50+ { "force_resampling", "Force Resampling", OFFSET(force_resampling), AV_OPT_TYPE_INT, { 0 }, 0, 1, PARAM },
51+ { "filter_size", "Resampling Filter Size", OFFSET(filter_size), AV_OPT_TYPE_INT, { 16 }, 0, 32, /* ??? */ PARAM },
52+ { "phase_shift", "Resampling Phase Shift", OFFSET(phase_shift), AV_OPT_TYPE_INT, { 10 }, 0, 30, /* ??? */ PARAM },
53+ { "linear_interp", "Use Linear Interpolation", OFFSET(linear_interp), AV_OPT_TYPE_INT, { 0 }, 0, 1, PARAM },
54+ { "cutoff", "Cutoff Frequency Ratio", OFFSET(cutoff), AV_OPT_TYPE_DOUBLE, { 0.8 }, 0.0, 1.0, PARAM },
55+ { NULL },
56+};
57+
58+static const AVClass av_resample_context_class = {
59+ .class_name = "AVAudioResampleContext",
60+ .item_name = av_default_item_name,
61+ .option = options,
62+ .version = LIBAVUTIL_VERSION_INT,
63+};
64+
65+AVAudioResampleContext *avresample_alloc_context(void)
66+{
67+ AVAudioResampleContext *avr;
68+
69+ avr = av_mallocz(sizeof(*avr));
70+ if (!avr)
71+ return NULL;
72+
73+ avr->av_class = &av_resample_context_class;
74+ av_opt_set_defaults(avr);
75+
76+ avr->am = av_mallocz(sizeof(*avr->am));
77+ if (!avr->am) {
78+ av_free(avr);
79+ return NULL;
80+ }
81+ avr->am->avr = avr;
82+
83+ return avr;
84+}
85+
86+const AVClass *avresample_get_class(void)
87+{
88+ return &av_resample_context_class;
89+}
libavresample/resample.c+480−0
@@ -0,0 +1,480 @@
1+/*
2+ * Copyright (c) 2004 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 "libavutil/libm.h"
23+#include "libavutil/log.h"
24+#include "internal.h"
25+#include "audio_data.h"
26+
27+#ifdef CONFIG_RESAMPLE_FLT
28+/* float template */
29+#define FILTER_SHIFT 0
30+#define FELEM float
31+#define FELEM2 float
32+#define FELEML float
33+#define WINDOW_TYPE 24
34+#elifdef CONFIG_RESAMPLE_S32
35+/* s32 template */
36+#define FILTER_SHIFT 30
37+#define FELEM int32_t
38+#define FELEM2 int64_t
39+#define FELEML int64_t
40+#define FELEM_MAX INT32_MAX
41+#define FELEM_MIN INT32_MIN
42+#define WINDOW_TYPE 12
43+#else
44+/* s16 template */
45+#define FILTER_SHIFT 15
46+#define FELEM int16_t
47+#define FELEM2 int32_t
48+#define FELEML int64_t
49+#define FELEM_MAX INT16_MAX
50+#define FELEM_MIN INT16_MIN
51+#define WINDOW_TYPE 9
52+#endif
53+
54+struct ResampleContext {
55+ AVAudioResampleContext *avr;
56+ AudioData *buffer;
57+ FELEM *filter_bank;
58+ int filter_length;
59+ int ideal_dst_incr;
60+ int dst_incr;
61+ int index;
62+ int frac;
63+ int src_incr;
64+ int compensation_distance;
65+ int phase_shift;
66+ int phase_mask;
67+ int linear;
68+ double factor;
69+};
70+
71+/**
72+ * 0th order modified bessel function of the first kind.
73+ */
74+static double bessel(double x)
75+{
76+ double v = 1;
77+ double lastv = 0;
78+ double t = 1;
79+ int i;
80+
81+ x = x * x / 4;
82+ for (i = 1; v != lastv; i++) {
83+ lastv = v;
84+ t *= x / (i * i);
85+ v += t;
86+ }
87+ return v;
88+}
89+
90+/**
91+ * Build a polyphase filterbank.
92+ *
93+ * @param[out] filter filter coefficients
94+ * @param factor resampling factor
95+ * @param tap_count tap count
96+ * @param phase_count phase count
97+ * @param scale wanted sum of coefficients for each filter
98+ * @param type 0->cubic
99+ * 1->blackman nuttall windowed sinc
100+ * 2..16->kaiser windowed sinc beta=2..16
101+ * @return 0 on success, negative AVERROR code on failure
102+ */
103+static int build_filter(FELEM *filter, double factor, int tap_count,
104+ int phase_count, int scale, int type)
105+{
106+ int ph, i;
107+ double x, y, w;
108+ double *tab;
109+ const int center = (tap_count - 1) / 2;
110+
111+ tab = av_malloc(tap_count * sizeof(*tab));
112+ if (!tab)
113+ return AVERROR(ENOMEM);
114+
115+ /* if upsampling, only need to interpolate, no filter */
116+ if (factor > 1.0)
117+ factor = 1.0;
118+
119+ for (ph = 0; ph < phase_count; ph++) {
120+ double norm = 0;
121+ for (i = 0; i < tap_count; i++) {
122+ x = M_PI * ((double)(i - center) - (double)ph / phase_count) * factor;
123+ if (x == 0) y = 1.0;
124+ else y = sin(x) / x;
125+ switch (type) {
126+ case 0: {
127+ const float d = -0.5; //first order derivative = -0.5
128+ x = fabs(((double)(i - center) - (double)ph / phase_count) * factor);
129+ if (x < 1.0) y = 1 - 3 * x*x + 2 * x*x*x + d * ( -x*x + x*x*x);
130+ else y = d * (-4 + 8 * x - 5 * x*x + x*x*x);
131+ break;
132+ }
133+ case 1:
134+ w = 2.0 * x / (factor * tap_count) + M_PI;
135+ y *= 0.3635819 - 0.4891775 * cos( w) +
136+ 0.1365995 * cos(2 * w) -
137+ 0.0106411 * cos(3 * w);
138+ break;
139+ default:
140+ w = 2.0 * x / (factor * tap_count * M_PI);
141+ y *= bessel(type * sqrt(FFMAX(1 - w * w, 0)));
142+ break;
143+ }
144+
145+ tab[i] = y;
146+ norm += y;
147+ }
148+
149+ /* normalize so that an uniform color remains the same */
150+ for (i = 0; i < tap_count; i++) {
151+#ifdef CONFIG_RESAMPLE_FLT
152+ filter[ph * tap_count + i] = tab[i] / norm;
153+#else
154+ filter[ph * tap_count + i] = av_clip(lrintf(tab[i] * scale / norm),
155+ FELEM_MIN, FELEM_MAX);
156+#endif
157+ }
158+ }
159+
160+ av_free(tab);
161+ return 0;
162+}
163+
164+ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr)
165+{
166+ ResampleContext *c;
167+ int out_rate = avr->out_sample_rate;
168+ int in_rate = avr->in_sample_rate;
169+ double factor = FFMIN(out_rate * avr->cutoff / in_rate, 1.0);
170+ int phase_count = 1 << avr->phase_shift;
171+
172+ /* TODO: add support for s32 and float internal formats */
173+ if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P) {
174+ av_log(avr, AV_LOG_ERROR, "Unsupported internal format for "
175+ "resampling: %s\n",
176+ av_get_sample_fmt_name(avr->internal_sample_fmt));
177+ return NULL;
178+ }
179+ c = av_mallocz(sizeof(*c));
180+ if (!c)
181+ return NULL;
182+
183+ c->avr = avr;
184+ c->phase_shift = avr->phase_shift;
185+ c->phase_mask = phase_count - 1;
186+ c->linear = avr->linear_interp;
187+ c->factor = factor;
188+ c->filter_length = FFMAX((int)ceil(avr->filter_size / factor), 1);
189+
190+ c->filter_bank = av_mallocz(c->filter_length * (phase_count + 1) * sizeof(FELEM));
191+ if (!c->filter_bank)
192+ goto error;
193+
194+ if (build_filter(c->filter_bank, factor, c->filter_length, phase_count,
195+ 1 << FILTER_SHIFT, WINDOW_TYPE) < 0)
196+ goto error;
197+
198+ memcpy(&c->filter_bank[c->filter_length * phase_count + 1],
199+ c->filter_bank, (c->filter_length - 1) * sizeof(FELEM));
200+ c->filter_bank[c->filter_length * phase_count] = c->filter_bank[c->filter_length - 1];
201+
202+ c->compensation_distance = 0;
203+ if (!av_reduce(&c->src_incr, &c->dst_incr, out_rate,
204+ in_rate * (int64_t)phase_count, INT32_MAX / 2))
205+ goto error;
206+ c->ideal_dst_incr = c->dst_incr;
207+
208+ c->index = -phase_count * ((c->filter_length - 1) / 2);
209+ c->frac = 0;
210+
211+ /* allocate internal buffer */
212+ c->buffer = ff_audio_data_alloc(avr->resample_channels, 0,
213+ avr->internal_sample_fmt,
214+ "resample buffer");
215+ if (!c->buffer)
216+ goto error;
217+
218+ av_log(avr, AV_LOG_DEBUG, "resample: %s from %d Hz to %d Hz\n",
219+ av_get_sample_fmt_name(avr->internal_sample_fmt),
220+ avr->in_sample_rate, avr->out_sample_rate);
221+
222+ return c;
223+
224+error:
225+ ff_audio_data_free(&c->buffer);
226+ av_free(c->filter_bank);
227+ av_free(c);
228+ return NULL;
229+}
230+
231+void ff_audio_resample_free(ResampleContext **c)
232+{
233+ if (!*c)
234+ return;
235+ ff_audio_data_free(&(*c)->buffer);
236+ av_free((*c)->filter_bank);
237+ av_freep(c);
238+}
239+
240+int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta,
241+ int compensation_distance)
242+{
243+ ResampleContext *c;
244+ AudioData *fifo_buf = NULL;
245+ int ret = 0;
246+
247+ if (compensation_distance < 0)
248+ return AVERROR(EINVAL);
249+ if (!compensation_distance && sample_delta)
250+ return AVERROR(EINVAL);
251+
252+ /* if resampling was not enabled previously, re-initialize the
253+ AVAudioResampleContext and force resampling */
254+ if (!avr->resample_needed) {
255+ int fifo_samples;
256+ double matrix[AVRESAMPLE_MAX_CHANNELS * AVRESAMPLE_MAX_CHANNELS] = { 0 };
257+
258+ /* buffer any remaining samples in the output FIFO before closing */
259+ fifo_samples = av_audio_fifo_size(avr->out_fifo);
260+ if (fifo_samples > 0) {
261+ fifo_buf = ff_audio_data_alloc(avr->out_channels, fifo_samples,
262+ avr->out_sample_fmt, NULL);
263+ if (!fifo_buf)
264+ return AVERROR(EINVAL);
265+ ret = ff_audio_data_read_from_fifo(avr->out_fifo, fifo_buf,
266+ fifo_samples);
267+ if (ret < 0)
268+ goto reinit_fail;
269+ }
270+ /* save the channel mixing matrix */
271+ ret = avresample_get_matrix(avr, matrix, AVRESAMPLE_MAX_CHANNELS);
272+ if (ret < 0)
273+ goto reinit_fail;
274+
275+ /* close the AVAudioResampleContext */
276+ avresample_close(avr);
277+
278+ avr->force_resampling = 1;
279+
280+ /* restore the channel mixing matrix */
281+ ret = avresample_set_matrix(avr, matrix, AVRESAMPLE_MAX_CHANNELS);
282+ if (ret < 0)
283+ goto reinit_fail;
284+
285+ /* re-open the AVAudioResampleContext */
286+ ret = avresample_open(avr);
287+ if (ret < 0)
288+ goto reinit_fail;
289+
290+ /* restore buffered samples to the output FIFO */
291+ if (fifo_samples > 0) {
292+ ret = ff_audio_data_add_to_fifo(avr->out_fifo, fifo_buf, 0,
293+ fifo_samples);
294+ if (ret < 0)
295+ goto reinit_fail;
296+ ff_audio_data_free(&fifo_buf);
297+ }
298+ }
299+ c = avr->resample;
300+ c->compensation_distance = compensation_distance;
301+ if (compensation_distance) {
302+ c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr *
303+ (int64_t)sample_delta / compensation_distance;
304+ } else {
305+ c->dst_incr = c->ideal_dst_incr;
306+ }
307+ return 0;
308+
309+reinit_fail:
310+ ff_audio_data_free(&fifo_buf);
311+ return ret;
312+}
313+
314+static int resample(ResampleContext *c, int16_t *dst, const int16_t *src,
315+ int *consumed, int src_size, int dst_size, int update_ctx)
316+{
317+ int dst_index, i;
318+ int index = c->index;
319+ int frac = c->frac;
320+ int dst_incr_frac = c->dst_incr % c->src_incr;
321+ int dst_incr = c->dst_incr / c->src_incr;
322+ int compensation_distance = c->compensation_distance;
323+
324+ if (!dst != !src)
325+ return AVERROR(EINVAL);
326+
327+ if (compensation_distance == 0 && c->filter_length == 1 &&
328+ c->phase_shift == 0) {
329+ int64_t index2 = ((int64_t)index) << 32;
330+ int64_t incr = (1LL << 32) * c->dst_incr / c->src_incr;
331+ dst_size = FFMIN(dst_size,
332+ (src_size-1-index) * (int64_t)c->src_incr /
333+ c->dst_incr);
334+
335+ if (dst) {
336+ for(dst_index = 0; dst_index < dst_size; dst_index++) {
337+ dst[dst_index] = src[index2 >> 32];
338+ index2 += incr;
339+ }
340+ } else {
341+ dst_index = dst_size;
342+ }
343+ index += dst_index * dst_incr;
344+ index += (frac + dst_index * (int64_t)dst_incr_frac) / c->src_incr;
345+ frac = (frac + dst_index * (int64_t)dst_incr_frac) % c->src_incr;
346+ } else {
347+ for (dst_index = 0; dst_index < dst_size; dst_index++) {
348+ FELEM *filter = c->filter_bank +
349+ c->filter_length * (index & c->phase_mask);
350+ int sample_index = index >> c->phase_shift;
351+
352+ if (!dst && (sample_index + c->filter_length > src_size ||
353+ -sample_index >= src_size))
354+ break;
355+
356+ if (dst) {
357+ FELEM2 val = 0;
358+
359+ if (sample_index < 0) {
360+ for (i = 0; i < c->filter_length; i++)
361+ val += src[FFABS(sample_index + i) % src_size] *
362+ (FELEM2)filter[i];
363+ } else if (sample_index + c->filter_length > src_size) {
364+ break;
365+ } else if (c->linear) {
366+ FELEM2 v2 = 0;
367+ for (i = 0; i < c->filter_length; i++) {
368+ val += src[abs(sample_index + i)] * (FELEM2)filter[i];
369+ v2 += src[abs(sample_index + i)] * (FELEM2)filter[i + c->filter_length];
370+ }
371+ val += (v2 - val) * (FELEML)frac / c->src_incr;
372+ } else {
373+ for (i = 0; i < c->filter_length; i++)
374+ val += src[sample_index + i] * (FELEM2)filter[i];
375+ }
376+
377+#ifdef CONFIG_RESAMPLE_FLT
378+ dst[dst_index] = av_clip_int16(lrintf(val));
379+#else
380+ val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;
381+ dst[dst_index] = av_clip_int16(val);
382+#endif
383+ }
384+
385+ frac += dst_incr_frac;
386+ index += dst_incr;
387+ if (frac >= c->src_incr) {
388+ frac -= c->src_incr;
389+ index++;
390+ }
391+ if (dst_index + 1 == compensation_distance) {
392+ compensation_distance = 0;
393+ dst_incr_frac = c->ideal_dst_incr % c->src_incr;
394+ dst_incr = c->ideal_dst_incr / c->src_incr;
395+ }
396+ }
397+ }
398+ if (consumed)
399+ *consumed = FFMAX(index, 0) >> c->phase_shift;
400+
401+ if (update_ctx) {
402+ if (index >= 0)
403+ index &= c->phase_mask;
404+
405+ if (compensation_distance) {
406+ compensation_distance -= dst_index;
407+ if (compensation_distance <= 0)
408+ return AVERROR_BUG;
409+ }
410+ c->frac = frac;
411+ c->index = index;
412+ c->dst_incr = dst_incr_frac + c->src_incr*dst_incr;
413+ c->compensation_distance = compensation_distance;
414+ }
415+
416+ return dst_index;
417+}
418+
419+int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src,
420+ int *consumed)
421+{
422+ int ch, in_samples, in_leftover, out_samples = 0;
423+ int ret = AVERROR(EINVAL);
424+
425+ in_samples = src ? src->nb_samples : 0;
426+ in_leftover = c->buffer->nb_samples;
427+
428+ /* add input samples to the internal buffer */
429+ if (src) {
430+ ret = ff_audio_data_combine(c->buffer, in_leftover, src, 0, in_samples);
431+ if (ret < 0)
432+ return ret;
433+ } else if (!in_leftover) {
434+ /* no remaining samples to flush */
435+ return 0;
436+ } else {
437+ /* TODO: pad buffer to flush completely */
438+ }
439+
440+ /* calculate output size and reallocate output buffer if needed */
441+ /* TODO: try to calculate this without the dummy resample() run */
442+ if (!dst->read_only && dst->allow_realloc) {
443+ out_samples = resample(c, NULL, NULL, NULL, c->buffer->nb_samples,
444+ INT_MAX, 0);
445+ ret = ff_audio_data_realloc(dst, out_samples);
446+ if (ret < 0) {
447+ av_log(c->avr, AV_LOG_ERROR, "error reallocating output\n");
448+ return ret;
449+ }
450+ }
451+
452+ /* resample each channel plane */
453+ for (ch = 0; ch < c->buffer->channels; ch++) {
454+ out_samples = resample(c, (int16_t *)dst->data[ch],
455+ (const int16_t *)c->buffer->data[ch], consumed,
456+ c->buffer->nb_samples, dst->allocated_samples,
457+ ch + 1 == c->buffer->channels);
458+ }
459+ if (out_samples < 0) {
460+ av_log(c->avr, AV_LOG_ERROR, "error during resampling\n");
461+ return out_samples;
462+ }
463+
464+ /* drain consumed samples from the internal buffer */
465+ ff_audio_data_drain(c->buffer, *consumed);
466+
467+ av_dlog(c->avr, "resampled %d in + %d leftover to %d out + %d leftover\n",
468+ in_samples, in_leftover, out_samples, c->buffer->nb_samples);
469+
470+ dst->nb_samples = out_samples;
471+ return 0;
472+}
473+
474+int avresample_get_delay(AVAudioResampleContext *avr)
475+{
476+ if (!avr->resample_needed || !avr->resample)
477+ return 0;
478+
479+ return avr->resample->buffer->nb_samples;
480+}
libavresample/resample.h+70−0
@@ -0,0 +1,70 @@
1+/*
2+ * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
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_RESAMPLE_H
22+#define AVRESAMPLE_RESAMPLE_H
23+
24+#include "avresample.h"
25+#include "audio_data.h"
26+
27+typedef struct ResampleContext ResampleContext;
28+
29+/**
30+ * Allocate and initialize a ResampleContext.
31+ *
32+ * The parameters in the AVAudioResampleContext are used to initialize the
33+ * ResampleContext.
34+ *
35+ * @param avr AVAudioResampleContext
36+ * @return newly-allocated ResampleContext
37+ */
38+ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr);
39+
40+/**
41+ * Free a ResampleContext.
42+ *
43+ * @param c ResampleContext
44+ */
45+void ff_audio_resample_free(ResampleContext **c);
46+
47+/**
48+ * Resample audio data.
49+ *
50+ * Changes the sample rate.
51+ *
52+ * @par
53+ * All samples in the source data may not be consumed depending on the
54+ * resampling parameters and the size of the output buffer. The unconsumed
55+ * samples are automatically added to the start of the source in the next call.
56+ * If the destination data can be reallocated, that may be done in this function
57+ * in order to fit all available output. If it cannot be reallocated, fewer
58+ * input samples will be consumed in order to have the output fit in the
59+ * destination data buffers.
60+ *
61+ * @param c ResampleContext
62+ * @param dst destination audio data
63+ * @param src source audio data
64+ * @param consumed number of samples consumed from the source
65+ * @return number of samples written to the destination
66+ */
67+int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src,
68+ int *consumed);
69+
70+#endif /* AVRESAMPLE_RESAMPLE_H */
libavresample/utils.c+405−0
@@ -0,0 +1,405 @@
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 "libavutil/dict.h"
22+// #include "libavutil/error.h"
23+#include "libavutil/log.h"
24+#include "libavutil/mem.h"
25+#include "libavutil/opt.h"
26+
27+#include "avresample.h"
28+#include "audio_data.h"
29+#include "internal.h"
30+
31+int avresample_open(AVAudioResampleContext *avr)
32+{
33+ int ret;
34+
35+ /* set channel mixing parameters */
36+ avr->in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
37+ if (avr->in_channels <= 0 || avr->in_channels > AVRESAMPLE_MAX_CHANNELS) {
38+ av_log(avr, AV_LOG_ERROR, "Invalid input channel layout: %"PRIu64"\n",
39+ avr->in_channel_layout);
40+ return AVERROR(EINVAL);
41+ }
42+ avr->out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
43+ if (avr->out_channels <= 0 || avr->out_channels > AVRESAMPLE_MAX_CHANNELS) {
44+ av_log(avr, AV_LOG_ERROR, "Invalid output channel layout: %"PRIu64"\n",
45+ avr->out_channel_layout);
46+ return AVERROR(EINVAL);
47+ }
48+ avr->resample_channels = FFMIN(avr->in_channels, avr->out_channels);
49+ avr->downmix_needed = avr->in_channels > avr->out_channels;
50+ avr->upmix_needed = avr->out_channels > avr->in_channels ||
51+ avr->am->matrix ||
52+ (avr->out_channels == avr->in_channels &&
53+ avr->in_channel_layout != avr->out_channel_layout);
54+ avr->mixing_needed = avr->downmix_needed || avr->upmix_needed;
55+
56+ /* set resampling parameters */
57+ avr->resample_needed = avr->in_sample_rate != avr->out_sample_rate ||
58+ avr->force_resampling;
59+
60+ /* set sample format conversion parameters */
61+ /* override user-requested internal format to avoid unexpected failures
62+ TODO: support more internal formats */
63+ if (avr->resample_needed && avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P) {
64+ av_log(avr, AV_LOG_WARNING, "Using s16p as internal sample format\n");
65+ avr->internal_sample_fmt = AV_SAMPLE_FMT_S16P;
66+ } else if (avr->mixing_needed &&
67+ avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P &&
68+ avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP) {
69+ av_log(avr, AV_LOG_WARNING, "Using fltp as internal sample format\n");
70+ avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP;
71+ }
72+ if (avr->in_channels == 1)
73+ avr->in_sample_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt);
74+ if (avr->out_channels == 1)
75+ avr->out_sample_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);
76+ avr->in_convert_needed = (avr->resample_needed || avr->mixing_needed) &&
77+ avr->in_sample_fmt != avr->internal_sample_fmt;
78+ if (avr->resample_needed || avr->mixing_needed)
79+ avr->out_convert_needed = avr->internal_sample_fmt != avr->out_sample_fmt;
80+ else
81+ avr->out_convert_needed = avr->in_sample_fmt != avr->out_sample_fmt;
82+
83+ /* allocate buffers */
84+ if (avr->mixing_needed || avr->in_convert_needed) {
85+ avr->in_buffer = ff_audio_data_alloc(FFMAX(avr->in_channels, avr->out_channels),
86+ 0, avr->internal_sample_fmt,
87+ "in_buffer");
88+ if (!avr->in_buffer) {
89+ ret = AVERROR(EINVAL);
90+ goto error;
91+ }
92+ }
93+ if (avr->resample_needed) {
94+ avr->resample_out_buffer = ff_audio_data_alloc(avr->out_channels,
95+ 0, avr->internal_sample_fmt,
96+ "resample_out_buffer");
97+ if (!avr->resample_out_buffer) {
98+ ret = AVERROR(EINVAL);
99+ goto error;
100+ }
101+ }
102+ if (avr->out_convert_needed) {
103+ avr->out_buffer = ff_audio_data_alloc(avr->out_channels, 0,
104+ avr->out_sample_fmt, "out_buffer");
105+ if (!avr->out_buffer) {
106+ ret = AVERROR(EINVAL);
107+ goto error;
108+ }
109+ }
110+ avr->out_fifo = av_audio_fifo_alloc(avr->out_sample_fmt, avr->out_channels,
111+ 1024);
112+ if (!avr->out_fifo) {
113+ ret = AVERROR(ENOMEM);
114+ goto error;
115+ }
116+
117+ /* setup contexts */
118+ if (avr->in_convert_needed) {
119+ avr->ac_in = ff_audio_convert_alloc(avr, avr->internal_sample_fmt,
120+ avr->in_sample_fmt, avr->in_channels);
121+ if (!avr->ac_in) {
122+ ret = AVERROR(ENOMEM);
123+ goto error;
124+ }
125+ }
126+ if (avr->out_convert_needed) {
127+ enum AVSampleFormat src_fmt;
128+ if (avr->in_convert_needed)
129+ src_fmt = avr->internal_sample_fmt;
130+ else
131+ src_fmt = avr->in_sample_fmt;
132+ avr->ac_out = ff_audio_convert_alloc(avr, avr->out_sample_fmt, src_fmt,
133+ avr->out_channels);
134+ if (!avr->ac_out) {
135+ ret = AVERROR(ENOMEM);
136+ goto error;
137+ }
138+ }
139+ if (avr->resample_needed) {
140+ avr->resample = ff_audio_resample_init(avr);
141+ if (!avr->resample) {
142+ ret = AVERROR(ENOMEM);
143+ goto error;
144+ }
145+ }
146+ if (avr->mixing_needed) {
147+ ret = ff_audio_mix_init(avr);
148+ if (ret < 0)
149+ goto error;
150+ }
151+
152+ return 0;
153+
154+error:
155+ avresample_close(avr);
156+ return ret;
157+}
158+
159+void avresample_close(AVAudioResampleContext *avr)
160+{
161+ ff_audio_data_free(&avr->in_buffer);
162+ ff_audio_data_free(&avr->resample_out_buffer);
163+ ff_audio_data_free(&avr->out_buffer);
164+ av_audio_fifo_free(avr->out_fifo);
165+ avr->out_fifo = NULL;
166+ av_freep(&avr->ac_in);
167+ av_freep(&avr->ac_out);
168+ ff_audio_resample_free(&avr->resample);
169+ ff_audio_mix_close(avr->am);
170+ return;
171+}
172+
173+void avresample_free(AVAudioResampleContext **avr)
174+{
175+ if (!*avr)
176+ return;
177+ avresample_close(*avr);
178+ av_freep(&(*avr)->am);
179+ av_opt_free(*avr);
180+ av_freep(avr);
181+}
182+
183+static int handle_buffered_output(AVAudioResampleContext *avr,
184+ AudioData *output, AudioData *converted)
185+{
186+ int ret;
187+
188+ if (!output || av_audio_fifo_size(avr->out_fifo) > 0 ||
189+ (converted && output->allocated_samples < converted->nb_samples)) {
190+ if (converted) {
191+ /* if there are any samples in the output FIFO or if the
192+ user-supplied output buffer is not large enough for all samples,
193+ we add to the output FIFO */
194+ av_dlog(avr, "[FIFO] add %s to out_fifo\n", converted->name);
195+ ret = ff_audio_data_add_to_fifo(avr->out_fifo, converted, 0,
196+ converted->nb_samples);
197+ if (ret < 0)
198+ return ret;
199+ }
200+
201+ /* if the user specified an output buffer, read samples from the output
202+ FIFO to the user output */
203+ if (output && output->allocated_samples > 0) {
204+ av_dlog(avr, "[FIFO] read from out_fifo to output\n");
205+ av_dlog(avr, "[end conversion]\n");
206+ return ff_audio_data_read_from_fifo(avr->out_fifo, output,
207+ output->allocated_samples);
208+ }
209+ } else if (converted) {
210+ /* copy directly to output if it is large enough or there is not any
211+ data in the output FIFO */
212+ av_dlog(avr, "[copy] %s to output\n", converted->name);
213+ output->nb_samples = 0;
214+ ret = ff_audio_data_copy(output, converted);
215+ if (ret < 0)
216+ return ret;
217+ av_dlog(avr, "[end conversion]\n");
218+ return output->nb_samples;
219+ }
220+ av_dlog(avr, "[end conversion]\n");
221+ return 0;
222+}
223+
224+int avresample_convert(AVAudioResampleContext *avr, void **output,
225+ int out_plane_size, int out_samples, void **input,
226+ int in_plane_size, int in_samples)
227+{
228+ AudioData input_buffer;
229+ AudioData output_buffer;
230+ AudioData *current_buffer;
231+ int ret;
232+
233+ /* reset internal buffers */
234+ if (avr->in_buffer) {
235+ avr->in_buffer->nb_samples = 0;
236+ ff_audio_data_set_channels(avr->in_buffer,
237+ avr->in_buffer->allocated_channels);
238+ }
239+ if (avr->resample_out_buffer) {
240+ avr->resample_out_buffer->nb_samples = 0;
241+ ff_audio_data_set_channels(avr->resample_out_buffer,
242+ avr->resample_out_buffer->allocated_channels);
243+ }
244+ if (avr->out_buffer) {
245+ avr->out_buffer->nb_samples = 0;
246+ ff_audio_data_set_channels(avr->out_buffer,
247+ avr->out_buffer->allocated_channels);
248+ }
249+
250+ av_dlog(avr, "[start conversion]\n");
251+
252+ /* initialize output_buffer with output data */
253+ if (output) {
254+ ret = ff_audio_data_init(&output_buffer, output, out_plane_size,
255+ avr->out_channels, out_samples,
256+ avr->out_sample_fmt, 0, "output");
257+ if (ret < 0)
258+ return ret;
259+ output_buffer.nb_samples = 0;
260+ }
261+
262+ if (input) {
263+ /* initialize input_buffer with input data */
264+ ret = ff_audio_data_init(&input_buffer, input, in_plane_size,
265+ avr->in_channels, in_samples,
266+ avr->in_sample_fmt, 1, "input");
267+ if (ret < 0)
268+ return ret;
269+ current_buffer = &input_buffer;
270+
271+ if (avr->upmix_needed && !avr->in_convert_needed && !avr->resample_needed &&
272+ !avr->out_convert_needed && output && out_samples >= in_samples) {
273+ /* in some rare cases we can copy input to output and upmix
274+ directly in the output buffer */
275+ av_dlog(avr, "[copy] %s to output\n", current_buffer->name);
276+ ret = ff_audio_data_copy(&output_buffer, current_buffer);
277+ if (ret < 0)
278+ return ret;
279+ current_buffer = &output_buffer;
280+ } else if (avr->mixing_needed || avr->in_convert_needed) {
281+ /* if needed, copy or convert input to in_buffer, and downmix if
282+ applicable */
283+ if (avr->in_convert_needed) {
284+ ret = ff_audio_data_realloc(avr->in_buffer,
285+ current_buffer->nb_samples);
286+ if (ret < 0)
287+ return ret;
288+ av_dlog(avr, "[convert] %s to in_buffer\n", current_buffer->name);
289+ ret = ff_audio_convert(avr->ac_in, avr->in_buffer, current_buffer,
290+ current_buffer->nb_samples);
291+ if (ret < 0)
292+ return ret;
293+ } else {
294+ av_dlog(avr, "[copy] %s to in_buffer\n", current_buffer->name);
295+ ret = ff_audio_data_copy(avr->in_buffer, current_buffer);
296+ if (ret < 0)
297+ return ret;
298+ }
299+ ff_audio_data_set_channels(avr->in_buffer, avr->in_channels);
300+ if (avr->downmix_needed) {
301+ av_dlog(avr, "[downmix] in_buffer\n");
302+ ret = ff_audio_mix(avr->am, avr->in_buffer);
303+ if (ret < 0)
304+ return ret;
305+ }
306+ current_buffer = avr->in_buffer;
307+ }
308+ } else {
309+ /* flush resampling buffer and/or output FIFO if input is NULL */
310+ if (!avr->resample_needed)
311+ return handle_buffered_output(avr, output ? &output_buffer : NULL,
312+ NULL);
313+ current_buffer = NULL;
314+ }
315+
316+ if (avr->resample_needed) {
317+ AudioData *resample_out;
318+ int consumed = 0;
319+
320+ if (!avr->out_convert_needed && output && out_samples > 0)
321+ resample_out = &output_buffer;
322+ else
323+ resample_out = avr->resample_out_buffer;
324+ av_dlog(avr, "[resample] %s to %s\n", current_buffer->name,
325+ resample_out->name);
326+ ret = ff_audio_resample(avr->resample, resample_out,
327+ current_buffer, &consumed);
328+ if (ret < 0)
329+ return ret;
330+
331+ /* if resampling did not produce any samples, just return 0 */
332+ if (resample_out->nb_samples == 0) {
333+ av_dlog(avr, "[end conversion]\n");
334+ return 0;
335+ }
336+
337+ current_buffer = resample_out;
338+ }
339+
340+ if (avr->upmix_needed) {
341+ av_dlog(avr, "[upmix] %s\n", current_buffer->name);
342+ ret = ff_audio_mix(avr->am, current_buffer);
343+ if (ret < 0)
344+ return ret;
345+ }
346+
347+ /* if we resampled or upmixed directly to output, return here */
348+ if (current_buffer == &output_buffer) {
349+ av_dlog(avr, "[end conversion]\n");
350+ return current_buffer->nb_samples;
351+ }
352+
353+ if (avr->out_convert_needed) {
354+ if (output && out_samples >= current_buffer->nb_samples) {
355+ /* convert directly to output */
356+ av_dlog(avr, "[convert] %s to output\n", current_buffer->name);
357+ ret = ff_audio_convert(avr->ac_out, &output_buffer, current_buffer,
358+ current_buffer->nb_samples);
359+ if (ret < 0)
360+ return ret;
361+
362+ av_dlog(avr, "[end conversion]\n");
363+ return output_buffer.nb_samples;
364+ } else {
365+ ret = ff_audio_data_realloc(avr->out_buffer,
366+ current_buffer->nb_samples);
367+ if (ret < 0)
368+ return ret;
369+ av_dlog(avr, "[convert] %s to out_buffer\n", current_buffer->name);
370+ ret = ff_audio_convert(avr->ac_out, avr->out_buffer,
371+ current_buffer, current_buffer->nb_samples);
372+ if (ret < 0)
373+ return ret;
374+ current_buffer = avr->out_buffer;
375+ }
376+ }
377+
378+ return handle_buffered_output(avr, &output_buffer, current_buffer);
379+}
380+
381+int avresample_available(AVAudioResampleContext *avr)
382+{
383+ return av_audio_fifo_size(avr->out_fifo);
384+}
385+
386+int avresample_read(AVAudioResampleContext *avr, void **output, int nb_samples)
387+{
388+ return av_audio_fifo_read(avr->out_fifo, output, nb_samples);
389+}
390+
391+unsigned avresample_version(void)
392+{
393+ return LIBAVRESAMPLE_VERSION_INT;
394+}
395+
396+const char *avresample_license(void)
397+{
398+#define LICENSE_PREFIX "libavresample license: "
399+ return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
400+}
401+
402+const char *avresample_configuration(void)
403+{
404+ return FFMPEG_CONFIGURATION;
405+}
libavresample/version.h+41−0
@@ -0,0 +1,41 @@
1+/*
2+ * This file is part of Libav.
3+ *
4+ * Libav is free software; you can redistribute it and/or
5+ * modify it under the terms of the GNU Lesser General Public
6+ * License as published by the Free Software Foundation; either
7+ * version 2.1 of the License, or (at your option) any later version.
8+ *
9+ * Libav is distributed in the hope that it will be useful,
10+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+ * Lesser General Public License for more details.
13+ *
14+ * You should have received a copy of the GNU Lesser General Public
15+ * License along with Libav; if not, write to the Free Software
16+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17+ */
18+
19+#ifndef AVRESAMPLE_VERSION_H
20+#define AVRESAMPLE_VERSION_H
21+
22+#define LIBAVRESAMPLE_VERSION_MAJOR 0
23+#define LIBAVRESAMPLE_VERSION_MINOR 0
24+#define LIBAVRESAMPLE_VERSION_MICRO 0
25+
26+#define LIBAVRESAMPLE_VERSION_INT AV_VERSION_INT(LIBAVRESAMPLE_VERSION_MAJOR, \
27+ LIBAVRESAMPLE_VERSION_MINOR, \
28+ LIBAVRESAMPLE_VERSION_MICRO)
29+#define LIBAVRESAMPLE_VERSION AV_VERSION(LIBAVRESAMPLE_VERSION_MAJOR, \
30+ LIBAVRESAMPLE_VERSION_MINOR, \
31+ LIBAVRESAMPLE_VERSION_MICRO)
32+#define LIBAVRESAMPLE_BUILD LIBAVRESAMPLE_VERSION_INT
33+
34+#define LIBAVRESAMPLE_IDENT "Lavr" AV_STRINGIFY(LIBAVRESAMPLE_VERSION)
35+
36+/**
37+ * These FF_API_* defines are not part of public API.
38+ * They may change, break or disappear at any time.
39+ */
40+
41+#endif /* AVRESAMPLE_VERSION_H */
libavresample/x86/Makefile+5−0
@@ -0,0 +1,5 @@
1+OBJS += x86/audio_convert_init.o \
2+ x86/audio_mix_init.o
3+
4+YASM-OBJS += x86/audio_convert.o \
5+ x86/audio_mix.o
libavresample/x86/audio_convert.asm+104−0
@@ -0,0 +1,104 @@
1+;******************************************************************************
2+;* x86 optimized Format Conversion Utils
3+;* Copyright (c) 2008 Loren Merritt
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 "x86inc.asm"
23+%include "x86util.asm"
24+
25+SECTION_TEXT
26+
27+;-----------------------------------------------------------------------------
28+; void ff_conv_fltp_to_flt_6ch(float *dst, float *const *src, int len,
29+; int channels);
30+;-----------------------------------------------------------------------------
31+
32+%macro CONV_FLTP_TO_FLT_6CH 0
33+cglobal conv_fltp_to_flt_6ch, 2,8,7, dst, src, src1, src2, src3, src4, src5, len
34+%if ARCH_X86_64
35+ mov lend, r2d
36+%else
37+ %define lend dword r2m
38+%endif
39+ mov src1q, [srcq+1*gprsize]
40+ mov src2q, [srcq+2*gprsize]
41+ mov src3q, [srcq+3*gprsize]
42+ mov src4q, [srcq+4*gprsize]
43+ mov src5q, [srcq+5*gprsize]
44+ mov srcq, [srcq]
45+ sub src1q, srcq
46+ sub src2q, srcq
47+ sub src3q, srcq
48+ sub src4q, srcq
49+ sub src5q, srcq
50+.loop:
51+ mova m0, [srcq ]
52+ mova m1, [srcq+src1q]
53+ mova m2, [srcq+src2q]
54+ mova m3, [srcq+src3q]
55+ mova m4, [srcq+src4q]
56+ mova m5, [srcq+src5q]
57+%if cpuflag(sse)
58+ SBUTTERFLYPS 0, 1, 6
59+ SBUTTERFLYPS 2, 3, 6
60+ SBUTTERFLYPS 4, 5, 6
61+
62+ movaps m6, m4
63+ shufps m4, m0, q3210
64+ movlhps m0, m2
65+ movhlps m6, m2
66+ movaps [dstq ], m0
67+ movaps [dstq+16], m4
68+ movaps [dstq+32], m6
69+
70+ movaps m6, m5
71+ shufps m5, m1, q3210
72+ movlhps m1, m3
73+ movhlps m6, m3
74+ movaps [dstq+48], m1
75+ movaps [dstq+64], m5
76+ movaps [dstq+80], m6
77+%else ; mmx
78+ SBUTTERFLY dq, 0, 1, 6
79+ SBUTTERFLY dq, 2, 3, 6
80+ SBUTTERFLY dq, 4, 5, 6
81+
82+ movq [dstq ], m0
83+ movq [dstq+ 8], m2
84+ movq [dstq+16], m4
85+ movq [dstq+24], m1
86+ movq [dstq+32], m3
87+ movq [dstq+40], m5
88+%endif
89+ add srcq, mmsize
90+ add dstq, mmsize*6
91+ sub lend, mmsize/4
92+ jg .loop
93+%if mmsize == 8
94+ emms
95+ RET
96+%else
97+ REP_RET
98+%endif
99+%endmacro
100+
101+INIT_MMX mmx
102+CONV_FLTP_TO_FLT_6CH
103+INIT_XMM sse
104+CONV_FLTP_TO_FLT_6CH
libavresample/x86/audio_convert_init.c+42−0
@@ -0,0 +1,42 @@
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 "config.h"
22+#include "libavutil/cpu.h"
23+#include "libavresample/audio_convert.h"
24+
25+extern void ff_conv_fltp_to_flt_6ch_mmx(float *dst, float *const *src, int len);
26+extern void ff_conv_fltp_to_flt_6ch_sse(float *dst, float *const *src, int len);
27+
28+av_cold void ff_audio_convert_init_x86(AudioConvert *ac)
29+{
30+#if HAVE_YASM
31+ int mm_flags = av_get_cpu_flags();
32+
33+ if (mm_flags & AV_CPU_FLAG_MMX && HAVE_MMX) {
34+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
35+ 6, 1, 4, "MMX", ff_conv_fltp_to_flt_6ch_mmx);
36+ }
37+ if (mm_flags & AV_CPU_FLAG_SSE && HAVE_SSE) {
38+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
39+ 6, 16, 4, "SSE", ff_conv_fltp_to_flt_6ch_sse);
40+ }
41+#endif
42+}
libavresample/x86/audio_mix.asm+64−0
@@ -0,0 +1,64 @@
1+;******************************************************************************
2+;* x86 optimized channel mixing
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 "x86inc.asm"
23+%include "x86util.asm"
24+
25+SECTION_TEXT
26+
27+;-----------------------------------------------------------------------------
28+; void ff_mix_2_to_1_fltp_flt(float **src, float **matrix, int len,
29+; int out_ch, int in_ch);
30+;-----------------------------------------------------------------------------
31+
32+%macro MIX_2_TO_1_FLTP_FLT 0
33+cglobal mix_2_to_1_fltp_flt, 3,4,6, src, matrix, len, src1
34+ mov src1q, [srcq+gprsize]
35+ mov srcq, [srcq ]
36+ sub src1q, srcq
37+ mov matrixq, [matrixq ]
38+ VBROADCASTSS m4, [matrixq ]
39+ VBROADCASTSS m5, [matrixq+4]
40+ ALIGN 16
41+.loop:
42+ mulps m0, m4, [srcq ]
43+ mulps m1, m5, [srcq+src1q ]
44+ mulps m2, m4, [srcq+ mmsize]
45+ mulps m3, m5, [srcq+src1q+mmsize]
46+ addps m0, m0, m1
47+ addps m2, m2, m3
48+ mova [srcq ], m0
49+ mova [srcq+mmsize], m2
50+ add srcq, mmsize*2
51+ sub lend, mmsize*2/4
52+ jg .loop
53+%if mmsize == 32
54+ vzeroupper
55+ RET
56+%else
57+ REP_RET
58+%endif
59+%endmacro
60+
61+INIT_XMM sse
62+MIX_2_TO_1_FLTP_FLT
63+INIT_YMM avx
64+MIX_2_TO_1_FLTP_FLT
libavresample/x86/audio_mix_init.c+44−0
@@ -0,0 +1,44 @@
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 "config.h"
22+#include "libavutil/cpu.h"
23+#include "libavresample/audio_mix.h"
24+
25+extern void ff_mix_2_to_1_fltp_flt_sse(float **src, float **matrix, int len,
26+ int out_ch, int in_ch);
27+extern void ff_mix_2_to_1_fltp_flt_avx(float **src, float **matrix, int len,
28+ int out_ch, int in_ch);
29+
30+av_cold void ff_audio_mix_init_x86(AudioMix *am)
31+{
32+#if HAVE_YASM
33+ int mm_flags = av_get_cpu_flags();
34+
35+ if (mm_flags & AV_CPU_FLAG_SSE && HAVE_SSE) {
36+ ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
37+ 2, 1, 16, 8, "SSE", ff_mix_2_to_1_fltp_flt_sse);
38+ }
39+ if (mm_flags & AV_CPU_FLAG_AVX && HAVE_AVX) {
40+ ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
41+ 2, 1, 32, 16, "AVX", ff_mix_2_to_1_fltp_flt_avx);
42+ }
43+#endif
44+}
libavutil/x86/x86util.asm+9−0
@@ -585,3 +585,12 @@ · 584 unmodified lines
585585 pminsd %1, %3
586586 pmaxsd %1, %2
587587 %endmacro
588+
589+%macro VBROADCASTSS 2 ; dst xmm/ymm, src m32
590+%if cpuflag(avx)
591+ vbroadcastss %1, %2
592+%else ; sse
593+ movss %1, %2
594+ shufps %1, %1, 0
595+%endif
596+%endmacro
tests/fate/aac.mak+2−2
@@ -55,8 +55,8 @@ fate-aac-ap05_48: CMD = pcm -i $(SAMPLES)/aac/ap05_48.mp4 · 54 unmodified lines
5555 fate-aac-ap05_48: REF = $(SAMPLES)/aac/ap05_48.s16
5656
5757 FATE_AAC += fate-aac-latm_stereo_to_51
58−fate-aac-latm_stereo_to_51: CMD = pcm -i $(SAMPLES)/aac/latm_stereo_to_51.ts -ac 6
59−fate-aac-latm_stereo_to_51: REF = $(SAMPLES)/aac/latm_stereo_to_51.s16
58+fate-aac-latm_stereo_to_51: CMD = pcm -i $(SAMPLES)/aac/latm_stereo_to_51.ts -channel_layout 5.1
59+fate-aac-latm_stereo_to_51: REF = $(SAMPLES)/aac/latm_stereo_to_51_ref.s16
6060
6161 fate-aac-ct%: CMD = pcm -i $(SAMPLES)/aac/CT_DecoderCheck/$(@:fate-aac-ct-%=%)
6262 fate-aac-ct%: REF = $(SAMPLES)/aac/CT_DecoderCheck/aacPlusv2.wav
tests/lavf-regression.sh+1−1
@@ -118,7 +118,7 @@ fi · 117 unmodified lines
118118 if [ -n "$do_dv_fmt" ] ; then
119119 do_lavf_timecode_nodrop dv "-ar 48000 -r 25 -s pal -ac 2"
120120 do_lavf_timecode_drop dv "-ar 48000 -pix_fmt yuv411p -s ntsc -ac 2"
121−do_lavf dv "-ar 48000" "-r 25 -s pal -ac 2"
121+do_lavf dv "-ar 48000 -channel_layout stereo" "-r 25 -s pal"
122122 fi
123123
124124 if [ -n "$do_gxf" ] ; then
tests/ref/lavf/dv_fmt+2−2
@@ -4,6 +4,6 @@ · 3 unmodified lines
44 cc33ae4f9e6828914dea0f09d1241b7e *./tests/data/lavf/lavf.dv
55 3480000 ./tests/data/lavf/lavf.dv
66 ./tests/data/lavf/lavf.dv CRC=0x8d5e9e8f
7−b36c83cd0ba0ebe719f09f885c4bbcd3 *./tests/data/lavf/lavf.dv
7+87d3b20f656235671383a7eaa2f66330 *./tests/data/lavf/lavf.dv
88 3600000 ./tests/data/lavf/lavf.dv
9−./tests/data/lavf/lavf.dv CRC=0x2bc2ae3a
9+./tests/data/lavf/lavf.dv CRC=0x0e868a82

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t