Browse code

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

Merged-by: Michael Niedermayer <michaelni@gmx.at>

Michael Niedermayer authored on 2012/04/26 05:01:59
Showing 33 changed files
... ...
@@ -26,6 +26,7 @@ version next:
26 26
 - drawtext video filter: fontconfig support
27 27
 - ffmpeg -benchmark_all option
28 28
 - super2xsai filter ported from libmpcodecs
29
+- add libavresample audio conversion library for compatibility
29 30
 
30 31
 
31 32
 version 0.10:
... ...
@@ -31,6 +31,7 @@ ALLMANPAGES = $(BASENAMES:%=%.1)
31 31
 FFLIBS-$(CONFIG_AVDEVICE) += avdevice
32 32
 FFLIBS-$(CONFIG_AVFILTER) += avfilter
33 33
 FFLIBS-$(CONFIG_AVFORMAT) += avformat
34
+FFLIBS-$(CONFIG_AVRESAMPLE) += avresample
34 35
 FFLIBS-$(CONFIG_AVCODEC)  += avcodec
35 36
 FFLIBS-$(CONFIG_POSTPROC) += postproc
36 37
 FFLIBS-$(CONFIG_SWRESAMPLE)+= swresample
... ...
@@ -32,6 +32,7 @@
32 32
 #include "libavformat/avformat.h"
33 33
 #include "libavfilter/avfilter.h"
34 34
 #include "libavdevice/avdevice.h"
35
+#include "libavresample/avresample.h"
35 36
 #include "libswscale/swscale.h"
36 37
 #include "libswresample/swresample.h"
37 38
 #if CONFIG_POSTPROC
... ...
@@ -633,7 +634,8 @@ static int warned_cfg = 0;
633 633
         const char *indent = flags & INDENT? "  " : "";                 \
634 634
         if (flags & SHOW_VERSION) {                                     \
635 635
             unsigned int version = libname##_version();                 \
636
-            av_log(NULL, level, "%slib%-11s %2d.%3d.%3d / %2d.%3d.%3d\n",\
636
+            av_log(NULL, level,                                         \
637
+                   "%slib%-11s %2d.%3d.%3d / %2d.%3d.%3d\n",            \
637 638
                    indent, #libname,                                    \
638 639
                    LIB##LIBNAME##_VERSION_MAJOR,                        \
639 640
                    LIB##LIBNAME##_VERSION_MINOR,                        \
... ...
@@ -662,6 +664,7 @@ static void print_all_libs_info(int flags, int level)
662 662
     PRINT_LIB_INFO(avformat, AVFORMAT, flags, level);
663 663
     PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level);
664 664
     PRINT_LIB_INFO(avfilter, AVFILTER, flags, level);
665
+//    PRINT_LIB_INFO(avresample, AVRESAMPLE, flags, level);
665 666
     PRINT_LIB_INFO(swscale,  SWSCALE,  flags, level);
666 667
     PRINT_LIB_INFO(swresample,SWRESAMPLE,  flags, level);
667 668
 #if CONFIG_POSTPROC
... ...
@@ -20,7 +20,7 @@ $(foreach VAR,$(SILENT),$(eval override $(VAR) = @$($(VAR))))
20 20
 $(eval INSTALL = @$(call ECHO,INSTALL,$$(^:$(SRC_DIR)/%=%)); $(INSTALL))
21 21
 endif
22 22
 
23
-ALLFFLIBS = avcodec avdevice avfilter avformat avutil postproc swscale swresample
23
+ALLFFLIBS = avcodec avdevice avfilter avformat avresample avutil postproc swscale swresample
24 24
 
25 25
 # NASM requires -I path terminated with /
26 26
 IFLAGS     := -I. -I$(SRC_PATH)/
... ...
@@ -112,6 +112,7 @@ Component options:
112 112
   --disable-swscale        disable libswscale build
113 113
   --disable-postproc       disable libpostproc build
114 114
   --disable-avfilter       disable video filter support [no]
115
+  --disable-avresample     disable libavresample build [no]
115 116
   --disable-pthreads       disable pthreads [auto]
116 117
   --disable-w32threads     disable Win32 threads [auto]
117 118
   --disable-os2threads     disable OS/2 threads [auto]
... ...
@@ -1013,6 +1014,7 @@ CONFIG_LIST="
1013 1013
     avdevice
1014 1014
     avfilter
1015 1015
     avformat
1016
+    avresample
1016 1017
     avisynth
1017 1018
     bzlib
1018 1019
     crystalhd
... ...
@@ -1870,6 +1872,7 @@ enable avcodec
1870 1870
 enable avdevice
1871 1871
 enable avfilter
1872 1872
 enable avformat
1873
+enable avresample
1873 1874
 enable avutil
1874 1875
 enable postproc
1875 1876
 enable stripping
... ...
@@ -3724,6 +3727,7 @@ get_version LIBAVCODEC  libavcodec/version.h
3724 3724
 get_version LIBAVDEVICE libavdevice/avdevice.h
3725 3725
 get_version LIBAVFILTER libavfilter/version.h
3726 3726
 get_version LIBAVFORMAT libavformat/version.h
3727
+get_version LIBAVRESAMPLE libavresample/version.h
3727 3728
 get_version LIBAVUTIL   libavutil/avutil.h
3728 3729
 get_version LIBPOSTPROC libpostproc/postprocess.h
3729 3730
 get_version LIBSWRESAMPLE libswresample/swresample.h
... ...
@@ -3869,5 +3873,6 @@ pkgconfig_generate libavformat "FFmpeg container format library" "$LIBAVFORMAT_V
3869 3869
 pkgconfig_generate libavdevice "FFmpeg device handling library" "$LIBAVDEVICE_VERSION" "$extralibs" "$libavdevice_pc_deps"
3870 3870
 pkgconfig_generate libavfilter "FFmpeg video filtering library" "$LIBAVFILTER_VERSION" "$extralibs" "$libavfilter_pc_deps"
3871 3871
 pkgconfig_generate libpostproc "FFmpeg postprocessing library" "$LIBPOSTPROC_VERSION" "" "libavutil = $LIBAVUTIL_VERSION"
3872
+pkgconfig_generate libavresample "Libav audio resampling library" "$LIBAVRESAMPLE_VERSION" "$extralibs"
3872 3873
 pkgconfig_generate libswscale "FFmpeg image rescaling library" "$LIBSWSCALE_VERSION" "$LIBM" "libavutil = $LIBAVUTIL_VERSION"
3873 3874
 pkgconfig_generate libswresample "FFmpeg audio rescaling library" "$LIBSWRESAMPLE_VERSION" "$LIBM" "libavutil = $LIBAVUTIL_VERSION"
... ...
@@ -6,6 +6,7 @@ libavcodec:  2012-01-27
6 6
 libavdevice: 2011-04-18
7 7
 libavfilter: 2011-04-18
8 8
 libavformat: 2012-01-27
9
+libavresample: 2012-xx-xx
9 10
 libpostproc: 2011-04-18
10 11
 libswscale:  2011-06-20
11 12
 libavutil:   2011-04-18
... ...
@@ -22,6 +23,9 @@ API changes, most recent first:
22 22
 2012-03-26 - a67d9cf - lavfi 2.66.100
23 23
   Add avfilter_fill_frame_from_{audio_,}buffer_ref() functions.
24 24
 
25
+2012-xx-xx - xxxxxxx - lavr 0.0.0
26
+  Add libavresample audio conversion library
27
+
25 28
 2012-xx-xx - xxxxxxx - lavu 51.28.0 - audio_fifo.h
26 29
   Add audio FIFO functions:
27 30
     av_audio_fifo_free()
... ...
@@ -36,7 +36,6 @@
36 36
 #include "libavdevice/avdevice.h"
37 37
 #include "libswscale/swscale.h"
38 38
 #include "libavutil/opt.h"
39
-#include "libavcodec/audioconvert.h"
40 39
 #include "libavutil/audioconvert.h"
41 40
 #include "libavutil/parseutils.h"
42 41
 #include "libavutil/samplefmt.h"
... ...
@@ -300,6 +299,7 @@ typedef struct OutputStream {
300 300
     int audio_channels_mapped;           ///< number of channels in audio_channels_map
301 301
     int resample_sample_fmt;
302 302
     int resample_channels;
303
+    uint64_t resample_channel_layout;
303 304
     int resample_sample_rate;
304 305
     float rematrix_volume;
305 306
     AVFifoBuffer *fifo;     /* for compression: one audio fifo per codec */
... ...
@@ -1525,7 +1525,7 @@ static int encode_audio_frame(AVFormatContext *s, OutputStream *ost,
1525 1525
 }
1526 1526
 
1527 1527
 static int alloc_audio_output_buf(AVCodecContext *dec, AVCodecContext *enc,
1528
-                                  int nb_samples)
1528
+                                  int nb_samples, int *buf_linesize)
1529 1529
 {
1530 1530
     int64_t audio_buf_samples;
1531 1531
     int audio_buf_size;
... ...
@@ -1538,7 +1538,7 @@ static int alloc_audio_output_buf(AVCodecContext *dec, AVCodecContext *enc,
1538 1538
     if (audio_buf_samples > INT_MAX)
1539 1539
         return AVERROR(EINVAL);
1540 1540
 
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,
1542 1542
                                                 audio_buf_samples,
1543 1543
                                                 enc->sample_fmt, 0);
1544 1544
     if (audio_buf_size < 0)
... ...
@@ -1557,7 +1557,7 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
1557 1557
     uint8_t *buftmp;
1558 1558
     int64_t size_out;
1559 1559
 
1560
-    int frame_bytes, resample_changed;
1560
+    int frame_bytes, resample_changed, ret;
1561 1561
     AVCodecContext *enc = ost->st->codec;
1562 1562
     AVCodecContext *dec = ist->st->codec;
1563 1563
     int osize = av_get_bytes_per_sample(enc->sample_fmt);
... ...
@@ -1566,37 +1566,46 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
1566 1566
     int size     = decoded_frame->nb_samples * dec->channels * isize;
1567 1567
     int planes   = av_sample_fmt_is_planar(dec->sample_fmt) ? dec->channels : 1;
1568 1568
     int i;
1569
+    int out_linesize = 0;
1570
+    int buf_linesize = decoded_frame->linesize[0];
1569 1571
 
1570 1572
     av_assert0(planes <= AV_NUM_DATA_POINTERS);
1571 1573
 
1572 1574
     for(i=0; i<planes; i++)
1573 1575
         buf[i]= decoded_frame->data[i];
1574 1576
 
1577
+
1575 1578
     get_default_channel_layouts(ost, ist);
1576 1579
 
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) {
1578 1581
         av_log(NULL, AV_LOG_FATAL, "Error allocating audio buffer\n");
1579 1582
         exit_program(1);
1580 1583
     }
1581 1584
 
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)
1586 1590
         ost->audio_resample = 1;
1587 1591
 
1588 1592
     resample_changed = ost->resample_sample_fmt  != dec->sample_fmt ||
1589 1593
                        ost->resample_channels    != dec->channels   ||
1594
+                       ost->resample_channel_layout != dec->channel_layout ||
1590 1595
                        ost->resample_sample_rate != dec->sample_rate;
1591 1596
 
1592 1597
     if ((ost->audio_resample && !ost->swr) || resample_changed || ost->audio_channels_mapped) {
1598
+
1593 1599
         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",
1595 1601
                    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);
1598 1606
             ost->resample_sample_fmt  = dec->sample_fmt;
1599 1607
             ost->resample_channels    = dec->channels;
1608
+            ost->resample_channel_layout = dec->channel_layout;
1600 1609
             ost->resample_sample_rate = dec->sample_rate;
1601 1610
             swr_free(&ost->swr);
1602 1611
         }
... ...
@@ -1604,6 +1613,7 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
1604 1604
         if (audio_sync_method <= 1 && !ost->audio_channels_mapped &&
1605 1605
             ost->resample_sample_fmt  == enc->sample_fmt &&
1606 1606
             ost->resample_channels    == enc->channels   &&
1607
+            ost->resample_channel_layout == enc->channel_layout &&
1607 1608
             ost->resample_sample_rate == enc->sample_rate) {
1608 1609
             //ost->swr = NULL;
1609 1610
             ost->audio_resample = 0;
... ...
@@ -1673,7 +1683,7 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
1673 1673
                         exit_program(1);
1674 1674
                     }
1675 1675
 
1676
-                    if (alloc_audio_output_buf(dec, enc, decoded_frame->nb_samples + idelta) < 0) {
1676
+                    if (alloc_audio_output_buf(dec, enc, decoded_frame->nb_samples + idelta, &out_linesize) < 0) {
1677 1677
                         av_log(NULL, AV_LOG_FATAL, "Error allocating audio buffer\n");
1678 1678
                         exit_program(1);
1679 1679
                     }
... ...
@@ -1686,11 +1696,11 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
1686 1686
                         buf[i] = t;
1687 1687
                     }
1688 1688
                     size += byte_delta;
1689
+                    buf_linesize = allocated_async_buf_size;
1689 1690
                     av_log(NULL, AV_LOG_VERBOSE, "adding %d audio samples of silence\n", idelta);
1690 1691
                 }
1691 1692
             } else if (audio_sync_method > 1) {
1692 1693
                 int comp = av_clip(delta, -audio_sync_method, audio_sync_method);
1693
-                av_assert0(ost->audio_resample);
1694 1694
                 av_log(NULL, AV_LOG_VERBOSE, "compensating audio timestamp drift:%f compensation:%d in:%d\n",
1695 1695
                        delta, comp, enc->sample_rate);
1696 1696
 //                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,
1703 1703
 
1704 1704
     if (ost->audio_resample || ost->audio_channels_mapped) {
1705 1705
         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));
1706
+        size_out = swr_convert(ost->swr, (      uint8_t*[]){buftmp},
1707
+                                      allocated_audio_buf_size / (enc->channels * osize),
1708
+                                      buf,
1709
+                                      size / (dec->channels * isize));
1708 1710
         if (size_out < 0) {
1709 1711
             av_log(NULL, AV_LOG_FATAL, "swr_convert failed\n");
1710 1712
             exit_program(1);
... ...
@@ -3078,6 +3090,7 @@ static int transcode_init(void)
3078 3078
                 if (!ost->fifo) {
3079 3079
                     return AVERROR(ENOMEM);
3080 3080
                 }
3081
+
3081 3082
                 if (!codec->sample_rate)
3082 3083
                     codec->sample_rate = icodec->sample_rate;
3083 3084
                 choose_sample_rate(ost->st, ost->enc);
... ...
@@ -3110,13 +3123,15 @@ static int transcode_init(void)
3110 3110
                 if (av_get_channel_layout_nb_channels(codec->channel_layout) != codec->channels)
3111 3111
                     codec->channel_layout = 0;
3112 3112
 
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;
3113
+
3114
+//                 ost->audio_resample       = codec->sample_rate != icodec->sample_rate || audio_sync_method > 1;
3115
+//                 ost->audio_resample      |=    codec->sample_fmt     != icodec->sample_fmt
3116
+//                                             || codec->channel_layout != icodec->channel_layout;
3117
+                icodec->request_channels  = codec-> channels;
3117 3118
                 ost->resample_sample_fmt  = icodec->sample_fmt;
3118 3119
                 ost->resample_sample_rate = icodec->sample_rate;
3119 3120
                 ost->resample_channels    = icodec->channels;
3121
+                ost->resample_channel_layout = icodec->channel_layout;
3120 3122
                 break;
3121 3123
             case AVMEDIA_TYPE_VIDEO:
3122 3124
                 if (!ost->filter) {
3123 3125
new file mode 100644
... ...
@@ -0,0 +1,15 @@
0
+NAME = avresample
1
+FFLIBS = avutil
2
+
3
+HEADERS = avresample.h                                                  \
4
+          version.h
5
+
6
+OBJS = audio_convert.o                                                  \
7
+       audio_data.o                                                     \
8
+       audio_mix.o                                                      \
9
+       audio_mix_matrix.o                                               \
10
+       options.o                                                        \
11
+       resample.o                                                       \
12
+       utils.o
13
+
14
+TESTPROGS = avresample
0 15
new file mode 100644
... ...
@@ -0,0 +1,334 @@
0
+/*
1
+ * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
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 "config.h"
24
+#include "libavutil/libm.h"
25
+#include "libavutil/log.h"
26
+#include "libavutil/mem.h"
27
+#include "libavutil/samplefmt.h"
28
+#include "audio_convert.h"
29
+#include "audio_data.h"
30
+
31
+enum ConvFuncType {
32
+    CONV_FUNC_TYPE_FLAT,
33
+    CONV_FUNC_TYPE_INTERLEAVE,
34
+    CONV_FUNC_TYPE_DEINTERLEAVE,
35
+};
36
+
37
+typedef void (conv_func_flat)(uint8_t *out, const uint8_t *in, int len);
38
+
39
+typedef void (conv_func_interleave)(uint8_t *out, uint8_t *const *in,
40
+                                    int len, int channels);
41
+
42
+typedef void (conv_func_deinterleave)(uint8_t **out, const uint8_t *in, int len,
43
+                                      int channels);
44
+
45
+struct AudioConvert {
46
+    AVAudioResampleContext *avr;
47
+    enum AVSampleFormat in_fmt;
48
+    enum AVSampleFormat out_fmt;
49
+    int channels;
50
+    int planes;
51
+    int ptr_align;
52
+    int samples_align;
53
+    int has_optimized_func;
54
+    const char *func_descr;
55
+    const char *func_descr_generic;
56
+    enum ConvFuncType func_type;
57
+    conv_func_flat         *conv_flat;
58
+    conv_func_flat         *conv_flat_generic;
59
+    conv_func_interleave   *conv_interleave;
60
+    conv_func_interleave   *conv_interleave_generic;
61
+    conv_func_deinterleave *conv_deinterleave;
62
+    conv_func_deinterleave *conv_deinterleave_generic;
63
+};
64
+
65
+void ff_audio_convert_set_func(AudioConvert *ac, enum AVSampleFormat out_fmt,
66
+                               enum AVSampleFormat in_fmt, int channels,
67
+                               int ptr_align, int samples_align,
68
+                               const char *descr, void *conv)
69
+{
70
+    int found = 0;
71
+
72
+    switch (ac->func_type) {
73
+    case CONV_FUNC_TYPE_FLAT:
74
+        if (av_get_packed_sample_fmt(ac->in_fmt)  == in_fmt &&
75
+            av_get_packed_sample_fmt(ac->out_fmt) == out_fmt) {
76
+            ac->conv_flat     = conv;
77
+            ac->func_descr    = descr;
78
+            ac->ptr_align     = ptr_align;
79
+            ac->samples_align = samples_align;
80
+            if (ptr_align == 1 && samples_align == 1) {
81
+                ac->conv_flat_generic  = conv;
82
+                ac->func_descr_generic = descr;
83
+            } else {
84
+                ac->has_optimized_func = 1;
85
+            }
86
+            found = 1;
87
+        }
88
+        break;
89
+    case CONV_FUNC_TYPE_INTERLEAVE:
90
+        if (ac->in_fmt == in_fmt && ac->out_fmt == out_fmt &&
91
+            (!channels || ac->channels == channels)) {
92
+            ac->conv_interleave = conv;
93
+            ac->func_descr      = descr;
94
+            ac->ptr_align       = ptr_align;
95
+            ac->samples_align   = samples_align;
96
+            if (ptr_align == 1 && samples_align == 1) {
97
+                ac->conv_interleave_generic = conv;
98
+                ac->func_descr_generic      = descr;
99
+            } else {
100
+                ac->has_optimized_func = 1;
101
+            }
102
+            found = 1;
103
+        }
104
+        break;
105
+    case CONV_FUNC_TYPE_DEINTERLEAVE:
106
+        if (ac->in_fmt == in_fmt && ac->out_fmt == out_fmt &&
107
+            (!channels || ac->channels == channels)) {
108
+            ac->conv_deinterleave = conv;
109
+            ac->func_descr        = descr;
110
+            ac->ptr_align         = ptr_align;
111
+            ac->samples_align     = samples_align;
112
+            if (ptr_align == 1 && samples_align == 1) {
113
+                ac->conv_deinterleave_generic = conv;
114
+                ac->func_descr_generic        = descr;
115
+            } else {
116
+                ac->has_optimized_func = 1;
117
+            }
118
+            found = 1;
119
+        }
120
+        break;
121
+    }
122
+    if (found) {
123
+        av_log(ac->avr, AV_LOG_DEBUG, "audio_convert: found function: %-4s "
124
+               "to %-4s (%s)\n", av_get_sample_fmt_name(ac->in_fmt),
125
+               av_get_sample_fmt_name(ac->out_fmt), descr);
126
+    }
127
+}
128
+
129
+#define CONV_FUNC_NAME(dst_fmt, src_fmt) conv_ ## src_fmt ## _to_ ## dst_fmt
130
+
131
+#define CONV_LOOP(otype, expr)                                              \
132
+    do {                                                                    \
133
+        *(otype *)po = expr;                                                \
134
+        pi += is;                                                           \
135
+        po += os;                                                           \
136
+    } while (po < end);                                                     \
137
+
138
+#define CONV_FUNC_FLAT(ofmt, otype, ifmt, itype, expr)                      \
139
+static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *out, const uint8_t *in,     \
140
+                                       int len)                             \
141
+{                                                                           \
142
+    int is       = sizeof(itype);                                           \
143
+    int os       = sizeof(otype);                                           \
144
+    const uint8_t *pi = in;                                                 \
145
+    uint8_t       *po = out;                                                \
146
+    uint8_t *end = out + os * len;                                          \
147
+    CONV_LOOP(otype, expr)                                                  \
148
+}
149
+
150
+#define CONV_FUNC_INTERLEAVE(ofmt, otype, ifmt, itype, expr)                \
151
+static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *out, const uint8_t **in,    \
152
+                                       int len, int channels)               \
153
+{                                                                           \
154
+    int ch;                                                                 \
155
+    int out_bps = sizeof(otype);                                            \
156
+    int is      = sizeof(itype);                                            \
157
+    int os      = channels * out_bps;                                       \
158
+    for (ch = 0; ch < channels; ch++) {                                     \
159
+        const uint8_t *pi = in[ch];                                         \
160
+        uint8_t       *po = out + ch * out_bps;                             \
161
+        uint8_t      *end = po + os * len;                                  \
162
+        CONV_LOOP(otype, expr)                                              \
163
+    }                                                                       \
164
+}
165
+
166
+#define CONV_FUNC_DEINTERLEAVE(ofmt, otype, ifmt, itype, expr)              \
167
+static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t **out, const uint8_t *in,    \
168
+                                       int len, int channels)               \
169
+{                                                                           \
170
+    int ch;                                                                 \
171
+    int in_bps = sizeof(itype);                                             \
172
+    int is     = channels * in_bps;                                         \
173
+    int os     = sizeof(otype);                                             \
174
+    for (ch = 0; ch < channels; ch++) {                                     \
175
+        const uint8_t *pi = in  + ch * in_bps;                              \
176
+        uint8_t       *po = out[ch];                                        \
177
+        uint8_t      *end = po + os * len;                                  \
178
+        CONV_LOOP(otype, expr)                                              \
179
+    }                                                                       \
180
+}
181
+
182
+#define CONV_FUNC_GROUP(ofmt, otype, ifmt, itype, expr) \
183
+CONV_FUNC_FLAT(        ofmt,      otype, ifmt,      itype, expr) \
184
+CONV_FUNC_INTERLEAVE(  ofmt,      otype, ifmt ## P, itype, expr) \
185
+CONV_FUNC_DEINTERLEAVE(ofmt ## P, otype, ifmt,      itype, expr)
186
+
187
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  uint8_t, AV_SAMPLE_FMT_U8,  uint8_t,  *(const uint8_t *)pi)
188
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_U8,  uint8_t, (*(const uint8_t *)pi - 0x80) <<  8)
189
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_U8,  uint8_t, (*(const uint8_t *)pi - 0x80) << 24)
190
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float,   AV_SAMPLE_FMT_U8,  uint8_t, (*(const uint8_t *)pi - 0x80) * (1.0f / (1 << 7)))
191
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double,  AV_SAMPLE_FMT_U8,  uint8_t, (*(const uint8_t *)pi - 0x80) * (1.0  / (1 << 7)))
192
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  uint8_t, AV_SAMPLE_FMT_S16, int16_t, (*(const int16_t *)pi >> 8) + 0x80)
193
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S16, int16_t,  *(const int16_t *)pi)
194
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, int16_t,  *(const int16_t *)pi << 16)
195
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float,   AV_SAMPLE_FMT_S16, int16_t,  *(const int16_t *)pi * (1.0f / (1 << 15)))
196
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double,  AV_SAMPLE_FMT_S16, int16_t,  *(const int16_t *)pi * (1.0  / (1 << 15)))
197
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  uint8_t, AV_SAMPLE_FMT_S32, int32_t, (*(const int32_t *)pi >> 24) + 0x80)
198
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S32, int32_t,  *(const int32_t *)pi >> 16)
199
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S32, int32_t,  *(const int32_t *)pi)
200
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float,   AV_SAMPLE_FMT_S32, int32_t,  *(const int32_t *)pi * (1.0f / (1U << 31)))
201
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double,  AV_SAMPLE_FMT_S32, int32_t,  *(const int32_t *)pi * (1.0  / (1U << 31)))
202
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  uint8_t, AV_SAMPLE_FMT_FLT, float,   av_clip_uint8(  lrintf(*(const float *)pi * (1  <<  7)) + 0x80))
203
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float,   av_clip_int16(  lrintf(*(const float *)pi * (1  << 15))))
204
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float,   av_clipl_int32(llrintf(*(const float *)pi * (1U << 31))))
205
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float,   AV_SAMPLE_FMT_FLT, float,   *(const float *)pi)
206
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double,  AV_SAMPLE_FMT_FLT, float,   *(const float *)pi)
207
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  uint8_t, AV_SAMPLE_FMT_DBL, double,  av_clip_uint8(  lrint(*(const double *)pi * (1  <<  7)) + 0x80))
208
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double,  av_clip_int16(  lrint(*(const double *)pi * (1  << 15))))
209
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double,  av_clipl_int32(llrint(*(const double *)pi * (1U << 31))))
210
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float,   AV_SAMPLE_FMT_DBL, double,  *(const double *)pi)
211
+CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double,  AV_SAMPLE_FMT_DBL, double,  *(const double *)pi)
212
+
213
+#define SET_CONV_FUNC_GROUP(ofmt, ifmt)                                                             \
214
+ff_audio_convert_set_func(ac, ofmt,      ifmt,      0, 1, 1, "C", CONV_FUNC_NAME(ofmt,      ifmt)); \
215
+ff_audio_convert_set_func(ac, ofmt ## P, ifmt,      0, 1, 1, "C", CONV_FUNC_NAME(ofmt ## P, ifmt)); \
216
+ff_audio_convert_set_func(ac, ofmt,      ifmt ## P, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt,      ifmt ## P));
217
+
218
+static void set_generic_function(AudioConvert *ac)
219
+{
220
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  AV_SAMPLE_FMT_U8)
221
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8)
222
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8)
223
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8)
224
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8)
225
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  AV_SAMPLE_FMT_S16)
226
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16)
227
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16)
228
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16)
229
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16)
230
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  AV_SAMPLE_FMT_S32)
231
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32)
232
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32)
233
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32)
234
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32)
235
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  AV_SAMPLE_FMT_FLT)
236
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT)
237
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT)
238
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT)
239
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT)
240
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8,  AV_SAMPLE_FMT_DBL)
241
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL)
242
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL)
243
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL)
244
+    SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL)
245
+}
246
+
247
+AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr,
248
+                                     enum AVSampleFormat out_fmt,
249
+                                     enum AVSampleFormat in_fmt,
250
+                                     int channels)
251
+{
252
+    AudioConvert *ac;
253
+    int in_planar, out_planar;
254
+
255
+    ac = av_mallocz(sizeof(*ac));
256
+    if (!ac)
257
+        return NULL;
258
+
259
+    ac->avr      = avr;
260
+    ac->out_fmt  = out_fmt;
261
+    ac->in_fmt   = in_fmt;
262
+    ac->channels = channels;
263
+
264
+    in_planar  = av_sample_fmt_is_planar(in_fmt);
265
+    out_planar = av_sample_fmt_is_planar(out_fmt);
266
+
267
+    if (in_planar == out_planar) {
268
+        ac->func_type = CONV_FUNC_TYPE_FLAT;
269
+        ac->planes    = in_planar ? ac->channels : 1;
270
+    } else if (in_planar)
271
+        ac->func_type = CONV_FUNC_TYPE_INTERLEAVE;
272
+    else
273
+        ac->func_type = CONV_FUNC_TYPE_DEINTERLEAVE;
274
+
275
+    set_generic_function(ac);
276
+
277
+    if (ARCH_X86)
278
+        ff_audio_convert_init_x86(ac);
279
+
280
+    return ac;
281
+}
282
+
283
+int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in, int len)
284
+{
285
+    int use_generic = 1;
286
+
287
+    /* determine whether to use the optimized function based on pointer and
288
+       samples alignment in both the input and output */
289
+    if (ac->has_optimized_func) {
290
+        int ptr_align     = FFMIN(in->ptr_align,     out->ptr_align);
291
+        int samples_align = FFMIN(in->samples_align, out->samples_align);
292
+        int aligned_len   = FFALIGN(len, ac->samples_align);
293
+        if (!(ptr_align % ac->ptr_align) && samples_align >= aligned_len) {
294
+            len = aligned_len;
295
+            use_generic = 0;
296
+        }
297
+    }
298
+    av_dlog(ac->avr, "%d samples - audio_convert: %s to %s (%s)\n", len,
299
+            av_get_sample_fmt_name(ac->in_fmt),
300
+            av_get_sample_fmt_name(ac->out_fmt),
301
+            use_generic ? ac->func_descr_generic : ac->func_descr);
302
+
303
+    switch (ac->func_type) {
304
+    case CONV_FUNC_TYPE_FLAT: {
305
+        int p;
306
+        if (!in->is_planar)
307
+            len *= in->channels;
308
+        if (use_generic) {
309
+            for (p = 0; p < ac->planes; p++)
310
+                ac->conv_flat_generic(out->data[p], in->data[p], len);
311
+        } else {
312
+            for (p = 0; p < ac->planes; p++)
313
+                ac->conv_flat(out->data[p], in->data[p], len);
314
+        }
315
+        break;
316
+    }
317
+    case CONV_FUNC_TYPE_INTERLEAVE:
318
+        if (use_generic)
319
+            ac->conv_interleave_generic(out->data[0], in->data, len, ac->channels);
320
+        else
321
+            ac->conv_interleave(out->data[0], in->data, len, ac->channels);
322
+        break;
323
+    case CONV_FUNC_TYPE_DEINTERLEAVE:
324
+        if (use_generic)
325
+            ac->conv_deinterleave_generic(out->data, in->data[0], len, ac->channels);
326
+        else
327
+            ac->conv_deinterleave(out->data, in->data[0], len, ac->channels);
328
+        break;
329
+    }
330
+
331
+    out->nb_samples = in->nb_samples;
332
+    return 0;
333
+}
0 334
new file mode 100644
... ...
@@ -0,0 +1,87 @@
0
+/*
1
+ * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
2
+ *
3
+ * This file is part of Libav.
4
+ *
5
+ * Libav is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * Libav is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with Libav; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#ifndef AVRESAMPLE_AUDIO_CONVERT_H
21
+#define AVRESAMPLE_AUDIO_CONVERT_H
22
+
23
+#include "libavutil/samplefmt.h"
24
+#include "avresample.h"
25
+#include "audio_data.h"
26
+
27
+typedef struct AudioConvert AudioConvert;
28
+
29
+/**
30
+ * Set conversion function if the parameters match.
31
+ *
32
+ * This compares the parameters of the conversion function to the parameters
33
+ * in the AudioConvert context. If the parameters do not match, no changes are
34
+ * made to the active functions. If the parameters do match and the alignment
35
+ * is not constrained, the function is set as the generic conversion function.
36
+ * If the parameters match and the alignment is constrained, the function is
37
+ * set as the optimized conversion function.
38
+ *
39
+ * @param ac             AudioConvert context
40
+ * @param out_fmt        output sample format
41
+ * @param in_fmt         input sample format
42
+ * @param channels       number of channels, or 0 for any number of channels
43
+ * @param ptr_align      buffer pointer alignment, in bytes
44
+ * @param sample_align   buffer size alignment, in samples
45
+ * @param descr          function type description (e.g. "C" or "SSE")
46
+ * @param conv           conversion function pointer
47
+ */
48
+void ff_audio_convert_set_func(AudioConvert *ac, enum AVSampleFormat out_fmt,
49
+                               enum AVSampleFormat in_fmt, int channels,
50
+                               int ptr_align, int samples_align,
51
+                               const char *descr, void *conv);
52
+
53
+/**
54
+ * Allocate and initialize AudioConvert context for sample format conversion.
55
+ *
56
+ * @param avr      AVAudioResampleContext
57
+ * @param out_fmt  output sample format
58
+ * @param in_fmt   input sample format
59
+ * @param channels number of channels
60
+ * @return         newly-allocated AudioConvert context
61
+ */
62
+AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr,
63
+                                     enum AVSampleFormat out_fmt,
64
+                                     enum AVSampleFormat in_fmt,
65
+                                     int channels);
66
+
67
+/**
68
+ * Convert audio data from one sample format to another.
69
+ *
70
+ * For each call, the alignment of the input and output AudioData buffers are
71
+ * examined to determine whether to use the generic or optimized conversion
72
+ * function (when available).
73
+ *
74
+ * @param ac     AudioConvert context
75
+ * @param out    output audio data
76
+ * @param in     input audio data
77
+ * @param len    number of samples to convert
78
+ * @return       0 on success, negative AVERROR code on failure
79
+ */
80
+int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in, int len);
81
+
82
+/* arch-specific initialization functions */
83
+
84
+void ff_audio_convert_init_x86(AudioConvert *ac);
85
+
86
+#endif /* AVRESAMPLE_AUDIO_CONVERT_H */
0 87
new file mode 100644
... ...
@@ -0,0 +1,345 @@
0
+/*
1
+ * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
2
+ *
3
+ * This file is part of Libav.
4
+ *
5
+ * Libav is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * Libav is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with Libav; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#include <stdint.h>
21
+
22
+#include "libavutil/mem.h"
23
+#include "audio_data.h"
24
+
25
+static const AVClass audio_data_class = {
26
+    .class_name = "AudioData",
27
+    .item_name  = av_default_item_name,
28
+    .version    = LIBAVUTIL_VERSION_INT,
29
+};
30
+
31
+/*
32
+ * Calculate alignment for data pointers.
33
+ */
34
+static void calc_ptr_alignment(AudioData *a)
35
+{
36
+    int p;
37
+    int min_align = 128;
38
+
39
+    for (p = 0; p < a->planes; p++) {
40
+        int cur_align = 128;
41
+        while ((intptr_t)a->data[p] % cur_align)
42
+            cur_align >>= 1;
43
+        if (cur_align < min_align)
44
+            min_align = cur_align;
45
+    }
46
+    a->ptr_align = min_align;
47
+}
48
+
49
+int ff_audio_data_set_channels(AudioData *a, int channels)
50
+{
51
+    if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS ||
52
+        channels > a->allocated_channels)
53
+        return AVERROR(EINVAL);
54
+
55
+    a->channels  = channels;
56
+    a->planes    = a->is_planar ? channels : 1;
57
+
58
+    calc_ptr_alignment(a);
59
+
60
+    return 0;
61
+}
62
+
63
+int ff_audio_data_init(AudioData *a, void **src, int plane_size, int channels,
64
+                       int nb_samples, enum AVSampleFormat sample_fmt,
65
+                       int read_only, const char *name)
66
+{
67
+    int p;
68
+
69
+    memset(a, 0, sizeof(*a));
70
+    a->class = &audio_data_class;
71
+
72
+    if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS) {
73
+        av_log(a, AV_LOG_ERROR, "invalid channel count: %d\n", channels);
74
+        return AVERROR(EINVAL);
75
+    }
76
+
77
+    a->sample_size = av_get_bytes_per_sample(sample_fmt);
78
+    if (!a->sample_size) {
79
+        av_log(a, AV_LOG_ERROR, "invalid sample format\n");
80
+        return AVERROR(EINVAL);
81
+    }
82
+    a->is_planar = av_sample_fmt_is_planar(sample_fmt);
83
+    a->planes    = a->is_planar ? channels : 1;
84
+    a->stride    = a->sample_size * (a->is_planar ? 1 : channels);
85
+
86
+    for (p = 0; p < (a->is_planar ? channels : 1); p++) {
87
+        if (!src[p]) {
88
+            av_log(a, AV_LOG_ERROR, "invalid NULL pointer for src[%d]\n", p);
89
+            return AVERROR(EINVAL);
90
+        }
91
+        a->data[p] = src[p];
92
+    }
93
+    a->allocated_samples  = nb_samples * !read_only;
94
+    a->nb_samples         = nb_samples;
95
+    a->sample_fmt         = sample_fmt;
96
+    a->channels           = channels;
97
+    a->allocated_channels = channels;
98
+    a->read_only          = read_only;
99
+    a->allow_realloc      = 0;
100
+    a->name               = name ? name : "{no name}";
101
+
102
+    calc_ptr_alignment(a);
103
+    a->samples_align = plane_size / a->stride;
104
+
105
+    return 0;
106
+}
107
+
108
+AudioData *ff_audio_data_alloc(int channels, int nb_samples,
109
+                               enum AVSampleFormat sample_fmt, const char *name)
110
+{
111
+    AudioData *a;
112
+    int ret;
113
+
114
+    if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS)
115
+        return NULL;
116
+
117
+    a = av_mallocz(sizeof(*a));
118
+    if (!a)
119
+        return NULL;
120
+
121
+    a->sample_size = av_get_bytes_per_sample(sample_fmt);
122
+    if (!a->sample_size) {
123
+        av_free(a);
124
+        return NULL;
125
+    }
126
+    a->is_planar = av_sample_fmt_is_planar(sample_fmt);
127
+    a->planes    = a->is_planar ? channels : 1;
128
+    a->stride    = a->sample_size * (a->is_planar ? 1 : channels);
129
+
130
+    a->class              = &audio_data_class;
131
+    a->sample_fmt         = sample_fmt;
132
+    a->channels           = channels;
133
+    a->allocated_channels = channels;
134
+    a->read_only          = 0;
135
+    a->allow_realloc      = 1;
136
+    a->name               = name ? name : "{no name}";
137
+
138
+    if (nb_samples > 0) {
139
+        ret = ff_audio_data_realloc(a, nb_samples);
140
+        if (ret < 0) {
141
+            av_free(a);
142
+            return NULL;
143
+        }
144
+        return a;
145
+    } else {
146
+        calc_ptr_alignment(a);
147
+        return a;
148
+    }
149
+}
150
+
151
+int ff_audio_data_realloc(AudioData *a, int nb_samples)
152
+{
153
+    int ret, new_buf_size, plane_size, p;
154
+
155
+    /* check if buffer is already large enough */
156
+    if (a->allocated_samples >= nb_samples)
157
+        return 0;
158
+
159
+    /* validate that the output is not read-only and realloc is allowed */
160
+    if (a->read_only || !a->allow_realloc)
161
+        return AVERROR(EINVAL);
162
+
163
+    new_buf_size = av_samples_get_buffer_size(&plane_size,
164
+                                              a->allocated_channels, nb_samples,
165
+                                              a->sample_fmt, 0);
166
+    if (new_buf_size < 0)
167
+        return new_buf_size;
168
+
169
+    /* if there is already data in the buffer and the sample format is planar,
170
+       allocate a new buffer and copy the data, otherwise just realloc the
171
+       internal buffer and set new data pointers */
172
+    if (a->nb_samples > 0 && a->is_planar) {
173
+        uint8_t *new_data[AVRESAMPLE_MAX_CHANNELS] = { NULL };
174
+
175
+        ret = av_samples_alloc(new_data, &plane_size, a->allocated_channels,
176
+                               nb_samples, a->sample_fmt, 0);
177
+        if (ret < 0)
178
+            return ret;
179
+
180
+        for (p = 0; p < a->planes; p++)
181
+            memcpy(new_data[p], a->data[p], a->nb_samples * a->stride);
182
+
183
+        av_freep(&a->buffer);
184
+        memcpy(a->data, new_data, sizeof(new_data));
185
+        a->buffer = a->data[0];
186
+    } else {
187
+        av_freep(&a->buffer);
188
+        a->buffer = av_malloc(new_buf_size);
189
+        if (!a->buffer)
190
+            return AVERROR(ENOMEM);
191
+        ret = av_samples_fill_arrays(a->data, &plane_size, a->buffer,
192
+                                     a->allocated_channels, nb_samples,
193
+                                     a->sample_fmt, 0);
194
+        if (ret < 0)
195
+            return ret;
196
+    }
197
+    a->buffer_size       = new_buf_size;
198
+    a->allocated_samples = nb_samples;
199
+
200
+    calc_ptr_alignment(a);
201
+    a->samples_align = plane_size / a->stride;
202
+
203
+    return 0;
204
+}
205
+
206
+void ff_audio_data_free(AudioData **a)
207
+{
208
+    if (!*a)
209
+        return;
210
+    av_free((*a)->buffer);
211
+    av_freep(a);
212
+}
213
+
214
+int ff_audio_data_copy(AudioData *dst, AudioData *src)
215
+{
216
+    int ret, p;
217
+
218
+    /* validate input/output compatibility */
219
+    if (dst->sample_fmt != src->sample_fmt || dst->channels < src->channels)
220
+        return AVERROR(EINVAL);
221
+
222
+    /* if the input is empty, just empty the output */
223
+    if (!src->nb_samples) {
224
+        dst->nb_samples = 0;
225
+        return 0;
226
+    }
227
+
228
+    /* reallocate output if necessary */
229
+    ret = ff_audio_data_realloc(dst, src->nb_samples);
230
+    if (ret < 0)
231
+        return ret;
232
+
233
+    /* copy data */
234
+    for (p = 0; p < src->planes; p++)
235
+        memcpy(dst->data[p], src->data[p], src->nb_samples * src->stride);
236
+    dst->nb_samples = src->nb_samples;
237
+
238
+    return 0;
239
+}
240
+
241
+int ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src,
242
+                          int src_offset, int nb_samples)
243
+{
244
+    int ret, p, dst_offset2, dst_move_size;
245
+
246
+    /* validate input/output compatibility */
247
+    if (dst->sample_fmt != src->sample_fmt || dst->channels != src->channels) {
248
+        av_log(src, AV_LOG_ERROR, "sample format mismatch\n");
249
+        return AVERROR(EINVAL);
250
+    }
251
+
252
+    /* validate offsets are within the buffer bounds */
253
+    if (dst_offset < 0 || dst_offset > dst->nb_samples ||
254
+        src_offset < 0 || src_offset > src->nb_samples) {
255
+        av_log(src, AV_LOG_ERROR, "offset out-of-bounds: src=%d dst=%d\n",
256
+               src_offset, dst_offset);
257
+        return AVERROR(EINVAL);
258
+    }
259
+
260
+    /* check offsets and sizes to see if we can just do nothing and return */
261
+    if (nb_samples > src->nb_samples - src_offset)
262
+        nb_samples = src->nb_samples - src_offset;
263
+    if (nb_samples <= 0)
264
+        return 0;
265
+
266
+    /* validate that the output is not read-only */
267
+    if (dst->read_only) {
268
+        av_log(dst, AV_LOG_ERROR, "dst is read-only\n");
269
+        return AVERROR(EINVAL);
270
+    }
271
+
272
+    /* reallocate output if necessary */
273
+    ret = ff_audio_data_realloc(dst, dst->nb_samples + nb_samples);
274
+    if (ret < 0) {
275
+        av_log(dst, AV_LOG_ERROR, "error reallocating dst\n");
276
+        return ret;
277
+    }
278
+
279
+    dst_offset2   = dst_offset + nb_samples;
280
+    dst_move_size = dst->nb_samples - dst_offset;
281
+
282
+    for (p = 0; p < src->planes; p++) {
283
+        if (dst_move_size > 0) {
284
+            memmove(dst->data[p] + dst_offset2 * dst->stride,
285
+                    dst->data[p] + dst_offset  * dst->stride,
286
+                    dst_move_size * dst->stride);
287
+        }
288
+        memcpy(dst->data[p] + dst_offset * dst->stride,
289
+               src->data[p] + src_offset * src->stride,
290
+               nb_samples * src->stride);
291
+    }
292
+    dst->nb_samples += nb_samples;
293
+
294
+    return 0;
295
+}
296
+
297
+void ff_audio_data_drain(AudioData *a, int nb_samples)
298
+{
299
+    if (a->nb_samples <= nb_samples) {
300
+        /* drain the whole buffer */
301
+        a->nb_samples = 0;
302
+    } else {
303
+        int p;
304
+        int move_offset = a->stride * nb_samples;
305
+        int move_size   = a->stride * (a->nb_samples - nb_samples);
306
+
307
+        for (p = 0; p < a->planes; p++)
308
+            memmove(a->data[p], a->data[p] + move_offset, move_size);
309
+
310
+        a->nb_samples -= nb_samples;
311
+    }
312
+}
313
+
314
+int ff_audio_data_add_to_fifo(AVAudioFifo *af, AudioData *a, int offset,
315
+                              int nb_samples)
316
+{
317
+    uint8_t *offset_data[AVRESAMPLE_MAX_CHANNELS];
318
+    int offset_size, p;
319
+
320
+    if (offset >= a->nb_samples)
321
+        return 0;
322
+    offset_size = offset * a->stride;
323
+    for (p = 0; p < a->planes; p++)
324
+        offset_data[p] = a->data[p] + offset_size;
325
+
326
+    return av_audio_fifo_write(af, (void **)offset_data, nb_samples);
327
+}
328
+
329
+int ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples)
330
+{
331
+    int ret;
332
+
333
+    if (a->read_only)
334
+        return AVERROR(EINVAL);
335
+
336
+    ret = ff_audio_data_realloc(a, nb_samples);
337
+    if (ret < 0)
338
+        return ret;
339
+
340
+    ret = av_audio_fifo_read(af, (void **)a->data, nb_samples);
341
+    if (ret >= 0)
342
+        a->nb_samples = ret;
343
+    return ret;
344
+}
0 345
new file mode 100644
... ...
@@ -0,0 +1,173 @@
0
+/*
1
+ * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
2
+ *
3
+ * This file is part of Libav.
4
+ *
5
+ * Libav is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * Libav is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with Libav; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#ifndef AVRESAMPLE_AUDIO_DATA_H
21
+#define AVRESAMPLE_AUDIO_DATA_H
22
+
23
+#include <stdint.h>
24
+
25
+#include "libavutil/audio_fifo.h"
26
+#include "libavutil/log.h"
27
+#include "libavutil/samplefmt.h"
28
+#include "avresample.h"
29
+
30
+/**
31
+ * Audio buffer used for intermediate storage between conversion phases.
32
+ */
33
+typedef struct AudioData {
34
+    const AVClass *class;               /**< AVClass for logging            */
35
+    uint8_t *data[AVRESAMPLE_MAX_CHANNELS]; /**< data plane pointers        */
36
+    uint8_t *buffer;                    /**< data buffer                    */
37
+    unsigned int buffer_size;           /**< allocated buffer size          */
38
+    int allocated_samples;              /**< number of samples the buffer can hold */
39
+    int nb_samples;                     /**< current number of samples      */
40
+    enum AVSampleFormat sample_fmt;     /**< sample format                  */
41
+    int channels;                       /**< channel count                  */
42
+    int allocated_channels;             /**< allocated channel count        */
43
+    int is_planar;                      /**< sample format is planar        */
44
+    int planes;                         /**< number of data planes          */
45
+    int sample_size;                    /**< bytes per sample               */
46
+    int stride;                         /**< sample byte offset within a plane */
47
+    int read_only;                      /**< data is read-only              */
48
+    int allow_realloc;                  /**< realloc is allowed             */
49
+    int ptr_align;                      /**< minimum data pointer alignment */
50
+    int samples_align;                  /**< allocated samples alignment    */
51
+    const char *name;                   /**< name for debug logging         */
52
+} AudioData;
53
+
54
+int ff_audio_data_set_channels(AudioData *a, int channels);
55
+
56
+/**
57
+ * Initialize AudioData using a given source.
58
+ *
59
+ * This does not allocate an internal buffer. It only sets the data pointers
60
+ * and audio parameters.
61
+ *
62
+ * @param a               AudioData struct
63
+ * @param src             source data pointers
64
+ * @param plane_size      plane size, in bytes.
65
+ *                        This can be 0 if unknown, but that will lead to
66
+ *                        optimized functions not being used in many cases,
67
+ *                        which could slow down some conversions.
68
+ * @param channels        channel count
69
+ * @param nb_samples      number of samples in the source data
70
+ * @param sample_fmt      sample format
71
+ * @param read_only       indicates if buffer is read only or read/write
72
+ * @param name            name for debug logging (can be NULL)
73
+ * @return                0 on success, negative AVERROR value on error
74
+ */
75
+int ff_audio_data_init(AudioData *a, void **src, int plane_size, int channels,
76
+                       int nb_samples, enum AVSampleFormat sample_fmt,
77
+                       int read_only, const char *name);
78
+
79
+/**
80
+ * Allocate AudioData.
81
+ *
82
+ * This allocates an internal buffer and sets audio parameters.
83
+ *
84
+ * @param channels        channel count
85
+ * @param nb_samples      number of samples to allocate space for
86
+ * @param sample_fmt      sample format
87
+ * @param name            name for debug logging (can be NULL)
88
+ * @return                newly allocated AudioData struct, or NULL on error
89
+ */
90
+AudioData *ff_audio_data_alloc(int channels, int nb_samples,
91
+                               enum AVSampleFormat sample_fmt,
92
+                               const char *name);
93
+
94
+/**
95
+ * Reallocate AudioData.
96
+ *
97
+ * The AudioData must have been previously allocated with ff_audio_data_alloc().
98
+ *
99
+ * @param a           AudioData struct
100
+ * @param nb_samples  number of samples to allocate space for
101
+ * @return            0 on success, negative AVERROR value on error
102
+ */
103
+int ff_audio_data_realloc(AudioData *a, int nb_samples);
104
+
105
+/**
106
+ * Free AudioData.
107
+ *
108
+ * The AudioData must have been previously allocated with ff_audio_data_alloc().
109
+ *
110
+ * @param a  AudioData struct
111
+ */
112
+void ff_audio_data_free(AudioData **a);
113
+
114
+/**
115
+ * Copy data from one AudioData to another.
116
+ *
117
+ * @param out  output AudioData
118
+ * @param in   input AudioData
119
+ * @return     0 on success, negative AVERROR value on error
120
+ */
121
+int ff_audio_data_copy(AudioData *out, AudioData *in);
122
+
123
+/**
124
+ * Append data from one AudioData to the end of another.
125
+ *
126
+ * @param dst         destination AudioData
127
+ * @param dst_offset  offset, in samples, to start writing, relative to the
128
+ *                    start of dst
129
+ * @param src         source AudioData
130
+ * @param src_offset  offset, in samples, to start copying, relative to the
131
+ *                    start of the src
132
+ * @param nb_samples  number of samples to copy
133
+ * @return            0 on success, negative AVERROR value on error
134
+ */
135
+int ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src,
136
+                          int src_offset, int nb_samples);
137
+
138
+/**
139
+ * Drain samples from the start of the AudioData.
140
+ *
141
+ * Remaining samples are shifted to the start of the AudioData.
142
+ *
143
+ * @param a           AudioData struct
144
+ * @param nb_samples  number of samples to drain
145
+ */
146
+void ff_audio_data_drain(AudioData *a, int nb_samples);
147
+
148
+/**
149
+ * Add samples in AudioData to an AVAudioFifo.
150
+ *
151
+ * @param af          Audio FIFO Buffer
152
+ * @param a           AudioData struct
153
+ * @param offset      number of samples to skip from the start of the data
154
+ * @param nb_samples  number of samples to add to the FIFO
155
+ * @return            number of samples actually added to the FIFO, or
156
+ *                    negative AVERROR code on error
157
+ */
158
+int ff_audio_data_add_to_fifo(AVAudioFifo *af, AudioData *a, int offset,
159
+                              int nb_samples);
160
+
161
+/**
162
+ * Read samples from an AVAudioFifo to AudioData.
163
+ *
164
+ * @param af          Audio FIFO Buffer
165
+ * @param a           AudioData struct
166
+ * @param nb_samples  number of samples to read from the FIFO
167
+ * @return            number of samples actually read from the FIFO, or
168
+ *                    negative AVERROR code on error
169
+ */
170
+int ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples);
171
+
172
+#endif /* AVRESAMPLE_AUDIO_DATA_H */
0 173
new file mode 100644
... ...
@@ -0,0 +1,356 @@
0
+/*
1
+ * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
2
+ *
3
+ * This file is part of Libav.
4
+ *
5
+ * Libav is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * Libav is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with Libav; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#include <stdint.h>
21
+
22
+#include "libavutil/libm.h"
23
+#include "libavutil/samplefmt.h"
24
+#include "avresample.h"
25
+#include "internal.h"
26
+#include "audio_data.h"
27
+#include "audio_mix.h"
28
+
29
+static const char *coeff_type_names[] = { "q6", "q15", "flt" };
30
+
31
+void ff_audio_mix_set_func(AudioMix *am, enum AVSampleFormat fmt,
32
+                           enum AVMixCoeffType coeff_type, int in_channels,
33
+                           int out_channels, int ptr_align, int samples_align,
34
+                           const char *descr, void *mix_func)
35
+{
36
+    if (fmt == am->fmt && coeff_type == am->coeff_type &&
37
+        ( in_channels ==  am->in_channels ||  in_channels == 0) &&
38
+        (out_channels == am->out_channels || out_channels == 0)) {
39
+        char chan_str[16];
40
+        am->mix           = mix_func;
41
+        am->func_descr    = descr;
42
+        am->ptr_align     = ptr_align;
43
+        am->samples_align = samples_align;
44
+        if (ptr_align == 1 && samples_align == 1) {
45
+            am->mix_generic        = mix_func;
46
+            am->func_descr_generic = descr;
47
+        } else {
48
+            am->has_optimized_func = 1;
49
+        }
50
+        if (in_channels) {
51
+            if (out_channels)
52
+                snprintf(chan_str, sizeof(chan_str), "[%d to %d] ",
53
+                         in_channels, out_channels);
54
+            else
55
+                snprintf(chan_str, sizeof(chan_str), "[%d to any] ",
56
+                         in_channels);
57
+        } else if (out_channels) {
58
+                snprintf(chan_str, sizeof(chan_str), "[any to %d] ",
59
+                         out_channels);
60
+        }
61
+        av_log(am->avr, AV_LOG_DEBUG, "audio_mix: found function: [fmt=%s] "
62
+               "[c=%s] %s(%s)\n", av_get_sample_fmt_name(fmt),
63
+               coeff_type_names[coeff_type],
64
+               (in_channels || out_channels) ? chan_str : "", descr);
65
+    }
66
+}
67
+
68
+#define MIX_FUNC_NAME(fmt, cfmt) mix_any_ ## fmt ##_## cfmt ##_c
69
+
70
+#define MIX_FUNC_GENERIC(fmt, cfmt, stype, ctype, sumtype, expr)            \
71
+static void MIX_FUNC_NAME(fmt, cfmt)(stype **samples, ctype **matrix,       \
72
+                                     int len, int out_ch, int in_ch)        \
73
+{                                                                           \
74
+    int i, in, out;                                                         \
75
+    stype temp[AVRESAMPLE_MAX_CHANNELS];                                    \
76
+    for (i = 0; i < len; i++) {                                             \
77
+        for (out = 0; out < out_ch; out++) {                                \
78
+            sumtype sum = 0;                                                \
79
+            for (in = 0; in < in_ch; in++)                                  \
80
+                sum += samples[in][i] * matrix[out][in];                    \
81
+            temp[out] = expr;                                               \
82
+        }                                                                   \
83
+        for (out = 0; out < out_ch; out++)                                  \
84
+            samples[out][i] = temp[out];                                    \
85
+    }                                                                       \
86
+}
87
+
88
+MIX_FUNC_GENERIC(FLTP, FLT, float,   float,   float,   sum)
89
+MIX_FUNC_GENERIC(S16P, FLT, int16_t, float,   float,   av_clip_int16(lrintf(sum)))
90
+MIX_FUNC_GENERIC(S16P, Q15, int16_t, int32_t, int64_t, av_clip_int16(sum >> 15))
91
+MIX_FUNC_GENERIC(S16P, Q6,  int16_t, int16_t, int32_t, av_clip_int16(sum >> 6))
92
+
93
+/* TODO: templatize the channel-specific C functions */
94
+
95
+static void mix_2_to_1_fltp_flt_c(float **samples, float **matrix, int len,
96
+                                  int out_ch, int in_ch)
97
+{
98
+    float *src0 = samples[0];
99
+    float *src1 = samples[1];
100
+    float *dst  = src0;
101
+    float m0    = matrix[0][0];
102
+    float m1    = matrix[0][1];
103
+
104
+    while (len > 4) {
105
+        *dst++ = *src0++ * m0 + *src1++ * m1;
106
+        *dst++ = *src0++ * m0 + *src1++ * m1;
107
+        *dst++ = *src0++ * m0 + *src1++ * m1;
108
+        *dst++ = *src0++ * m0 + *src1++ * m1;
109
+        len -= 4;
110
+    }
111
+    while (len > 0) {
112
+        *dst++ = *src0++ * m0 + *src1++ * m1;
113
+        len--;
114
+    }
115
+}
116
+
117
+static void mix_1_to_2_fltp_flt_c(float **samples, float **matrix, int len,
118
+                                  int out_ch, int in_ch)
119
+{
120
+    float v;
121
+    float *dst0 = samples[0];
122
+    float *dst1 = samples[1];
123
+    float *src  = dst0;
124
+    float m0    = matrix[0][0];
125
+    float m1    = matrix[1][0];
126
+
127
+    while (len > 4) {
128
+        v = *src++;
129
+        *dst0++ = v * m1;
130
+        *dst1++ = v * m0;
131
+        v = *src++;
132
+        *dst0++ = v * m1;
133
+        *dst1++ = v * m0;
134
+        v = *src++;
135
+        *dst0++ = v * m1;
136
+        *dst1++ = v * m0;
137
+        v = *src++;
138
+        *dst0++ = v * m1;
139
+        *dst1++ = v * m0;
140
+        len -= 4;
141
+    }
142
+    while (len > 0) {
143
+        v = *src++;
144
+        *dst0++ = v * m1;
145
+        *dst1++ = v * m0;
146
+        len--;
147
+    }
148
+}
149
+
150
+static void mix_6_to_2_fltp_flt_c(float **samples, float **matrix, int len,
151
+                                  int out_ch, int in_ch)
152
+{
153
+    float v0, v1;
154
+    float *src0 = samples[0];
155
+    float *src1 = samples[1];
156
+    float *src2 = samples[2];
157
+    float *src3 = samples[3];
158
+    float *src4 = samples[4];
159
+    float *src5 = samples[5];
160
+    float *dst0 = src0;
161
+    float *dst1 = src1;
162
+    float *m0   = matrix[0];
163
+    float *m1   = matrix[1];
164
+
165
+    while (len > 0) {
166
+        v0 = *src0++;
167
+        v1 = *src1++;
168
+        *dst0++ = v0      * m0[0] +
169
+                  v1      * m0[1] +
170
+                  *src2   * m0[2] +
171
+                  *src3   * m0[3] +
172
+                  *src4   * m0[4] +
173
+                  *src5   * m0[5];
174
+        *dst1++ = v0      * m1[0] +
175
+                  v1      * m1[1] +
176
+                  *src2++ * m1[2] +
177
+                  *src3++ * m1[3] +
178
+                  *src4++ * m1[4] +
179
+                  *src5++ * m1[5];
180
+        len--;
181
+    }
182
+}
183
+
184
+static void mix_2_to_6_fltp_flt_c(float **samples, float **matrix, int len,
185
+                                  int out_ch, int in_ch)
186
+{
187
+    float v0, v1;
188
+    float *dst0 = samples[0];
189
+    float *dst1 = samples[1];
190
+    float *dst2 = samples[2];
191
+    float *dst3 = samples[3];
192
+    float *dst4 = samples[4];
193
+    float *dst5 = samples[5];
194
+    float *src0 = dst0;
195
+    float *src1 = dst1;
196
+
197
+    while (len > 0) {
198
+        v0 = *src0++;
199
+        v1 = *src1++;
200
+        *dst0++ = v0 * matrix[0][0] + v1 * matrix[0][1];
201
+        *dst1++ = v0 * matrix[1][0] + v1 * matrix[1][1];
202
+        *dst2++ = v0 * matrix[2][0] + v1 * matrix[2][1];
203
+        *dst3++ = v0 * matrix[3][0] + v1 * matrix[3][1];
204
+        *dst4++ = v0 * matrix[4][0] + v1 * matrix[4][1];
205
+        *dst5++ = v0 * matrix[5][0] + v1 * matrix[5][1];
206
+        len--;
207
+    }
208
+}
209
+
210
+static int mix_function_init(AudioMix *am)
211
+{
212
+    /* any-to-any C versions */
213
+
214
+    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
215
+                          0, 0, 1, 1, "C", MIX_FUNC_NAME(FLTP, FLT));
216
+
217
+    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
218
+                          0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, FLT));
219
+
220
+    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q15,
221
+                          0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q15));
222
+
223
+    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q6,
224
+                          0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q6));
225
+
226
+    /* channel-specific C versions */
227
+
228
+    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
229
+                          2, 1, 1, 1, "C", mix_2_to_1_fltp_flt_c);
230
+
231
+    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
232
+                          1, 2, 1, 1, "C", mix_1_to_2_fltp_flt_c);
233
+
234
+    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
235
+                          6, 2, 1, 1, "C", mix_6_to_2_fltp_flt_c);
236
+
237
+    ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
238
+                          2, 6, 1, 1, "C", mix_2_to_6_fltp_flt_c);
239
+
240
+    if (ARCH_X86)
241
+        ff_audio_mix_init_x86(am);
242
+
243
+    if (!am->mix) {
244
+        av_log(am->avr, AV_LOG_ERROR, "audio_mix: NO FUNCTION FOUND: [fmt=%s] "
245
+               "[c=%s] [%d to %d]\n", av_get_sample_fmt_name(am->fmt),
246
+               coeff_type_names[am->coeff_type], am->in_channels,
247
+               am->out_channels);
248
+        return AVERROR_PATCHWELCOME;
249
+    }
250
+    return 0;
251
+}
252
+
253
+int ff_audio_mix_init(AVAudioResampleContext *avr)
254
+{
255
+    int ret;
256
+
257
+    /* build matrix if the user did not already set one */
258
+    if (!avr->am->matrix) {
259
+        int i, j;
260
+        char in_layout_name[128];
261
+        char out_layout_name[128];
262
+        double *matrix_dbl = av_mallocz(avr->out_channels * avr->in_channels *
263
+                                        sizeof(*matrix_dbl));
264
+        if (!matrix_dbl)
265
+            return AVERROR(ENOMEM);
266
+
267
+        ret = avresample_build_matrix(avr->in_channel_layout,
268
+                                      avr->out_channel_layout,
269
+                                      avr->center_mix_level,
270
+                                      avr->surround_mix_level,
271
+                                      avr->lfe_mix_level, 1, matrix_dbl,
272
+                                      avr->in_channels);
273
+        if (ret < 0) {
274
+            av_free(matrix_dbl);
275
+            return ret;
276
+        }
277
+
278
+        av_get_channel_layout_string(in_layout_name, sizeof(in_layout_name),
279
+                                     avr->in_channels, avr->in_channel_layout);
280
+        av_get_channel_layout_string(out_layout_name, sizeof(out_layout_name),
281
+                                     avr->out_channels, avr->out_channel_layout);
282
+        av_log(avr, AV_LOG_DEBUG, "audio_mix: %s to %s\n",
283
+               in_layout_name, out_layout_name);
284
+        for (i = 0; i < avr->out_channels; i++) {
285
+            for (j = 0; j < avr->in_channels; j++) {
286
+                av_log(avr, AV_LOG_DEBUG, "  %0.3f ",
287
+                       matrix_dbl[i * avr->in_channels + j]);
288
+            }
289
+            av_log(avr, AV_LOG_DEBUG, "\n");
290
+        }
291
+
292
+        ret = avresample_set_matrix(avr, matrix_dbl, avr->in_channels);
293
+        if (ret < 0) {
294
+            av_free(matrix_dbl);
295
+            return ret;
296
+        }
297
+        av_free(matrix_dbl);
298
+    }
299
+
300
+    avr->am->fmt          = avr->internal_sample_fmt;
301
+    avr->am->coeff_type   = avr->mix_coeff_type;
302
+    avr->am->in_layout    = avr->in_channel_layout;
303
+    avr->am->out_layout   = avr->out_channel_layout;
304
+    avr->am->in_channels  = avr->in_channels;
305
+    avr->am->out_channels = avr->out_channels;
306
+
307
+    ret = mix_function_init(avr->am);
308
+    if (ret < 0)
309
+        return ret;
310
+
311
+    return 0;
312
+}
313
+
314
+void ff_audio_mix_close(AudioMix *am)
315
+{
316
+    if (!am)
317
+        return;
318
+    if (am->matrix) {
319
+        av_free(am->matrix[0]);
320
+        am->matrix = NULL;
321
+    }
322
+    memset(am->matrix_q6,  0, sizeof(am->matrix_q6 ));
323
+    memset(am->matrix_q15, 0, sizeof(am->matrix_q15));
324
+    memset(am->matrix_flt, 0, sizeof(am->matrix_flt));
325
+}
326
+
327
+int ff_audio_mix(AudioMix *am, AudioData *src)
328
+{
329
+    int use_generic = 1;
330
+    int len = src->nb_samples;
331
+
332
+    /* determine whether to use the optimized function based on pointer and
333
+       samples alignment in both the input and output */
334
+    if (am->has_optimized_func) {
335
+        int aligned_len = FFALIGN(len, am->samples_align);
336
+        if (!(src->ptr_align % am->ptr_align) &&
337
+            src->samples_align >= aligned_len) {
338
+            len = aligned_len;
339
+            use_generic = 0;
340
+        }
341
+    }
342
+    av_dlog(am->avr, "audio_mix: %d samples - %d to %d channels (%s)\n",
343
+            src->nb_samples, am->in_channels, am->out_channels,
344
+            use_generic ? am->func_descr_generic : am->func_descr);
345
+
346
+    if (use_generic)
347
+        am->mix_generic(src->data, am->matrix, len, am->out_channels,
348
+                        am->in_channels);
349
+    else
350
+        am->mix(src->data, am->matrix, len, am->out_channels, am->in_channels);
351
+
352
+    ff_audio_data_set_channels(src, am->out_channels);
353
+
354
+    return 0;
355
+}
0 356
new file mode 100644
... ...
@@ -0,0 +1,108 @@
0
+/*
1
+ * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
2
+ *
3
+ * This file is part of Libav.
4
+ *
5
+ * Libav is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * Libav is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with Libav; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#ifndef AVRESAMPLE_AUDIO_MIX_H
21
+#define AVRESAMPLE_AUDIO_MIX_H
22
+
23
+#include <stdint.h>
24
+
25
+#include "libavutil/samplefmt.h"
26
+#include "avresample.h"
27
+#include "audio_data.h"
28
+
29
+typedef void (mix_func)(uint8_t **src, void **matrix, int len, int out_ch,
30
+                        int in_ch);
31
+
32
+typedef struct AudioMix {
33
+    AVAudioResampleContext *avr;
34
+    enum AVSampleFormat fmt;
35
+    enum AVMixCoeffType coeff_type;
36
+    uint64_t in_layout;
37
+    uint64_t out_layout;
38
+    int in_channels;
39
+    int out_channels;
40
+
41
+    int ptr_align;
42
+    int samples_align;
43
+    int has_optimized_func;
44
+    const char *func_descr;
45
+    const char *func_descr_generic;
46
+    mix_func *mix;
47
+    mix_func *mix_generic;
48
+
49
+    int16_t *matrix_q6[AVRESAMPLE_MAX_CHANNELS];
50
+    int32_t *matrix_q15[AVRESAMPLE_MAX_CHANNELS];
51
+    float   *matrix_flt[AVRESAMPLE_MAX_CHANNELS];
52
+    void   **matrix;
53
+} AudioMix;
54
+
55
+/**
56
+ * Set mixing function if the parameters match.
57
+ *
58
+ * This compares the parameters of the mixing function to the parameters in the
59
+ * AudioMix context. If the parameters do not match, no changes are made to the
60
+ * active functions. If the parameters do match and the alignment is not
61
+ * constrained, the function is set as the generic mixing function. If the
62
+ * parameters match and the alignment is constrained, the function is set as
63
+ * the optimized mixing function.
64
+ *
65
+ * @param am             AudioMix context
66
+ * @param fmt            input/output sample format
67
+ * @param coeff_type     mixing coefficient type
68
+ * @param in_channels    number of input channels, or 0 for any number of channels
69
+ * @param out_channels   number of output channels, or 0 for any number of channels
70
+ * @param ptr_align      buffer pointer alignment, in bytes
71
+ * @param sample_align   buffer size alignment, in samples
72
+ * @param descr          function type description (e.g. "C" or "SSE")
73
+ * @param mix_func       mixing function pointer
74
+ */
75
+void ff_audio_mix_set_func(AudioMix *am, enum AVSampleFormat fmt,
76
+                           enum AVMixCoeffType coeff_type, int in_channels,
77
+                           int out_channels, int ptr_align, int samples_align,
78
+                           const char *descr, void *mix_func);
79
+
80
+/**
81
+ * Initialize the AudioMix context in the AVAudioResampleContext.
82
+ *
83
+ * The parameters in the AVAudioResampleContext are used to initialize the
84
+ * AudioMix context and set the mixing matrix.
85
+ *
86
+ * @param avr  AVAudioResampleContext
87
+ * @return     0 on success, negative AVERROR code on failure
88
+ */
89
+int ff_audio_mix_init(AVAudioResampleContext *avr);
90
+
91
+/**
92
+ * Close an AudioMix context.
93
+ *
94
+ * This clears and frees the mixing matrix arrays.
95
+ */
96
+void ff_audio_mix_close(AudioMix *am);
97
+
98
+/**
99
+ * Apply channel mixing to audio data using the current mixing matrix.
100
+ */
101
+int ff_audio_mix(AudioMix *am, AudioData *src);
102
+
103
+/* arch-specific initialization functions */
104
+
105
+void ff_audio_mix_init_x86(AudioMix *am);
106
+
107
+#endif /* AVRESAMPLE_AUDIO_MIX_H */
0 108
new file mode 100644
... ...
@@ -0,0 +1,346 @@
0
+/*
1
+ * Copyright (C) 2011 Michael Niedermayer (michaelni@gmx.at)
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
+/* channel positions */
31
+#define FRONT_LEFT              0
32
+#define FRONT_RIGHT             1
33
+#define FRONT_CENTER            2
34
+#define LOW_FREQUENCY           3
35
+#define BACK_LEFT               4
36
+#define BACK_RIGHT              5
37
+#define FRONT_LEFT_OF_CENTER    6
38
+#define FRONT_RIGHT_OF_CENTER   7
39
+#define BACK_CENTER             8
40
+#define SIDE_LEFT               9
41
+#define SIDE_RIGHT             10
42
+#define TOP_CENTER             11
43
+#define TOP_FRONT_LEFT         12
44
+#define TOP_FRONT_CENTER       13
45
+#define TOP_FRONT_RIGHT        14
46
+#define TOP_BACK_LEFT          15
47
+#define TOP_BACK_CENTER        16
48
+#define TOP_BACK_RIGHT         17
49
+#define STEREO_LEFT            29
50
+#define STEREO_RIGHT           30
51
+#define WIDE_LEFT              31
52
+#define WIDE_RIGHT             32
53
+#define SURROUND_DIRECT_LEFT   33
54
+#define SURROUND_DIRECT_RIGHT  34
55
+
56
+static av_always_inline int even(uint64_t layout)
57
+{
58
+    return (!layout || (layout & (layout - 1)));
59
+}
60
+
61
+static int sane_layout(uint64_t layout)
62
+{
63
+    /* check that there is at least 1 front speaker */
64
+    if (!(layout & AV_CH_LAYOUT_SURROUND))
65
+        return 0;
66
+
67
+    /* check for left/right symmetry */
68
+    if (!even(layout & (AV_CH_FRONT_LEFT           | AV_CH_FRONT_RIGHT))           ||
69
+        !even(layout & (AV_CH_SIDE_LEFT            | AV_CH_SIDE_RIGHT))            ||
70
+        !even(layout & (AV_CH_BACK_LEFT            | AV_CH_BACK_RIGHT))            ||
71
+        !even(layout & (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)) ||
72
+        !even(layout & (AV_CH_TOP_FRONT_LEFT       | AV_CH_TOP_FRONT_RIGHT))       ||
73
+        !even(layout & (AV_CH_TOP_BACK_LEFT        | AV_CH_TOP_BACK_RIGHT))        ||
74
+        !even(layout & (AV_CH_STEREO_LEFT          | AV_CH_STEREO_RIGHT))          ||
75
+        !even(layout & (AV_CH_WIDE_LEFT            | AV_CH_WIDE_RIGHT))            ||
76
+        !even(layout & (AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT)))
77
+        return 0;
78
+
79
+    return 1;
80
+}
81
+
82
+int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
83
+                            double center_mix_level, double surround_mix_level,
84
+                            double lfe_mix_level, int normalize,
85
+                            double *matrix_out, int stride)
86
+{
87
+    int i, j, out_i, out_j;
88
+    double matrix[64][64] = {{0}};
89
+    int64_t unaccounted = in_layout & ~out_layout;
90
+    double maxcoef = 0;
91
+    int in_channels, out_channels;
92
+
93
+    in_channels  = av_get_channel_layout_nb_channels( in_layout);
94
+    out_channels = av_get_channel_layout_nb_channels(out_layout);
95
+
96
+    memset(matrix_out, 0, out_channels * stride * sizeof(*matrix_out));
97
+
98
+    /* check if layouts are supported */
99
+    if (!in_layout || in_channels > AVRESAMPLE_MAX_CHANNELS)
100
+        return AVERROR(EINVAL);
101
+    if (!out_layout || out_channels > AVRESAMPLE_MAX_CHANNELS)
102
+        return AVERROR(EINVAL);
103
+
104
+    /* check if layouts are unbalanced or abnormal */
105
+    if (!sane_layout(in_layout) || !sane_layout(out_layout))
106
+        return AVERROR_PATCHWELCOME;
107
+
108
+    /* route matching input/output channels */
109
+    for (i = 0; i < 64; i++) {
110
+        if (in_layout & out_layout & (1ULL << i))
111
+            matrix[i][i] = 1.0;
112
+    }
113
+
114
+    /* mix front center to front left/right */
115
+    if (unaccounted & AV_CH_FRONT_CENTER) {
116
+        if ((out_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO) {
117
+            matrix[FRONT_LEFT ][FRONT_CENTER] += M_SQRT1_2;
118
+            matrix[FRONT_RIGHT][FRONT_CENTER] += M_SQRT1_2;
119
+        } else
120
+            return AVERROR_PATCHWELCOME;
121
+    }
122
+    /* mix front left/right to center */
123
+    if (unaccounted & AV_CH_LAYOUT_STEREO) {
124
+        if (out_layout & AV_CH_FRONT_CENTER) {
125
+            matrix[FRONT_CENTER][FRONT_LEFT ] += M_SQRT1_2;
126
+            matrix[FRONT_CENTER][FRONT_RIGHT] += M_SQRT1_2;
127
+            /* mix left/right/center to center */
128
+            if (in_layout & AV_CH_FRONT_CENTER)
129
+                matrix[FRONT_CENTER][FRONT_CENTER] = center_mix_level * M_SQRT2;
130
+        } else
131
+            return AVERROR_PATCHWELCOME;
132
+    }
133
+    /* mix back center to back, side, or front */
134
+    if (unaccounted & AV_CH_BACK_CENTER) {
135
+        if (out_layout & AV_CH_BACK_LEFT) {
136
+            matrix[BACK_LEFT ][BACK_CENTER] += M_SQRT1_2;
137
+            matrix[BACK_RIGHT][BACK_CENTER] += M_SQRT1_2;
138
+        } else if (out_layout & AV_CH_SIDE_LEFT) {
139
+            matrix[SIDE_LEFT ][BACK_CENTER] += M_SQRT1_2;
140
+            matrix[SIDE_RIGHT][BACK_CENTER] += M_SQRT1_2;
141
+        } else if (out_layout & AV_CH_FRONT_LEFT) {
142
+            matrix[FRONT_LEFT ][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
143
+            matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
144
+        } else if (out_layout & AV_CH_FRONT_CENTER) {
145
+            matrix[FRONT_CENTER][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
146
+        } else
147
+            return AVERROR_PATCHWELCOME;
148
+    }
149
+    /* mix back left/right to back center, side, or front */
150
+    if (unaccounted & AV_CH_BACK_LEFT) {
151
+        if (out_layout & AV_CH_BACK_CENTER) {
152
+            matrix[BACK_CENTER][BACK_LEFT ] += M_SQRT1_2;
153
+            matrix[BACK_CENTER][BACK_RIGHT] += M_SQRT1_2;
154
+        } else if (out_layout & AV_CH_SIDE_LEFT) {
155
+            /* if side channels do not exist in the input, just copy back
156
+               channels to side channels, otherwise mix back into side */
157
+            if (in_layout & AV_CH_SIDE_LEFT) {
158
+                matrix[SIDE_LEFT ][BACK_LEFT ] += M_SQRT1_2;
159
+                matrix[SIDE_RIGHT][BACK_RIGHT] += M_SQRT1_2;
160
+            } else {
161
+                matrix[SIDE_LEFT ][BACK_LEFT ] += 1.0;
162
+                matrix[SIDE_RIGHT][BACK_RIGHT] += 1.0;
163
+            }
164
+        } else if (out_layout & AV_CH_FRONT_LEFT) {
165
+            matrix[FRONT_LEFT ][BACK_LEFT ] += surround_mix_level;
166
+            matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
167
+        } else if (out_layout & AV_CH_FRONT_CENTER) {
168
+            matrix[FRONT_CENTER][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
169
+            matrix[FRONT_CENTER][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
170
+        } else
171
+            return AVERROR_PATCHWELCOME;
172
+    }
173
+    /* mix side left/right into back or front */
174
+    if (unaccounted & AV_CH_SIDE_LEFT) {
175
+        if (out_layout & AV_CH_BACK_LEFT) {
176
+            /* if back channels do not exist in the input, just copy side
177
+               channels to back channels, otherwise mix side into back */
178
+            if (in_layout & AV_CH_BACK_LEFT) {
179
+                matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
180
+                matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
181
+            } else {
182
+                matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
183
+                matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
184
+            }
185
+        } else if (out_layout & AV_CH_BACK_CENTER) {
186
+            matrix[BACK_CENTER][SIDE_LEFT ] += M_SQRT1_2;
187
+            matrix[BACK_CENTER][SIDE_RIGHT] += M_SQRT1_2;
188
+        } else if (out_layout & AV_CH_FRONT_LEFT) {
189
+            matrix[FRONT_LEFT ][SIDE_LEFT ] += surround_mix_level;
190
+            matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
191
+        } else if (out_layout & AV_CH_FRONT_CENTER) {
192
+            matrix[FRONT_CENTER][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
193
+            matrix[FRONT_CENTER][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
194
+        } else
195
+            return AVERROR_PATCHWELCOME;
196
+    }
197
+    /* mix left-of-center/right-of-center into front left/right or center */
198
+    if (unaccounted & AV_CH_FRONT_LEFT_OF_CENTER) {
199
+        if (out_layout & AV_CH_FRONT_LEFT) {
200
+            matrix[FRONT_LEFT ][FRONT_LEFT_OF_CENTER ] += 1.0;
201
+            matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER] += 1.0;
202
+        } else if (out_layout & AV_CH_FRONT_CENTER) {
203
+            matrix[FRONT_CENTER][FRONT_LEFT_OF_CENTER ] += M_SQRT1_2;
204
+            matrix[FRONT_CENTER][FRONT_RIGHT_OF_CENTER] += M_SQRT1_2;
205
+        } else
206
+            return AVERROR_PATCHWELCOME;
207
+    }
208
+    /* mix LFE into front left/right or center */
209
+    if (unaccounted & AV_CH_LOW_FREQUENCY) {
210
+        if (out_layout & AV_CH_FRONT_CENTER) {
211
+            matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level;
212
+        } else if (out_layout & AV_CH_FRONT_LEFT) {
213
+            matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
214
+            matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
215
+        } else
216
+            return AVERROR_PATCHWELCOME;
217
+    }
218
+
219
+    /* transfer internal matrix to output matrix and calculate maximum
220
+       per-channel coefficient sum */
221
+    for (out_i = i = 0; out_i < out_channels && i < 64; i++) {
222
+        double sum = 0;
223
+        for (out_j = j = 0; out_j < in_channels && j < 64; j++) {
224
+            matrix_out[out_i * stride + out_j] = matrix[i][j];
225
+            sum += fabs(matrix[i][j]);
226
+            if (in_layout & (1ULL << j))
227
+                out_j++;
228
+        }
229
+        maxcoef = FFMAX(maxcoef, sum);
230
+        if (out_layout & (1ULL << i))
231
+            out_i++;
232
+    }
233
+
234
+    /* normalize */
235
+    if (normalize && maxcoef > 1.0) {
236
+        for (i = 0; i < out_channels; i++)
237
+            for (j = 0; j < in_channels; j++)
238
+                matrix_out[i * stride + j] /= maxcoef;
239
+    }
240
+
241
+    return 0;
242
+}
243
+
244
+int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix,
245
+                          int stride)
246
+{
247
+    int in_channels, out_channels, i, o;
248
+
249
+    in_channels  = av_get_channel_layout_nb_channels(avr->in_channel_layout);
250
+    out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
251
+
252
+    if ( in_channels < 0 ||  in_channels > AVRESAMPLE_MAX_CHANNELS ||
253
+        out_channels < 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
254
+        av_log(avr, AV_LOG_ERROR, "Invalid channel layouts\n");
255
+        return AVERROR(EINVAL);
256
+    }
257
+
258
+    switch (avr->mix_coeff_type) {
259
+    case AV_MIX_COEFF_TYPE_Q6:
260
+        if (!avr->am->matrix_q6[0]) {
261
+            av_log(avr, AV_LOG_ERROR, "matrix is not set\n");
262
+            return AVERROR(EINVAL);
263
+        }
264
+        for (o = 0; o < out_channels; o++)
265
+            for (i = 0; i < in_channels; i++)
266
+                matrix[o * stride + i] = avr->am->matrix_q6[o][i] / 64.0;
267
+        break;
268
+    case AV_MIX_COEFF_TYPE_Q15:
269
+        if (!avr->am->matrix_q15[0]) {
270
+            av_log(avr, AV_LOG_ERROR, "matrix is not set\n");
271
+            return AVERROR(EINVAL);
272
+        }
273
+        for (o = 0; o < out_channels; o++)
274
+            for (i = 0; i < in_channels; i++)
275
+                matrix[o * stride + i] = avr->am->matrix_q15[o][i] / 32768.0;
276
+        break;
277
+    case AV_MIX_COEFF_TYPE_FLT:
278
+        if (!avr->am->matrix_flt[0]) {
279
+            av_log(avr, AV_LOG_ERROR, "matrix is not set\n");
280
+            return AVERROR(EINVAL);
281
+        }
282
+        for (o = 0; o < out_channels; o++)
283
+            for (i = 0; i < in_channels; i++)
284
+                matrix[o * stride + i] = avr->am->matrix_flt[o][i];
285
+        break;
286
+    default:
287
+        av_log(avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
288
+        return AVERROR(EINVAL);
289
+    }
290
+    return 0;
291
+}
292
+
293
+int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix,
294
+                          int stride)
295
+{
296
+    int in_channels, out_channels, i, o;
297
+
298
+    in_channels  = av_get_channel_layout_nb_channels(avr->in_channel_layout);
299
+    out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
300
+
301
+    if ( in_channels < 0 ||  in_channels > AVRESAMPLE_MAX_CHANNELS ||
302
+        out_channels < 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
303
+        av_log(avr, AV_LOG_ERROR, "Invalid channel layouts\n");
304
+        return AVERROR(EINVAL);
305
+    }
306
+
307
+    if (avr->am->matrix)
308
+        av_freep(avr->am->matrix);
309
+
310
+#define CONVERT_MATRIX(type, expr)                                          \
311
+    avr->am->matrix_## type[0] = av_mallocz(out_channels * in_channels *    \
312
+                                            sizeof(*avr->am->matrix_## type[0])); \
313
+    if (!avr->am->matrix_## type[0])                                        \
314
+        return AVERROR(ENOMEM);                                             \
315
+    for (o = 0; o < out_channels; o++) {                                    \
316
+        if (o > 0)                                                          \
317
+            avr->am->matrix_## type[o] = avr->am->matrix_## type[o - 1] +   \
318
+                                         in_channels;                       \
319
+        for (i = 0; i < in_channels; i++) {                                 \
320
+            double v = matrix[o * stride + i];                              \
321
+            avr->am->matrix_## type[o][i] = expr;                           \
322
+        }                                                                   \
323
+    }                                                                       \
324
+    avr->am->matrix = (void **)avr->am->matrix_## type;
325
+
326
+    switch (avr->mix_coeff_type) {
327
+    case AV_MIX_COEFF_TYPE_Q6:
328
+        CONVERT_MATRIX(q6, av_clip_int16(lrint(64.0 * v)))
329
+        break;
330
+    case AV_MIX_COEFF_TYPE_Q15:
331
+        CONVERT_MATRIX(q15, av_clipl_int32(llrint(32768.0 * v)))
332
+        break;
333
+    case AV_MIX_COEFF_TYPE_FLT:
334
+        CONVERT_MATRIX(flt, v)
335
+        break;
336
+    default:
337
+        av_log(avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
338
+        return AVERROR(EINVAL);
339
+    }
340
+
341
+    /* TODO: detect situations where we can just swap around pointers
342
+             instead of doing matrix multiplications with 0.0 and 1.0 */
343
+
344
+    return 0;
345
+}
0 346
new file mode 100644
... ...
@@ -0,0 +1,340 @@
0
+/*
1
+ * Copyright (c) 2002 Fabrice Bellard
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
+#include <stdio.h>
23
+
24
+#include "libavutil/avstring.h"
25
+#include "libavutil/lfg.h"
26
+#include "libavutil/libm.h"
27
+#include "libavutil/log.h"
28
+#include "libavutil/mem.h"
29
+#include "libavutil/opt.h"
30
+#include "libavutil/samplefmt.h"
31
+#include "avresample.h"
32
+
33
+static double dbl_rand(AVLFG *lfg)
34
+{
35
+    return 2.0 * (av_lfg_get(lfg) / (double)UINT_MAX) - 1.0;
36
+}
37
+
38
+#define PUT_FUNC(name, fmt, type, expr)                                     \
39
+static void put_sample_ ## name(void **data, enum AVSampleFormat sample_fmt,\
40
+                                int channels, int sample, int ch,           \
41
+                                double v_dbl)                               \
42
+{                                                                           \
43
+    type v = expr;                                                          \
44
+    type **out = (type **)data;                                             \
45
+    if (av_sample_fmt_is_planar(sample_fmt))                                \
46
+        out[ch][sample] = v;                                                \
47
+    else                                                                    \
48
+        out[0][sample * channels + ch] = v;                                 \
49
+}
50
+
51
+PUT_FUNC(u8,  AV_SAMPLE_FMT_U8,  uint8_t, av_clip_uint8 ( lrint(v_dbl * (1  <<  7)) + 128))
52
+PUT_FUNC(s16, AV_SAMPLE_FMT_S16, int16_t, av_clip_int16 ( lrint(v_dbl * (1  << 15))))
53
+PUT_FUNC(s32, AV_SAMPLE_FMT_S32, int32_t, av_clipl_int32(llrint(v_dbl * (1U << 31))))
54
+PUT_FUNC(flt, AV_SAMPLE_FMT_FLT, float,   v_dbl)
55
+PUT_FUNC(dbl, AV_SAMPLE_FMT_DBL, double,  v_dbl)
56
+
57
+static void put_sample(void **data, enum AVSampleFormat sample_fmt,
58
+                       int channels, int sample, int ch, double v_dbl)
59
+{
60
+    switch (av_get_packed_sample_fmt(sample_fmt)) {
61
+    case AV_SAMPLE_FMT_U8:
62
+        put_sample_u8(data, sample_fmt, channels, sample, ch, v_dbl);
63
+        break;
64
+    case AV_SAMPLE_FMT_S16:
65
+        put_sample_s16(data, sample_fmt, channels, sample, ch, v_dbl);
66
+        break;
67
+    case AV_SAMPLE_FMT_S32:
68
+        put_sample_s32(data, sample_fmt, channels, sample, ch, v_dbl);
69
+        break;
70
+    case AV_SAMPLE_FMT_FLT:
71
+        put_sample_flt(data, sample_fmt, channels, sample, ch, v_dbl);
72
+        break;
73
+    case AV_SAMPLE_FMT_DBL:
74
+        put_sample_dbl(data, sample_fmt, channels, sample, ch, v_dbl);
75
+        break;
76
+    }
77
+}
78
+
79
+static void audiogen(AVLFG *rnd, void **data, enum AVSampleFormat sample_fmt,
80
+                     int channels, int sample_rate, int nb_samples)
81
+{
82
+    int i, ch, k;
83
+    double v, f, a, ampa;
84
+    double tabf1[AVRESAMPLE_MAX_CHANNELS];
85
+    double tabf2[AVRESAMPLE_MAX_CHANNELS];
86
+    double taba[AVRESAMPLE_MAX_CHANNELS];
87
+
88
+#define PUT_SAMPLE put_sample(data, sample_fmt, channels, k, ch, v);
89
+
90
+    k = 0;
91
+
92
+    /* 1 second of single freq sinus at 1000 Hz */
93
+    a = 0;
94
+    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
95
+        v = sin(a) * 0.30;
96
+        for (ch = 0; ch < channels; ch++)
97
+            PUT_SAMPLE
98
+        a += M_PI * 1000.0 * 2.0 / sample_rate;
99
+    }
100
+
101
+    /* 1 second of varing frequency between 100 and 10000 Hz */
102
+    a = 0;
103
+    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
104
+        v = sin(a) * 0.30;
105
+        for (ch = 0; ch < channels; ch++)
106
+            PUT_SAMPLE
107
+        f  = 100.0 + (((10000.0 - 100.0) * i) / sample_rate);
108
+        a += M_PI * f * 2.0 / sample_rate;
109
+    }
110
+
111
+    /* 0.5 second of low amplitude white noise */
112
+    for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
113
+        v = dbl_rand(rnd) * 0.30;
114
+        for (ch = 0; ch < channels; ch++)
115
+            PUT_SAMPLE
116
+    }
117
+
118
+    /* 0.5 second of high amplitude white noise */
119
+    for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
120
+        v = dbl_rand(rnd);
121
+        for (ch = 0; ch < channels; ch++)
122
+            PUT_SAMPLE
123
+    }
124
+
125
+    /* 1 second of unrelated ramps for each channel */
126
+    for (ch = 0; ch < channels; ch++) {
127
+        taba[ch]  = 0;
128
+        tabf1[ch] = 100 + av_lfg_get(rnd) % 5000;
129
+        tabf2[ch] = 100 + av_lfg_get(rnd) % 5000;
130
+    }
131
+    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
132
+        for (ch = 0; ch < channels; ch++) {
133
+            v = sin(taba[ch]) * 0.30;
134
+            PUT_SAMPLE
135
+            f = tabf1[ch] + (((tabf2[ch] - tabf1[ch]) * i) / sample_rate);
136
+            taba[ch] += M_PI * f * 2.0 / sample_rate;
137
+        }
138
+    }
139
+
140
+    /* 2 seconds of 500 Hz with varying volume */
141
+    a    = 0;
142
+    ampa = 0;
143
+    for (i = 0; i < 2 * sample_rate && k < nb_samples; i++, k++) {
144
+        for (ch = 0; ch < channels; ch++) {
145
+            double amp = (1.0 + sin(ampa)) * 0.15;
146
+            if (ch & 1)
147
+                amp = 0.30 - amp;
148
+            v = sin(a) * amp;
149
+            PUT_SAMPLE
150
+            a    += M_PI * 500.0 * 2.0 / sample_rate;
151
+            ampa += M_PI *  2.0 / sample_rate;
152
+        }
153
+    }
154
+}
155
+
156
+/* formats, rates, and layouts are ordered for priority in testing.
157
+   e.g. 'avresample-test 4 2 2' will test all input/output combinations of
158
+   S16/FLTP/S16P/FLT, 48000/44100, and stereo/mono */
159
+
160
+static const enum AVSampleFormat formats[] = {
161
+    AV_SAMPLE_FMT_S16,
162
+    AV_SAMPLE_FMT_FLTP,
163
+    AV_SAMPLE_FMT_S16P,
164
+    AV_SAMPLE_FMT_FLT,
165
+    AV_SAMPLE_FMT_S32P,
166
+    AV_SAMPLE_FMT_S32,
167
+    AV_SAMPLE_FMT_U8P,
168
+    AV_SAMPLE_FMT_U8,
169
+    AV_SAMPLE_FMT_DBLP,
170
+    AV_SAMPLE_FMT_DBL,
171
+};
172
+
173
+static const int rates[] = {
174
+    48000,
175
+    44100,
176
+    16000
177
+};
178
+
179
+static const uint64_t layouts[] = {
180
+    AV_CH_LAYOUT_STEREO,
181
+    AV_CH_LAYOUT_MONO,
182
+    AV_CH_LAYOUT_5POINT1,
183
+    AV_CH_LAYOUT_7POINT1,
184
+};
185
+
186
+int main(int argc, char **argv)
187
+{
188
+    AVAudioResampleContext *s;
189
+    AVLFG rnd;
190
+    int ret = 0;
191
+    uint8_t *in_buf = NULL;
192
+    uint8_t *out_buf = NULL;
193
+    unsigned int in_buf_size;
194
+    unsigned int out_buf_size;
195
+    uint8_t  *in_data[AVRESAMPLE_MAX_CHANNELS] = { 0 };
196
+    uint8_t *out_data[AVRESAMPLE_MAX_CHANNELS] = { 0 };
197
+    int in_linesize;
198
+    int out_linesize;
199
+    uint64_t in_ch_layout;
200
+    int in_channels;
201
+    enum AVSampleFormat in_fmt;
202
+    int in_rate;
203
+    uint64_t out_ch_layout;
204
+    int out_channels;
205
+    enum AVSampleFormat out_fmt;
206
+    int out_rate;
207
+    int num_formats, num_rates, num_layouts;
208
+    int i, j, k, l, m, n;
209
+
210
+    num_formats = 2;
211
+    num_rates   = 2;
212
+    num_layouts = 2;
213
+    if (argc > 1) {
214
+        if (!av_strncasecmp(argv[1], "-h", 3)) {
215
+            av_log(NULL, AV_LOG_INFO, "Usage: avresample-test [<num formats> "
216
+                   "[<num sample rates> [<num channel layouts>]]]\n"
217
+                   "Default is 2 2 2\n");
218
+            return 0;
219
+        }
220
+        num_formats = strtol(argv[1], NULL, 0);
221
+        num_formats = av_clip(num_formats, 1, FF_ARRAY_ELEMS(formats));
222
+    }
223
+    if (argc > 2) {
224
+        num_rates = strtol(argv[2], NULL, 0);
225
+        num_rates = av_clip(num_rates, 1, FF_ARRAY_ELEMS(rates));
226
+    }
227
+    if (argc > 3) {
228
+        num_layouts = strtol(argv[3], NULL, 0);
229
+        num_layouts = av_clip(num_layouts, 1, FF_ARRAY_ELEMS(layouts));
230
+    }
231
+
232
+    av_log_set_level(AV_LOG_DEBUG);
233
+
234
+    av_lfg_init(&rnd, 0xC0FFEE);
235
+
236
+    in_buf_size = av_samples_get_buffer_size(&in_linesize, 8, 48000 * 6,
237
+                                             AV_SAMPLE_FMT_DBLP, 0);
238
+    out_buf_size = in_buf_size;
239
+
240
+    in_buf = av_malloc(in_buf_size);
241
+    if (!in_buf)
242
+        goto end;
243
+    out_buf = av_malloc(out_buf_size);
244
+    if (!out_buf)
245
+        goto end;
246
+
247
+    s = avresample_alloc_context();
248
+    if (!s) {
249
+        av_log(NULL, AV_LOG_ERROR, "Error allocating AVAudioResampleContext\n");
250
+        ret = 1;
251
+        goto end;
252
+    }
253
+
254
+    for (i = 0; i < num_formats; i++) {
255
+        in_fmt = formats[i];
256
+        for (k = 0; k < num_layouts; k++) {
257
+            in_ch_layout = layouts[k];
258
+            in_channels  = av_get_channel_layout_nb_channels(in_ch_layout);
259
+            for (m = 0; m < num_rates; m++) {
260
+                in_rate = rates[m];
261
+
262
+                ret = av_samples_fill_arrays(in_data, &in_linesize, in_buf,
263
+                                             in_channels, in_rate * 6,
264
+                                             in_fmt, 0);
265
+                if (ret < 0) {
266
+                    av_log(s, AV_LOG_ERROR, "failed in_data fill arrays\n");
267
+                    goto end;
268
+                }
269
+                audiogen(&rnd, (void **)in_data, in_fmt, in_channels, in_rate, in_rate * 6);
270
+
271
+                for (j = 0; j < num_formats; j++) {
272
+                    out_fmt = formats[j];
273
+                    for (l = 0; l < num_layouts; l++) {
274
+                        out_ch_layout = layouts[l];
275
+                        out_channels  = av_get_channel_layout_nb_channels(out_ch_layout);
276
+                        for (n = 0; n < num_rates; n++) {
277
+                            out_rate = rates[n];
278
+
279
+                            av_log(NULL, AV_LOG_INFO, "%s to %s, %d to %d channels, %d Hz to %d Hz\n",
280
+                                   av_get_sample_fmt_name(in_fmt), av_get_sample_fmt_name(out_fmt),
281
+                                   in_channels, out_channels, in_rate, out_rate);
282
+
283
+                            ret = av_samples_fill_arrays(out_data, &out_linesize,
284
+                                                         out_buf, out_channels,
285
+                                                         out_rate * 6, out_fmt, 0);
286
+                            if (ret < 0) {
287
+                                av_log(s, AV_LOG_ERROR, "failed out_data fill arrays\n");
288
+                                goto end;
289
+                            }
290
+
291
+                            av_opt_set_int(s, "in_channel_layout",  in_ch_layout,  0);
292
+                            av_opt_set_int(s, "in_sample_fmt",      in_fmt,        0);
293
+                            av_opt_set_int(s, "in_sample_rate",     in_rate,       0);
294
+                            av_opt_set_int(s, "out_channel_layout", out_ch_layout, 0);
295
+                            av_opt_set_int(s, "out_sample_fmt",     out_fmt,       0);
296
+                            av_opt_set_int(s, "out_sample_rate",    out_rate,      0);
297
+
298
+                            av_opt_set_int(s, "internal_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
299
+
300
+                            ret = avresample_open(s);
301
+                            if (ret < 0) {
302
+                                av_log(s, AV_LOG_ERROR, "Error opening context\n");
303
+                                goto end;
304
+                            }
305
+
306
+                            ret = avresample_convert(s, (void **)out_data, out_linesize, out_rate * 6,
307
+                                                        (void **) in_data,  in_linesize,  in_rate * 6);
308
+                            if (ret < 0) {
309
+                                char errbuf[256];
310
+                                av_strerror(ret, errbuf, sizeof(errbuf));
311
+                                av_log(NULL, AV_LOG_ERROR, "%s\n", errbuf);
312
+                                goto end;
313
+                            }
314
+                            av_log(NULL, AV_LOG_INFO, "Converted %d samples to %d samples\n",
315
+                                   in_rate * 6, ret);
316
+                            if (avresample_get_delay(s) > 0)
317
+                                av_log(NULL, AV_LOG_INFO, "%d delay samples not converted\n",
318
+                                       avresample_get_delay(s));
319
+                            if (avresample_available(s) > 0)
320
+                                av_log(NULL, AV_LOG_INFO, "%d samples available for output\n",
321
+                                       avresample_available(s));
322
+                            av_log(NULL, AV_LOG_INFO, "\n");
323
+
324
+                            avresample_close(s);
325
+                        }
326
+                    }
327
+                }
328
+            }
329
+        }
330
+    }
331
+
332
+    ret = 0;
333
+
334
+end:
335
+    av_freep(&in_buf);
336
+    av_freep(&out_buf);
337
+    avresample_free(&s);
338
+    return ret;
339
+}
0 340
new file mode 100644
... ...
@@ -0,0 +1,283 @@
0
+/*
1
+ * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
2
+ *
3
+ * This file is part of Libav.
4
+ *
5
+ * Libav is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * Libav is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with Libav; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#ifndef AVRESAMPLE_AVRESAMPLE_H
21
+#define AVRESAMPLE_AVRESAMPLE_H
22
+
23
+/**
24
+ * @file
25
+ * external API header
26
+ */
27
+
28
+#include "libavutil/audioconvert.h"
29
+#include "libavutil/avutil.h"
30
+#include "libavutil/dict.h"
31
+#include "libavutil/log.h"
32
+
33
+#include "libavresample/version.h"
34
+
35
+#define AVRESAMPLE_MAX_CHANNELS 32
36
+
37
+typedef struct AVAudioResampleContext AVAudioResampleContext;
38
+
39
+/** Mixing Coefficient Types */
40
+enum AVMixCoeffType {
41
+    AV_MIX_COEFF_TYPE_Q6,   /** 16-bit 10.6 fixed-point                     */
42
+    AV_MIX_COEFF_TYPE_Q15,  /** 32-bit 17.15 fixed-point                    */
43
+    AV_MIX_COEFF_TYPE_FLT,  /** floating-point                              */
44
+    AV_MIX_COEFF_TYPE_NB,   /** Number of coeff types. Not part of ABI      */
45
+};
46
+
47
+/**
48
+ * Return the LIBAVRESAMPLE_VERSION_INT constant.
49
+ */
50
+unsigned avresample_version(void);
51
+
52
+/**
53
+ * Return the libavresample build-time configuration.
54
+ * @return  configure string
55
+ */
56
+const char *avresample_configuration(void);
57
+
58
+/**
59
+ * Return the libavresample license.
60
+ */
61
+const char *avresample_license(void);
62
+
63
+/**
64
+ * Get the AVClass for AVAudioResampleContext.
65
+ *
66
+ * Can be used in combination with AV_OPT_SEARCH_FAKE_OBJ for examining options
67
+ * without allocating a context.
68
+ *
69
+ * @see av_opt_find().
70
+ *
71
+ * @return AVClass for AVAudioResampleContext
72
+ */
73
+const AVClass *avresample_get_class(void);
74
+
75
+/**
76
+ * Allocate AVAudioResampleContext and set options.
77
+ *
78
+ * @return  allocated audio resample context, or NULL on failure
79
+ */
80
+AVAudioResampleContext *avresample_alloc_context(void);
81
+
82
+/**
83
+ * Initialize AVAudioResampleContext.
84
+ *
85
+ * @param avr  audio resample context
86
+ * @return     0 on success, negative AVERROR code on failure
87
+ */
88
+int avresample_open(AVAudioResampleContext *avr);
89
+
90
+/**
91
+ * Close AVAudioResampleContext.
92
+ *
93
+ * This closes the context, but it does not change the parameters. The context
94
+ * can be reopened with avresample_open(). It does, however, clear the output
95
+ * FIFO and any remaining leftover samples in the resampling delay buffer. If
96
+ * there was a custom matrix being used, that is also cleared.
97
+ *
98
+ * @see avresample_convert()
99
+ * @see avresample_set_matrix()
100
+ *
101
+ * @param avr  audio resample context
102
+ */
103
+void avresample_close(AVAudioResampleContext *avr);
104
+
105
+/**
106
+ * Free AVAudioResampleContext and associated AVOption values.
107
+ *
108
+ * This also calls avresample_close() before freeing.
109
+ *
110
+ * @param avr  audio resample context
111
+ */
112
+void avresample_free(AVAudioResampleContext **avr);
113
+
114
+/**
115
+ * Generate a channel mixing matrix.
116
+ *
117
+ * This function is the one used internally by libavresample for building the
118
+ * default mixing matrix. It is made public just as a utility function for
119
+ * building custom matrices.
120
+ *
121
+ * @param in_layout           input channel layout
122
+ * @param out_layout          output channel layout
123
+ * @param center_mix_level    mix level for the center channel
124
+ * @param surround_mix_level  mix level for the surround channel(s)
125
+ * @param lfe_mix_level       mix level for the low-frequency effects channel
126
+ * @param normalize           if 1, coefficients will be normalized to prevent
127
+ *                            overflow. if 0, coefficients will not be
128
+ *                            normalized.
129
+ * @param[out] matrix         mixing coefficients; matrix[i + stride * o] is
130
+ *                            the weight of input channel i in output channel o.
131
+ * @param stride              distance between adjacent input channels in the
132
+ *                            matrix array
133
+ * @return                    0 on success, negative AVERROR code on failure
134
+ */
135
+int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
136
+                            double center_mix_level, double surround_mix_level,
137
+                            double lfe_mix_level, int normalize, double *matrix,
138
+                            int stride);
139
+
140
+/**
141
+ * Get the current channel mixing matrix.
142
+ *
143
+ * @param avr     audio resample context
144
+ * @param matrix  mixing coefficients; matrix[i + stride * o] is the weight of
145
+ *                input channel i in output channel o.
146
+ * @param stride  distance between adjacent input channels in the matrix array
147
+ * @return        0 on success, negative AVERROR code on failure
148
+ */
149
+int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix,
150
+                          int stride);
151
+
152
+/**
153
+ * Set channel mixing matrix.
154
+ *
155
+ * Allows for setting a custom mixing matrix, overriding the default matrix
156
+ * generated internally during avresample_open(). This function can be called
157
+ * anytime on an allocated context, either before or after calling
158
+ * avresample_open(). avresample_convert() always uses the current matrix.
159
+ * Calling avresample_close() on the context will clear the current matrix.
160
+ *
161
+ * @see avresample_close()
162
+ *
163
+ * @param avr     audio resample context
164
+ * @param matrix  mixing coefficients; matrix[i + stride * o] is the weight of
165
+ *                input channel i in output channel o.
166
+ * @param stride  distance between adjacent input channels in the matrix array
167
+ * @return        0 on success, negative AVERROR code on failure
168
+ */
169
+int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix,
170
+                          int stride);
171
+
172
+/**
173
+ * Set compensation for resampling.
174
+ *
175
+ * This can be called anytime after avresample_open(). If resampling was not
176
+ * being done previously, the AVAudioResampleContext is closed and reopened
177
+ * with resampling enabled. In this case, any samples remaining in the output
178
+ * FIFO and the current channel mixing matrix will be restored after reopening
179
+ * the context.
180
+ *
181
+ * @param avr                    audio resample context
182
+ * @param sample_delta           compensation delta, in samples
183
+ * @param compensation_distance  compensation distance, in samples
184
+ * @return                       0 on success, negative AVERROR code on failure
185
+ */
186
+int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta,
187
+                                int compensation_distance);
188
+
189
+/**
190
+ * Convert input samples and write them to the output FIFO.
191
+ *
192
+ * The output data can be NULL or have fewer allocated samples than required.
193
+ * In this case, any remaining samples not written to the output will be added
194
+ * to an internal FIFO buffer, to be returned at the next call to this function
195
+ * or to avresample_read().
196
+ *
197
+ * If converting sample rate, there may be data remaining in the internal
198
+ * resampling delay buffer. avresample_get_delay() tells the number of remaining
199
+ * samples. To get this data as output, call avresample_convert() with NULL
200
+ * input.
201
+ *
202
+ * At the end of the conversion process, there may be data remaining in the
203
+ * internal FIFO buffer. avresample_available() tells the number of remaining
204
+ * samples. To get this data as output, either call avresample_convert() with
205
+ * NULL input or call avresample_read().
206
+ *
207
+ * @see avresample_available()
208
+ * @see avresample_read()
209
+ * @see avresample_get_delay()
210
+ *
211
+ * @param avr             audio resample context
212
+ * @param output          output data pointers
213
+ * @param out_plane_size  output plane size, in bytes.
214
+ *                        This can be 0 if unknown, but that will lead to
215
+ *                        optimized functions not being used directly on the
216
+ *                        output, which could slow down some conversions.
217
+ * @param out_samples     maximum number of samples that the output buffer can hold
218
+ * @param input           input data pointers
219
+ * @param in_plane_size   input plane size, in bytes
220
+ *                        This can be 0 if unknown, but that will lead to
221
+ *                        optimized functions not being used directly on the
222
+ *                        input, which could slow down some conversions.
223
+ * @param in_samples      number of input samples to convert
224
+ * @return                number of samples written to the output buffer,
225
+ *                        not including converted samples added to the internal
226
+ *                        output FIFO
227
+ */
228
+int avresample_convert(AVAudioResampleContext *avr, void **output,
229
+                       int out_plane_size, int out_samples, void **input,
230
+                       int in_plane_size, int in_samples);
231
+
232
+/**
233
+ * Return the number of samples currently in the resampling delay buffer.
234
+ *
235
+ * When resampling, there may be a delay between the input and output. Any
236
+ * unconverted samples in each call are stored internally in a delay buffer.
237
+ * This function allows the user to determine the current number of samples in
238
+ * the delay buffer, which can be useful for synchronization.
239
+ *
240
+ * @see avresample_convert()
241
+ *
242
+ * @param avr  audio resample context
243
+ * @return     number of samples currently in the resampling delay buffer
244
+ */
245
+int avresample_get_delay(AVAudioResampleContext *avr);
246
+
247
+/**
248
+ * Return the number of available samples in the output FIFO.
249
+ *
250
+ * During conversion, if the user does not specify an output buffer or
251
+ * specifies an output buffer that is smaller than what is needed, remaining
252
+ * samples that are not written to the output are stored to an internal FIFO
253
+ * buffer. The samples in the FIFO can be read with avresample_read() or
254
+ * avresample_convert().
255
+ *
256
+ * @see avresample_read()
257
+ * @see avresample_convert()
258
+ *
259
+ * @param avr  audio resample context
260
+ * @return     number of samples available for reading
261
+ */
262
+int avresample_available(AVAudioResampleContext *avr);
263
+
264
+/**
265
+ * Read samples from the output FIFO.
266
+ *
267
+ * During conversion, if the user does not specify an output buffer or
268
+ * specifies an output buffer that is smaller than what is needed, remaining
269
+ * samples that are not written to the output are stored to an internal FIFO
270
+ * buffer. This function can be used to read samples from that internal FIFO.
271
+ *
272
+ * @see avresample_available()
273
+ * @see avresample_convert()
274
+ *
275
+ * @param avr         audio resample context
276
+ * @param output      output data pointers
277
+ * @param nb_samples  number of samples to read from the FIFO
278
+ * @return            the number of samples written to output
279
+ */
280
+int avresample_read(AVAudioResampleContext *avr, void **output, int nb_samples);
281
+
282
+#endif /* AVRESAMPLE_AVRESAMPLE_H */
0 283
new file mode 100644
... ...
@@ -0,0 +1,75 @@
0
+/*
1
+ * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
2
+ *
3
+ * This file is part of Libav.
4
+ *
5
+ * Libav is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * Libav is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with Libav; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#ifndef AVRESAMPLE_INTERNAL_H
21
+#define AVRESAMPLE_INTERNAL_H
22
+
23
+#include "libavutil/audio_fifo.h"
24
+#include "libavutil/log.h"
25
+#include "libavutil/opt.h"
26
+#include "libavutil/samplefmt.h"
27
+#include "avresample.h"
28
+#include "audio_convert.h"
29
+#include "audio_data.h"
30
+#include "audio_mix.h"
31
+#include "resample.h"
32
+
33
+struct AVAudioResampleContext {
34
+    const AVClass *av_class;        /**< AVClass for logging and AVOptions  */
35
+
36
+    uint64_t in_channel_layout;                 /**< input channel layout   */
37
+    enum AVSampleFormat in_sample_fmt;          /**< input sample format    */
38
+    int in_sample_rate;                         /**< input sample rate      */
39
+    uint64_t out_channel_layout;                /**< output channel layout  */
40
+    enum AVSampleFormat out_sample_fmt;         /**< output sample format   */
41
+    int out_sample_rate;                        /**< output sample rate     */
42
+    enum AVSampleFormat internal_sample_fmt;    /**< internal sample format */
43
+    enum AVMixCoeffType mix_coeff_type;         /**< mixing coefficient type */
44
+    double center_mix_level;                    /**< center mix level       */
45
+    double surround_mix_level;                  /**< surround mix level     */
46
+    double lfe_mix_level;                       /**< lfe mix level          */
47
+    int force_resampling;                       /**< force resampling       */
48
+    int filter_size;                            /**< length of each FIR filter in the resampling filterbank relative to the cutoff frequency */
49
+    int phase_shift;                            /**< log2 of the number of entries in the resampling polyphase filterbank */
50
+    int linear_interp;                          /**< if 1 then the resampling FIR filter will be linearly interpolated */
51
+    double cutoff;                              /**< resampling cutoff frequency. 1.0 corresponds to half the output sample rate */
52
+
53
+    int in_channels;        /**< number of input channels                   */
54
+    int out_channels;       /**< number of output channels                  */
55
+    int resample_channels;  /**< number of channels used for resampling     */
56
+    int downmix_needed;     /**< downmixing is needed                       */
57
+    int upmix_needed;       /**< upmixing is needed                         */
58
+    int mixing_needed;      /**< either upmixing or downmixing is needed    */
59
+    int resample_needed;    /**< resampling is needed                       */
60
+    int in_convert_needed;  /**< input sample format conversion is needed   */
61
+    int out_convert_needed; /**< output sample format conversion is needed  */
62
+
63
+    AudioData *in_buffer;           /**< buffer for converted input         */
64
+    AudioData *resample_out_buffer; /**< buffer for output from resampler   */
65
+    AudioData *out_buffer;          /**< buffer for converted output        */
66
+    AVAudioFifo *out_fifo;          /**< FIFO for output samples            */
67
+
68
+    AudioConvert *ac_in;        /**< input sample format conversion context  */
69
+    AudioConvert *ac_out;       /**< output sample format conversion context */
70
+    ResampleContext *resample;  /**< resampling context                      */
71
+    AudioMix *am;               /**< channel mixing context                  */
72
+};
73
+
74
+#endif /* AVRESAMPLE_INTERNAL_H */
0 75
new file mode 100644
... ...
@@ -0,0 +1,4 @@
0
+LIBAVRESAMPLE_$MAJOR {
1
+        global: av*;
2
+        local:  *;
3
+};
0 4
new file mode 100644
... ...
@@ -0,0 +1,89 @@
0
+/*
1
+ * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
2
+ *
3
+ * This file is part of Libav.
4
+ *
5
+ * Libav is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * Libav is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with Libav; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#include "libavutil/mathematics.h"
21
+#include "libavutil/opt.h"
22
+#include "avresample.h"
23
+#include "internal.h"
24
+#include "audio_mix.h"
25
+
26
+/**
27
+ * @file
28
+ * Options definition for AVAudioResampleContext.
29
+ */
30
+
31
+#define OFFSET(x) offsetof(AVAudioResampleContext, x)
32
+#define PARAM AV_OPT_FLAG_AUDIO_PARAM
33
+
34
+static const AVOption options[] = {
35
+    { "in_channel_layout",      "Input Channel Layout",     OFFSET(in_channel_layout),      AV_OPT_TYPE_INT64,  { 0                     }, INT64_MIN,            INT64_MAX,              PARAM },
36
+    { "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 },
37
+    { "in_sample_rate",         "Input Sample Rate",        OFFSET(in_sample_rate),         AV_OPT_TYPE_INT,    { 48000                 }, 1,                    INT_MAX,                PARAM },
38
+    { "out_channel_layout",     "Output Channel Layout",    OFFSET(out_channel_layout),     AV_OPT_TYPE_INT64,  { 0                     }, INT64_MIN,            INT64_MAX,              PARAM },
39
+    { "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 },
40
+    { "out_sample_rate",        "Output Sample Rate",       OFFSET(out_sample_rate),        AV_OPT_TYPE_INT,    { 48000                 }, 1,                    INT_MAX,                PARAM },
41
+    { "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 },
42
+    { "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" },
43
+        { "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" },
44
+        { "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" },
45
+        { "flt", "Floating-Point",           0, AV_OPT_TYPE_CONST, { AV_MIX_COEFF_TYPE_FLT }, INT_MIN, INT_MAX, PARAM, "mix_coeff_type" },
46
+    { "center_mix_level",       "Center Mix Level",         OFFSET(center_mix_level),       AV_OPT_TYPE_DOUBLE, { M_SQRT1_2             }, -32.0,                32.0,                   PARAM },
47
+    { "surround_mix_level",     "Surround Mix Level",       OFFSET(surround_mix_level),     AV_OPT_TYPE_DOUBLE, { M_SQRT1_2             }, -32.0,                32.0,                   PARAM },
48
+    { "lfe_mix_level",          "LFE Mix Level",            OFFSET(lfe_mix_level),          AV_OPT_TYPE_DOUBLE, { 0.0                   }, -32.0,                32.0,                   PARAM },
49
+    { "force_resampling",       "Force Resampling",         OFFSET(force_resampling),       AV_OPT_TYPE_INT,    { 0                     }, 0,                    1,                      PARAM },
50
+    { "filter_size",            "Resampling Filter Size",   OFFSET(filter_size),            AV_OPT_TYPE_INT,    { 16                    }, 0,                    32, /* ??? */           PARAM },
51
+    { "phase_shift",            "Resampling Phase Shift",   OFFSET(phase_shift),            AV_OPT_TYPE_INT,    { 10                    }, 0,                    30, /* ??? */           PARAM },
52
+    { "linear_interp",          "Use Linear Interpolation", OFFSET(linear_interp),          AV_OPT_TYPE_INT,    { 0                     }, 0,                    1,                      PARAM },
53
+    { "cutoff",                 "Cutoff Frequency Ratio",   OFFSET(cutoff),                 AV_OPT_TYPE_DOUBLE, { 0.8                   }, 0.0,                  1.0,                    PARAM },
54
+    { NULL },
55
+};
56
+
57
+static const AVClass av_resample_context_class = {
58
+    .class_name = "AVAudioResampleContext",
59
+    .item_name  = av_default_item_name,
60
+    .option     = options,
61
+    .version    = LIBAVUTIL_VERSION_INT,
62
+};
63
+
64
+AVAudioResampleContext *avresample_alloc_context(void)
65
+{
66
+    AVAudioResampleContext *avr;
67
+
68
+    avr = av_mallocz(sizeof(*avr));
69
+    if (!avr)
70
+        return NULL;
71
+
72
+    avr->av_class = &av_resample_context_class;
73
+    av_opt_set_defaults(avr);
74
+
75
+    avr->am = av_mallocz(sizeof(*avr->am));
76
+    if (!avr->am) {
77
+        av_free(avr);
78
+        return NULL;
79
+    }
80
+    avr->am->avr = avr;
81
+
82
+    return avr;
83
+}
84
+
85
+const AVClass *avresample_get_class(void)
86
+{
87
+    return &av_resample_context_class;
88
+}
0 89
new file mode 100644
... ...
@@ -0,0 +1,480 @@
0
+/*
1
+ * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
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/libm.h"
22
+#include "libavutil/log.h"
23
+#include "internal.h"
24
+#include "audio_data.h"
25
+
26
+#ifdef CONFIG_RESAMPLE_FLT
27
+/* float template */
28
+#define FILTER_SHIFT  0
29
+#define FELEM         float
30
+#define FELEM2        float
31
+#define FELEML        float
32
+#define WINDOW_TYPE   24
33
+#elifdef CONFIG_RESAMPLE_S32
34
+/* s32 template */
35
+#define FILTER_SHIFT  30
36
+#define FELEM         int32_t
37
+#define FELEM2        int64_t
38
+#define FELEML        int64_t
39
+#define FELEM_MAX     INT32_MAX
40
+#define FELEM_MIN     INT32_MIN
41
+#define WINDOW_TYPE   12
42
+#else
43
+/* s16 template */
44
+#define FILTER_SHIFT  15
45
+#define FELEM         int16_t
46
+#define FELEM2        int32_t
47
+#define FELEML        int64_t
48
+#define FELEM_MAX     INT16_MAX
49
+#define FELEM_MIN     INT16_MIN
50
+#define WINDOW_TYPE   9
51
+#endif
52
+
53
+struct ResampleContext {
54
+    AVAudioResampleContext *avr;
55
+    AudioData *buffer;
56
+    FELEM *filter_bank;
57
+    int filter_length;
58
+    int ideal_dst_incr;
59
+    int dst_incr;
60
+    int index;
61
+    int frac;
62
+    int src_incr;
63
+    int compensation_distance;
64
+    int phase_shift;
65
+    int phase_mask;
66
+    int linear;
67
+    double factor;
68
+};
69
+
70
+/**
71
+ * 0th order modified bessel function of the first kind.
72
+ */
73
+static double bessel(double x)
74
+{
75
+    double v     = 1;
76
+    double lastv = 0;
77
+    double t     = 1;
78
+    int i;
79
+
80
+    x = x * x / 4;
81
+    for (i = 1; v != lastv; i++) {
82
+        lastv = v;
83
+        t    *= x / (i * i);
84
+        v    += t;
85
+    }
86
+    return v;
87
+}
88
+
89
+/**
90
+ * Build a polyphase filterbank.
91
+ *
92
+ * @param[out] filter       filter coefficients
93
+ * @param      factor       resampling factor
94
+ * @param      tap_count    tap count
95
+ * @param      phase_count  phase count
96
+ * @param      scale        wanted sum of coefficients for each filter
97
+ * @param      type         0->cubic
98
+ *                          1->blackman nuttall windowed sinc
99
+ *                          2..16->kaiser windowed sinc beta=2..16
100
+ * @return                  0 on success, negative AVERROR code on failure
101
+ */
102
+static int build_filter(FELEM *filter, double factor, int tap_count,
103
+                        int phase_count, int scale, int type)
104
+{
105
+    int ph, i;
106
+    double x, y, w;
107
+    double *tab;
108
+    const int center = (tap_count - 1) / 2;
109
+
110
+    tab = av_malloc(tap_count * sizeof(*tab));
111
+    if (!tab)
112
+        return AVERROR(ENOMEM);
113
+
114
+    /* if upsampling, only need to interpolate, no filter */
115
+    if (factor > 1.0)
116
+        factor = 1.0;
117
+
118
+    for (ph = 0; ph < phase_count; ph++) {
119
+        double norm = 0;
120
+        for (i = 0; i < tap_count; i++) {
121
+            x = M_PI * ((double)(i - center) - (double)ph / phase_count) * factor;
122
+            if (x == 0) y = 1.0;
123
+            else        y = sin(x) / x;
124
+            switch (type) {
125
+            case 0: {
126
+                const float d = -0.5; //first order derivative = -0.5
127
+                x = fabs(((double)(i - center) - (double)ph / phase_count) * factor);
128
+                if (x < 1.0) y = 1 - 3 * x*x + 2 * x*x*x + d * (                -x*x + x*x*x);
129
+                else         y =                           d * (-4 + 8 * x - 5 * x*x + x*x*x);
130
+                break;
131
+            }
132
+            case 1:
133
+                w  = 2.0 * x / (factor * tap_count) + M_PI;
134
+                y *= 0.3635819 - 0.4891775 * cos(    w) +
135
+                                 0.1365995 * cos(2 * w) -
136
+                                 0.0106411 * cos(3 * w);
137
+                break;
138
+            default:
139
+                w  = 2.0 * x / (factor * tap_count * M_PI);
140
+                y *= bessel(type * sqrt(FFMAX(1 - w * w, 0)));
141
+                break;
142
+            }
143
+
144
+            tab[i] = y;
145
+            norm  += y;
146
+        }
147
+
148
+        /* normalize so that an uniform color remains the same */
149
+        for (i = 0; i < tap_count; i++) {
150
+#ifdef CONFIG_RESAMPLE_FLT
151
+            filter[ph * tap_count + i] = tab[i] / norm;
152
+#else
153
+            filter[ph * tap_count + i] = av_clip(lrintf(tab[i] * scale / norm),
154
+                                                 FELEM_MIN, FELEM_MAX);
155
+#endif
156
+        }
157
+    }
158
+
159
+    av_free(tab);
160
+    return 0;
161
+}
162
+
163
+ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr)
164
+{
165
+    ResampleContext *c;
166
+    int out_rate    = avr->out_sample_rate;
167
+    int in_rate     = avr->in_sample_rate;
168
+    double factor   = FFMIN(out_rate * avr->cutoff / in_rate, 1.0);
169
+    int phase_count = 1 << avr->phase_shift;
170
+
171
+    /* TODO: add support for s32 and float internal formats */
172
+    if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P) {
173
+        av_log(avr, AV_LOG_ERROR, "Unsupported internal format for "
174
+               "resampling: %s\n",
175
+               av_get_sample_fmt_name(avr->internal_sample_fmt));
176
+        return NULL;
177
+    }
178
+    c = av_mallocz(sizeof(*c));
179
+    if (!c)
180
+        return NULL;
181
+
182
+    c->avr           = avr;
183
+    c->phase_shift   = avr->phase_shift;
184
+    c->phase_mask    = phase_count - 1;
185
+    c->linear        = avr->linear_interp;
186
+    c->factor        = factor;
187
+    c->filter_length = FFMAX((int)ceil(avr->filter_size / factor), 1);
188
+
189
+    c->filter_bank = av_mallocz(c->filter_length * (phase_count + 1) * sizeof(FELEM));
190
+    if (!c->filter_bank)
191
+        goto error;
192
+
193
+    if (build_filter(c->filter_bank, factor, c->filter_length, phase_count,
194
+                     1 << FILTER_SHIFT, WINDOW_TYPE) < 0)
195
+        goto error;
196
+
197
+    memcpy(&c->filter_bank[c->filter_length * phase_count + 1],
198
+           c->filter_bank, (c->filter_length - 1) * sizeof(FELEM));
199
+    c->filter_bank[c->filter_length * phase_count] = c->filter_bank[c->filter_length - 1];
200
+
201
+    c->compensation_distance = 0;
202
+    if (!av_reduce(&c->src_incr, &c->dst_incr, out_rate,
203
+                   in_rate * (int64_t)phase_count, INT32_MAX / 2))
204
+        goto error;
205
+    c->ideal_dst_incr = c->dst_incr;
206
+
207
+    c->index = -phase_count * ((c->filter_length - 1) / 2);
208
+    c->frac  = 0;
209
+
210
+    /* allocate internal buffer */
211
+    c->buffer = ff_audio_data_alloc(avr->resample_channels, 0,
212
+                                    avr->internal_sample_fmt,
213
+                                    "resample buffer");
214
+    if (!c->buffer)
215
+        goto error;
216
+
217
+    av_log(avr, AV_LOG_DEBUG, "resample: %s from %d Hz to %d Hz\n",
218
+           av_get_sample_fmt_name(avr->internal_sample_fmt),
219
+           avr->in_sample_rate, avr->out_sample_rate);
220
+
221
+    return c;
222
+
223
+error:
224
+    ff_audio_data_free(&c->buffer);
225
+    av_free(c->filter_bank);
226
+    av_free(c);
227
+    return NULL;
228
+}
229
+
230
+void ff_audio_resample_free(ResampleContext **c)
231
+{
232
+    if (!*c)
233
+        return;
234
+    ff_audio_data_free(&(*c)->buffer);
235
+    av_free((*c)->filter_bank);
236
+    av_freep(c);
237
+}
238
+
239
+int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta,
240
+                                int compensation_distance)
241
+{
242
+    ResampleContext *c;
243
+    AudioData *fifo_buf = NULL;
244
+    int ret = 0;
245
+
246
+    if (compensation_distance < 0)
247
+        return AVERROR(EINVAL);
248
+    if (!compensation_distance && sample_delta)
249
+        return AVERROR(EINVAL);
250
+
251
+    /* if resampling was not enabled previously, re-initialize the
252
+       AVAudioResampleContext and force resampling */
253
+    if (!avr->resample_needed) {
254
+        int fifo_samples;
255
+        double matrix[AVRESAMPLE_MAX_CHANNELS * AVRESAMPLE_MAX_CHANNELS] = { 0 };
256
+
257
+        /* buffer any remaining samples in the output FIFO before closing */
258
+        fifo_samples = av_audio_fifo_size(avr->out_fifo);
259
+        if (fifo_samples > 0) {
260
+            fifo_buf = ff_audio_data_alloc(avr->out_channels, fifo_samples,
261
+                                           avr->out_sample_fmt, NULL);
262
+            if (!fifo_buf)
263
+                return AVERROR(EINVAL);
264
+            ret = ff_audio_data_read_from_fifo(avr->out_fifo, fifo_buf,
265
+                                               fifo_samples);
266
+            if (ret < 0)
267
+                goto reinit_fail;
268
+        }
269
+        /* save the channel mixing matrix */
270
+        ret = avresample_get_matrix(avr, matrix, AVRESAMPLE_MAX_CHANNELS);
271
+        if (ret < 0)
272
+            goto reinit_fail;
273
+
274
+        /* close the AVAudioResampleContext */
275
+        avresample_close(avr);
276
+
277
+        avr->force_resampling = 1;
278
+
279
+        /* restore the channel mixing matrix */
280
+        ret = avresample_set_matrix(avr, matrix, AVRESAMPLE_MAX_CHANNELS);
281
+        if (ret < 0)
282
+            goto reinit_fail;
283
+
284
+        /* re-open the AVAudioResampleContext */
285
+        ret = avresample_open(avr);
286
+        if (ret < 0)
287
+            goto reinit_fail;
288
+
289
+        /* restore buffered samples to the output FIFO */
290
+        if (fifo_samples > 0) {
291
+            ret = ff_audio_data_add_to_fifo(avr->out_fifo, fifo_buf, 0,
292
+                                            fifo_samples);
293
+            if (ret < 0)
294
+                goto reinit_fail;
295
+            ff_audio_data_free(&fifo_buf);
296
+        }
297
+    }
298
+    c = avr->resample;
299
+    c->compensation_distance = compensation_distance;
300
+    if (compensation_distance) {
301
+        c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr *
302
+                      (int64_t)sample_delta / compensation_distance;
303
+    } else {
304
+        c->dst_incr = c->ideal_dst_incr;
305
+    }
306
+    return 0;
307
+
308
+reinit_fail:
309
+    ff_audio_data_free(&fifo_buf);
310
+    return ret;
311
+}
312
+
313
+static int resample(ResampleContext *c, int16_t *dst, const int16_t *src,
314
+                    int *consumed, int src_size, int dst_size, int update_ctx)
315
+{
316
+    int dst_index, i;
317
+    int index         = c->index;
318
+    int frac          = c->frac;
319
+    int dst_incr_frac = c->dst_incr % c->src_incr;
320
+    int dst_incr      = c->dst_incr / c->src_incr;
321
+    int compensation_distance = c->compensation_distance;
322
+
323
+    if (!dst != !src)
324
+        return AVERROR(EINVAL);
325
+
326
+    if (compensation_distance == 0 && c->filter_length == 1 &&
327
+        c->phase_shift == 0) {
328
+        int64_t index2 = ((int64_t)index) << 32;
329
+        int64_t incr   = (1LL << 32) * c->dst_incr / c->src_incr;
330
+        dst_size       = FFMIN(dst_size,
331
+                               (src_size-1-index) * (int64_t)c->src_incr /
332
+                               c->dst_incr);
333
+
334
+        if (dst) {
335
+            for(dst_index = 0; dst_index < dst_size; dst_index++) {
336
+                dst[dst_index] = src[index2 >> 32];
337
+                index2 += incr;
338
+            }
339
+        } else {
340
+            dst_index = dst_size;
341
+        }
342
+        index += dst_index * dst_incr;
343
+        index += (frac + dst_index * (int64_t)dst_incr_frac) / c->src_incr;
344
+        frac   = (frac + dst_index * (int64_t)dst_incr_frac) % c->src_incr;
345
+    } else {
346
+        for (dst_index = 0; dst_index < dst_size; dst_index++) {
347
+            FELEM *filter = c->filter_bank +
348
+                            c->filter_length * (index & c->phase_mask);
349
+            int sample_index = index >> c->phase_shift;
350
+
351
+            if (!dst && (sample_index + c->filter_length > src_size ||
352
+                         -sample_index >= src_size))
353
+                break;
354
+
355
+            if (dst) {
356
+                FELEM2 val = 0;
357
+
358
+                if (sample_index < 0) {
359
+                    for (i = 0; i < c->filter_length; i++)
360
+                        val += src[FFABS(sample_index + i) % src_size] *
361
+                               (FELEM2)filter[i];
362
+                } else if (sample_index + c->filter_length > src_size) {
363
+                    break;
364
+                } else if (c->linear) {
365
+                    FELEM2 v2 = 0;
366
+                    for (i = 0; i < c->filter_length; i++) {
367
+                        val += src[abs(sample_index + i)] * (FELEM2)filter[i];
368
+                        v2  += src[abs(sample_index + i)] * (FELEM2)filter[i + c->filter_length];
369
+                    }
370
+                    val += (v2 - val) * (FELEML)frac / c->src_incr;
371
+                } else {
372
+                    for (i = 0; i < c->filter_length; i++)
373
+                        val += src[sample_index + i] * (FELEM2)filter[i];
374
+                }
375
+
376
+#ifdef CONFIG_RESAMPLE_FLT
377
+                dst[dst_index] = av_clip_int16(lrintf(val));
378
+#else
379
+                val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;
380
+                dst[dst_index] = av_clip_int16(val);
381
+#endif
382
+            }
383
+
384
+            frac  += dst_incr_frac;
385
+            index += dst_incr;
386
+            if (frac >= c->src_incr) {
387
+                frac -= c->src_incr;
388
+                index++;
389
+            }
390
+            if (dst_index + 1 == compensation_distance) {
391
+                compensation_distance = 0;
392
+                dst_incr_frac = c->ideal_dst_incr % c->src_incr;
393
+                dst_incr      = c->ideal_dst_incr / c->src_incr;
394
+            }
395
+        }
396
+    }
397
+    if (consumed)
398
+        *consumed = FFMAX(index, 0) >> c->phase_shift;
399
+
400
+    if (update_ctx) {
401
+        if (index >= 0)
402
+            index &= c->phase_mask;
403
+
404
+        if (compensation_distance) {
405
+            compensation_distance -= dst_index;
406
+            if (compensation_distance <= 0)
407
+                return AVERROR_BUG;
408
+        }
409
+        c->frac     = frac;
410
+        c->index    = index;
411
+        c->dst_incr = dst_incr_frac + c->src_incr*dst_incr;
412
+        c->compensation_distance = compensation_distance;
413
+    }
414
+
415
+    return dst_index;
416
+}
417
+
418
+int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src,
419
+                      int *consumed)
420
+{
421
+    int ch, in_samples, in_leftover, out_samples = 0;
422
+    int ret = AVERROR(EINVAL);
423
+
424
+    in_samples  = src ? src->nb_samples : 0;
425
+    in_leftover = c->buffer->nb_samples;
426
+
427
+    /* add input samples to the internal buffer */
428
+    if (src) {
429
+        ret = ff_audio_data_combine(c->buffer, in_leftover, src, 0, in_samples);
430
+        if (ret < 0)
431
+            return ret;
432
+    } else if (!in_leftover) {
433
+        /* no remaining samples to flush */
434
+        return 0;
435
+    } else {
436
+        /* TODO: pad buffer to flush completely */
437
+    }
438
+
439
+    /* calculate output size and reallocate output buffer if needed */
440
+    /* TODO: try to calculate this without the dummy resample() run */
441
+    if (!dst->read_only && dst->allow_realloc) {
442
+        out_samples = resample(c, NULL, NULL, NULL, c->buffer->nb_samples,
443
+                               INT_MAX, 0);
444
+        ret = ff_audio_data_realloc(dst, out_samples);
445
+        if (ret < 0) {
446
+            av_log(c->avr, AV_LOG_ERROR, "error reallocating output\n");
447
+            return ret;
448
+        }
449
+    }
450
+
451
+    /* resample each channel plane */
452
+    for (ch = 0; ch < c->buffer->channels; ch++) {
453
+        out_samples = resample(c, (int16_t *)dst->data[ch],
454
+                               (const int16_t *)c->buffer->data[ch], consumed,
455
+                               c->buffer->nb_samples, dst->allocated_samples,
456
+                               ch + 1 == c->buffer->channels);
457
+    }
458
+    if (out_samples < 0) {
459
+        av_log(c->avr, AV_LOG_ERROR, "error during resampling\n");
460
+        return out_samples;
461
+    }
462
+
463
+    /* drain consumed samples from the internal buffer */
464
+    ff_audio_data_drain(c->buffer, *consumed);
465
+
466
+    av_dlog(c->avr, "resampled %d in + %d leftover to %d out + %d leftover\n",
467
+            in_samples, in_leftover, out_samples, c->buffer->nb_samples);
468
+
469
+    dst->nb_samples = out_samples;
470
+    return 0;
471
+}
472
+
473
+int avresample_get_delay(AVAudioResampleContext *avr)
474
+{
475
+    if (!avr->resample_needed || !avr->resample)
476
+        return 0;
477
+
478
+    return avr->resample->buffer->nb_samples;
479
+}
0 480
new file mode 100644
... ...
@@ -0,0 +1,70 @@
0
+/*
1
+ * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
2
+ *
3
+ * This file is part of Libav.
4
+ *
5
+ * Libav is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * Libav is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with Libav; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#ifndef AVRESAMPLE_RESAMPLE_H
21
+#define AVRESAMPLE_RESAMPLE_H
22
+
23
+#include "avresample.h"
24
+#include "audio_data.h"
25
+
26
+typedef struct ResampleContext ResampleContext;
27
+
28
+/**
29
+ * Allocate and initialize a ResampleContext.
30
+ *
31
+ * The parameters in the AVAudioResampleContext are used to initialize the
32
+ * ResampleContext.
33
+ *
34
+ * @param avr  AVAudioResampleContext
35
+ * @return     newly-allocated ResampleContext
36
+ */
37
+ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr);
38
+
39
+/**
40
+ * Free a ResampleContext.
41
+ *
42
+ * @param c  ResampleContext
43
+ */
44
+void ff_audio_resample_free(ResampleContext **c);
45
+
46
+/**
47
+ * Resample audio data.
48
+ *
49
+ * Changes the sample rate.
50
+ *
51
+ * @par
52
+ * All samples in the source data may not be consumed depending on the
53
+ * resampling parameters and the size of the output buffer. The unconsumed
54
+ * samples are automatically added to the start of the source in the next call.
55
+ * If the destination data can be reallocated, that may be done in this function
56
+ * in order to fit all available output. If it cannot be reallocated, fewer
57
+ * input samples will be consumed in order to have the output fit in the
58
+ * destination data buffers.
59
+ *
60
+ * @param c         ResampleContext
61
+ * @param dst       destination audio data
62
+ * @param src       source audio data
63
+ * @param consumed  number of samples consumed from the source
64
+ * @return          number of samples written to the destination
65
+ */
66
+int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src,
67
+                      int *consumed);
68
+
69
+#endif /* AVRESAMPLE_RESAMPLE_H */
0 70
new file mode 100644
... ...
@@ -0,0 +1,405 @@
0
+/*
1
+ * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
2
+ *
3
+ * This file is part of Libav.
4
+ *
5
+ * Libav is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * Libav is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with Libav; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#include "libavutil/dict.h"
21
+// #include "libavutil/error.h"
22
+#include "libavutil/log.h"
23
+#include "libavutil/mem.h"
24
+#include "libavutil/opt.h"
25
+
26
+#include "avresample.h"
27
+#include "audio_data.h"
28
+#include "internal.h"
29
+
30
+int avresample_open(AVAudioResampleContext *avr)
31
+{
32
+    int ret;
33
+
34
+    /* set channel mixing parameters */
35
+    avr->in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
36
+    if (avr->in_channels <= 0 || avr->in_channels > AVRESAMPLE_MAX_CHANNELS) {
37
+        av_log(avr, AV_LOG_ERROR, "Invalid input channel layout: %"PRIu64"\n",
38
+               avr->in_channel_layout);
39
+        return AVERROR(EINVAL);
40
+    }
41
+    avr->out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
42
+    if (avr->out_channels <= 0 || avr->out_channels > AVRESAMPLE_MAX_CHANNELS) {
43
+        av_log(avr, AV_LOG_ERROR, "Invalid output channel layout: %"PRIu64"\n",
44
+               avr->out_channel_layout);
45
+        return AVERROR(EINVAL);
46
+    }
47
+    avr->resample_channels = FFMIN(avr->in_channels, avr->out_channels);
48
+    avr->downmix_needed    = avr->in_channels  > avr->out_channels;
49
+    avr->upmix_needed      = avr->out_channels > avr->in_channels ||
50
+                             avr->am->matrix                      ||
51
+                             (avr->out_channels == avr->in_channels &&
52
+                              avr->in_channel_layout != avr->out_channel_layout);
53
+    avr->mixing_needed     = avr->downmix_needed || avr->upmix_needed;
54
+
55
+    /* set resampling parameters */
56
+    avr->resample_needed   = avr->in_sample_rate != avr->out_sample_rate ||
57
+                             avr->force_resampling;
58
+
59
+    /* set sample format conversion parameters */
60
+    /* override user-requested internal format to avoid unexpected failures
61
+       TODO: support more internal formats */
62
+    if (avr->resample_needed && avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P) {
63
+        av_log(avr, AV_LOG_WARNING, "Using s16p as internal sample format\n");
64
+        avr->internal_sample_fmt = AV_SAMPLE_FMT_S16P;
65
+    } else if (avr->mixing_needed &&
66
+               avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P &&
67
+               avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP) {
68
+        av_log(avr, AV_LOG_WARNING, "Using fltp as internal sample format\n");
69
+        avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP;
70
+    }
71
+    if (avr->in_channels == 1)
72
+        avr->in_sample_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt);
73
+    if (avr->out_channels == 1)
74
+        avr->out_sample_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);
75
+    avr->in_convert_needed = (avr->resample_needed || avr->mixing_needed) &&
76
+                              avr->in_sample_fmt != avr->internal_sample_fmt;
77
+    if (avr->resample_needed || avr->mixing_needed)
78
+        avr->out_convert_needed = avr->internal_sample_fmt != avr->out_sample_fmt;
79
+    else
80
+        avr->out_convert_needed = avr->in_sample_fmt != avr->out_sample_fmt;
81
+
82
+    /* allocate buffers */
83
+    if (avr->mixing_needed || avr->in_convert_needed) {
84
+        avr->in_buffer = ff_audio_data_alloc(FFMAX(avr->in_channels, avr->out_channels),
85
+                                             0, avr->internal_sample_fmt,
86
+                                             "in_buffer");
87
+        if (!avr->in_buffer) {
88
+            ret = AVERROR(EINVAL);
89
+            goto error;
90
+        }
91
+    }
92
+    if (avr->resample_needed) {
93
+        avr->resample_out_buffer = ff_audio_data_alloc(avr->out_channels,
94
+                                                       0, avr->internal_sample_fmt,
95
+                                                       "resample_out_buffer");
96
+        if (!avr->resample_out_buffer) {
97
+            ret = AVERROR(EINVAL);
98
+            goto error;
99
+        }
100
+    }
101
+    if (avr->out_convert_needed) {
102
+        avr->out_buffer = ff_audio_data_alloc(avr->out_channels, 0,
103
+                                              avr->out_sample_fmt, "out_buffer");
104
+        if (!avr->out_buffer) {
105
+            ret = AVERROR(EINVAL);
106
+            goto error;
107
+        }
108
+    }
109
+    avr->out_fifo = av_audio_fifo_alloc(avr->out_sample_fmt, avr->out_channels,
110
+                                        1024);
111
+    if (!avr->out_fifo) {
112
+        ret = AVERROR(ENOMEM);
113
+        goto error;
114
+    }
115
+
116
+    /* setup contexts */
117
+    if (avr->in_convert_needed) {
118
+        avr->ac_in = ff_audio_convert_alloc(avr, avr->internal_sample_fmt,
119
+                                            avr->in_sample_fmt, avr->in_channels);
120
+        if (!avr->ac_in) {
121
+            ret = AVERROR(ENOMEM);
122
+            goto error;
123
+        }
124
+    }
125
+    if (avr->out_convert_needed) {
126
+        enum AVSampleFormat src_fmt;
127
+        if (avr->in_convert_needed)
128
+            src_fmt = avr->internal_sample_fmt;
129
+        else
130
+            src_fmt = avr->in_sample_fmt;
131
+        avr->ac_out = ff_audio_convert_alloc(avr, avr->out_sample_fmt, src_fmt,
132
+                                             avr->out_channels);
133
+        if (!avr->ac_out) {
134
+            ret = AVERROR(ENOMEM);
135
+            goto error;
136
+        }
137
+    }
138
+    if (avr->resample_needed) {
139
+        avr->resample = ff_audio_resample_init(avr);
140
+        if (!avr->resample) {
141
+            ret = AVERROR(ENOMEM);
142
+            goto error;
143
+        }
144
+    }
145
+    if (avr->mixing_needed) {
146
+        ret = ff_audio_mix_init(avr);
147
+        if (ret < 0)
148
+            goto error;
149
+    }
150
+
151
+    return 0;
152
+
153
+error:
154
+    avresample_close(avr);
155
+    return ret;
156
+}
157
+
158
+void avresample_close(AVAudioResampleContext *avr)
159
+{
160
+    ff_audio_data_free(&avr->in_buffer);
161
+    ff_audio_data_free(&avr->resample_out_buffer);
162
+    ff_audio_data_free(&avr->out_buffer);
163
+    av_audio_fifo_free(avr->out_fifo);
164
+    avr->out_fifo = NULL;
165
+    av_freep(&avr->ac_in);
166
+    av_freep(&avr->ac_out);
167
+    ff_audio_resample_free(&avr->resample);
168
+    ff_audio_mix_close(avr->am);
169
+    return;
170
+}
171
+
172
+void avresample_free(AVAudioResampleContext **avr)
173
+{
174
+    if (!*avr)
175
+        return;
176
+    avresample_close(*avr);
177
+    av_freep(&(*avr)->am);
178
+    av_opt_free(*avr);
179
+    av_freep(avr);
180
+}
181
+
182
+static int handle_buffered_output(AVAudioResampleContext *avr,
183
+                                  AudioData *output, AudioData *converted)
184
+{
185
+    int ret;
186
+
187
+    if (!output || av_audio_fifo_size(avr->out_fifo) > 0 ||
188
+        (converted && output->allocated_samples < converted->nb_samples)) {
189
+        if (converted) {
190
+            /* if there are any samples in the output FIFO or if the
191
+               user-supplied output buffer is not large enough for all samples,
192
+               we add to the output FIFO */
193
+            av_dlog(avr, "[FIFO] add %s to out_fifo\n", converted->name);
194
+            ret = ff_audio_data_add_to_fifo(avr->out_fifo, converted, 0,
195
+                                            converted->nb_samples);
196
+            if (ret < 0)
197
+                return ret;
198
+        }
199
+
200
+        /* if the user specified an output buffer, read samples from the output
201
+           FIFO to the user output */
202
+        if (output && output->allocated_samples > 0) {
203
+            av_dlog(avr, "[FIFO] read from out_fifo to output\n");
204
+            av_dlog(avr, "[end conversion]\n");
205
+            return ff_audio_data_read_from_fifo(avr->out_fifo, output,
206
+                                                output->allocated_samples);
207
+        }
208
+    } else if (converted) {
209
+        /* copy directly to output if it is large enough or there is not any
210
+           data in the output FIFO */
211
+        av_dlog(avr, "[copy] %s to output\n", converted->name);
212
+        output->nb_samples = 0;
213
+        ret = ff_audio_data_copy(output, converted);
214
+        if (ret < 0)
215
+            return ret;
216
+        av_dlog(avr, "[end conversion]\n");
217
+        return output->nb_samples;
218
+    }
219
+    av_dlog(avr, "[end conversion]\n");
220
+    return 0;
221
+}
222
+
223
+int avresample_convert(AVAudioResampleContext *avr, void **output,
224
+                       int out_plane_size, int out_samples, void **input,
225
+                       int in_plane_size, int in_samples)
226
+{
227
+    AudioData input_buffer;
228
+    AudioData output_buffer;
229
+    AudioData *current_buffer;
230
+    int ret;
231
+
232
+    /* reset internal buffers */
233
+    if (avr->in_buffer) {
234
+        avr->in_buffer->nb_samples = 0;
235
+        ff_audio_data_set_channels(avr->in_buffer,
236
+                                   avr->in_buffer->allocated_channels);
237
+    }
238
+    if (avr->resample_out_buffer) {
239
+        avr->resample_out_buffer->nb_samples = 0;
240
+        ff_audio_data_set_channels(avr->resample_out_buffer,
241
+                                   avr->resample_out_buffer->allocated_channels);
242
+    }
243
+    if (avr->out_buffer) {
244
+        avr->out_buffer->nb_samples = 0;
245
+        ff_audio_data_set_channels(avr->out_buffer,
246
+                                   avr->out_buffer->allocated_channels);
247
+    }
248
+
249
+    av_dlog(avr, "[start conversion]\n");
250
+
251
+    /* initialize output_buffer with output data */
252
+    if (output) {
253
+        ret = ff_audio_data_init(&output_buffer, output, out_plane_size,
254
+                                 avr->out_channels, out_samples,
255
+                                 avr->out_sample_fmt, 0, "output");
256
+        if (ret < 0)
257
+            return ret;
258
+        output_buffer.nb_samples = 0;
259
+    }
260
+
261
+    if (input) {
262
+        /* initialize input_buffer with input data */
263
+        ret = ff_audio_data_init(&input_buffer, input, in_plane_size,
264
+                                 avr->in_channels, in_samples,
265
+                                 avr->in_sample_fmt, 1, "input");
266
+        if (ret < 0)
267
+            return ret;
268
+        current_buffer = &input_buffer;
269
+
270
+        if (avr->upmix_needed && !avr->in_convert_needed && !avr->resample_needed &&
271
+            !avr->out_convert_needed && output && out_samples >= in_samples) {
272
+            /* in some rare cases we can copy input to output and upmix
273
+               directly in the output buffer */
274
+            av_dlog(avr, "[copy] %s to output\n", current_buffer->name);
275
+            ret = ff_audio_data_copy(&output_buffer, current_buffer);
276
+            if (ret < 0)
277
+                return ret;
278
+            current_buffer = &output_buffer;
279
+        } else if (avr->mixing_needed || avr->in_convert_needed) {
280
+            /* if needed, copy or convert input to in_buffer, and downmix if
281
+               applicable */
282
+            if (avr->in_convert_needed) {
283
+                ret = ff_audio_data_realloc(avr->in_buffer,
284
+                                            current_buffer->nb_samples);
285
+                if (ret < 0)
286
+                    return ret;
287
+                av_dlog(avr, "[convert] %s to in_buffer\n", current_buffer->name);
288
+                ret = ff_audio_convert(avr->ac_in, avr->in_buffer, current_buffer,
289
+                                       current_buffer->nb_samples);
290
+                if (ret < 0)
291
+                    return ret;
292
+            } else {
293
+                av_dlog(avr, "[copy] %s to in_buffer\n", current_buffer->name);
294
+                ret = ff_audio_data_copy(avr->in_buffer, current_buffer);
295
+                if (ret < 0)
296
+                    return ret;
297
+            }
298
+            ff_audio_data_set_channels(avr->in_buffer, avr->in_channels);
299
+            if (avr->downmix_needed) {
300
+                av_dlog(avr, "[downmix] in_buffer\n");
301
+                ret = ff_audio_mix(avr->am, avr->in_buffer);
302
+                if (ret < 0)
303
+                    return ret;
304
+            }
305
+            current_buffer = avr->in_buffer;
306
+        }
307
+    } else {
308
+        /* flush resampling buffer and/or output FIFO if input is NULL */
309
+        if (!avr->resample_needed)
310
+            return handle_buffered_output(avr, output ? &output_buffer : NULL,
311
+                                          NULL);
312
+        current_buffer = NULL;
313
+    }
314
+
315
+    if (avr->resample_needed) {
316
+        AudioData *resample_out;
317
+        int consumed = 0;
318
+
319
+        if (!avr->out_convert_needed && output && out_samples > 0)
320
+            resample_out = &output_buffer;
321
+        else
322
+            resample_out = avr->resample_out_buffer;
323
+        av_dlog(avr, "[resample] %s to %s\n", current_buffer->name,
324
+                resample_out->name);
325
+        ret = ff_audio_resample(avr->resample, resample_out,
326
+                                current_buffer, &consumed);
327
+        if (ret < 0)
328
+            return ret;
329
+
330
+        /* if resampling did not produce any samples, just return 0 */
331
+        if (resample_out->nb_samples == 0) {
332
+            av_dlog(avr, "[end conversion]\n");
333
+            return 0;
334
+        }
335
+
336
+        current_buffer = resample_out;
337
+    }
338
+
339
+    if (avr->upmix_needed) {
340
+        av_dlog(avr, "[upmix] %s\n", current_buffer->name);
341
+        ret = ff_audio_mix(avr->am, current_buffer);
342
+        if (ret < 0)
343
+            return ret;
344
+    }
345
+
346
+    /* if we resampled or upmixed directly to output, return here */
347
+    if (current_buffer == &output_buffer) {
348
+        av_dlog(avr, "[end conversion]\n");
349
+        return current_buffer->nb_samples;
350
+    }
351
+
352
+    if (avr->out_convert_needed) {
353
+        if (output && out_samples >= current_buffer->nb_samples) {
354
+            /* convert directly to output */
355
+            av_dlog(avr, "[convert] %s to output\n", current_buffer->name);
356
+            ret = ff_audio_convert(avr->ac_out, &output_buffer, current_buffer,
357
+                                   current_buffer->nb_samples);
358
+            if (ret < 0)
359
+                return ret;
360
+
361
+            av_dlog(avr, "[end conversion]\n");
362
+            return output_buffer.nb_samples;
363
+        } else {
364
+            ret = ff_audio_data_realloc(avr->out_buffer,
365
+                                        current_buffer->nb_samples);
366
+            if (ret < 0)
367
+                return ret;
368
+            av_dlog(avr, "[convert] %s to out_buffer\n", current_buffer->name);
369
+            ret = ff_audio_convert(avr->ac_out, avr->out_buffer,
370
+                                   current_buffer, current_buffer->nb_samples);
371
+            if (ret < 0)
372
+                return ret;
373
+            current_buffer = avr->out_buffer;
374
+        }
375
+    }
376
+
377
+    return handle_buffered_output(avr, &output_buffer, current_buffer);
378
+}
379
+
380
+int avresample_available(AVAudioResampleContext *avr)
381
+{
382
+    return av_audio_fifo_size(avr->out_fifo);
383
+}
384
+
385
+int avresample_read(AVAudioResampleContext *avr, void **output, int nb_samples)
386
+{
387
+    return av_audio_fifo_read(avr->out_fifo, output, nb_samples);
388
+}
389
+
390
+unsigned avresample_version(void)
391
+{
392
+    return LIBAVRESAMPLE_VERSION_INT;
393
+}
394
+
395
+const char *avresample_license(void)
396
+{
397
+#define LICENSE_PREFIX "libavresample license: "
398
+    return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
399
+}
400
+
401
+const char *avresample_configuration(void)
402
+{
403
+    return FFMPEG_CONFIGURATION;
404
+}
0 405
new file mode 100644
... ...
@@ -0,0 +1,41 @@
0
+/*
1
+ * This file is part of Libav.
2
+ *
3
+ * Libav is free software; you can redistribute it and/or
4
+ * modify it under the terms of the GNU Lesser General Public
5
+ * License as published by the Free Software Foundation; either
6
+ * version 2.1 of the License, or (at your option) any later version.
7
+ *
8
+ * Libav is distributed in the hope that it will be useful,
9
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
+ * Lesser General Public License for more details.
12
+ *
13
+ * You should have received a copy of the GNU Lesser General Public
14
+ * License along with Libav; if not, write to the Free Software
15
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+ */
17
+
18
+#ifndef AVRESAMPLE_VERSION_H
19
+#define AVRESAMPLE_VERSION_H
20
+
21
+#define LIBAVRESAMPLE_VERSION_MAJOR  0
22
+#define LIBAVRESAMPLE_VERSION_MINOR  0
23
+#define LIBAVRESAMPLE_VERSION_MICRO  0
24
+
25
+#define LIBAVRESAMPLE_VERSION_INT  AV_VERSION_INT(LIBAVRESAMPLE_VERSION_MAJOR, \
26
+                                                  LIBAVRESAMPLE_VERSION_MINOR, \
27
+                                                  LIBAVRESAMPLE_VERSION_MICRO)
28
+#define LIBAVRESAMPLE_VERSION          AV_VERSION(LIBAVRESAMPLE_VERSION_MAJOR, \
29
+                                                  LIBAVRESAMPLE_VERSION_MINOR, \
30
+                                                  LIBAVRESAMPLE_VERSION_MICRO)
31
+#define LIBAVRESAMPLE_BUILD        LIBAVRESAMPLE_VERSION_INT
32
+
33
+#define LIBAVRESAMPLE_IDENT        "Lavr" AV_STRINGIFY(LIBAVRESAMPLE_VERSION)
34
+
35
+/**
36
+ * These FF_API_* defines are not part of public API.
37
+ * They may change, break or disappear at any time.
38
+ */
39
+
40
+#endif /* AVRESAMPLE_VERSION_H */
0 41
new file mode 100644
... ...
@@ -0,0 +1,5 @@
0
+OBJS      += x86/audio_convert_init.o                                   \
1
+             x86/audio_mix_init.o
2
+
3
+YASM-OBJS += x86/audio_convert.o                                        \
4
+             x86/audio_mix.o
0 5
new file mode 100644
... ...
@@ -0,0 +1,104 @@
0
+;******************************************************************************
1
+;* x86 optimized Format Conversion Utils
2
+;* Copyright (c) 2008 Loren Merritt
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 "x86inc.asm"
22
+%include "x86util.asm"
23
+
24
+SECTION_TEXT
25
+
26
+;-----------------------------------------------------------------------------
27
+; void ff_conv_fltp_to_flt_6ch(float *dst, float *const *src, int len,
28
+;                              int channels);
29
+;-----------------------------------------------------------------------------
30
+
31
+%macro CONV_FLTP_TO_FLT_6CH 0
32
+cglobal conv_fltp_to_flt_6ch, 2,8,7, dst, src, src1, src2, src3, src4, src5, len
33
+%if ARCH_X86_64
34
+    mov     lend, r2d
35
+%else
36
+    %define lend dword r2m
37
+%endif
38
+    mov    src1q, [srcq+1*gprsize]
39
+    mov    src2q, [srcq+2*gprsize]
40
+    mov    src3q, [srcq+3*gprsize]
41
+    mov    src4q, [srcq+4*gprsize]
42
+    mov    src5q, [srcq+5*gprsize]
43
+    mov     srcq, [srcq]
44
+    sub    src1q, srcq
45
+    sub    src2q, srcq
46
+    sub    src3q, srcq
47
+    sub    src4q, srcq
48
+    sub    src5q, srcq
49
+.loop:
50
+    mova      m0, [srcq      ]
51
+    mova      m1, [srcq+src1q]
52
+    mova      m2, [srcq+src2q]
53
+    mova      m3, [srcq+src3q]
54
+    mova      m4, [srcq+src4q]
55
+    mova      m5, [srcq+src5q]
56
+%if cpuflag(sse)
57
+    SBUTTERFLYPS 0, 1, 6
58
+    SBUTTERFLYPS 2, 3, 6
59
+    SBUTTERFLYPS 4, 5, 6
60
+
61
+    movaps    m6, m4
62
+    shufps    m4, m0, q3210
63
+    movlhps   m0, m2
64
+    movhlps   m6, m2
65
+    movaps [dstq   ], m0
66
+    movaps [dstq+16], m4
67
+    movaps [dstq+32], m6
68
+
69
+    movaps    m6, m5
70
+    shufps    m5, m1, q3210
71
+    movlhps   m1, m3
72
+    movhlps   m6, m3
73
+    movaps [dstq+48], m1
74
+    movaps [dstq+64], m5
75
+    movaps [dstq+80], m6
76
+%else ; mmx
77
+    SBUTTERFLY dq, 0, 1, 6
78
+    SBUTTERFLY dq, 2, 3, 6
79
+    SBUTTERFLY dq, 4, 5, 6
80
+
81
+    movq   [dstq   ], m0
82
+    movq   [dstq+ 8], m2
83
+    movq   [dstq+16], m4
84
+    movq   [dstq+24], m1
85
+    movq   [dstq+32], m3
86
+    movq   [dstq+40], m5
87
+%endif
88
+    add      srcq, mmsize
89
+    add      dstq, mmsize*6
90
+    sub      lend, mmsize/4
91
+    jg .loop
92
+%if mmsize == 8
93
+    emms
94
+    RET
95
+%else
96
+    REP_RET
97
+%endif
98
+%endmacro
99
+
100
+INIT_MMX mmx
101
+CONV_FLTP_TO_FLT_6CH
102
+INIT_XMM sse
103
+CONV_FLTP_TO_FLT_6CH
0 104
new file mode 100644
... ...
@@ -0,0 +1,42 @@
0
+/*
1
+ * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
2
+ *
3
+ * This file is part of Libav.
4
+ *
5
+ * Libav is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * Libav is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with Libav; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#include "config.h"
21
+#include "libavutil/cpu.h"
22
+#include "libavresample/audio_convert.h"
23
+
24
+extern void ff_conv_fltp_to_flt_6ch_mmx(float *dst, float *const *src, int len);
25
+extern void ff_conv_fltp_to_flt_6ch_sse(float *dst, float *const *src, int len);
26
+
27
+av_cold void ff_audio_convert_init_x86(AudioConvert *ac)
28
+{
29
+#if HAVE_YASM
30
+    int mm_flags = av_get_cpu_flags();
31
+
32
+    if (mm_flags & AV_CPU_FLAG_MMX && HAVE_MMX) {
33
+        ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
34
+                                  6, 1, 4, "MMX", ff_conv_fltp_to_flt_6ch_mmx);
35
+    }
36
+    if (mm_flags & AV_CPU_FLAG_SSE && HAVE_SSE) {
37
+        ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
38
+                                  6, 16, 4, "SSE", ff_conv_fltp_to_flt_6ch_sse);
39
+    }
40
+#endif
41
+}
0 42
new file mode 100644
... ...
@@ -0,0 +1,64 @@
0
+;******************************************************************************
1
+;* x86 optimized channel mixing
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 "x86inc.asm"
22
+%include "x86util.asm"
23
+
24
+SECTION_TEXT
25
+
26
+;-----------------------------------------------------------------------------
27
+; void ff_mix_2_to_1_fltp_flt(float **src, float **matrix, int len,
28
+;                             int out_ch, int in_ch);
29
+;-----------------------------------------------------------------------------
30
+
31
+%macro MIX_2_TO_1_FLTP_FLT 0
32
+cglobal mix_2_to_1_fltp_flt, 3,4,6, src, matrix, len, src1
33
+    mov       src1q, [srcq+gprsize]
34
+    mov        srcq, [srcq        ]
35
+    sub       src1q, srcq
36
+    mov     matrixq, [matrixq  ]
37
+    VBROADCASTSS m4, [matrixq  ]
38
+    VBROADCASTSS m5, [matrixq+4]
39
+    ALIGN 16
40
+.loop:
41
+    mulps        m0, m4, [srcq             ]
42
+    mulps        m1, m5, [srcq+src1q       ]
43
+    mulps        m2, m4, [srcq+      mmsize]
44
+    mulps        m3, m5, [srcq+src1q+mmsize]
45
+    addps        m0, m0, m1
46
+    addps        m2, m2, m3
47
+    mova  [srcq       ], m0
48
+    mova  [srcq+mmsize], m2
49
+    add        srcq, mmsize*2
50
+    sub        lend, mmsize*2/4
51
+    jg .loop
52
+%if mmsize == 32
53
+    vzeroupper
54
+    RET
55
+%else
56
+    REP_RET
57
+%endif
58
+%endmacro
59
+
60
+INIT_XMM sse
61
+MIX_2_TO_1_FLTP_FLT
62
+INIT_YMM avx
63
+MIX_2_TO_1_FLTP_FLT
0 64
new file mode 100644
... ...
@@ -0,0 +1,44 @@
0
+/*
1
+ * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
2
+ *
3
+ * This file is part of Libav.
4
+ *
5
+ * Libav is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * Libav is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with Libav; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#include "config.h"
21
+#include "libavutil/cpu.h"
22
+#include "libavresample/audio_mix.h"
23
+
24
+extern void ff_mix_2_to_1_fltp_flt_sse(float **src, float **matrix, int len,
25
+                                       int out_ch, int in_ch);
26
+extern void ff_mix_2_to_1_fltp_flt_avx(float **src, float **matrix, int len,
27
+                                       int out_ch, int in_ch);
28
+
29
+av_cold void ff_audio_mix_init_x86(AudioMix *am)
30
+{
31
+#if HAVE_YASM
32
+    int mm_flags = av_get_cpu_flags();
33
+
34
+    if (mm_flags & AV_CPU_FLAG_SSE && HAVE_SSE) {
35
+        ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
36
+                              2, 1, 16, 8, "SSE", ff_mix_2_to_1_fltp_flt_sse);
37
+    }
38
+    if (mm_flags & AV_CPU_FLAG_AVX && HAVE_AVX) {
39
+        ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
40
+                              2, 1, 32, 16, "AVX", ff_mix_2_to_1_fltp_flt_avx);
41
+    }
42
+#endif
43
+}
... ...
@@ -585,3 +585,12 @@
585 585
     pminsd  %1, %3
586 586
     pmaxsd  %1, %2
587 587
 %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
... ...
@@ -55,8 +55,8 @@ fate-aac-ap05_48: CMD = pcm -i $(SAMPLES)/aac/ap05_48.mp4
55 55
 fate-aac-ap05_48: REF = $(SAMPLES)/aac/ap05_48.s16
56 56
 
57 57
 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
60 60
 
61 61
 fate-aac-ct%: CMD = pcm -i $(SAMPLES)/aac/CT_DecoderCheck/$(@:fate-aac-ct-%=%)
62 62
 fate-aac-ct%: REF = $(SAMPLES)/aac/CT_DecoderCheck/aacPlusv2.wav
... ...
@@ -118,7 +118,7 @@ fi
118 118
 if [ -n "$do_dv_fmt" ] ; then
119 119
 do_lavf_timecode_nodrop dv "-ar 48000 -r 25 -s pal -ac 2"
120 120
 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"
122 122
 fi
123 123
 
124 124
 if [ -n "$do_gxf" ] ; then
... ...
@@ -4,6 +4,6 @@
4 4
 cc33ae4f9e6828914dea0f09d1241b7e *./tests/data/lavf/lavf.dv
5 5
 3480000 ./tests/data/lavf/lavf.dv
6 6
 ./tests/data/lavf/lavf.dv CRC=0x8d5e9e8f
7
-b36c83cd0ba0ebe719f09f885c4bbcd3 *./tests/data/lavf/lavf.dv
7
+87d3b20f656235671383a7eaa2f66330 *./tests/data/lavf/lavf.dv
8 8
 3600000 ./tests/data/lavf/lavf.dv
9
-./tests/data/lavf/lavf.dv CRC=0x2bc2ae3a
9
+./tests/data/lavf/lavf.dv CRC=0x0e868a82