History

libavresample: Remove deprecated library

Deprecated in c29038f3041a4080342b2e333c1967d136749c0f. The resample filter based upon this library has been removed as well.

Andreas Rheinhardt committed 5 years ago

Commit 420cedd1 parent d40bb5159 files · +5 −10167Browse files

Unified · Split

59 files
  1. Makefile +0 −1
  2. configure +3 −13
  3. doc/APIchanges +0 −1
  4. ffbuild/common.mak +1 −1
  5. fftools/cmdutils.c +0 −12
  6. fftools/ffmpeg_filter.c +0 −2
  7. libavfilter/Makefile +0 −1
  8. libavfilter/af_resample.c +0 −369
  9. libavfilter/allfilters.c +0 −1
  10. libavresample/Makefile +0 −19
  11. libavresample/aarch64/Makefile +0 −7
  12. libavresample/aarch64/asm-offsets.h +0 −28
  13. libavresample/aarch64/audio_convert_init.c +0 −49
  14. libavresample/aarch64/audio_convert_neon.S +0 −363
  15. libavresample/aarch64/neontest.c +0 −31
  16. libavresample/aarch64/resample_init.c +0 −71
  17. libavresample/aarch64/resample_neon.S +0 −233
  18. libavresample/arm/Makefile +0 −7
  19. libavresample/arm/asm-offsets.h +0 −29
  20. libavresample/arm/audio_convert_init.c +0 −49
  21. libavresample/arm/audio_convert_neon.S +0 −363
  22. libavresample/arm/neontest.c +0 −31
  23. libavresample/arm/resample_init.c +0 −74
  24. libavresample/arm/resample_neon.S +0 −358
  25. libavresample/audio_convert.c +0 −416
  26. libavresample/audio_convert.h +0 −103
  27. libavresample/audio_data.c +0 −381
  28. libavresample/audio_data.h +0 −178
  29. libavresample/audio_mix.c +0 −742
  30. libavresample/audio_mix.h +0 −94
  31. libavresample/audio_mix_matrix.c +0 −294
  32. libavresample/avresample.h +0 −595
  33. libavresample/avresampleres.rc +0 −55
  34. libavresample/dither.c +0 −440
  35. libavresample/dither.h +0 −93
  36. libavresample/internal.h +0 −116
  37. libavresample/libavresample.v +0 −6
  38. libavresample/options.c +0 −113
  39. libavresample/resample.c +0 −446
  40. libavresample/resample.h +0 −96
  41. libavresample/resample_template.c +0 −118
  42. libavresample/tests/.gitignore +0 −1
  43. libavresample/tests/avresample.c +0 −342
  44. libavresample/utils.c +0 −793
  45. libavresample/version.h +0 −50
  46. libavresample/x86/Makefile +0 −9
  47. libavresample/x86/audio_convert.asm +0 −1261
  48. libavresample/x86/audio_convert_init.c +0 −265
  49. libavresample/x86/audio_mix.asm +0 −511
  50. libavresample/x86/audio_mix_init.c +0 −215
  51. libavresample/x86/dither.asm +0 −117
  52. libavresample/x86/dither_init.c +0 −60
  53. libavresample/x86/util.asm +0 −41
  54. libavresample/x86/w64xmmtest.c +0 −31
  55. tests/Makefile +0 −1
  56. tests/fate.sh +0 −1
  57. tests/fate/libavresample.mak +0 −68
  58. tools/gen-rc +0 −1
  59. tools/target_dec_fuzzer.c +1 −1
Makefile+0−1
@@ -23,7 +23,6 @@ FFLIBS-$(CONFIG_AVDEVICE) += avdevice · 22 unmodified lines
23FFLIBS-$(CONFIG_AVFILTER) += avfilter23FFLIBS-$(CONFIG_AVFILTER) += avfilter
24FFLIBS-$(CONFIG_AVFORMAT) += avformat24FFLIBS-$(CONFIG_AVFORMAT) += avformat
25FFLIBS-$(CONFIG_AVCODEC) += avcodec25FFLIBS-$(CONFIG_AVCODEC) += avcodec
26FFLIBS-$(CONFIG_AVRESAMPLE) += avresample
27FFLIBS-$(CONFIG_POSTPROC) += postproc26FFLIBS-$(CONFIG_POSTPROC) += postproc
28FFLIBS-$(CONFIG_SWRESAMPLE) += swresample27FFLIBS-$(CONFIG_SWRESAMPLE) += swresample
29FFLIBS-$(CONFIG_SWSCALE) += swscale28FFLIBS-$(CONFIG_SWSCALE) += swscale
configure+3−13
@@ -132,7 +132,6 @@ Component options: · 131 unmodified lines
132 --disable-swscale disable libswscale build132 --disable-swscale disable libswscale build
133 --disable-postproc disable libpostproc build133 --disable-postproc disable libpostproc build
134 --disable-avfilter disable libavfilter build134 --disable-avfilter disable libavfilter build
135 --enable-avresample enable libavresample build (deprecated) [no]
136 --disable-pthreads disable pthreads [autodetect]135 --disable-pthreads disable pthreads [autodetect]
137 --disable-w32threads disable Win32 threads [autodetect]136 --disable-w32threads disable Win32 threads [autodetect]
138 --disable-os2threads disable OS/2 threads [autodetect]137 --disable-os2threads disable OS/2 threads [autodetect]
@@ -1901,7 +1900,6 @@ LIBRARY_LIST=" · 1762 unmodified lines
1901 avformat1900 avformat
1902 avcodec1901 avcodec
1903 swresample1902 swresample
1904 avresample
1905 avutil1903 avutil
1906"1904"
1907 1905
@@ -3609,7 +3607,6 @@ program_opencl_filter_deps="opencl" · 1701 unmodified lines
3609pullup_filter_deps="gpl"3607pullup_filter_deps="gpl"
3610removelogo_filter_deps="avcodec avformat swscale"3608removelogo_filter_deps="avcodec avformat swscale"
3611repeatfields_filter_deps="gpl"3609repeatfields_filter_deps="gpl"
3612resample_filter_deps="avresample"
3613roberts_opencl_filter_deps="opencl"3610roberts_opencl_filter_deps="opencl"
3614rubberband_filter_deps="librubberband"3611rubberband_filter_deps="librubberband"
3615sab_filter_deps="gpl swscale"3612sab_filter_deps="gpl swscale"
@@ -3711,8 +3708,6 @@ avfilter_deps="avutil" · 95 unmodified lines
3711avfilter_suggest="libm"3708avfilter_suggest="libm"
3712avformat_deps="avcodec avutil"3709avformat_deps="avcodec avutil"
3713avformat_suggest="libm network zlib"3710avformat_suggest="libm network zlib"
3714avresample_deps="avutil"
3715avresample_suggest="libm"
3716avutil_suggest="clock_gettime ffnvcodec libm libdrm libmfx opencl user32 vaapi vulkan videotoolbox corefoundation corevideo coremedia bcrypt"3711avutil_suggest="clock_gettime ffnvcodec libm libdrm libmfx opencl user32 vaapi vulkan videotoolbox corefoundation corevideo coremedia bcrypt"
3717postproc_deps="avutil gpl"3712postproc_deps="avutil gpl"
3718postproc_suggest="libm"3713postproc_suggest="libm"
@@ -3795,7 +3790,7 @@ intrinsics="none" · 76 unmodified lines
3795enable $PROGRAM_LIST3790enable $PROGRAM_LIST
3796enable $DOCUMENT_LIST3791enable $DOCUMENT_LIST
3797enable $EXAMPLE_LIST3792enable $EXAMPLE_LIST
3798enable $(filter_out avresample $LIBRARY_LIST)3793enable $LIBRARY_LIST
3799enable stripping3794enable stripping
3800 3795
3801enable asm3796enable asm
@@ -6845,7 +6840,7 @@ EOF · 3043 unmodified lines
6845 6840
6846# add some linker flags6841# add some linker flags
6847check_ldflags -Wl,--warn-common6842check_ldflags -Wl,--warn-common
6848check_ldflags -Wl,-rpath-link=:libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil:libavresample6843check_ldflags -Wl,-rpath-link=:libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil
6849enabled rpath && add_ldexeflags -Wl,-rpath,$libdir && add_ldsoflags -Wl,-rpath,$libdir6844enabled rpath && add_ldexeflags -Wl,-rpath,$libdir && add_ldsoflags -Wl,-rpath,$libdir
6850test_ldflags -Wl,-Bsymbolic && append SHFLAGS -Wl,-Bsymbolic6845test_ldflags -Wl,-Bsymbolic && append SHFLAGS -Wl,-Bsymbolic
6851 6846
@@ -6860,8 +6855,7 @@ enabled neon_clobber_test && · 8 unmodified lines
6860 -Wl,--wrap,avcodec_receive_packet \6855 -Wl,--wrap,avcodec_receive_packet \
6861 -Wl,--wrap,avcodec_send_frame \6856 -Wl,--wrap,avcodec_send_frame \
6862 -Wl,--wrap,avcodec_receive_frame \6857 -Wl,--wrap,avcodec_receive_frame \
6863 -Wl,--wrap,swr_convert \6858 -Wl,--wrap,swr_convert ||
6864 -Wl,--wrap,avresample_convert ||
6865 disable neon_clobber_test6859 disable neon_clobber_test
6866 6860
6867enabled xmm_clobber_test &&6861enabled xmm_clobber_test &&
@@ -6873,7 +6867,6 @@ enabled xmm_clobber_test && · 5 unmodified lines
6873 -Wl,--wrap,avcodec_send_frame \6867 -Wl,--wrap,avcodec_send_frame \
6874 -Wl,--wrap,avcodec_receive_frame \6868 -Wl,--wrap,avcodec_receive_frame \
6875 -Wl,--wrap,swr_convert \6869 -Wl,--wrap,swr_convert \
6876 -Wl,--wrap,avresample_convert \
6877 -Wl,--wrap,sws_scale ||6870 -Wl,--wrap,sws_scale ||
6878 disable xmm_clobber_test6871 disable xmm_clobber_test
6879 6872
@@ -7098,7 +7091,6 @@ check_deps $CONFIG_LIST \ · 218 unmodified lines
7098 $ALL_COMPONENTS \7091 $ALL_COMPONENTS \
7099 7092
7100enabled threads && ! enabled pthreads && ! enabled atomics_native && die "non pthread threading without atomics not supported, try adding --enable-pthreads or --cpu=i486 or higher if you are on x86"7093enabled threads && ! enabled pthreads && ! enabled atomics_native && die "non pthread threading without atomics not supported, try adding --enable-pthreads or --cpu=i486 or higher if you are on x86"
7101enabled avresample && warn "Building with deprecated library libavresample"
7102 7094
7103case $target_os in7095case $target_os in
7104haiku)7096haiku)
@@ -7214,7 +7206,6 @@ enabled movie_filter && prepend avfilter_deps "avformat avcodec" · 109 unmodified lines
7214enabled pan_filter && prepend avfilter_deps "swresample"7206enabled pan_filter && prepend avfilter_deps "swresample"
7215enabled pp_filter && prepend avfilter_deps "postproc"7207enabled pp_filter && prepend avfilter_deps "postproc"
7216enabled removelogo_filter && prepend avfilter_deps "avformat avcodec swscale"7208enabled removelogo_filter && prepend avfilter_deps "avformat avcodec swscale"
7217enabled resample_filter && prepend avfilter_deps "avresample"
7218enabled sab_filter && prepend avfilter_deps "swscale"7209enabled sab_filter && prepend avfilter_deps "swscale"
7219enabled scale_filter && prepend avfilter_deps "swscale"7210enabled scale_filter && prepend avfilter_deps "swscale"
7220enabled scale2ref_filter && prepend avfilter_deps "swscale"7211enabled scale2ref_filter && prepend avfilter_deps "swscale"
@@ -7707,7 +7698,6 @@ extralibs_avcodec="$avcodec_extralibs" · 486 unmodified lines
7707extralibs_avformat="$avformat_extralibs"7698extralibs_avformat="$avformat_extralibs"
7708extralibs_avdevice="$avdevice_extralibs"7699extralibs_avdevice="$avdevice_extralibs"
7709extralibs_avfilter="$avfilter_extralibs"7700extralibs_avfilter="$avfilter_extralibs"
7710extralibs_avresample="$avresample_extralibs"
7711extralibs_postproc="$postproc_extralibs"7701extralibs_postproc="$postproc_extralibs"
7712extralibs_swscale="$swscale_extralibs"7702extralibs_swscale="$swscale_extralibs"
7713extralibs_swresample="$swresample_extralibs"7703extralibs_swresample="$swresample_extralibs"
doc/APIchanges+0−1
@@ -6,7 +6,6 @@ libavcodec: 2017-10-21 · 5 unmodified lines
6libavdevice: 2017-10-216libavdevice: 2017-10-21
7libavfilter: 2017-10-217libavfilter: 2017-10-21
8libavformat: 2017-10-218libavformat: 2017-10-21
9libavresample: 2017-10-21
10libpostproc: 2017-10-219libpostproc: 2017-10-21
11libswresample: 2017-10-2110libswresample: 2017-10-21
12libswscale: 2017-10-2111libswscale: 2017-10-21
ffbuild/common.mak+1−1
@@ -26,7 +26,7 @@ $(foreach VAR,$(SILENT),$(eval override $(VAR) = @$($(VAR)))) · 25 unmodified lines
26$(eval INSTALL = @$(call ECHO,INSTALL,$$(^:$(SRC_DIR)/%=%)); $(INSTALL))26$(eval INSTALL = @$(call ECHO,INSTALL,$$(^:$(SRC_DIR)/%=%)); $(INSTALL))
27endif27endif
28 28
29ALLFFLIBS = avcodec avdevice avfilter avformat avresample avutil postproc swscale swresample29ALLFFLIBS = avcodec avdevice avfilter avformat avutil postproc swscale swresample
30 30
31# NASM requires -I path terminated with /31# NASM requires -I path terminated with /
32IFLAGS := -I. -I$(SRC_LINK)/32IFLAGS := -I. -I$(SRC_LINK)/
fftools/cmdutils.c+0−12
@@ -34,7 +34,6 @@ · 33 unmodified lines
34#include "libavformat/avformat.h"34#include "libavformat/avformat.h"
35#include "libavfilter/avfilter.h"35#include "libavfilter/avfilter.h"
36#include "libavdevice/avdevice.h"36#include "libavdevice/avdevice.h"
37#include "libavresample/avresample.h"
38#include "libswscale/swscale.h"37#include "libswscale/swscale.h"
39#include "libswresample/swresample.h"38#include "libswresample/swresample.h"
40#include "libpostproc/postprocess.h"39#include "libpostproc/postprocess.h"
@@ -545,9 +544,6 @@ int opt_default(void *optctx, const char *opt, const char *arg) · 504 unmodified lines
545 char opt_stripped[128];544 char opt_stripped[128];
546 const char *p;545 const char *p;
547 const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class();546 const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class();
548#if CONFIG_AVRESAMPLE
549 const AVClass *rc = avresample_get_class();
550#endif
551#if CONFIG_SWSCALE547#if CONFIG_SWSCALE
552 const AVClass *sc = sws_get_class();548 const AVClass *sc = sws_get_class();
553#endif549#endif
@@ -617,13 +613,6 @@ int opt_default(void *optctx, const char *opt, const char *arg) · 63 unmodified lines
617 consumed = 1;613 consumed = 1;
618 }614 }
619#endif615#endif
620#if CONFIG_AVRESAMPLE
621 if ((o=opt_find(&rc, opt, NULL, 0,
622 AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
623 av_dict_set(&resample_opts, opt, arg, FLAGS);
624 consumed = 1;
625 }
626#endif
627 616
628 if (consumed)617 if (consumed)
629 return 0;618 return 0;
@@ -1134,7 +1123,6 @@ static void print_all_libs_info(int flags, int level) · 504 unmodified lines
1134 PRINT_LIB_INFO(avformat, AVFORMAT, flags, level);1123 PRINT_LIB_INFO(avformat, AVFORMAT, flags, level);
1135 PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level);1124 PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level);
1136 PRINT_LIB_INFO(avfilter, AVFILTER, flags, level);1125 PRINT_LIB_INFO(avfilter, AVFILTER, flags, level);
1137 PRINT_LIB_INFO(avresample, AVRESAMPLE, flags, level);
1138 PRINT_LIB_INFO(swscale, SWSCALE, flags, level);1126 PRINT_LIB_INFO(swscale, SWSCALE, flags, level);
1139 PRINT_LIB_INFO(swresample, SWRESAMPLE, flags, level);1127 PRINT_LIB_INFO(swresample, SWRESAMPLE, flags, level);
1140 PRINT_LIB_INFO(postproc, POSTPROC, flags, level);1128 PRINT_LIB_INFO(postproc, POSTPROC, flags, level);
fftools/ffmpeg_filter.c+0−2
@@ -26,8 +26,6 @@ · 25 unmodified lines
26#include "libavfilter/buffersink.h"26#include "libavfilter/buffersink.h"
27#include "libavfilter/buffersrc.h"27#include "libavfilter/buffersrc.h"
28 28
29#include "libavresample/avresample.h"
30
31#include "libavutil/avassert.h"29#include "libavutil/avassert.h"
32#include "libavutil/avstring.h"30#include "libavutil/avstring.h"
33#include "libavutil/bprint.h"31#include "libavutil/bprint.h"
libavfilter/Makefile+0−1
@@ -135,7 +135,6 @@ OBJS-$(CONFIG_LV2_FILTER) += af_lv2.o · 134 unmodified lines
135OBJS-$(CONFIG_MCOMPAND_FILTER) += af_mcompand.o135OBJS-$(CONFIG_MCOMPAND_FILTER) += af_mcompand.o
136OBJS-$(CONFIG_PAN_FILTER) += af_pan.o136OBJS-$(CONFIG_PAN_FILTER) += af_pan.o
137OBJS-$(CONFIG_REPLAYGAIN_FILTER) += af_replaygain.o137OBJS-$(CONFIG_REPLAYGAIN_FILTER) += af_replaygain.o
138OBJS-$(CONFIG_RESAMPLE_FILTER) += af_resample.o
139OBJS-$(CONFIG_RUBBERBAND_FILTER) += af_rubberband.o138OBJS-$(CONFIG_RUBBERBAND_FILTER) += af_rubberband.o
140OBJS-$(CONFIG_SIDECHAINCOMPRESS_FILTER) += af_sidechaincompress.o139OBJS-$(CONFIG_SIDECHAINCOMPRESS_FILTER) += af_sidechaincompress.o
141OBJS-$(CONFIG_SIDECHAINGATE_FILTER) += af_agate.o140OBJS-$(CONFIG_SIDECHAINGATE_FILTER) += af_agate.o
libavfilter/af_resample.c+0−369
@@ -1,369 +0,0 @@
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19/**
20 * @file
21 * sample format and channel layout conversion audio filter
22 */
23
24#include "libavutil/avassert.h"
25#include "libavutil/avstring.h"
26#include "libavutil/common.h"
27#include "libavutil/dict.h"
28#include "libavutil/mathematics.h"
29#include "libavutil/opt.h"
30
31#include "libavresample/avresample.h"
32
33#include "audio.h"
34#include "avfilter.h"
35#include "formats.h"
36#include "internal.h"
37
38typedef struct ResampleContext {
39 const AVClass *class;
40 AVAudioResampleContext *avr;
41 AVDictionary *options;
42
43 int resampling;
44 int64_t next_pts;
45 int64_t next_in_pts;
46
47 /* set by filter_frame() to signal an output frame to request_frame() */
48 int got_output;
49} ResampleContext;
50
51static av_cold int init(AVFilterContext *ctx, AVDictionary **opts)
52{
53 ResampleContext *s = ctx->priv;
54 const AVClass *avr_class = avresample_get_class();
55 AVDictionaryEntry *e = NULL;
56
57 while ((e = av_dict_get(*opts, "", e, AV_DICT_IGNORE_SUFFIX))) {
58 if (av_opt_find(&avr_class, e->key, NULL, 0,
59 AV_OPT_SEARCH_FAKE_OBJ | AV_OPT_SEARCH_CHILDREN))
60 av_dict_set(&s->options, e->key, e->value, 0);
61 }
62
63 e = NULL;
64 while ((e = av_dict_get(s->options, "", e, AV_DICT_IGNORE_SUFFIX)))
65 av_dict_set(opts, e->key, NULL, 0);
66
67 /* do not allow the user to override basic format options */
68 av_dict_set(&s->options, "in_channel_layout", NULL, 0);
69 av_dict_set(&s->options, "out_channel_layout", NULL, 0);
70 av_dict_set(&s->options, "in_sample_fmt", NULL, 0);
71 av_dict_set(&s->options, "out_sample_fmt", NULL, 0);
72 av_dict_set(&s->options, "in_sample_rate", NULL, 0);
73 av_dict_set(&s->options, "out_sample_rate", NULL, 0);
74
75 return 0;
76}
77
78static av_cold void uninit(AVFilterContext *ctx)
79{
80 ResampleContext *s = ctx->priv;
81
82 if (s->avr) {
83 avresample_close(s->avr);
84 avresample_free(&s->avr);
85 }
86 av_dict_free(&s->options);
87}
88
89static int query_formats(AVFilterContext *ctx)
90{
91 AVFilterLink *inlink = ctx->inputs[0];
92 AVFilterLink *outlink = ctx->outputs[0];
93 AVFilterFormats *in_formats, *out_formats, *in_samplerates, *out_samplerates;
94 AVFilterChannelLayouts *in_layouts, *out_layouts;
95 int ret;
96
97 if (!(in_formats = ff_all_formats (AVMEDIA_TYPE_AUDIO)) ||
98 !(out_formats = ff_all_formats (AVMEDIA_TYPE_AUDIO)) ||
99 !(in_samplerates = ff_all_samplerates ( )) ||
100 !(out_samplerates = ff_all_samplerates ( )) ||
101 !(in_layouts = ff_all_channel_layouts ( )) ||
102 !(out_layouts = ff_all_channel_layouts ( )))
103 return AVERROR(ENOMEM);
104
105 if ((ret = ff_formats_ref (in_formats, &inlink->outcfg.formats )) < 0 ||
106 (ret = ff_formats_ref (out_formats, &outlink->incfg.formats )) < 0 ||
107 (ret = ff_formats_ref (in_samplerates, &inlink->outcfg.samplerates )) < 0 ||
108 (ret = ff_formats_ref (out_samplerates, &outlink->incfg.samplerates )) < 0 ||
109 (ret = ff_channel_layouts_ref (in_layouts, &inlink->outcfg.channel_layouts)) < 0 ||
110 (ret = ff_channel_layouts_ref (out_layouts, &outlink->incfg.channel_layouts)) < 0)
111 return ret;
112
113 return 0;
114}
115
116static int config_output(AVFilterLink *outlink)
117{
118 AVFilterContext *ctx = outlink->src;
119 AVFilterLink *inlink = ctx->inputs[0];
120 ResampleContext *s = ctx->priv;
121 char buf1[64], buf2[64];
122 int ret;
123
124 int64_t resampling_forced;
125
126 if (s->avr) {
127 avresample_close(s->avr);
128 avresample_free(&s->avr);
129 }
130
131 if (inlink->channel_layout == outlink->channel_layout &&
132 inlink->sample_rate == outlink->sample_rate &&
133 (inlink->format == outlink->format ||
134 (av_get_channel_layout_nb_channels(inlink->channel_layout) == 1 &&
135 av_get_channel_layout_nb_channels(outlink->channel_layout) == 1 &&
136 av_get_planar_sample_fmt(inlink->format) ==
137 av_get_planar_sample_fmt(outlink->format))))
138 return 0;
139
140 if (!(s->avr = avresample_alloc_context()))
141 return AVERROR(ENOMEM);
142
143 if (s->options) {
144 int ret;
145 AVDictionaryEntry *e = NULL;
146 while ((e = av_dict_get(s->options, "", e, AV_DICT_IGNORE_SUFFIX)))
147 av_log(ctx, AV_LOG_VERBOSE, "lavr option: %s=%s\n", e->key, e->value);
148
149 ret = av_opt_set_dict(s->avr, &s->options);
150 if (ret < 0)
151 return ret;
152 }
153
154 av_opt_set_int(s->avr, "in_channel_layout", inlink ->channel_layout, 0);
155 av_opt_set_int(s->avr, "out_channel_layout", outlink->channel_layout, 0);
156 av_opt_set_int(s->avr, "in_sample_fmt", inlink ->format, 0);
157 av_opt_set_int(s->avr, "out_sample_fmt", outlink->format, 0);
158 av_opt_set_int(s->avr, "in_sample_rate", inlink ->sample_rate, 0);
159 av_opt_set_int(s->avr, "out_sample_rate", outlink->sample_rate, 0);
160
161 if ((ret = avresample_open(s->avr)) < 0)
162 return ret;
163
164 av_opt_get_int(s->avr, "force_resampling", 0, &resampling_forced);
165 s->resampling = resampling_forced || (inlink->sample_rate != outlink->sample_rate);
166
167 if (s->resampling) {
168 outlink->time_base = (AVRational){ 1, outlink->sample_rate };
169 s->next_pts = AV_NOPTS_VALUE;
170 s->next_in_pts = AV_NOPTS_VALUE;
171 } else
172 outlink->time_base = inlink->time_base;
173
174 av_get_channel_layout_string(buf1, sizeof(buf1),
175 -1, inlink ->channel_layout);
176 av_get_channel_layout_string(buf2, sizeof(buf2),
177 -1, outlink->channel_layout);
178 av_log(ctx, AV_LOG_VERBOSE,
179 "fmt:%s srate:%d cl:%s -> fmt:%s srate:%d cl:%s\n",
180 av_get_sample_fmt_name(inlink ->format), inlink ->sample_rate, buf1,
181 av_get_sample_fmt_name(outlink->format), outlink->sample_rate, buf2);
182
183 return 0;
184}
185
186static int request_frame(AVFilterLink *outlink)
187{
188 AVFilterContext *ctx = outlink->src;
189 ResampleContext *s = ctx->priv;
190 int ret = 0;
191
192 s->got_output = 0;
193 while (ret >= 0 && !s->got_output)
194 ret = ff_request_frame(ctx->inputs[0]);
195
196 /* flush the lavr delay buffer */
197 if (ret == AVERROR_EOF && s->avr) {
198 AVFrame *frame;
199 int nb_samples = avresample_get_out_samples(s->avr, 0);
200
201 if (!nb_samples)
202 return ret;
203
204 frame = ff_get_audio_buffer(outlink, nb_samples);
205 if (!frame)
206 return AVERROR(ENOMEM);
207
208 ret = avresample_convert(s->avr, frame->extended_data,
209 frame->linesize[0], nb_samples,
210 NULL, 0, 0);
211 if (ret <= 0) {
212 av_frame_free(&frame);
213 return (ret == 0) ? AVERROR_EOF : ret;
214 }
215
216 frame->nb_samples = ret;
217 frame->pts = s->next_pts;
218 return ff_filter_frame(outlink, frame);
219 }
220 return ret;
221}
222
223static int filter_frame(AVFilterLink *inlink, AVFrame *in)
224{
225 AVFilterContext *ctx = inlink->dst;
226 ResampleContext *s = ctx->priv;
227 AVFilterLink *outlink = ctx->outputs[0];
228 int ret;
229
230 if (s->avr) {
231 AVFrame *out;
232 int delay, nb_samples;
233
234 /* maximum possible samples lavr can output */
235 delay = avresample_get_delay(s->avr);
236 nb_samples = avresample_get_out_samples(s->avr, in->nb_samples);
237
238 out = ff_get_audio_buffer(outlink, nb_samples);
239 if (!out) {
240 ret = AVERROR(ENOMEM);
241 goto fail;
242 }
243
244 ret = avresample_convert(s->avr, out->extended_data, out->linesize[0],
245 nb_samples, in->extended_data, in->linesize[0],
246 in->nb_samples);
247 if (ret <= 0) {
248 av_frame_free(&out);
249 if (ret < 0)
250 goto fail;
251 }
252
253 av_assert0(!avresample_available(s->avr));
254
255 if (s->resampling && s->next_pts == AV_NOPTS_VALUE) {
256 if (in->pts == AV_NOPTS_VALUE) {
257 av_log(ctx, AV_LOG_WARNING, "First timestamp is missing, "
258 "assuming 0.\n");
259 s->next_pts = 0;
260 } else
261 s->next_pts = av_rescale_q(in->pts, inlink->time_base,
262 outlink->time_base);
263 }
264
265 if (ret > 0) {
266 out->nb_samples = ret;
267
268 ret = av_frame_copy_props(out, in);
269 if (ret < 0) {
270 av_frame_free(&out);
271 goto fail;
272 }
273
274 if (s->resampling) {
275 out->sample_rate = outlink->sample_rate;
276 /* Only convert in->pts if there is a discontinuous jump.
277 This ensures that out->pts tracks the number of samples actually
278 output by the resampler in the absence of such a jump.
279 Otherwise, the rounding in av_rescale_q() and av_rescale()
280 causes off-by-1 errors. */
281 if (in->pts != AV_NOPTS_VALUE && in->pts != s->next_in_pts) {
282 out->pts = av_rescale_q(in->pts, inlink->time_base,
283 outlink->time_base) -
284 av_rescale(delay, outlink->sample_rate,
285 inlink->sample_rate);
286 } else
287 out->pts = s->next_pts;
288
289 s->next_pts = out->pts + out->nb_samples;
290 s->next_in_pts = in->pts + in->nb_samples;
291 } else
292 out->pts = in->pts;
293
294 ret = ff_filter_frame(outlink, out);
295 s->got_output = 1;
296 }
297
298fail:
299 av_frame_free(&in);
300 } else {
301 in->format = outlink->format;
302 ret = ff_filter_frame(outlink, in);
303 s->got_output = 1;
304 }
305
306 return ret;
307}
308
309#if FF_API_CHILD_CLASS_NEXT
310static const AVClass *resample_child_class_next(const AVClass *prev)
311{
312 return prev ? NULL : avresample_get_class();
313}
314#endif
315
316static const AVClass *resample_child_class_iterate(void **iter)
317{
318 const AVClass *c = *iter ? NULL : avresample_get_class();
319 *iter = (void*)(uintptr_t)c;
320 return c;
321}
322
323static void *resample_child_next(void *obj, void *prev)
324{
325 ResampleContext *s = obj;
326 return prev ? NULL : s->avr;
327}
328
329static const AVClass resample_class = {
330 .class_name = "resample",
331 .item_name = av_default_item_name,
332 .version = LIBAVUTIL_VERSION_INT,
333#if FF_API_CHILD_CLASS_NEXT
334 .child_class_next = resample_child_class_next,
335#endif
336 .child_class_iterate = resample_child_class_iterate,
337 .child_next = resample_child_next,
338};
339
340static const AVFilterPad avfilter_af_resample_inputs[] = {
341 {
342 .name = "default",
343 .type = AVMEDIA_TYPE_AUDIO,
344 .filter_frame = filter_frame,
345 },
346 { NULL }
347};
348
349static const AVFilterPad avfilter_af_resample_outputs[] = {
350 {
351 .name = "default",
352 .type = AVMEDIA_TYPE_AUDIO,
353 .config_props = config_output,
354 .request_frame = request_frame
355 },
356 { NULL }
357};
358
359AVFilter ff_af_resample = {
360 .name = "resample",
361 .description = NULL_IF_CONFIG_SMALL("Audio resampling and conversion."),
362 .priv_size = sizeof(ResampleContext),
363 .priv_class = &resample_class,
364 .init_dict = init,
365 .uninit = uninit,
366 .query_formats = query_formats,
367 .inputs = avfilter_af_resample_inputs,
368 .outputs = avfilter_af_resample_outputs,
369};
libavfilter/allfilters.c+0−1
@@ -129,7 +129,6 @@ extern AVFilter ff_af_lv2; · 128 unmodified lines
129extern AVFilter ff_af_mcompand;129extern AVFilter ff_af_mcompand;
130extern AVFilter ff_af_pan;130extern AVFilter ff_af_pan;
131extern AVFilter ff_af_replaygain;131extern AVFilter ff_af_replaygain;
132extern AVFilter ff_af_resample;
133extern AVFilter ff_af_rubberband;132extern AVFilter ff_af_rubberband;
134extern AVFilter ff_af_sidechaincompress;133extern AVFilter ff_af_sidechaincompress;
135extern AVFilter ff_af_sidechaingate;134extern AVFilter ff_af_sidechaingate;
libavresample/Makefile+0−19
@@ -1,19 +0,0 @@
1NAME = avresample
2DESC = Libav audio resampling library
3
4HEADERS = avresample.h \
5 version.h \
6
7OBJS = audio_convert.o \
8 audio_data.o \
9 audio_mix.o \
10 audio_mix_matrix.o \
11 dither.o \
12 options.o \
13 resample.o \
14 utils.o \
15
16# Windows resource file
17SLIBOBJS-$(HAVE_GNU_WINDRES) += avresampleres.o
18
19TESTPROGS = avresample
libavresample/aarch64/Makefile+0−7
@@ -1,7 +0,0 @@
1OBJS += aarch64/audio_convert_init.o \
2 aarch64/resample_init.o \
3
4OBJS-$(CONFIG_NEON_CLOBBER_TEST) += aarch64/neontest.o
5
6NEON-OBJS += aarch64/audio_convert_neon.o \
7 aarch64/resample_neon.o \
libavresample/aarch64/asm-offsets.h+0−28
@@ -1,28 +0,0 @@
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#ifndef AVRESAMPLE_AARCH64_ASM_OFFSETS_H
20#define AVRESAMPLE_AARCH64_ASM_OFFSETS_H
21
22/* struct ResampleContext */
23#define FILTER_BANK 0x10
24#define FILTER_LENGTH 0x18
25#define PHASE_SHIFT 0x34
26#define PHASE_MASK (PHASE_SHIFT + 0x04) // loaded as pair
27
28#endif /* AVRESAMPLE_AARCH64_ASM_OFFSETS_H */
libavresample/aarch64/audio_convert_init.c+0−49
@@ -1,49 +0,0 @@
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include <stdint.h>
20
21#include "config.h"
22#include "libavutil/attributes.h"
23#include "libavutil/cpu.h"
24#include "libavutil/aarch64/cpu.h"
25#include "libavutil/samplefmt.h"
26#include "libavresample/audio_convert.h"
27
28void ff_conv_flt_to_s16_neon(int16_t *dst, const float *src, int len);
29void ff_conv_fltp_to_s16_neon(int16_t *dst, float *const *src,
30 int len, int channels);
31void ff_conv_fltp_to_s16_2ch_neon(int16_t *dst, float *const *src,
32 int len, int channels);
33
34av_cold void ff_audio_convert_init_aarch64(AudioConvert *ac)
35{
36 int cpu_flags = av_get_cpu_flags();
37
38 if (have_neon(cpu_flags)) {
39 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT,
40 0, 16, 8, "NEON",
41 ff_conv_flt_to_s16_neon);
42 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLTP,
43 2, 16, 8, "NEON",
44 ff_conv_fltp_to_s16_2ch_neon);
45 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLTP,
46 0, 16, 8, "NEON",
47 ff_conv_fltp_to_s16_neon);
48 }
49}
libavresample/aarch64/audio_convert_neon.S+0−363
@@ -1,363 +0,0 @@
1/*
2 * Copyright (c) 2008 Mans Rullgard <mans@mansr.com>
3 * Copyright (c) 2014 Janne Grunau <janne-libav@jannau.net>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "config.h"
23#include "libavutil/aarch64/asm.S"
24
25function ff_conv_flt_to_s16_neon, export=1
26 subs x2, x2, #8
27 ld1 {v0.4s}, [x1], #16
28 fcvtzs v4.4s, v0.4s, #31
29 ld1 {v1.4s}, [x1], #16
30 fcvtzs v5.4s, v1.4s, #31
31 b.eq 3f
32 ands x12, x2, #~15
33 b.eq 2f
341: subs x12, x12, #16
35 sqrshrn v4.4h, v4.4s, #16
36 ld1 {v2.4s}, [x1], #16
37 fcvtzs v6.4s, v2.4s, #31
38 sqrshrn2 v4.8h, v5.4s, #16
39 ld1 {v3.4s}, [x1], #16
40 fcvtzs v7.4s, v3.4s, #31
41 sqrshrn v6.4h, v6.4s, #16
42 st1 {v4.8h}, [x0], #16
43 sqrshrn2 v6.8h, v7.4s, #16
44 ld1 {v0.4s}, [x1], #16
45 fcvtzs v4.4s, v0.4s, #31
46 ld1 {v1.4s}, [x1], #16
47 fcvtzs v5.4s, v1.4s, #31
48 st1 {v6.8h}, [x0], #16
49 b.ne 1b
50 ands x2, x2, #15
51 b.eq 3f
522: ld1 {v2.4s}, [x1], #16
53 sqrshrn v4.4h, v4.4s, #16
54 fcvtzs v6.4s, v2.4s, #31
55 ld1 {v3.4s}, [x1], #16
56 sqrshrn2 v4.8h, v5.4s, #16
57 fcvtzs v7.4s, v3.4s, #31
58 sqrshrn v6.4h, v6.4s, #16
59 st1 {v4.8h}, [x0], #16
60 sqrshrn2 v6.8h, v7.4s, #16
61 st1 {v6.8h}, [x0]
62 ret
633: sqrshrn v4.4h, v4.4s, #16
64 sqrshrn2 v4.8h, v5.4s, #16
65 st1 {v4.8h}, [x0]
66 ret
67endfunc
68
69function ff_conv_fltp_to_s16_2ch_neon, export=1
70 ldp x4, x5, [x1]
71 subs x2, x2, #8
72 ld1 {v0.4s}, [x4], #16
73 fcvtzs v4.4s, v0.4s, #31
74 ld1 {v1.4s}, [x4], #16
75 fcvtzs v5.4s, v1.4s, #31
76 ld1 {v2.4s}, [x5], #16
77 fcvtzs v6.4s, v2.4s, #31
78 ld1 {v3.4s}, [x5], #16
79 fcvtzs v7.4s, v3.4s, #31
80 b.eq 3f
81 ands x12, x2, #~15
82 b.eq 2f
831: subs x12, x12, #16
84 ld1 {v16.4s}, [x4], #16
85 fcvtzs v20.4s, v16.4s, #31
86 sri v6.4s, v4.4s, #16
87 ld1 {v17.4s}, [x4], #16
88 fcvtzs v21.4s, v17.4s, #31
89 ld1 {v18.4s}, [x5], #16
90 fcvtzs v22.4s, v18.4s, #31
91 ld1 {v19.4s}, [x5], #16
92 sri v7.4s, v5.4s, #16
93 st1 {v6.4s}, [x0], #16
94 fcvtzs v23.4s, v19.4s, #31
95 st1 {v7.4s}, [x0], #16
96 sri v22.4s, v20.4s, #16
97 ld1 {v0.4s}, [x4], #16
98 sri v23.4s, v21.4s, #16
99 st1 {v22.4s}, [x0], #16
100 fcvtzs v4.4s, v0.4s, #31
101 ld1 {v1.4s}, [x4], #16
102 fcvtzs v5.4s, v1.4s, #31
103 ld1 {v2.4s}, [x5], #16
104 fcvtzs v6.4s, v2.4s, #31
105 ld1 {v3.4s}, [x5], #16
106 fcvtzs v7.4s, v3.4s, #31
107 st1 {v23.4s}, [x0], #16
108 b.ne 1b
109 ands x2, x2, #15
110 b.eq 3f
1112: sri v6.4s, v4.4s, #16
112 ld1 {v0.4s}, [x4], #16
113 fcvtzs v0.4s, v0.4s, #31
114 ld1 {v1.4s}, [x4], #16
115 fcvtzs v1.4s, v1.4s, #31
116 ld1 {v2.4s}, [x5], #16
117 fcvtzs v2.4s, v2.4s, #31
118 sri v7.4s, v5.4s, #16
119 ld1 {v3.4s}, [x5], #16
120 fcvtzs v3.4s, v3.4s, #31
121 sri v2.4s, v0.4s, #16
122 st1 {v6.4s,v7.4s}, [x0], #32
123 sri v3.4s, v1.4s, #16
124 st1 {v2.4s,v3.4s}, [x0], #32
125 ret
1263: sri v6.4s, v4.4s, #16
127 sri v7.4s, v5.4s, #16
128 st1 {v6.4s,v7.4s}, [x0]
129 ret
130endfunc
131
132function ff_conv_fltp_to_s16_neon, export=1
133 cmp w3, #2
134 b.eq X(ff_conv_fltp_to_s16_2ch_neon)
135 b.gt 1f
136 ldr x1, [x1]
137 b X(ff_conv_flt_to_s16_neon)
1381:
139 cmp w3, #4
140 lsl x12, x3, #1
141 b.lt 4f
142
1435: // 4 channels
144 ldp x4, x5, [x1], #16
145 ldp x6, x7, [x1], #16
146 mov w9, w2
147 mov x8, x0
148 ld1 {v4.4s}, [x4], #16
149 fcvtzs v4.4s, v4.4s, #31
150 ld1 {v5.4s}, [x5], #16
151 fcvtzs v5.4s, v5.4s, #31
152 ld1 {v6.4s}, [x6], #16
153 fcvtzs v6.4s, v6.4s, #31
154 ld1 {v7.4s}, [x7], #16
155 fcvtzs v7.4s, v7.4s, #31
1566:
157 subs w9, w9, #8
158 ld1 {v0.4s}, [x4], #16
159 fcvtzs v0.4s, v0.4s, #31
160 sri v5.4s, v4.4s, #16
161 ld1 {v1.4s}, [x5], #16
162 fcvtzs v1.4s, v1.4s, #31
163 sri v7.4s, v6.4s, #16
164 ld1 {v2.4s}, [x6], #16
165 fcvtzs v2.4s, v2.4s, #31
166 zip1 v16.4s, v5.4s, v7.4s
167 ld1 {v3.4s}, [x7], #16
168 fcvtzs v3.4s, v3.4s, #31
169 zip2 v17.4s, v5.4s, v7.4s
170 st1 {v16.d}[0], [x8], x12
171 sri v1.4s, v0.4s, #16
172 st1 {v16.d}[1], [x8], x12
173 sri v3.4s, v2.4s, #16
174 st1 {v17.d}[0], [x8], x12
175 zip1 v18.4s, v1.4s, v3.4s
176 st1 {v17.d}[1], [x8], x12
177 zip2 v19.4s, v1.4s, v3.4s
178 b.eq 7f
179 ld1 {v4.4s}, [x4], #16
180 fcvtzs v4.4s, v4.4s, #31
181 st1 {v18.d}[0], [x8], x12
182 ld1 {v5.4s}, [x5], #16
183 fcvtzs v5.4s, v5.4s, #31
184 st1 {v18.d}[1], [x8], x12
185 ld1 {v6.4s}, [x6], #16
186 fcvtzs v6.4s, v6.4s, #31
187 st1 {v19.d}[0], [x8], x12
188 ld1 {v7.4s}, [x7], #16
189 fcvtzs v7.4s, v7.4s, #31
190 st1 {v19.d}[1], [x8], x12
191 b 6b
1927:
193 st1 {v18.d}[0], [x8], x12
194 st1 {v18.d}[1], [x8], x12
195 st1 {v19.d}[0], [x8], x12
196 st1 {v19.d}[1], [x8], x12
197 subs w3, w3, #4
198 b.eq end
199 cmp w3, #4
200 add x0, x0, #8
201 b.ge 5b
202
2034: // 2 channels
204 cmp w3, #2
205 b.lt 4f
206 ldp x4, x5, [x1], #16
207 mov w9, w2
208 mov x8, x0
209 tst w9, #8
210 ld1 {v4.4s}, [x4], #16
211 fcvtzs v4.4s, v4.4s, #31
212 ld1 {v5.4s}, [x5], #16
213 fcvtzs v5.4s, v5.4s, #31
214 ld1 {v6.4s}, [x4], #16
215 fcvtzs v6.4s, v6.4s, #31
216 ld1 {v7.4s}, [x5], #16
217 fcvtzs v7.4s, v7.4s, #31
218 b.eq 6f
219 subs w9, w9, #8
220 b.eq 7f
221 sri v5.4s, v4.4s, #16
222 ld1 {v4.4s}, [x4], #16
223 fcvtzs v4.4s, v4.4s, #31
224 st1 {v5.s}[0], [x8], x12
225 sri v7.4s, v6.4s, #16
226 st1 {v5.s}[1], [x8], x12
227 ld1 {v6.4s}, [x4], #16
228 fcvtzs v6.4s, v6.4s, #31
229 st1 {v5.s}[2], [x8], x12
230 st1 {v5.s}[3], [x8], x12
231 st1 {v7.s}[0], [x8], x12
232 st1 {v7.s}[1], [x8], x12
233 ld1 {v5.4s}, [x5], #16
234 fcvtzs v5.4s, v5.4s, #31
235 st1 {v7.s}[2], [x8], x12
236 st1 {v7.s}[3], [x8], x12
237 ld1 {v7.4s}, [x5], #16
238 fcvtzs v7.4s, v7.4s, #31
2396:
240 subs w9, w9, #16
241 ld1 {v0.4s}, [x4], #16
242 sri v5.4s, v4.4s, #16
243 fcvtzs v0.4s, v0.4s, #31
244 ld1 {v1.4s}, [x5], #16
245 sri v7.4s, v6.4s, #16
246 st1 {v5.s}[0], [x8], x12
247 st1 {v5.s}[1], [x8], x12
248 fcvtzs v1.4s, v1.4s, #31
249 st1 {v5.s}[2], [x8], x12
250 st1 {v5.s}[3], [x8], x12
251 ld1 {v2.4s}, [x4], #16
252 st1 {v7.s}[0], [x8], x12
253 fcvtzs v2.4s, v2.4s, #31
254 st1 {v7.s}[1], [x8], x12
255 ld1 {v3.4s}, [x5], #16
256 st1 {v7.s}[2], [x8], x12
257 fcvtzs v3.4s, v3.4s, #31
258 st1 {v7.s}[3], [x8], x12
259 sri v1.4s, v0.4s, #16
260 sri v3.4s, v2.4s, #16
261 b.eq 6f
262 ld1 {v4.4s}, [x4], #16
263 st1 {v1.s}[0], [x8], x12
264 fcvtzs v4.4s, v4.4s, #31
265 st1 {v1.s}[1], [x8], x12
266 ld1 {v5.4s}, [x5], #16
267 st1 {v1.s}[2], [x8], x12
268 fcvtzs v5.4s, v5.4s, #31
269 st1 {v1.s}[3], [x8], x12
270 ld1 {v6.4s}, [x4], #16
271 st1 {v3.s}[0], [x8], x12
272 fcvtzs v6.4s, v6.4s, #31
273 st1 {v3.s}[1], [x8], x12
274 ld1 {v7.4s}, [x5], #16
275 st1 {v3.s}[2], [x8], x12
276 fcvtzs v7.4s, v7.4s, #31
277 st1 {v3.s}[3], [x8], x12
278 b.gt 6b
2796:
280 st1 {v1.s}[0], [x8], x12
281 st1 {v1.s}[1], [x8], x12
282 st1 {v1.s}[2], [x8], x12
283 st1 {v1.s}[3], [x8], x12
284 st1 {v3.s}[0], [x8], x12
285 st1 {v3.s}[1], [x8], x12
286 st1 {v3.s}[2], [x8], x12
287 st1 {v3.s}[3], [x8], x12
288 b 8f
2897:
290 sri v5.4s, v4.4s, #16
291 sri v7.4s, v6.4s, #16
292 st1 {v5.s}[0], [x8], x12
293 st1 {v5.s}[1], [x8], x12
294 st1 {v5.s}[2], [x8], x12
295 st1 {v5.s}[3], [x8], x12
296 st1 {v7.s}[0], [x8], x12
297 st1 {v7.s}[1], [x8], x12
298 st1 {v7.s}[2], [x8], x12
299 st1 {v7.s}[3], [x8], x12
3008:
301 subs w3, w3, #2
302 add x0, x0, #4
303 b.eq end
304
3054: // 1 channel
306 ldr x4, [x1]
307 tst w2, #8
308 mov w9, w2
309 mov x5, x0
310 ld1 {v0.4s}, [x4], #16
311 fcvtzs v0.4s, v0.4s, #31
312 ld1 {v1.4s}, [x4], #16
313 fcvtzs v1.4s, v1.4s, #31
314 b.ne 8f
3156:
316 subs w9, w9, #16
317 ld1 {v2.4s}, [x4], #16
318 fcvtzs v2.4s, v2.4s, #31
319 ld1 {v3.4s}, [x4], #16
320 fcvtzs v3.4s, v3.4s, #31
321 st1 {v0.h}[1], [x5], x12
322 st1 {v0.h}[3], [x5], x12
323 st1 {v0.h}[5], [x5], x12
324 st1 {v0.h}[7], [x5], x12
325 st1 {v1.h}[1], [x5], x12
326 st1 {v1.h}[3], [x5], x12
327 st1 {v1.h}[5], [x5], x12
328 st1 {v1.h}[7], [x5], x12
329 b.eq 7f
330 ld1 {v0.4s}, [x4], #16
331 fcvtzs v0.4s, v0.4s, #31
332 ld1 {v1.4s}, [x4], #16
333 fcvtzs v1.4s, v1.4s, #31
3347:
335 st1 {v2.h}[1], [x5], x12
336 st1 {v2.h}[3], [x5], x12
337 st1 {v2.h}[5], [x5], x12
338 st1 {v2.h}[7], [x5], x12
339 st1 {v3.h}[1], [x5], x12
340 st1 {v3.h}[3], [x5], x12
341 st1 {v3.h}[5], [x5], x12
342 st1 {v3.h}[7], [x5], x12
343 b.gt 6b
344 ret
3458:
346 subs w9, w9, #8
347 st1 {v0.h}[1], [x5], x12
348 st1 {v0.h}[3], [x5], x12
349 st1 {v0.h}[5], [x5], x12
350 st1 {v0.h}[7], [x5], x12
351 st1 {v1.h}[1], [x5], x12
352 st1 {v1.h}[3], [x5], x12
353 st1 {v1.h}[5], [x5], x12
354 st1 {v1.h}[7], [x5], x12
355 b.eq end
356 ld1 {v0.4s}, [x4], #16
357 fcvtzs v0.4s, v0.4s, #31
358 ld1 {v1.4s}, [x4], #16
359 fcvtzs v1.4s, v1.4s, #31
360 b 6b
361end:
362 ret
363endfunc
libavresample/aarch64/neontest.c+0−31
@@ -1,31 +0,0 @@
1/*
2 * check NEON registers for clobbers
3 * Copyright (c) 2013 Martin Storsjo
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "libavresample/avresample.h"
23#include "libavutil/aarch64/neontest.h"
24
25wrap(avresample_convert(AVAudioResampleContext *avr, uint8_t **output,
26 int out_plane_size, int out_samples, uint8_t **input,
27 int in_plane_size, int in_samples))
28{
29 testneonclobbers(avresample_convert, avr, output, out_plane_size,
30 out_samples, input, in_plane_size, in_samples);
31}
libavresample/aarch64/resample_init.c+0−71
@@ -1,71 +0,0 @@
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include <stdint.h>
20
21#include "config.h"
22#include "libavutil/cpu.h"
23#include "libavutil/aarch64/cpu.h"
24#include "libavutil/internal.h"
25#include "libavutil/samplefmt.h"
26#include "libavresample/resample.h"
27
28#include "asm-offsets.h"
29
30AV_CHECK_OFFSET(struct ResampleContext, filter_bank, FILTER_BANK);
31AV_CHECK_OFFSET(struct ResampleContext, filter_length, FILTER_LENGTH);
32AV_CHECK_OFFSET(struct ResampleContext, phase_shift, PHASE_SHIFT);
33AV_CHECK_OFFSET(struct ResampleContext, phase_mask, PHASE_MASK);
34
35void ff_resample_one_dbl_neon(struct ResampleContext *c, void *dst0,
36 int dst_index, const void *src0,
37 unsigned int index, int frac);
38void ff_resample_one_flt_neon(struct ResampleContext *c, void *dst0,
39 int dst_index, const void *src0,
40 unsigned int index, int frac);
41void ff_resample_one_s16_neon(struct ResampleContext *c, void *dst0,
42 int dst_index, const void *src0,
43 unsigned int index, int frac);
44void ff_resample_one_s32_neon(struct ResampleContext *c, void *dst0,
45 int dst_index, const void *src0,
46 unsigned int index, int frac);
47
48av_cold void ff_audio_resample_init_aarch64(ResampleContext *c,
49 enum AVSampleFormat sample_fmt)
50{
51 int cpu_flags = av_get_cpu_flags();
52
53 if (have_neon(cpu_flags)) {
54 if (!c->linear) {
55 switch (sample_fmt) {
56 case AV_SAMPLE_FMT_DBLP:
57 c->resample_one = ff_resample_one_dbl_neon;
58 break;
59 case AV_SAMPLE_FMT_FLTP:
60 c->resample_one = ff_resample_one_flt_neon;
61 break;
62 case AV_SAMPLE_FMT_S16P:
63 c->resample_one = ff_resample_one_s16_neon;
64 break;
65 case AV_SAMPLE_FMT_S32P:
66 c->resample_one = ff_resample_one_s32_neon;
67 break;
68 }
69 }
70 }
71}
libavresample/aarch64/resample_neon.S+0−233
@@ -1,233 +0,0 @@
1/*
2 * Copyright (c) 2014 Janne Grunau <janne-libav@jannau.net>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "libavutil/aarch64/asm.S"
22#include "asm-offsets.h"
23
24.macro resample_one fmt, es=2
25.ifnc \fmt, dbl
26 .macro M_MUL2 x:vararg
27 .endm
28 .macro M_MLA2 x:vararg
29 .endm
30.endif
31function ff_resample_one_\fmt\()_neon, export=1
32 sxtw x2, w2
33 ldr x9, [x0, #FILTER_BANK]
34 ldr w6, [x0, #FILTER_LENGTH]
35 ldp w7, w8, [x0, #PHASE_SHIFT] // and phase_mask
36 lsr x10, x4, x7 // sample_index
37 and x4, x4, x8
38 lsl x11, x6, #\es // filter_length * elem_size
39 add x3, x3, x10, lsl #\es // src[sample_index]
40 madd x9, x11, x4, x9 // filter
41 cmp w6, #16
42 b.lt 5f
438: // remaining filter_length at least 16
44 subs w6, w6, #16
45 LOAD8 v4, v5, v6, v7, x3
46 LOAD8 v16, v17, v18, v19, x9
47 M_MUL v0, v4, v16, v1
48 M_MUL2 v1, v6, v18
497:
50 LOAD8 v20, v21, v22, v23, x3
51 M_MLA v0, v5, v17, v1
52 M_MLA2 v1, v7, v19
53 LOAD8 v24, v25, v26, v27, x9
54 M_MLA v0, v20, v24, v1
55 M_MLA2 v1, v22, v26
56 b.eq 6f
57 cmp w6, #16
58 M_MLA v0, v21, v25, v1
59 M_MLA2 v1, v23, v27
60 b.lt 4f
61 subs w6, w6, #16
62 LOAD8 v4, v5, v6, v7, x3
63 LOAD8 v16, v17, v18, v19, x9
64 M_MLA v0, v4, v16, v1
65 M_MLA2 v1, v6, v18
66 b 7b
676:
68 M_MLA v0, v21, v25, v1
69 M_MLA2 v1, v23, v27
70 STORE_ONE 0, x1, x2, v1
71 ret
725:
73 movi v0.16b, #0
74 movi v1.16b, #0
754: // remaining filter_length 1-15
76 cmp w6, #4
77 b.lt 2f
78 subs w6, w6, #4
79 LOAD4 v4, v5, x3
80 LOAD4 v6, v7, x9
81 M_MLA v0, v4, v6, v1
82 M_MLA2 v1, v5, v7
83 b.eq 0f
84 b 4b
852: // remaining filter_length 1-3
86 cmp w6, #2
87 b.lt 1f
88 LOAD2 2, x3
89 LOAD2 3, x9
90 subs w6, w6, #2
91 M_MLA v0, v2, v3
92 b.eq 0f
931: // remaining filter_length 1
94 LOAD1 6, x3
95 LOAD1 7, x9
96 M_MLA v0, v6, v7
970:
98 STORE_ONE 0, x1, x2, v1
99 ret
100endfunc
101
102.purgem LOAD1
103.purgem LOAD2
104.purgem LOAD4
105.purgem LOAD8
106.purgem M_MLA
107.purgem M_MLA2
108.purgem M_MUL
109.purgem M_MUL2
110.purgem STORE_ONE
111.endm
112
113
114.macro LOAD1 d1, addr
115 ldr d\d1, [\addr], #8
116.endm
117.macro LOAD2 d1, addr
118 ld1 {v\d1\().2d}, [\addr], #16
119.endm
120.macro LOAD4 d1, d2, addr
121 ld1 {\d1\().2d,\d2\().2d}, [\addr], #32
122.endm
123.macro LOAD8 d1, d2, d3, d4, addr
124 ld1 {\d1\().2d,\d2\().2d,\d3\().2d,\d4\().2d}, [\addr], #64
125.endm
126.macro M_MLA d, r0, r1, d2:vararg
127 fmla \d\().2d, \r0\().2d, \r1\().2d
128.endm
129.macro M_MLA2 second:vararg
130 M_MLA \second
131.endm
132.macro M_MUL d, r0, r1, d2:vararg
133 fmul \d\().2d, \r0\().2d, \r1\().2d
134.endm
135.macro M_MUL2 second:vararg
136 M_MUL \second
137.endm
138.macro STORE_ONE rn, addr, idx, d2
139 fadd v\rn\().2d, v\rn\().2d, \d2\().2d
140 faddp d\rn\(), v\rn\().2d
141 str d\rn\(), [\addr, \idx, lsl #3]
142.endm
143
144resample_one dbl, 3
145
146
147.macro LOAD1 d1, addr
148 ldr s\d1, [\addr], #4
149.endm
150.macro LOAD2 d1, addr
151 ld1 {v\d1\().2s}, [\addr], #8
152.endm
153.macro LOAD4 d1, d2, addr
154 ld1 {\d1\().4s}, [\addr], #16
155.endm
156.macro LOAD8 d1, d2, d3, d4, addr
157 ld1 {\d1\().4s,\d2\().4s}, [\addr], #32
158.endm
159.macro M_MLA d, r0, r1, d2:vararg
160 fmla \d\().4s, \r0\().4s, \r1\().4s
161.endm
162.macro M_MUL d, r0, r1, d2:vararg
163 fmul \d\().4s, \r0\().4s, \r1\().4s
164.endm
165.macro STORE_ONE rn, addr, idx, d2
166 faddp v\rn\().4s, v\rn\().4s, v\rn\().4s
167 faddp s\rn\(), v\rn\().2s
168 str s\rn\(), [\addr, \idx, lsl #2]
169.endm
170
171resample_one flt
172
173
174.macro LOAD1 d1, addr
175 ldr h\d1, [\addr], #2
176.endm
177.macro LOAD2 d1, addr
178 ldr s\d1, [\addr], #4
179.endm
180.macro LOAD4 d1, d2, addr
181 ld1 {\d1\().4h}, [\addr], #8
182.endm
183.macro LOAD8 d1, d2, d3, d4, addr
184 ld1 {\d1\().4h,\d2\().4h}, [\addr], #16
185.endm
186.macro M_MLA d, r0, r1, d2:vararg
187 smlal \d\().4s, \r0\().4h, \r1\().4h
188.endm
189.macro M_MUL d, r0, r1, d2:vararg
190 smull \d\().4s, \r0\().4h, \r1\().4h
191.endm
192.macro STORE_ONE rn, addr, idx, d2
193 addp v\rn\().4s, v\rn\().4s, v\rn\().4s
194 addp v\rn\().4s, v\rn\().4s, v\rn\().4s
195 sqrshrn v\rn\().4h, v\rn\().4s, #15
196 str h\rn\(), [\addr, \idx, lsl #1]
197.endm
198
199resample_one s16, 1
200
201
202.macro LOAD1 d1, addr
203 ldr s\d1, [\addr], #4
204.endm
205.macro LOAD2 d1, addr
206 ld1 {v\d1\().2s}, [\addr], #8
207.endm
208.macro LOAD4 d1, d2, addr
209 ld1 {\d1\().4s}, [\addr], #16
210.endm
211.macro LOAD8 d1, d2, d3, d4, addr
212 ld1 {\d1\().4s,\d2\().4s}, [\addr], #32
213.endm
214.macro M_MLA d1, r0, r1, d2:vararg
215 smlal \d1\().2d, \r0\().2s, \r1\().2s
216.ifnb \d2
217 smlal2 \d2\().2d, \r0\().4s, \r1\().4s
218.endif
219.endm
220.macro M_MUL d1, r0, r1, d2:vararg
221 smull \d1\().2d, \r0\().2s, \r1\().2s
222.ifnb \d2
223 smull2 \d2\().2d, \r0\().4s, \r1\().4s
224.endif
225.endm
226.macro STORE_ONE rn, addr, idx, d2
227 add v\rn\().2d, v\rn\().2d, \d2\().2d
228 addp d\rn\(), v\rn\().2d
229 sqrshrn v\rn\().2s, v\rn\().2d, #30
230 str s\rn\(), [\addr, \idx, lsl #2]
231.endm
232
233resample_one s32
libavresample/arm/Makefile+0−7
@@ -1,7 +0,0 @@
1OBJS += arm/audio_convert_init.o \
2 arm/resample_init.o
3
4OBJS-$(CONFIG_NEON_CLOBBER_TEST) += arm/neontest.o
5
6NEON-OBJS += arm/audio_convert_neon.o \
7 arm/resample_neon.o
libavresample/arm/asm-offsets.h+0−29
@@ -1,29 +0,0 @@
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#ifndef AVRESAMPLE_ARM_ASM_OFFSETS_H
20#define AVRESAMPLE_ARM_ASM_OFFSETS_H
21
22/* struct ResampleContext */
23#define FILTER_BANK 0x08
24#define FILTER_LENGTH 0x0c
25#define SRC_INCR 0x20
26#define PHASE_SHIFT 0x28
27#define PHASE_MASK (PHASE_SHIFT + 0x04)
28
29#endif /* AVRESAMPLE_ARM_ASM_OFFSETS_H */
libavresample/arm/audio_convert_init.c+0−49
@@ -1,49 +0,0 @@
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include <stdint.h>
20
21#include "config.h"
22#include "libavutil/attributes.h"
23#include "libavutil/cpu.h"
24#include "libavutil/arm/cpu.h"
25#include "libavutil/samplefmt.h"
26#include "libavresample/audio_convert.h"
27
28void ff_conv_flt_to_s16_neon(int16_t *dst, const float *src, int len);
29void ff_conv_fltp_to_s16_neon(int16_t *dst, float *const *src,
30 int len, int channels);
31void ff_conv_fltp_to_s16_2ch_neon(int16_t *dst, float *const *src,
32 int len, int channels);
33
34av_cold void ff_audio_convert_init_arm(AudioConvert *ac)
35{
36 int cpu_flags = av_get_cpu_flags();
37
38 if (have_neon(cpu_flags)) {
39 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT,
40 0, 16, 8, "NEON",
41 ff_conv_flt_to_s16_neon);
42 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLTP,
43 0, 16, 8, "NEON",
44 ff_conv_fltp_to_s16_neon);
45 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLTP,
46 2, 16, 8, "NEON",
47 ff_conv_fltp_to_s16_2ch_neon);
48 }
49}
libavresample/arm/audio_convert_neon.S+0−363
@@ -1,363 +0,0 @@
1/*
2 * Copyright (c) 2008 Mans Rullgard <mans@mansr.com>
3 *
4 * This file is part of FFmpeg
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "config.h"
22#include "libavutil/arm/asm.S"
23
24function ff_conv_flt_to_s16_neon, export=1
25 subs r2, r2, #8
26 vld1.32 {q0}, [r1,:128]!
27 vcvt.s32.f32 q8, q0, #31
28 vld1.32 {q1}, [r1,:128]!
29 vcvt.s32.f32 q9, q1, #31
30 beq 3f
31 bics r12, r2, #15
32 beq 2f
331: subs r12, r12, #16
34 vqrshrn.s32 d4, q8, #16
35 vld1.32 {q0}, [r1,:128]!
36 vcvt.s32.f32 q0, q0, #31
37 vqrshrn.s32 d5, q9, #16
38 vld1.32 {q1}, [r1,:128]!
39 vcvt.s32.f32 q1, q1, #31
40 vqrshrn.s32 d6, q0, #16
41 vst1.16 {q2}, [r0,:128]!
42 vqrshrn.s32 d7, q1, #16
43 vld1.32 {q8}, [r1,:128]!
44 vcvt.s32.f32 q8, q8, #31
45 vld1.32 {q9}, [r1,:128]!
46 vcvt.s32.f32 q9, q9, #31
47 vst1.16 {q3}, [r0,:128]!
48 bne 1b
49 ands r2, r2, #15
50 beq 3f
512: vld1.32 {q0}, [r1,:128]!
52 vqrshrn.s32 d4, q8, #16
53 vcvt.s32.f32 q0, q0, #31
54 vld1.32 {q1}, [r1,:128]!
55 vqrshrn.s32 d5, q9, #16
56 vcvt.s32.f32 q1, q1, #31
57 vqrshrn.s32 d6, q0, #16
58 vst1.16 {q2}, [r0,:128]!
59 vqrshrn.s32 d7, q1, #16
60 vst1.16 {q3}, [r0,:128]!
61 bx lr
623: vqrshrn.s32 d4, q8, #16
63 vqrshrn.s32 d5, q9, #16
64 vst1.16 {q2}, [r0,:128]!
65 bx lr
66endfunc
67
68function ff_conv_fltp_to_s16_2ch_neon, export=1
69 ldm r1, {r1, r3}
70 subs r2, r2, #8
71 vld1.32 {q0}, [r1,:128]!
72 vcvt.s32.f32 q8, q0, #31
73 vld1.32 {q1}, [r1,:128]!
74 vcvt.s32.f32 q9, q1, #31
75 vld1.32 {q10}, [r3,:128]!
76 vcvt.s32.f32 q10, q10, #31
77 vld1.32 {q11}, [r3,:128]!
78 vcvt.s32.f32 q11, q11, #31
79 beq 3f
80 bics r12, r2, #15
81 beq 2f
821: subs r12, r12, #16
83 vld1.32 {q0}, [r1,:128]!
84 vcvt.s32.f32 q0, q0, #31
85 vsri.32 q10, q8, #16
86 vld1.32 {q1}, [r1,:128]!
87 vcvt.s32.f32 q1, q1, #31
88 vld1.32 {q12}, [r3,:128]!
89 vcvt.s32.f32 q12, q12, #31
90 vld1.32 {q13}, [r3,:128]!
91 vsri.32 q11, q9, #16
92 vst1.16 {q10}, [r0,:128]!
93 vcvt.s32.f32 q13, q13, #31
94 vst1.16 {q11}, [r0,:128]!
95 vsri.32 q12, q0, #16
96 vld1.32 {q8}, [r1,:128]!
97 vsri.32 q13, q1, #16
98 vst1.16 {q12}, [r0,:128]!
99 vcvt.s32.f32 q8, q8, #31
100 vld1.32 {q9}, [r1,:128]!
101 vcvt.s32.f32 q9, q9, #31
102 vld1.32 {q10}, [r3,:128]!
103 vcvt.s32.f32 q10, q10, #31
104 vld1.32 {q11}, [r3,:128]!
105 vcvt.s32.f32 q11, q11, #31
106 vst1.16 {q13}, [r0,:128]!
107 bne 1b
108 ands r2, r2, #15
109 beq 3f
1102: vsri.32 q10, q8, #16
111 vld1.32 {q0}, [r1,:128]!
112 vcvt.s32.f32 q0, q0, #31
113 vld1.32 {q1}, [r1,:128]!
114 vcvt.s32.f32 q1, q1, #31
115 vld1.32 {q12}, [r3,:128]!
116 vcvt.s32.f32 q12, q12, #31
117 vsri.32 q11, q9, #16
118 vld1.32 {q13}, [r3,:128]!
119 vcvt.s32.f32 q13, q13, #31
120 vst1.16 {q10}, [r0,:128]!
121 vsri.32 q12, q0, #16
122 vst1.16 {q11}, [r0,:128]!
123 vsri.32 q13, q1, #16
124 vst1.16 {q12-q13},[r0,:128]!
125 bx lr
1263: vsri.32 q10, q8, #16
127 vsri.32 q11, q9, #16
128 vst1.16 {q10-q11},[r0,:128]!
129 bx lr
130endfunc
131
132function ff_conv_fltp_to_s16_neon, export=1
133 cmp r3, #2
134 itt lt
135 ldrlt r1, [r1]
136 blt X(ff_conv_flt_to_s16_neon)
137 beq X(ff_conv_fltp_to_s16_2ch_neon)
138
139 push {r4-r8, lr}
140 cmp r3, #4
141 lsl r12, r3, #1
142 blt 4f
143
144 @ 4 channels
1455: ldm r1!, {r4-r7}
146 mov lr, r2
147 mov r8, r0
148 vld1.32 {q8}, [r4,:128]!
149 vcvt.s32.f32 q8, q8, #31
150 vld1.32 {q9}, [r5,:128]!
151 vcvt.s32.f32 q9, q9, #31
152 vld1.32 {q10}, [r6,:128]!
153 vcvt.s32.f32 q10, q10, #31
154 vld1.32 {q11}, [r7,:128]!
155 vcvt.s32.f32 q11, q11, #31
1566: subs lr, lr, #8
157 vld1.32 {q0}, [r4,:128]!
158 vcvt.s32.f32 q0, q0, #31
159 vsri.32 q9, q8, #16
160 vld1.32 {q1}, [r5,:128]!
161 vcvt.s32.f32 q1, q1, #31
162 vsri.32 q11, q10, #16
163 vld1.32 {q2}, [r6,:128]!
164 vcvt.s32.f32 q2, q2, #31
165 vzip.32 d18, d22
166 vld1.32 {q3}, [r7,:128]!
167 vcvt.s32.f32 q3, q3, #31
168 vzip.32 d19, d23
169 vst1.16 {d18}, [r8], r12
170 vsri.32 q1, q0, #16
171 vst1.16 {d22}, [r8], r12
172 vsri.32 q3, q2, #16
173 vst1.16 {d19}, [r8], r12
174 vzip.32 d2, d6
175 vst1.16 {d23}, [r8], r12
176 vzip.32 d3, d7
177 beq 7f
178 vld1.32 {q8}, [r4,:128]!
179 vcvt.s32.f32 q8, q8, #31
180 vst1.16 {d2}, [r8], r12
181 vld1.32 {q9}, [r5,:128]!
182 vcvt.s32.f32 q9, q9, #31
183 vst1.16 {d6}, [r8], r12
184 vld1.32 {q10}, [r6,:128]!
185 vcvt.s32.f32 q10, q10, #31
186 vst1.16 {d3}, [r8], r12
187 vld1.32 {q11}, [r7,:128]!
188 vcvt.s32.f32 q11, q11, #31
189 vst1.16 {d7}, [r8], r12
190 b 6b
1917: vst1.16 {d2}, [r8], r12
192 vst1.16 {d6}, [r8], r12
193 vst1.16 {d3}, [r8], r12
194 vst1.16 {d7}, [r8], r12
195 subs r3, r3, #4
196 it eq
197 popeq {r4-r8, pc}
198 cmp r3, #4
199 add r0, r0, #8
200 bge 5b
201
202 @ 2 channels
2034: cmp r3, #2
204 blt 4f
205 ldm r1!, {r4-r5}
206 mov lr, r2
207 mov r8, r0
208 tst lr, #8
209 vld1.32 {q8}, [r4,:128]!
210 vcvt.s32.f32 q8, q8, #31
211 vld1.32 {q9}, [r5,:128]!
212 vcvt.s32.f32 q9, q9, #31
213 vld1.32 {q10}, [r4,:128]!
214 vcvt.s32.f32 q10, q10, #31
215 vld1.32 {q11}, [r5,:128]!
216 vcvt.s32.f32 q11, q11, #31
217 beq 6f
218 subs lr, lr, #8
219 beq 7f
220 vsri.32 d18, d16, #16
221 vsri.32 d19, d17, #16
222 vld1.32 {q8}, [r4,:128]!
223 vcvt.s32.f32 q8, q8, #31
224 vst1.32 {d18[0]}, [r8], r12
225 vsri.32 d22, d20, #16
226 vst1.32 {d18[1]}, [r8], r12
227 vsri.32 d23, d21, #16
228 vst1.32 {d19[0]}, [r8], r12
229 vst1.32 {d19[1]}, [r8], r12
230 vld1.32 {q9}, [r5,:128]!
231 vcvt.s32.f32 q9, q9, #31
232 vst1.32 {d22[0]}, [r8], r12
233 vst1.32 {d22[1]}, [r8], r12
234 vld1.32 {q10}, [r4,:128]!
235 vcvt.s32.f32 q10, q10, #31
236 vst1.32 {d23[0]}, [r8], r12
237 vst1.32 {d23[1]}, [r8], r12
238 vld1.32 {q11}, [r5,:128]!
239 vcvt.s32.f32 q11, q11, #31
2406: subs lr, lr, #16
241 vld1.32 {q0}, [r4,:128]!
242 vcvt.s32.f32 q0, q0, #31
243 vsri.32 d18, d16, #16
244 vld1.32 {q1}, [r5,:128]!
245 vcvt.s32.f32 q1, q1, #31
246 vsri.32 d19, d17, #16
247 vld1.32 {q2}, [r4,:128]!
248 vcvt.s32.f32 q2, q2, #31
249 vld1.32 {q3}, [r5,:128]!
250 vcvt.s32.f32 q3, q3, #31
251 vst1.32 {d18[0]}, [r8], r12
252 vsri.32 d22, d20, #16
253 vst1.32 {d18[1]}, [r8], r12
254 vsri.32 d23, d21, #16
255 vst1.32 {d19[0]}, [r8], r12
256 vsri.32 d2, d0, #16
257 vst1.32 {d19[1]}, [r8], r12
258 vsri.32 d3, d1, #16
259 vst1.32 {d22[0]}, [r8], r12
260 vsri.32 d6, d4, #16
261 vst1.32 {d22[1]}, [r8], r12
262 vsri.32 d7, d5, #16
263 vst1.32 {d23[0]}, [r8], r12
264 vst1.32 {d23[1]}, [r8], r12
265 beq 6f
266 vld1.32 {q8}, [r4,:128]!
267 vcvt.s32.f32 q8, q8, #31
268 vst1.32 {d2[0]}, [r8], r12
269 vst1.32 {d2[1]}, [r8], r12
270 vld1.32 {q9}, [r5,:128]!
271 vcvt.s32.f32 q9, q9, #31
272 vst1.32 {d3[0]}, [r8], r12
273 vst1.32 {d3[1]}, [r8], r12
274 vld1.32 {q10}, [r4,:128]!
275 vcvt.s32.f32 q10, q10, #31
276 vst1.32 {d6[0]}, [r8], r12
277 vst1.32 {d6[1]}, [r8], r12
278 vld1.32 {q11}, [r5,:128]!
279 vcvt.s32.f32 q11, q11, #31
280 vst1.32 {d7[0]}, [r8], r12
281 vst1.32 {d7[1]}, [r8], r12
282 bgt 6b
2836: vst1.32 {d2[0]}, [r8], r12
284 vst1.32 {d2[1]}, [r8], r12
285 vst1.32 {d3[0]}, [r8], r12
286 vst1.32 {d3[1]}, [r8], r12
287 vst1.32 {d6[0]}, [r8], r12
288 vst1.32 {d6[1]}, [r8], r12
289 vst1.32 {d7[0]}, [r8], r12
290 vst1.32 {d7[1]}, [r8], r12
291 b 8f
2927: vsri.32 d18, d16, #16
293 vsri.32 d19, d17, #16
294 vst1.32 {d18[0]}, [r8], r12
295 vsri.32 d22, d20, #16
296 vst1.32 {d18[1]}, [r8], r12
297 vsri.32 d23, d21, #16
298 vst1.32 {d19[0]}, [r8], r12
299 vst1.32 {d19[1]}, [r8], r12
300 vst1.32 {d22[0]}, [r8], r12
301 vst1.32 {d22[1]}, [r8], r12
302 vst1.32 {d23[0]}, [r8], r12
303 vst1.32 {d23[1]}, [r8], r12
3048: subs r3, r3, #2
305 add r0, r0, #4
306 it eq
307 popeq {r4-r8, pc}
308
309 @ 1 channel
3104: ldr r4, [r1]
311 tst r2, #8
312 mov lr, r2
313 mov r5, r0
314 vld1.32 {q0}, [r4,:128]!
315 vcvt.s32.f32 q0, q0, #31
316 vld1.32 {q1}, [r4,:128]!
317 vcvt.s32.f32 q1, q1, #31
318 bne 8f
3196: subs lr, lr, #16
320 vld1.32 {q2}, [r4,:128]!
321 vcvt.s32.f32 q2, q2, #31
322 vld1.32 {q3}, [r4,:128]!
323 vcvt.s32.f32 q3, q3, #31
324 vst1.16 {d0[1]}, [r5,:16], r12
325 vst1.16 {d0[3]}, [r5,:16], r12
326 vst1.16 {d1[1]}, [r5,:16], r12
327 vst1.16 {d1[3]}, [r5,:16], r12
328 vst1.16 {d2[1]}, [r5,:16], r12
329 vst1.16 {d2[3]}, [r5,:16], r12
330 vst1.16 {d3[1]}, [r5,:16], r12
331 vst1.16 {d3[3]}, [r5,:16], r12
332 beq 7f
333 vld1.32 {q0}, [r4,:128]!
334 vcvt.s32.f32 q0, q0, #31
335 vld1.32 {q1}, [r4,:128]!
336 vcvt.s32.f32 q1, q1, #31
3377: vst1.16 {d4[1]}, [r5,:16], r12
338 vst1.16 {d4[3]}, [r5,:16], r12
339 vst1.16 {d5[1]}, [r5,:16], r12
340 vst1.16 {d5[3]}, [r5,:16], r12
341 vst1.16 {d6[1]}, [r5,:16], r12
342 vst1.16 {d6[3]}, [r5,:16], r12
343 vst1.16 {d7[1]}, [r5,:16], r12
344 vst1.16 {d7[3]}, [r5,:16], r12
345 bgt 6b
346 pop {r4-r8, pc}
3478: subs lr, lr, #8
348 vst1.16 {d0[1]}, [r5,:16], r12
349 vst1.16 {d0[3]}, [r5,:16], r12
350 vst1.16 {d1[1]}, [r5,:16], r12
351 vst1.16 {d1[3]}, [r5,:16], r12
352 vst1.16 {d2[1]}, [r5,:16], r12
353 vst1.16 {d2[3]}, [r5,:16], r12
354 vst1.16 {d3[1]}, [r5,:16], r12
355 vst1.16 {d3[3]}, [r5,:16], r12
356 it eq
357 popeq {r4-r8, pc}
358 vld1.32 {q0}, [r4,:128]!
359 vcvt.s32.f32 q0, q0, #31
360 vld1.32 {q1}, [r4,:128]!
361 vcvt.s32.f32 q1, q1, #31
362 b 6b
363endfunc
libavresample/arm/neontest.c+0−31
@@ -1,31 +0,0 @@
1/*
2 * check NEON registers for clobbers
3 * Copyright (c) 2013 Martin Storsjo
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "libavresample/avresample.h"
23#include "libavutil/arm/neontest.h"
24
25wrap(avresample_convert(AVAudioResampleContext *avr, uint8_t **output,
26 int out_plane_size, int out_samples, uint8_t **input,
27 int in_plane_size, int in_samples))
28{
29 testneonclobbers(avresample_convert, avr, output, out_plane_size,
30 out_samples, input, in_plane_size, in_samples);
31}
libavresample/arm/resample_init.c+0−74
@@ -1,74 +0,0 @@
1/*
2 * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "config.h"
22
23#include "libavutil/cpu.h"
24#include "libavutil/arm/cpu.h"
25#include "libavutil/internal.h"
26#include "libavutil/samplefmt.h"
27
28#include "libavresample/resample.h"
29
30#include "asm-offsets.h"
31
32AV_CHECK_OFFSET(struct ResampleContext, filter_bank, FILTER_BANK);
33AV_CHECK_OFFSET(struct ResampleContext, filter_length, FILTER_LENGTH);
34AV_CHECK_OFFSET(struct ResampleContext, src_incr, SRC_INCR);
35AV_CHECK_OFFSET(struct ResampleContext, phase_shift, PHASE_SHIFT);
36AV_CHECK_OFFSET(struct ResampleContext, phase_mask, PHASE_MASK);
37
38void ff_resample_one_flt_neon(struct ResampleContext *c, void *dst0,
39 int dst_index, const void *src0,
40 unsigned int index, int frac);
41void ff_resample_one_s16_neon(struct ResampleContext *c, void *dst0,
42 int dst_index, const void *src0,
43 unsigned int index, int frac);
44void ff_resample_one_s32_neon(struct ResampleContext *c, void *dst0,
45 int dst_index, const void *src0,
46 unsigned int index, int frac);
47
48void ff_resample_linear_flt_neon(struct ResampleContext *c, void *dst0,
49 int dst_index, const void *src0,
50 unsigned int index, int frac);
51
52av_cold void ff_audio_resample_init_arm(ResampleContext *c,
53 enum AVSampleFormat sample_fmt)
54{
55 int cpu_flags = av_get_cpu_flags();
56 if (have_neon(cpu_flags)) {
57 switch (sample_fmt) {
58 case AV_SAMPLE_FMT_FLTP:
59 if (c->linear)
60 c->resample_one = ff_resample_linear_flt_neon;
61 else
62 c->resample_one = ff_resample_one_flt_neon;
63 break;
64 case AV_SAMPLE_FMT_S16P:
65 if (!c->linear)
66 c->resample_one = ff_resample_one_s16_neon;
67 break;
68 case AV_SAMPLE_FMT_S32P:
69 if (!c->linear)
70 c->resample_one = ff_resample_one_s32_neon;
71 break;
72 }
73 }
74}
libavresample/arm/resample_neon.S+0−358
@@ -1,358 +0,0 @@
1/*
2 * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "libavutil/arm/asm.S"
22
23#include "asm-offsets.h"
24
25.macro resample_one fmt, es=2
26function ff_resample_one_\fmt\()_neon, export=1
27 push {r4, r5}
28 add r1, r1, r2, lsl #\es
29
30 ldr r2, [r0, #PHASE_SHIFT+4] /* phase_mask */
31 ldr ip, [sp, #8] /* index */
32 ldr r5, [r0, #FILTER_LENGTH]
33 and r2, ip, r2 /* (index & phase_mask) */
34 ldr r4, [r0, #PHASE_SHIFT]
35 lsr r4, ip, r4 /* compute sample_index */
36 mul r2, r2, r5
37
38 ldr ip, [r0, #FILTER_BANK]
39 add r3, r3, r4, lsl #\es /* &src[sample_index] */
40
41 cmp r5, #8
42 add r0, ip, r2, lsl #\es /* filter = &filter_bank[...] */
43
44 blt 5f
458:
46 subs r5, r5, #8
47 LOAD4
48 MUL4
497:
50 LOAD4
51 beq 6f
52 cmp r5, #8
53 MLA4
54 blt 4f
55 subs r5, r5, #8
56 LOAD4
57 MLA4
58 b 7b
596:
60 MLA4
61 STORE
62 pop {r4, r5}
63 bx lr
645:
65 INIT4
664: /* remaining filter_length 1 to 7 */
67 cmp r5, #4
68 blt 2f
69 subs r5, r5, #4
70 LOAD4
71 MLA4
72 beq 0f
732: /* remaining filter_length 1 to 3 */
74 cmp r5, #2
75 blt 1f
76 subs r5, r5, #2
77 LOAD2
78 MLA2
79 beq 0f
801: /* remaining filter_length 1 */
81 LOAD1
82 MLA1
830:
84 STORE
85 pop {r4, r5}
86 bx lr
87endfunc
88
89.purgem LOAD1
90.purgem LOAD2
91.purgem LOAD4
92.purgem MLA1
93.purgem MLA2
94.purgem MLA4
95.purgem MUL4
96.purgem INIT4
97.purgem STORE
98.endm
99
100
101/* float32 */
102.macro LOAD1
103 veor.32 d0, d0
104 vld1.32 {d0[0]}, [r0]! /* load filter */
105 vld1.32 {d4[0]}, [r3]! /* load src */
106.endm
107.macro LOAD2
108 vld1.32 {d0}, [r0]! /* load filter */
109 vld1.32 {d4}, [r3]! /* load src */
110.endm
111.macro LOAD4
112 vld1.32 {d0,d1}, [r0]! /* load filter */
113 vld1.32 {d4,d5}, [r3]! /* load src */
114.endm
115.macro MLA1
116 vmla.f32 d16, d0, d4[0]
117.endm
118.macro MLA2
119 vmla.f32 d16, d0, d4
120.endm
121.macro MLA4
122 vmla.f32 d16, d0, d4
123 vmla.f32 d17, d1, d5
124.endm
125.macro MUL4
126 vmul.f32 d16, d0, d4
127 vmul.f32 d17, d1, d5
128.endm
129.macro INIT4
130 veor.f32 q8, q8
131.endm
132.macro STORE
133 vpadd.f32 d16, d16, d17
134 vpadd.f32 d16, d16, d16
135 vst1.32 d16[0], [r1]
136.endm
137
138resample_one flt, 2
139
140
141/* s32 */
142.macro LOAD1
143 veor.32 d0, d0
144 vld1.32 {d0[0]}, [r0]! /* load filter */
145 vld1.32 {d4[0]}, [r3]! /* load src */
146.endm
147.macro LOAD2
148 vld1.32 {d0}, [r0]! /* load filter */
149 vld1.32 {d4}, [r3]! /* load src */
150.endm
151.macro LOAD4
152 vld1.32 {d0,d1}, [r0]! /* load filter */
153 vld1.32 {d4,d5}, [r3]! /* load src */
154.endm
155.macro MLA1
156 vmlal.s32 q8, d0, d4[0]
157.endm
158.macro MLA2
159 vmlal.s32 q8, d0, d4
160.endm
161.macro MLA4
162 vmlal.s32 q8, d0, d4
163 vmlal.s32 q9, d1, d5
164.endm
165.macro MUL4
166 vmull.s32 q8, d0, d4
167 vmull.s32 q9, d1, d5
168.endm
169.macro INIT4
170 veor.s64 q8, q8
171 veor.s64 q9, q9
172.endm
173.macro STORE
174 vadd.s64 q8, q8, q9
175 vadd.s64 d16, d16, d17
176 vqrshrn.s64 d16, q8, #30
177 vst1.32 d16[0], [r1]
178.endm
179
180resample_one s32, 2
181
182
183/* s16 */
184.macro LOAD1
185 veor.16 d0, d0
186 vld1.16 {d0[0]}, [r0]! /* load filter */
187 vld1.16 {d4[0]}, [r3]! /* load src */
188.endm
189.macro LOAD2
190 veor.16 d0, d0
191 vld1.32 {d0[0]}, [r0]! /* load filter */
192 veor.16 d4, d4
193 vld1.32 {d4[0]}, [r3]! /* load src */
194.endm
195.macro LOAD4
196 vld1.16 {d0}, [r0]! /* load filter */
197 vld1.16 {d4}, [r3]! /* load src */
198.endm
199.macro MLA1
200 vmlal.s16 q8, d0, d4[0]
201.endm
202.macro MLA2
203 vmlal.s16 q8, d0, d4
204.endm
205.macro MLA4
206 vmlal.s16 q8, d0, d4
207.endm
208.macro MUL4
209 vmull.s16 q8, d0, d4
210.endm
211.macro INIT4
212 veor.s32 q8, q8
213.endm
214.macro STORE
215 vpadd.s32 d16, d16, d17
216 vpadd.s32 d16, d16, d16
217 vqrshrn.s32 d16, q8, #15
218 vst1.16 d16[0], [r1]
219.endm
220
221resample_one s16, 1
222
223
224.macro resample_linear fmt, es=2
225function ff_resample_linear_\fmt\()_neon, export=1
226 push {r4, r5}
227 add r1, r1, r2, lsl #\es
228
229 ldr r2, [r0, #PHASE_SHIFT+4] /* phase_mask */
230 ldr ip, [sp, #8] /* index */
231 ldr r5, [r0, #FILTER_LENGTH]
232 and r2, ip, r2 /* (index & phase_mask) */
233 ldr r4, [r0, #PHASE_SHIFT]
234 lsr r4, ip, r4 /* compute sample_index */
235 mul r2, r2, r5
236
237 ldr ip, [r0, #FILTER_BANK]
238 add r3, r3, r4, lsl #\es /* &src[sample_index] */
239
240 cmp r5, #8
241 ldr r4, [r0, #SRC_INCR]
242 add r0, ip, r2, lsl #\es /* filter = &filter_bank[...] */
243 add r2, r0, r5, lsl #\es /* filter[... + c->filter_length] */
244
245 blt 5f
2468:
247 subs r5, r5, #8
248 LOAD4
249 MUL4
2507:
251 LOAD4
252 beq 6f
253 cmp r5, #8
254 MLA4
255 blt 4f
256 subs r5, r5, #8
257 LOAD4
258 MLA4
259 b 7b
2606:
261 MLA4
262 STORE
263 pop {r4, r5}
264 bx lr
2655:
266 INIT4
2674: /* remaining filter_length 1 to 7 */
268 cmp r5, #4
269 blt 2f
270 subs r5, r5, #4
271 LOAD4
272 MLA4
273 beq 0f
2742: /* remaining filter_length 1 to 3 */
275 cmp r5, #2
276 blt 1f
277 subs r5, r5, #2
278 LOAD2
279 MLA2
280 beq 0f
2811: /* remaining filter_length 1 */
282 LOAD1
283 MLA1
2840:
285 STORE
286 pop {r4, r5}
287 bx lr
288endfunc
289
290.purgem LOAD1
291.purgem LOAD2
292.purgem LOAD4
293.purgem MLA1
294.purgem MLA2
295.purgem MLA4
296.purgem MUL4
297.purgem INIT4
298.purgem STORE
299.endm
300
301
302/* float32 linear */
303.macro LOAD1
304 veor.32 d0, d0
305 veor.32 d2, d2
306 vld1.32 {d0[0]}, [r0]! /* load filter */
307 vld1.32 {d2[0]}, [r2]! /* load filter */
308 vld1.32 {d4[0]}, [r3]! /* load src */
309.endm
310.macro LOAD2
311 vld1.32 {d0}, [r0]! /* load filter */
312 vld1.32 {d2}, [r2]! /* load filter */
313 vld1.32 {d4}, [r3]! /* load src */
314.endm
315.macro LOAD4
316 vld1.32 {d0,d1}, [r0]! /* load filter */
317 vld1.32 {d2,d3}, [r2]! /* load filter */
318 vld1.32 {d4,d5}, [r3]! /* load src */
319.endm
320.macro MLA1
321 vmla.f32 d18, d0, d4[0]
322 vmla.f32 d16, d2, d4[0]
323.endm
324.macro MLA2
325 vmla.f32 d18, d0, d4
326 vmla.f32 d16, d2, d4
327.endm
328.macro MLA4
329 vmla.f32 q9, q0, q2
330 vmla.f32 q8, q1, q2
331.endm
332.macro MUL4
333 vmul.f32 q9, q0, q2
334 vmul.f32 q8, q1, q2
335.endm
336.macro INIT4
337 veor.f32 q9, q9
338 veor.f32 q8, q8
339.endm
340.macro STORE
341 vldr s0, [sp, #12] /* frac */
342 vmov s1, r4
343 vcvt.f32.s32 d0, d0
344
345 vsub.f32 q8, q8, q9 /* v2 - val */
346 vpadd.f32 d18, d18, d19
347 vpadd.f32 d16, d16, d17
348 vpadd.f32 d2, d18, d18
349 vpadd.f32 d1, d16, d16
350
351 vmul.f32 s2, s2, s0 /* (v2 - val) * frac */
352 vdiv.f32 s2, s2, s1 /* / c->src_incr */
353 vadd.f32 s4, s4, s2
354
355 vstr s4, [r1]
356.endm
357
358resample_linear flt, 2
libavresample/audio_convert.c+0−416
@@ -1,416 +0,0 @@
1/*
2 * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
3 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <stdint.h>
23
24#include "config.h"
25#include "libavutil/common.h"
26#include "libavutil/libm.h"
27#include "libavutil/log.h"
28#include "libavutil/mem.h"
29#include "libavutil/samplefmt.h"
30#include "audio_convert.h"
31#include "audio_data.h"
32#include "dither.h"
33
34enum ConvFuncType {
35 CONV_FUNC_TYPE_FLAT,
36 CONV_FUNC_TYPE_INTERLEAVE,
37 CONV_FUNC_TYPE_DEINTERLEAVE,
38};
39
40typedef void (conv_func_flat)(uint8_t *out, const uint8_t *in, int len);
41
42typedef void (conv_func_interleave)(uint8_t *out, uint8_t *const *in,
43 int len, int channels);
44
45typedef void (conv_func_deinterleave)(uint8_t **out, const uint8_t *in, int len,
46 int channels);
47
48struct AudioConvert {
49 AVAudioResampleContext *avr;
50 DitherContext *dc;
51 enum AVSampleFormat in_fmt;
52 enum AVSampleFormat out_fmt;
53 int apply_map;
54 int channels;
55 int planes;
56 int ptr_align;
57 int samples_align;
58 int has_optimized_func;
59 const char *func_descr;
60 const char *func_descr_generic;
61 enum ConvFuncType func_type;
62 conv_func_flat *conv_flat;
63 conv_func_flat *conv_flat_generic;
64 conv_func_interleave *conv_interleave;
65 conv_func_interleave *conv_interleave_generic;
66 conv_func_deinterleave *conv_deinterleave;
67 conv_func_deinterleave *conv_deinterleave_generic;
68};
69
70void ff_audio_convert_set_func(AudioConvert *ac, enum AVSampleFormat out_fmt,
71 enum AVSampleFormat in_fmt, int channels,
72 int ptr_align, int samples_align,
73 const char *descr, void *conv)
74{
75 int found = 0;
76
77 switch (ac->func_type) {
78 case CONV_FUNC_TYPE_FLAT:
79 if (av_get_packed_sample_fmt(ac->in_fmt) == in_fmt &&
80 av_get_packed_sample_fmt(ac->out_fmt) == out_fmt) {
81 ac->conv_flat = conv;
82 ac->func_descr = descr;
83 ac->ptr_align = ptr_align;
84 ac->samples_align = samples_align;
85 if (ptr_align == 1 && samples_align == 1) {
86 ac->conv_flat_generic = conv;
87 ac->func_descr_generic = descr;
88 } else {
89 ac->has_optimized_func = 1;
90 }
91 found = 1;
92 }
93 break;
94 case CONV_FUNC_TYPE_INTERLEAVE:
95 if (ac->in_fmt == in_fmt && ac->out_fmt == out_fmt &&
96 (!channels || ac->channels == channels)) {
97 ac->conv_interleave = conv;
98 ac->func_descr = descr;
99 ac->ptr_align = ptr_align;
100 ac->samples_align = samples_align;
101 if (ptr_align == 1 && samples_align == 1) {
102 ac->conv_interleave_generic = conv;
103 ac->func_descr_generic = descr;
104 } else {
105 ac->has_optimized_func = 1;
106 }
107 found = 1;
108 }
109 break;
110 case CONV_FUNC_TYPE_DEINTERLEAVE:
111 if (ac->in_fmt == in_fmt && ac->out_fmt == out_fmt &&
112 (!channels || ac->channels == channels)) {
113 ac->conv_deinterleave = conv;
114 ac->func_descr = descr;
115 ac->ptr_align = ptr_align;
116 ac->samples_align = samples_align;
117 if (ptr_align == 1 && samples_align == 1) {
118 ac->conv_deinterleave_generic = conv;
119 ac->func_descr_generic = descr;
120 } else {
121 ac->has_optimized_func = 1;
122 }
123 found = 1;
124 }
125 break;
126 }
127 if (found) {
128 av_log(ac->avr, AV_LOG_DEBUG, "audio_convert: found function: %-4s "
129 "to %-4s (%s)\n", av_get_sample_fmt_name(ac->in_fmt),
130 av_get_sample_fmt_name(ac->out_fmt), descr);
131 }
132}
133
134#define CONV_FUNC_NAME(dst_fmt, src_fmt) conv_ ## src_fmt ## _to_ ## dst_fmt
135
136#define CONV_LOOP(otype, expr) \
137 do { \
138 *(otype *)po = expr; \
139 pi += is; \
140 po += os; \
141 } while (po < end); \
142
143#define CONV_FUNC_FLAT(ofmt, otype, ifmt, itype, expr) \
144static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *out, const uint8_t *in, \
145 int len) \
146{ \
147 int is = sizeof(itype); \
148 int os = sizeof(otype); \
149 const uint8_t *pi = in; \
150 uint8_t *po = out; \
151 uint8_t *end = out + os * len; \
152 CONV_LOOP(otype, expr) \
153}
154
155#define CONV_FUNC_INTERLEAVE(ofmt, otype, ifmt, itype, expr) \
156static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *out, const uint8_t **in, \
157 int len, int channels) \
158{ \
159 int ch; \
160 int out_bps = sizeof(otype); \
161 int is = sizeof(itype); \
162 int os = channels * out_bps; \
163 for (ch = 0; ch < channels; ch++) { \
164 const uint8_t *pi = in[ch]; \
165 uint8_t *po = out + ch * out_bps; \
166 uint8_t *end = po + os * len; \
167 CONV_LOOP(otype, expr) \
168 } \
169}
170
171#define CONV_FUNC_DEINTERLEAVE(ofmt, otype, ifmt, itype, expr) \
172static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t **out, const uint8_t *in, \
173 int len, int channels) \
174{ \
175 int ch; \
176 int in_bps = sizeof(itype); \
177 int is = channels * in_bps; \
178 int os = sizeof(otype); \
179 for (ch = 0; ch < channels; ch++) { \
180 const uint8_t *pi = in + ch * in_bps; \
181 uint8_t *po = out[ch]; \
182 uint8_t *end = po + os * len; \
183 CONV_LOOP(otype, expr) \
184 } \
185}
186
187#define CONV_FUNC_GROUP(ofmt, otype, ifmt, itype, expr) \
188CONV_FUNC_FLAT( ofmt, otype, ifmt, itype, expr) \
189CONV_FUNC_INTERLEAVE( ofmt, otype, ifmt ## P, itype, expr) \
190CONV_FUNC_DEINTERLEAVE(ofmt ## P, otype, ifmt, itype, expr)
191
192CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_U8, uint8_t, *(const uint8_t *)pi)
193CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) << 8)
194CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) << 24)
195CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) * (1.0f / (1 << 7)))
196CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) * (1.0 / (1 << 7)))
197CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t, (*(const int16_t *)pi >> 8) + 0x80)
198CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi)
199CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi << 16)
200CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi * (1.0f / (1 << 15)))
201CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi * (1.0 / (1 << 15)))
202CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t, (*(const int32_t *)pi >> 24) + 0x80)
203CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi >> 16)
204CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi)
205CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi * (1.0f / (1U << 31)))
206CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi * (1.0 / (1U << 31)))
207CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8( lrintf(*(const float *)pi * (1 << 7)) + 0x80))
208CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16( lrintf(*(const float *)pi * (1 << 15))))
209CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *)pi * (1U << 31))))
210CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_FLT, float, *(const float *)pi)
211CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_FLT, float, *(const float *)pi)
212CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8( lrint(*(const double *)pi * (1 << 7)) + 0x80))
213CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16( lrint(*(const double *)pi * (1 << 15))))
214CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *)pi * (1U << 31))))
215CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_DBL, double, *(const double *)pi)
216CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_DBL, double, *(const double *)pi)
217
218#define SET_CONV_FUNC_GROUP(ofmt, ifmt) \
219ff_audio_convert_set_func(ac, ofmt, ifmt, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt, ifmt)); \
220ff_audio_convert_set_func(ac, ofmt ## P, ifmt, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt ## P, ifmt)); \
221ff_audio_convert_set_func(ac, ofmt, ifmt ## P, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt, ifmt ## P));
222
223static void set_generic_function(AudioConvert *ac)
224{
225 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8)
226 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8)
227 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8)
228 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8)
229 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8)
230 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16)
231 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16)
232 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16)
233 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16)
234 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16)
235 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32)
236 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32)
237 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32)
238 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32)
239 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32)
240 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT)
241 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT)
242 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT)
243 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT)
244 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT)
245 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL)
246 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL)
247 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL)
248 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL)
249 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL)
250}
251
252void ff_audio_convert_free(AudioConvert **ac)
253{
254 if (!*ac)
255 return;
256 ff_dither_free(&(*ac)->dc);
257 av_freep(ac);
258}
259
260AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr,
261 enum AVSampleFormat out_fmt,
262 enum AVSampleFormat in_fmt,
263 int channels, int sample_rate,
264 int apply_map)
265{
266 AudioConvert *ac;
267 int in_planar, out_planar;
268
269 ac = av_mallocz(sizeof(*ac));
270 if (!ac)
271 return NULL;
272
273 ac->avr = avr;
274 ac->out_fmt = out_fmt;
275 ac->in_fmt = in_fmt;
276 ac->channels = channels;
277 ac->apply_map = apply_map;
278
279 if (avr->dither_method != AV_RESAMPLE_DITHER_NONE &&
280 av_get_packed_sample_fmt(out_fmt) == AV_SAMPLE_FMT_S16 &&
281 av_get_bytes_per_sample(in_fmt) > 2) {
282 ac->dc = ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate,
283 apply_map);
284 if (!ac->dc) {
285 av_free(ac);
286 return NULL;
287 }
288 return ac;
289 }
290
291 in_planar = ff_sample_fmt_is_planar(in_fmt, channels);
292 out_planar = ff_sample_fmt_is_planar(out_fmt, channels);
293
294 if (in_planar == out_planar) {
295 ac->func_type = CONV_FUNC_TYPE_FLAT;
296 ac->planes = in_planar ? ac->channels : 1;
297 } else if (in_planar)
298 ac->func_type = CONV_FUNC_TYPE_INTERLEAVE;
299 else
300 ac->func_type = CONV_FUNC_TYPE_DEINTERLEAVE;
301
302 set_generic_function(ac);
303
304 if (ARCH_AARCH64)
305 ff_audio_convert_init_aarch64(ac);
306 if (ARCH_ARM)
307 ff_audio_convert_init_arm(ac);
308 if (ARCH_X86)
309 ff_audio_convert_init_x86(ac);
310
311 return ac;
312}
313
314int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in)
315{
316 int use_generic = 1;
317 int len = in->nb_samples;
318 int p;
319
320 if (ac->dc) {
321 /* dithered conversion */
322 av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\n",
323 len, av_get_sample_fmt_name(ac->in_fmt),
324 av_get_sample_fmt_name(ac->out_fmt));
325
326 return ff_convert_dither(ac->dc, out, in);
327 }
328
329 /* determine whether to use the optimized function based on pointer and
330 samples alignment in both the input and output */
331 if (ac->has_optimized_func) {
332 int ptr_align = FFMIN(in->ptr_align, out->ptr_align);
333 int samples_align = FFMIN(in->samples_align, out->samples_align);
334 int aligned_len = FFALIGN(len, ac->samples_align);
335 if (!(ptr_align % ac->ptr_align) && samples_align >= aligned_len) {
336 len = aligned_len;
337 use_generic = 0;
338 }
339 }
340 av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (%s)\n", len,
341 av_get_sample_fmt_name(ac->in_fmt),
342 av_get_sample_fmt_name(ac->out_fmt),
343 use_generic ? ac->func_descr_generic : ac->func_descr);
344
345 if (ac->apply_map) {
346 ChannelMapInfo *map = &ac->avr->ch_map_info;
347
348 if (!ff_sample_fmt_is_planar(ac->out_fmt, ac->channels)) {
349 av_log(ac->avr, AV_LOG_ERROR, "cannot remap packed format during conversion\n");
350 return AVERROR(EINVAL);
351 }
352
353 if (map->do_remap) {
354 if (ff_sample_fmt_is_planar(ac->in_fmt, ac->channels)) {
355 conv_func_flat *convert = use_generic ? ac->conv_flat_generic :
356 ac->conv_flat;
357
358 for (p = 0; p < ac->planes; p++)
359 if (map->channel_map[p] >= 0)
360 convert(out->data[p], in->data[map->channel_map[p]], len);
361 } else {
362 uint8_t *data[AVRESAMPLE_MAX_CHANNELS];
363 conv_func_deinterleave *convert = use_generic ?
364 ac->conv_deinterleave_generic :
365 ac->conv_deinterleave;
366
367 for (p = 0; p < ac->channels; p++)
368 data[map->input_map[p]] = out->data[p];
369
370 convert(data, in->data[0], len, ac->channels);
371 }
372 }
373 if (map->do_copy || map->do_zero) {
374 for (p = 0; p < ac->planes; p++) {
375 if (map->channel_copy[p])
376 memcpy(out->data[p], out->data[map->channel_copy[p]],
377 len * out->stride);
378 else if (map->channel_zero[p])
379 av_samples_set_silence(&out->data[p], 0, len, 1, ac->out_fmt);
380 }
381 }
382 } else {
383 switch (ac->func_type) {
384 case CONV_FUNC_TYPE_FLAT: {
385 if (!in->is_planar)
386 len *= in->channels;
387 if (use_generic) {
388 for (p = 0; p < ac->planes; p++)
389 ac->conv_flat_generic(out->data[p], in->data[p], len);
390 } else {
391 for (p = 0; p < ac->planes; p++)
392 ac->conv_flat(out->data[p], in->data[p], len);
393 }
394 break;
395 }
396 case CONV_FUNC_TYPE_INTERLEAVE:
397 if (use_generic)
398 ac->conv_interleave_generic(out->data[0], in->data, len,
399 ac->channels);
400 else
401 ac->conv_interleave(out->data[0], in->data, len, ac->channels);
402 break;
403 case CONV_FUNC_TYPE_DEINTERLEAVE:
404 if (use_generic)
405 ac->conv_deinterleave_generic(out->data, in->data[0], len,
406 ac->channels);
407 else
408 ac->conv_deinterleave(out->data, in->data[0], len,
409 ac->channels);
410 break;
411 }
412 }
413
414 out->nb_samples = in->nb_samples;
415 return 0;
416}
libavresample/audio_convert.h+0−103
@@ -1,103 +0,0 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifndef AVRESAMPLE_AUDIO_CONVERT_H
22#define AVRESAMPLE_AUDIO_CONVERT_H
23
24#include "libavutil/samplefmt.h"
25#include "avresample.h"
26#include "internal.h"
27#include "audio_data.h"
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 samples_align buffer size alignment, in samples
45 * @param descr function type description (e.g. "C" or "SSE")
46 * @param conv conversion function pointer
47 */
48void 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 * @param sample_rate sample rate (used for dithering)
61 * @param apply_map apply channel map during conversion
62 * @return newly-allocated AudioConvert context
63 */
64AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr,
65 enum AVSampleFormat out_fmt,
66 enum AVSampleFormat in_fmt,
67 int channels, int sample_rate,
68 int apply_map);
69
70/**
71 * Free AudioConvert.
72 *
73 * The AudioConvert must have been previously allocated with ff_audio_convert_alloc().
74 *
75 * @param ac AudioConvert struct
76 */
77void ff_audio_convert_free(AudioConvert **ac);
78
79/**
80 * Convert audio data from one sample format to another.
81 *
82 * For each call, the alignment of the input and output AudioData buffers are
83 * examined to determine whether to use the generic or optimized conversion
84 * function (when available).
85 *
86 * The number of samples to convert is determined by in->nb_samples. The output
87 * buffer must be large enough to handle this many samples. out->nb_samples is
88 * set by this function before a successful return.
89 *
90 * @param ac AudioConvert context
91 * @param out output audio data
92 * @param in input audio data
93 * @return 0 on success, negative AVERROR code on failure
94 */
95int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in);
96
97/* arch-specific initialization functions */
98
99void ff_audio_convert_init_aarch64(AudioConvert *ac);
100void ff_audio_convert_init_arm(AudioConvert *ac);
101void ff_audio_convert_init_x86(AudioConvert *ac);
102
103#endif /* AVRESAMPLE_AUDIO_CONVERT_H */
libavresample/audio_data.c+0−381
@@ -1,381 +0,0 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <stdint.h>
22#include <string.h>
23
24#include "libavutil/mem.h"
25#include "audio_data.h"
26
27static const AVClass audio_data_class = {
28 .class_name = "AudioData",
29 .item_name = av_default_item_name,
30 .version = LIBAVUTIL_VERSION_INT,
31};
32
33/*
34 * Calculate alignment for data pointers.
35 */
36static void calc_ptr_alignment(AudioData *a)
37{
38 int p;
39 int min_align = 128;
40
41 for (p = 0; p < a->planes; p++) {
42 int cur_align = 128;
43 while ((intptr_t)a->data[p] % cur_align)
44 cur_align >>= 1;
45 if (cur_align < min_align)
46 min_align = cur_align;
47 }
48 a->ptr_align = min_align;
49}
50
51int ff_sample_fmt_is_planar(enum AVSampleFormat sample_fmt, int channels)
52{
53 if (channels == 1)
54 return 1;
55 else
56 return av_sample_fmt_is_planar(sample_fmt);
57}
58
59int ff_audio_data_set_channels(AudioData *a, int channels)
60{
61 if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS ||
62 channels > a->allocated_channels)
63 return AVERROR(EINVAL);
64
65 a->channels = channels;
66 a->planes = a->is_planar ? channels : 1;
67
68 calc_ptr_alignment(a);
69
70 return 0;
71}
72
73int ff_audio_data_init(AudioData *a, uint8_t * const *src, int plane_size,
74 int channels, int nb_samples,
75 enum AVSampleFormat sample_fmt, int read_only,
76 const char *name)
77{
78 int p;
79
80 memset(a, 0, sizeof(*a));
81 a->class = &audio_data_class;
82
83 if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS) {
84 av_log(a, AV_LOG_ERROR, "invalid channel count: %d\n", channels);
85 return AVERROR(EINVAL);
86 }
87
88 a->sample_size = av_get_bytes_per_sample(sample_fmt);
89 if (!a->sample_size) {
90 av_log(a, AV_LOG_ERROR, "invalid sample format\n");
91 return AVERROR(EINVAL);
92 }
93 a->is_planar = ff_sample_fmt_is_planar(sample_fmt, channels);
94 a->planes = a->is_planar ? channels : 1;
95 a->stride = a->sample_size * (a->is_planar ? 1 : channels);
96
97 for (p = 0; p < (a->is_planar ? channels : 1); p++) {
98 if (!src[p]) {
99 av_log(a, AV_LOG_ERROR, "invalid NULL pointer for src[%d]\n", p);
100 return AVERROR(EINVAL);
101 }
102 a->data[p] = src[p];
103 }
104 a->allocated_samples = nb_samples * !read_only;
105 a->nb_samples = nb_samples;
106 a->sample_fmt = sample_fmt;
107 a->channels = channels;
108 a->allocated_channels = channels;
109 a->read_only = read_only;
110 a->allow_realloc = 0;
111 a->name = name ? name : "{no name}";
112
113 calc_ptr_alignment(a);
114 a->samples_align = plane_size / a->stride;
115
116 return 0;
117}
118
119AudioData *ff_audio_data_alloc(int channels, int nb_samples,
120 enum AVSampleFormat sample_fmt, const char *name)
121{
122 AudioData *a;
123 int ret;
124
125 if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS)
126 return NULL;
127
128 a = av_mallocz(sizeof(*a));
129 if (!a)
130 return NULL;
131
132 a->sample_size = av_get_bytes_per_sample(sample_fmt);
133 if (!a->sample_size) {
134 av_free(a);
135 return NULL;
136 }
137 a->is_planar = ff_sample_fmt_is_planar(sample_fmt, channels);
138 a->planes = a->is_planar ? channels : 1;
139 a->stride = a->sample_size * (a->is_planar ? 1 : channels);
140
141 a->class = &audio_data_class;
142 a->sample_fmt = sample_fmt;
143 a->channels = channels;
144 a->allocated_channels = channels;
145 a->read_only = 0;
146 a->allow_realloc = 1;
147 a->name = name ? name : "{no name}";
148
149 if (nb_samples > 0) {
150 ret = ff_audio_data_realloc(a, nb_samples);
151 if (ret < 0) {
152 av_free(a);
153 return NULL;
154 }
155 return a;
156 } else {
157 calc_ptr_alignment(a);
158 return a;
159 }
160}
161
162int ff_audio_data_realloc(AudioData *a, int nb_samples)
163{
164 int ret, new_buf_size, plane_size, p;
165
166 /* check if buffer is already large enough */
167 if (a->allocated_samples >= nb_samples)
168 return 0;
169
170 /* validate that the output is not read-only and realloc is allowed */
171 if (a->read_only || !a->allow_realloc)
172 return AVERROR(EINVAL);
173
174 new_buf_size = av_samples_get_buffer_size(&plane_size,
175 a->allocated_channels, nb_samples,
176 a->sample_fmt, 0);
177 if (new_buf_size < 0)
178 return new_buf_size;
179
180 /* if there is already data in the buffer and the sample format is planar,
181 allocate a new buffer and copy the data, otherwise just realloc the
182 internal buffer and set new data pointers */
183 if (a->nb_samples > 0 && a->is_planar) {
184 uint8_t *new_data[AVRESAMPLE_MAX_CHANNELS] = { NULL };
185
186 ret = av_samples_alloc(new_data, &plane_size, a->allocated_channels,
187 nb_samples, a->sample_fmt, 0);
188 if (ret < 0)
189 return ret;
190
191 for (p = 0; p < a->planes; p++)
192 memcpy(new_data[p], a->data[p], a->nb_samples * a->stride);
193
194 av_freep(&a->buffer);
195 memcpy(a->data, new_data, sizeof(new_data));
196 a->buffer = a->data[0];
197 } else {
198 av_freep(&a->buffer);
199 a->buffer = av_malloc(new_buf_size);
200 if (!a->buffer)
201 return AVERROR(ENOMEM);
202 ret = av_samples_fill_arrays(a->data, &plane_size, a->buffer,
203 a->allocated_channels, nb_samples,
204 a->sample_fmt, 0);
205 if (ret < 0)
206 return ret;
207 }
208 a->buffer_size = new_buf_size;
209 a->allocated_samples = nb_samples;
210
211 calc_ptr_alignment(a);
212 a->samples_align = plane_size / a->stride;
213
214 return 0;
215}
216
217void ff_audio_data_free(AudioData **a)
218{
219 if (!*a)
220 return;
221 av_free((*a)->buffer);
222 av_freep(a);
223}
224
225int ff_audio_data_copy(AudioData *dst, AudioData *src, ChannelMapInfo *map)
226{
227 int ret, p;
228
229 /* validate input/output compatibility */
230 if (dst->sample_fmt != src->sample_fmt || dst->channels < src->channels)
231 return AVERROR(EINVAL);
232
233 if (map && !src->is_planar) {
234 av_log(src, AV_LOG_ERROR, "cannot remap packed format during copy\n");
235 return AVERROR(EINVAL);
236 }
237
238 /* if the input is empty, just empty the output */
239 if (!src->nb_samples) {
240 dst->nb_samples = 0;
241 return 0;
242 }
243
244 /* reallocate output if necessary */
245 ret = ff_audio_data_realloc(dst, src->nb_samples);
246 if (ret < 0)
247 return ret;
248
249 /* copy data */
250 if (map) {
251 if (map->do_remap) {
252 for (p = 0; p < src->planes; p++) {
253 if (map->channel_map[p] >= 0)
254 memcpy(dst->data[p], src->data[map->channel_map[p]],
255 src->nb_samples * src->stride);
256 }
257 }
258 if (map->do_copy || map->do_zero) {
259 for (p = 0; p < src->planes; p++) {
260 if (map->channel_copy[p])
261 memcpy(dst->data[p], dst->data[map->channel_copy[p]],
262 src->nb_samples * src->stride);
263 else if (map->channel_zero[p])
264 av_samples_set_silence(&dst->data[p], 0, src->nb_samples,
265 1, dst->sample_fmt);
266 }
267 }
268 } else {
269 for (p = 0; p < src->planes; p++)
270 memcpy(dst->data[p], src->data[p], src->nb_samples * src->stride);
271 }
272
273 dst->nb_samples = src->nb_samples;
274
275 return 0;
276}
277
278int ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src,
279 int src_offset, int nb_samples)
280{
281 int ret, p, dst_offset2, dst_move_size;
282
283 /* validate input/output compatibility */
284 if (dst->sample_fmt != src->sample_fmt || dst->channels != src->channels) {
285 av_log(src, AV_LOG_ERROR, "sample format mismatch\n");
286 return AVERROR(EINVAL);
287 }
288
289 /* validate offsets are within the buffer bounds */
290 if (dst_offset < 0 || dst_offset > dst->nb_samples ||
291 src_offset < 0 || src_offset > src->nb_samples) {
292 av_log(src, AV_LOG_ERROR, "offset out-of-bounds: src=%d dst=%d\n",
293 src_offset, dst_offset);
294 return AVERROR(EINVAL);
295 }
296
297 /* check offsets and sizes to see if we can just do nothing and return */
298 if (nb_samples > src->nb_samples - src_offset)
299 nb_samples = src->nb_samples - src_offset;
300 if (nb_samples <= 0)
301 return 0;
302
303 /* validate that the output is not read-only */
304 if (dst->read_only) {
305 av_log(dst, AV_LOG_ERROR, "dst is read-only\n");
306 return AVERROR(EINVAL);
307 }
308
309 /* reallocate output if necessary */
310 ret = ff_audio_data_realloc(dst, dst->nb_samples + nb_samples);
311 if (ret < 0) {
312 av_log(dst, AV_LOG_ERROR, "error reallocating dst\n");
313 return ret;
314 }
315
316 dst_offset2 = dst_offset + nb_samples;
317 dst_move_size = dst->nb_samples - dst_offset;
318
319 for (p = 0; p < src->planes; p++) {
320 if (dst_move_size > 0) {
321 memmove(dst->data[p] + dst_offset2 * dst->stride,
322 dst->data[p] + dst_offset * dst->stride,
323 dst_move_size * dst->stride);
324 }
325 memcpy(dst->data[p] + dst_offset * dst->stride,
326 src->data[p] + src_offset * src->stride,
327 nb_samples * src->stride);
328 }
329 dst->nb_samples += nb_samples;
330
331 return 0;
332}
333
334void ff_audio_data_drain(AudioData *a, int nb_samples)
335{
336 if (a->nb_samples <= nb_samples) {
337 /* drain the whole buffer */
338 a->nb_samples = 0;
339 } else {
340 int p;
341 int move_offset = a->stride * nb_samples;
342 int move_size = a->stride * (a->nb_samples - nb_samples);
343
344 for (p = 0; p < a->planes; p++)
345 memmove(a->data[p], a->data[p] + move_offset, move_size);
346
347 a->nb_samples -= nb_samples;
348 }
349}
350
351int ff_audio_data_add_to_fifo(AVAudioFifo *af, AudioData *a, int offset,
352 int nb_samples)
353{
354 uint8_t *offset_data[AVRESAMPLE_MAX_CHANNELS];
355 int offset_size, p;
356
357 if (offset >= a->nb_samples)
358 return 0;
359 offset_size = offset * a->stride;
360 for (p = 0; p < a->planes; p++)
361 offset_data[p] = a->data[p] + offset_size;
362
363 return av_audio_fifo_write(af, (void **)offset_data, nb_samples);
364}
365
366int ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples)
367{
368 int ret;
369
370 if (a->read_only)
371 return AVERROR(EINVAL);
372
373 ret = ff_audio_data_realloc(a, nb_samples);
374 if (ret < 0)
375 return ret;
376
377 ret = av_audio_fifo_read(af, (void **)a->data, nb_samples);
378 if (ret >= 0)
379 a->nb_samples = ret;
380 return ret;
381}
libavresample/audio_data.h+0−178
@@ -1,178 +0,0 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifndef AVRESAMPLE_AUDIO_DATA_H
22#define AVRESAMPLE_AUDIO_DATA_H
23
24#include <stdint.h>
25
26#include "libavutil/audio_fifo.h"
27#include "libavutil/log.h"
28#include "libavutil/samplefmt.h"
29#include "avresample.h"
30#include "internal.h"
31
32int ff_sample_fmt_is_planar(enum AVSampleFormat sample_fmt, int channels);
33
34/**
35 * Audio buffer used for intermediate storage between conversion phases.
36 */
37struct AudioData {
38 const AVClass *class; /**< AVClass for logging */
39 uint8_t *data[AVRESAMPLE_MAX_CHANNELS]; /**< data plane pointers */
40 uint8_t *buffer; /**< data buffer */
41 unsigned int buffer_size; /**< allocated buffer size */
42 int allocated_samples; /**< number of samples the buffer can hold */
43 int nb_samples; /**< current number of samples */
44 enum AVSampleFormat sample_fmt; /**< sample format */
45 int channels; /**< channel count */
46 int allocated_channels; /**< allocated channel count */
47 int is_planar; /**< sample format is planar */
48 int planes; /**< number of data planes */
49 int sample_size; /**< bytes per sample */
50 int stride; /**< sample byte offset within a plane */
51 int read_only; /**< data is read-only */
52 int allow_realloc; /**< realloc is allowed */
53 int ptr_align; /**< minimum data pointer alignment */
54 int samples_align; /**< allocated samples alignment */
55 const char *name; /**< name for debug logging */
56};
57
58int ff_audio_data_set_channels(AudioData *a, int channels);
59
60/**
61 * Initialize AudioData using a given source.
62 *
63 * This does not allocate an internal buffer. It only sets the data pointers
64 * and audio parameters.
65 *
66 * @param a AudioData struct
67 * @param src source data pointers
68 * @param plane_size plane size, in bytes.
69 * This can be 0 if unknown, but that will lead to
70 * optimized functions not being used in many cases,
71 * which could slow down some conversions.
72 * @param channels channel count
73 * @param nb_samples number of samples in the source data
74 * @param sample_fmt sample format
75 * @param read_only indicates if buffer is read only or read/write
76 * @param name name for debug logging (can be NULL)
77 * @return 0 on success, negative AVERROR value on error
78 */
79int ff_audio_data_init(AudioData *a, uint8_t * const *src, int plane_size,
80 int channels, int nb_samples,
81 enum AVSampleFormat sample_fmt, int read_only,
82 const char *name);
83
84/**
85 * Allocate AudioData.
86 *
87 * This allocates an internal buffer and sets audio parameters.
88 *
89 * @param channels channel count
90 * @param nb_samples number of samples to allocate space for
91 * @param sample_fmt sample format
92 * @param name name for debug logging (can be NULL)
93 * @return newly allocated AudioData struct, or NULL on error
94 */
95AudioData *ff_audio_data_alloc(int channels, int nb_samples,
96 enum AVSampleFormat sample_fmt,
97 const char *name);
98
99/**
100 * Reallocate AudioData.
101 *
102 * The AudioData must have been previously allocated with ff_audio_data_alloc().
103 *
104 * @param a AudioData struct
105 * @param nb_samples number of samples to allocate space for
106 * @return 0 on success, negative AVERROR value on error
107 */
108int ff_audio_data_realloc(AudioData *a, int nb_samples);
109
110/**
111 * Free AudioData.
112 *
113 * The AudioData must have been previously allocated with ff_audio_data_alloc().
114 *
115 * @param a AudioData struct
116 */
117void ff_audio_data_free(AudioData **a);
118
119/**
120 * Copy data from one AudioData to another.
121 *
122 * @param out output AudioData
123 * @param in input AudioData
124 * @param map channel map, NULL if not remapping
125 * @return 0 on success, negative AVERROR value on error
126 */
127int ff_audio_data_copy(AudioData *out, AudioData *in, ChannelMapInfo *map);
128
129/**
130 * Append data from one AudioData to the end of another.
131 *
132 * @param dst destination AudioData
133 * @param dst_offset offset, in samples, to start writing, relative to the
134 * start of dst
135 * @param src source AudioData
136 * @param src_offset offset, in samples, to start copying, relative to the
137 * start of the src
138 * @param nb_samples number of samples to copy
139 * @return 0 on success, negative AVERROR value on error
140 */
141int ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src,
142 int src_offset, int nb_samples);
143
144/**
145 * Drain samples from the start of the AudioData.
146 *
147 * Remaining samples are shifted to the start of the AudioData.
148 *
149 * @param a AudioData struct
150 * @param nb_samples number of samples to drain
151 */
152void ff_audio_data_drain(AudioData *a, int nb_samples);
153
154/**
155 * Add samples in AudioData to an AVAudioFifo.
156 *
157 * @param af Audio FIFO Buffer
158 * @param a AudioData struct
159 * @param offset number of samples to skip from the start of the data
160 * @param nb_samples number of samples to add to the FIFO
161 * @return number of samples actually added to the FIFO, or
162 * negative AVERROR code on error
163 */
164int ff_audio_data_add_to_fifo(AVAudioFifo *af, AudioData *a, int offset,
165 int nb_samples);
166
167/**
168 * Read samples from an AVAudioFifo to AudioData.
169 *
170 * @param af Audio FIFO Buffer
171 * @param a AudioData struct
172 * @param nb_samples number of samples to read from the FIFO
173 * @return number of samples actually read from the FIFO, or
174 * negative AVERROR code on error
175 */
176int ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples);
177
178#endif /* AVRESAMPLE_AUDIO_DATA_H */
libavresample/audio_mix.c+0−742
@@ -1,742 +0,0 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <stdint.h>
22
23#include "libavutil/common.h"
24#include "libavutil/libm.h"
25#include "libavutil/samplefmt.h"
26#include "avresample.h"
27#include "internal.h"
28#include "audio_data.h"
29#include "audio_mix.h"
30
31static const char * const coeff_type_names[] = { "q8", "q15", "flt" };
32
33struct AudioMix {
34 AVAudioResampleContext *avr;
35 enum AVSampleFormat fmt;
36 enum AVMixCoeffType coeff_type;
37 uint64_t in_layout;
38 uint64_t out_layout;
39 int in_channels;
40 int out_channels;
41
42 int ptr_align;
43 int samples_align;
44 int has_optimized_func;
45 const char *func_descr;
46 const char *func_descr_generic;
47 mix_func *mix;
48 mix_func *mix_generic;
49
50 int in_matrix_channels;
51 int out_matrix_channels;
52 int output_zero[AVRESAMPLE_MAX_CHANNELS];
53 int input_skip[AVRESAMPLE_MAX_CHANNELS];
54 int output_skip[AVRESAMPLE_MAX_CHANNELS];
55 int16_t *matrix_q8[AVRESAMPLE_MAX_CHANNELS];
56 int32_t *matrix_q15[AVRESAMPLE_MAX_CHANNELS];
57 float *matrix_flt[AVRESAMPLE_MAX_CHANNELS];
58 void **matrix;
59};
60
61void ff_audio_mix_set_func(AudioMix *am, enum AVSampleFormat fmt,
62 enum AVMixCoeffType coeff_type, int in_channels,
63 int out_channels, int ptr_align, int samples_align,
64 const char *descr, void *mix_func)
65{
66 if (fmt == am->fmt && coeff_type == am->coeff_type &&
67 ( in_channels == am->in_matrix_channels || in_channels == 0) &&
68 (out_channels == am->out_matrix_channels || out_channels == 0)) {
69 char chan_str[16];
70 am->mix = mix_func;
71 am->func_descr = descr;
72 am->ptr_align = ptr_align;
73 am->samples_align = samples_align;
74 if (ptr_align == 1 && samples_align == 1) {
75 am->mix_generic = mix_func;
76 am->func_descr_generic = descr;
77 } else {
78 am->has_optimized_func = 1;
79 }
80 if (in_channels) {
81 if (out_channels)
82 snprintf(chan_str, sizeof(chan_str), "[%d to %d] ",
83 in_channels, out_channels);
84 else
85 snprintf(chan_str, sizeof(chan_str), "[%d to any] ",
86 in_channels);
87 } else if (out_channels) {
88 snprintf(chan_str, sizeof(chan_str), "[any to %d] ",
89 out_channels);
90 } else {
91 snprintf(chan_str, sizeof(chan_str), "[any to any] ");
92 }
93 av_log(am->avr, AV_LOG_DEBUG, "audio_mix: found function: [fmt=%s] "
94 "[c=%s] %s(%s)\n", av_get_sample_fmt_name(fmt),
95 coeff_type_names[coeff_type], chan_str, descr);
96 }
97}
98
99#define MIX_FUNC_NAME(fmt, cfmt) mix_any_ ## fmt ##_## cfmt ##_c
100
101#define MIX_FUNC_GENERIC(fmt, cfmt, stype, ctype, sumtype, expr) \
102static void MIX_FUNC_NAME(fmt, cfmt)(stype **samples, ctype **matrix, \
103 int len, int out_ch, int in_ch) \
104{ \
105 int i, in, out; \
106 stype temp[AVRESAMPLE_MAX_CHANNELS]; \
107 for (i = 0; i < len; i++) { \
108 for (out = 0; out < out_ch; out++) { \
109 sumtype sum = 0; \
110 for (in = 0; in < in_ch; in++) \
111 sum += samples[in][i] * matrix[out][in]; \
112 temp[out] = expr; \
113 } \
114 for (out = 0; out < out_ch; out++) \
115 samples[out][i] = temp[out]; \
116 } \
117}
118
119MIX_FUNC_GENERIC(FLTP, FLT, float, float, float, sum)
120MIX_FUNC_GENERIC(S16P, FLT, int16_t, float, float, av_clip_int16(lrintf(sum)))
121MIX_FUNC_GENERIC(S16P, Q15, int16_t, int32_t, int64_t, av_clip_int16(sum >> 15))
122MIX_FUNC_GENERIC(S16P, Q8, int16_t, int16_t, int32_t, av_clip_int16(sum >> 8))
123
124/* TODO: templatize the channel-specific C functions */
125
126static void mix_2_to_1_fltp_flt_c(float **samples, float **matrix, int len,
127 int out_ch, int in_ch)
128{
129 float *src0 = samples[0];
130 float *src1 = samples[1];
131 float *dst = src0;
132 float m0 = matrix[0][0];
133 float m1 = matrix[0][1];
134
135 while (len > 4) {
136 *dst++ = *src0++ * m0 + *src1++ * m1;
137 *dst++ = *src0++ * m0 + *src1++ * m1;
138 *dst++ = *src0++ * m0 + *src1++ * m1;
139 *dst++ = *src0++ * m0 + *src1++ * m1;
140 len -= 4;
141 }
142 while (len > 0) {
143 *dst++ = *src0++ * m0 + *src1++ * m1;
144 len--;
145 }
146}
147
148static void mix_2_to_1_s16p_flt_c(int16_t **samples, float **matrix, int len,
149 int out_ch, int in_ch)
150{
151 int16_t *src0 = samples[0];
152 int16_t *src1 = samples[1];
153 int16_t *dst = src0;
154 float m0 = matrix[0][0];
155 float m1 = matrix[0][1];
156
157 while (len > 4) {
158 *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
159 *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
160 *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
161 *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
162 len -= 4;
163 }
164 while (len > 0) {
165 *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
166 len--;
167 }
168}
169
170static void mix_2_to_1_s16p_q8_c(int16_t **samples, int16_t **matrix, int len,
171 int out_ch, int in_ch)
172{
173 int16_t *src0 = samples[0];
174 int16_t *src1 = samples[1];
175 int16_t *dst = src0;
176 int16_t m0 = matrix[0][0];
177 int16_t m1 = matrix[0][1];
178
179 while (len > 4) {
180 *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
181 *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
182 *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
183 *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
184 len -= 4;
185 }
186 while (len > 0) {
187 *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
188 len--;
189 }
190}
191
192static void mix_1_to_2_fltp_flt_c(float **samples, float **matrix, int len,
193 int out_ch, int in_ch)
194{
195 float v;
196 float *dst0 = samples[0];
197 float *dst1 = samples[1];
198 float *src = dst0;
199 float m0 = matrix[0][0];
200 float m1 = matrix[1][0];
201
202 while (len > 4) {
203 v = *src++;
204 *dst0++ = v * m0;
205 *dst1++ = v * m1;
206 v = *src++;
207 *dst0++ = v * m0;
208 *dst1++ = v * m1;
209 v = *src++;
210 *dst0++ = v * m0;
211 *dst1++ = v * m1;
212 v = *src++;
213 *dst0++ = v * m0;
214 *dst1++ = v * m1;
215 len -= 4;
216 }
217 while (len > 0) {
218 v = *src++;
219 *dst0++ = v * m0;
220 *dst1++ = v * m1;
221 len--;
222 }
223}
224
225static void mix_6_to_2_fltp_flt_c(float **samples, float **matrix, int len,
226 int out_ch, int in_ch)
227{
228 float v0, v1;
229 float *src0 = samples[0];
230 float *src1 = samples[1];
231 float *src2 = samples[2];
232 float *src3 = samples[3];
233 float *src4 = samples[4];
234 float *src5 = samples[5];
235 float *dst0 = src0;
236 float *dst1 = src1;
237 float *m0 = matrix[0];
238 float *m1 = matrix[1];
239
240 while (len > 0) {
241 v0 = *src0++;
242 v1 = *src1++;
243 *dst0++ = v0 * m0[0] +
244 v1 * m0[1] +
245 *src2 * m0[2] +
246 *src3 * m0[3] +
247 *src4 * m0[4] +
248 *src5 * m0[5];
249 *dst1++ = v0 * m1[0] +
250 v1 * m1[1] +
251 *src2++ * m1[2] +
252 *src3++ * m1[3] +
253 *src4++ * m1[4] +
254 *src5++ * m1[5];
255 len--;
256 }
257}
258
259static void mix_2_to_6_fltp_flt_c(float **samples, float **matrix, int len,
260 int out_ch, int in_ch)
261{
262 float v0, v1;
263 float *dst0 = samples[0];
264 float *dst1 = samples[1];
265 float *dst2 = samples[2];
266 float *dst3 = samples[3];
267 float *dst4 = samples[4];
268 float *dst5 = samples[5];
269 float *src0 = dst0;
270 float *src1 = dst1;
271
272 while (len > 0) {
273 v0 = *src0++;
274 v1 = *src1++;
275 *dst0++ = v0 * matrix[0][0] + v1 * matrix[0][1];
276 *dst1++ = v0 * matrix[1][0] + v1 * matrix[1][1];
277 *dst2++ = v0 * matrix[2][0] + v1 * matrix[2][1];
278 *dst3++ = v0 * matrix[3][0] + v1 * matrix[3][1];
279 *dst4++ = v0 * matrix[4][0] + v1 * matrix[4][1];
280 *dst5++ = v0 * matrix[5][0] + v1 * matrix[5][1];
281 len--;
282 }
283}
284
285static av_cold int mix_function_init(AudioMix *am)
286{
287 am->func_descr = am->func_descr_generic = "n/a";
288 am->mix = am->mix_generic = NULL;
289
290 /* no need to set a mix function when we're skipping mixing */
291 if (!am->in_matrix_channels || !am->out_matrix_channels)
292 return 0;
293
294 /* any-to-any C versions */
295
296 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
297 0, 0, 1, 1, "C", MIX_FUNC_NAME(FLTP, FLT));
298
299 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
300 0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, FLT));
301
302 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q15,
303 0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q15));
304
305 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q8,
306 0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q8));
307
308 /* channel-specific C versions */
309
310 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
311 2, 1, 1, 1, "C", mix_2_to_1_fltp_flt_c);
312
313 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
314 2, 1, 1, 1, "C", mix_2_to_1_s16p_flt_c);
315
316 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q8,
317 2, 1, 1, 1, "C", mix_2_to_1_s16p_q8_c);
318
319 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
320 1, 2, 1, 1, "C", mix_1_to_2_fltp_flt_c);
321
322 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
323 6, 2, 1, 1, "C", mix_6_to_2_fltp_flt_c);
324
325 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
326 2, 6, 1, 1, "C", mix_2_to_6_fltp_flt_c);
327
328 if (ARCH_X86)
329 ff_audio_mix_init_x86(am);
330
331 if (!am->mix) {
332 av_log(am->avr, AV_LOG_ERROR, "audio_mix: NO FUNCTION FOUND: [fmt=%s] "
333 "[c=%s] [%d to %d]\n", av_get_sample_fmt_name(am->fmt),
334 coeff_type_names[am->coeff_type], am->in_channels,
335 am->out_channels);
336 return AVERROR_PATCHWELCOME;
337 }
338 return 0;
339}
340
341AudioMix *ff_audio_mix_alloc(AVAudioResampleContext *avr)
342{
343 AudioMix *am;
344 int ret;
345
346 am = av_mallocz(sizeof(*am));
347 if (!am)
348 return NULL;
349 am->avr = avr;
350
351 if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P &&
352 avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP) {
353 av_log(avr, AV_LOG_ERROR, "Unsupported internal format for "
354 "mixing: %s\n",
355 av_get_sample_fmt_name(avr->internal_sample_fmt));
356 goto error;
357 }
358
359 am->fmt = avr->internal_sample_fmt;
360 am->coeff_type = avr->mix_coeff_type;
361 am->in_layout = avr->in_channel_layout;
362 am->out_layout = avr->out_channel_layout;
363 am->in_channels = avr->in_channels;
364 am->out_channels = avr->out_channels;
365
366 /* build matrix if the user did not already set one */
367 if (avr->mix_matrix) {
368 ret = ff_audio_mix_set_matrix(am, avr->mix_matrix, avr->in_channels);
369 if (ret < 0)
370 goto error;
371 av_freep(&avr->mix_matrix);
372 } else {
373 double *matrix_dbl = av_mallocz(avr->out_channels * avr->in_channels *
374 sizeof(*matrix_dbl));
375 if (!matrix_dbl)
376 goto error;
377
378 ret = avresample_build_matrix(avr->in_channel_layout,
379 avr->out_channel_layout,
380 avr->center_mix_level,
381 avr->surround_mix_level,
382 avr->lfe_mix_level,
383 avr->normalize_mix_level,
384 matrix_dbl,
385 avr->in_channels,
386 avr->matrix_encoding);
387 if (ret < 0) {
388 av_free(matrix_dbl);
389 goto error;
390 }
391
392 ret = ff_audio_mix_set_matrix(am, matrix_dbl, avr->in_channels);
393 if (ret < 0) {
394 av_log(avr, AV_LOG_ERROR, "error setting mix matrix\n");
395 av_free(matrix_dbl);
396 goto error;
397 }
398
399 av_free(matrix_dbl);
400 }
401
402 return am;
403
404error:
405 av_free(am);
406 return NULL;
407}
408
409void ff_audio_mix_free(AudioMix **am_p)
410{
411 AudioMix *am;
412
413 if (!*am_p)
414 return;
415 am = *am_p;
416
417 if (am->matrix) {
418 av_free(am->matrix[0]);
419 am->matrix = NULL;
420 }
421 memset(am->matrix_q8, 0, sizeof(am->matrix_q8 ));
422 memset(am->matrix_q15, 0, sizeof(am->matrix_q15));
423 memset(am->matrix_flt, 0, sizeof(am->matrix_flt));
424
425 av_freep(am_p);
426}
427
428int ff_audio_mix(AudioMix *am, AudioData *src)
429{
430 int use_generic = 1;
431 int len = src->nb_samples;
432 int i, j;
433
434 /* determine whether to use the optimized function based on pointer and
435 samples alignment in both the input and output */
436 if (am->has_optimized_func) {
437 int aligned_len = FFALIGN(len, am->samples_align);
438 if (!(src->ptr_align % am->ptr_align) &&
439 src->samples_align >= aligned_len) {
440 len = aligned_len;
441 use_generic = 0;
442 }
443 }
444 av_log(am->avr, AV_LOG_TRACE, "audio_mix: %d samples - %d to %d channels (%s)\n",
445 src->nb_samples, am->in_channels, am->out_channels,
446 use_generic ? am->func_descr_generic : am->func_descr);
447
448 if (am->in_matrix_channels && am->out_matrix_channels) {
449 uint8_t **data;
450 uint8_t *data0[AVRESAMPLE_MAX_CHANNELS] = { NULL };
451
452 if (am->out_matrix_channels < am->out_channels ||
453 am->in_matrix_channels < am->in_channels) {
454 for (i = 0, j = 0; i < FFMAX(am->in_channels, am->out_channels); i++) {
455 if (am->input_skip[i] || am->output_skip[i] || am->output_zero[i])
456 continue;
457 data0[j++] = src->data[i];
458 }
459 data = data0;
460 } else {
461 data = src->data;
462 }
463
464 if (use_generic)
465 am->mix_generic(data, am->matrix, len, am->out_matrix_channels,
466 am->in_matrix_channels);
467 else
468 am->mix(data, am->matrix, len, am->out_matrix_channels,
469 am->in_matrix_channels);
470 }
471
472 if (am->out_matrix_channels < am->out_channels) {
473 for (i = 0; i < am->out_channels; i++)
474 if (am->output_zero[i])
475 av_samples_set_silence(&src->data[i], 0, len, 1, am->fmt);
476 }
477
478 ff_audio_data_set_channels(src, am->out_channels);
479
480 return 0;
481}
482
483int ff_audio_mix_get_matrix(AudioMix *am, double *matrix, int stride)
484{
485 int i, o, i0, o0;
486
487 if ( am->in_channels <= 0 || am->in_channels > AVRESAMPLE_MAX_CHANNELS ||
488 am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {
489 av_log(am->avr, AV_LOG_ERROR, "Invalid channel counts\n");
490 return AVERROR(EINVAL);
491 }
492
493#define GET_MATRIX_CONVERT(suffix, scale) \
494 if (!am->matrix_ ## suffix[0]) { \
495 av_log(am->avr, AV_LOG_ERROR, "matrix is not set\n"); \
496 return AVERROR(EINVAL); \
497 } \
498 for (o = 0, o0 = 0; o < am->out_channels; o++) { \
499 for (i = 0, i0 = 0; i < am->in_channels; i++) { \
500 if (am->input_skip[i] || am->output_zero[o]) \
501 matrix[o * stride + i] = 0.0; \
502 else \
503 matrix[o * stride + i] = am->matrix_ ## suffix[o0][i0] * \
504 (scale); \
505 if (!am->input_skip[i]) \
506 i0++; \
507 } \
508 if (!am->output_zero[o]) \
509 o0++; \
510 }
511
512 switch (am->coeff_type) {
513 case AV_MIX_COEFF_TYPE_Q8:
514 GET_MATRIX_CONVERT(q8, 1.0 / 256.0);
515 break;
516 case AV_MIX_COEFF_TYPE_Q15:
517 GET_MATRIX_CONVERT(q15, 1.0 / 32768.0);
518 break;
519 case AV_MIX_COEFF_TYPE_FLT:
520 GET_MATRIX_CONVERT(flt, 1.0);
521 break;
522 default:
523 av_log(am->avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
524 return AVERROR(EINVAL);
525 }
526
527 return 0;
528}
529
530static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
531{
532 int i, o;
533
534 memset(am->output_zero, 0, sizeof(am->output_zero));
535 memset(am->input_skip, 0, sizeof(am->input_skip));
536 memset(am->output_skip, 0, sizeof(am->output_skip));
537
538 /* exclude output channels if they can be zeroed instead of mixed */
539 for (o = 0; o < am->out_channels; o++) {
540 int zero = 1;
541
542 /* check if the output is always silent */
543 for (i = 0; i < am->in_channels; i++) {
544 if (matrix[o * stride + i] != 0.0) {
545 zero = 0;
546 break;
547 }
548 }
549 /* check if the corresponding input channel makes a contribution to
550 any output channel */
551 if (o < am->in_channels) {
552 for (i = 0; i < am->out_channels; i++) {
553 if (matrix[i * stride + o] != 0.0) {
554 zero = 0;
555 break;
556 }
557 }
558 }
559 if (zero) {
560 am->output_zero[o] = 1;
561 am->out_matrix_channels--;
562 if (o < am->in_channels)
563 am->in_matrix_channels--;
564 }
565 }
566 if (am->out_matrix_channels == 0 || am->in_matrix_channels == 0) {
567 am->out_matrix_channels = 0;
568 am->in_matrix_channels = 0;
569 return;
570 }
571
572 /* skip input channels that contribute fully only to the corresponding
573 output channel */
574 for (i = 0; i < FFMIN(am->in_channels, am->out_channels); i++) {
575 int skip = 1;
576
577 for (o = 0; o < am->out_channels; o++) {
578 int i0;
579 if ((o != i && matrix[o * stride + i] != 0.0) ||
580 (o == i && matrix[o * stride + i] != 1.0)) {
581 skip = 0;
582 break;
583 }
584 /* if the input contributes fully to the output, also check that no
585 other inputs contribute to this output */
586 if (o == i) {
587 for (i0 = 0; i0 < am->in_channels; i0++) {
588 if (i0 != i && matrix[o * stride + i0] != 0.0) {
589 skip = 0;
590 break;
591 }
592 }
593 }
594 }
595 if (skip) {
596 am->input_skip[i] = 1;
597 am->in_matrix_channels--;
598 }
599 }
600 /* skip input channels that do not contribute to any output channel */
601 for (; i < am->in_channels; i++) {
602 int contrib = 0;
603
604 for (o = 0; o < am->out_channels; o++) {
605 if (matrix[o * stride + i] != 0.0) {
606 contrib = 1;
607 break;
608 }
609 }
610 if (!contrib) {
611 am->input_skip[i] = 1;
612 am->in_matrix_channels--;
613 }
614 }
615 if (am->in_matrix_channels == 0) {
616 am->out_matrix_channels = 0;
617 return;
618 }
619
620 /* skip output channels that only get full contribution from the
621 corresponding input channel */
622 for (o = 0; o < FFMIN(am->in_channels, am->out_channels); o++) {
623 int skip = 1;
624 int o0;
625
626 for (i = 0; i < am->in_channels; i++) {
627 if ((o != i && matrix[o * stride + i] != 0.0) ||
628 (o == i && matrix[o * stride + i] != 1.0)) {
629 skip = 0;
630 break;
631 }
632 }
633 /* check if the corresponding input channel makes a contribution to
634 any other output channel */
635 i = o;
636 for (o0 = 0; o0 < am->out_channels; o0++) {
637 if (o0 != i && matrix[o0 * stride + i] != 0.0) {
638 skip = 0;
639 break;
640 }
641 }
642 if (skip) {
643 am->output_skip[o] = 1;
644 am->out_matrix_channels--;
645 }
646 }
647 if (am->out_matrix_channels == 0) {
648 am->in_matrix_channels = 0;
649 return;
650 }
651}
652
653int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride)
654{
655 int i, o, i0, o0, ret;
656 char in_layout_name[128];
657 char out_layout_name[128];
658
659 if ( am->in_channels <= 0 || am->in_channels > AVRESAMPLE_MAX_CHANNELS ||
660 am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {
661 av_log(am->avr, AV_LOG_ERROR, "Invalid channel counts\n");
662 return AVERROR(EINVAL);
663 }
664
665 if (am->matrix) {
666 av_free(am->matrix[0]);
667 am->matrix = NULL;
668 }
669
670 am->in_matrix_channels = am->in_channels;
671 am->out_matrix_channels = am->out_channels;
672
673 reduce_matrix(am, matrix, stride);
674
675#define CONVERT_MATRIX(type, expr) \
676 am->matrix_## type[0] = av_mallocz(am->out_matrix_channels * \
677 am->in_matrix_channels * \
678 sizeof(*am->matrix_## type[0])); \
679 if (!am->matrix_## type[0]) \
680 return AVERROR(ENOMEM); \
681 for (o = 0, o0 = 0; o < am->out_channels; o++) { \
682 if (am->output_zero[o] || am->output_skip[o]) \
683 continue; \
684 if (o0 > 0) \
685 am->matrix_## type[o0] = am->matrix_## type[o0 - 1] + \
686 am->in_matrix_channels; \
687 for (i = 0, i0 = 0; i < am->in_channels; i++) { \
688 double v; \
689 if (am->input_skip[i] || am->output_zero[i]) \
690 continue; \
691 v = matrix[o * stride + i]; \
692 am->matrix_## type[o0][i0] = expr; \
693 i0++; \
694 } \
695 o0++; \
696 } \
697 am->matrix = (void **)am->matrix_## type;
698
699 if (am->in_matrix_channels && am->out_matrix_channels) {
700 switch (am->coeff_type) {
701 case AV_MIX_COEFF_TYPE_Q8:
702 CONVERT_MATRIX(q8, av_clip_int16(lrint(256.0 * v)))
703 break;
704 case AV_MIX_COEFF_TYPE_Q15:
705 CONVERT_MATRIX(q15, av_clipl_int32(llrint(32768.0 * v)))
706 break;
707 case AV_MIX_COEFF_TYPE_FLT:
708 CONVERT_MATRIX(flt, v)
709 break;
710 default:
711 av_log(am->avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
712 return AVERROR(EINVAL);
713 }
714 }
715
716 ret = mix_function_init(am);
717 if (ret < 0)
718 return ret;
719
720 av_get_channel_layout_string(in_layout_name, sizeof(in_layout_name),
721 am->in_channels, am->in_layout);
722 av_get_channel_layout_string(out_layout_name, sizeof(out_layout_name),
723 am->out_channels, am->out_layout);
724 av_log(am->avr, AV_LOG_DEBUG, "audio_mix: %s to %s\n",
725 in_layout_name, out_layout_name);
726 av_log(am->avr, AV_LOG_DEBUG, "matrix size: %d x %d\n",
727 am->in_matrix_channels, am->out_matrix_channels);
728 for (o = 0; o < am->out_channels; o++) {
729 for (i = 0; i < am->in_channels; i++) {
730 if (am->output_zero[o])
731 av_log(am->avr, AV_LOG_DEBUG, " (ZERO)");
732 else if (am->input_skip[i] || am->output_zero[i] || am->output_skip[o])
733 av_log(am->avr, AV_LOG_DEBUG, " (SKIP)");
734 else
735 av_log(am->avr, AV_LOG_DEBUG, " %0.3f ",
736 matrix[o * am->in_channels + i]);
737 }
738 av_log(am->avr, AV_LOG_DEBUG, "\n");
739 }
740
741 return 0;
742}
libavresample/audio_mix.h+0−94
@@ -1,94 +0,0 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifndef AVRESAMPLE_AUDIO_MIX_H
22#define AVRESAMPLE_AUDIO_MIX_H
23
24#include <stdint.h>
25
26#include "libavutil/samplefmt.h"
27#include "avresample.h"
28#include "internal.h"
29#include "audio_data.h"
30
31typedef void (mix_func)(uint8_t **src, void **matrix, int len, int out_ch,
32 int in_ch);
33
34/**
35 * Set mixing function if the parameters match.
36 *
37 * This compares the parameters of the mixing function to the parameters in the
38 * AudioMix context. If the parameters do not match, no changes are made to the
39 * active functions. If the parameters do match and the alignment is not
40 * constrained, the function is set as the generic mixing function. If the
41 * parameters match and the alignment is constrained, the function is set as
42 * the optimized mixing function.
43 *
44 * @param am AudioMix context
45 * @param fmt input/output sample format
46 * @param coeff_type mixing coefficient type
47 * @param in_channels number of input channels, or 0 for any number of channels
48 * @param out_channels number of output channels, or 0 for any number of channels
49 * @param ptr_align buffer pointer alignment, in bytes
50 * @param samples_align buffer size alignment, in samples
51 * @param descr function type description (e.g. "C" or "SSE")
52 * @param mix_func mixing function pointer
53 */
54void ff_audio_mix_set_func(AudioMix *am, enum AVSampleFormat fmt,
55 enum AVMixCoeffType coeff_type, int in_channels,
56 int out_channels, int ptr_align, int samples_align,
57 const char *descr, void *mix_func);
58
59/**
60 * Allocate and initialize an AudioMix context.
61 *
62 * The parameters in the AVAudioResampleContext are used to initialize the
63 * AudioMix context.
64 *
65 * @param avr AVAudioResampleContext
66 * @return newly-allocated AudioMix context.
67 */
68AudioMix *ff_audio_mix_alloc(AVAudioResampleContext *avr);
69
70/**
71 * Free an AudioMix context.
72 */
73void ff_audio_mix_free(AudioMix **am);
74
75/**
76 * Apply channel mixing to audio data using the current mixing matrix.
77 */
78int ff_audio_mix(AudioMix *am, AudioData *src);
79
80/**
81 * Get the current mixing matrix.
82 */
83int ff_audio_mix_get_matrix(AudioMix *am, double *matrix, int stride);
84
85/**
86 * Set the current mixing matrix.
87 */
88int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride);
89
90/* arch-specific initialization functions */
91
92void ff_audio_mix_init_x86(AudioMix *am);
93
94#endif /* AVRESAMPLE_AUDIO_MIX_H */
libavresample/audio_mix_matrix.c+0−294
@@ -1,294 +0,0 @@
1/*
2 * Copyright (C) 2011 Michael Niedermayer (michaelni@gmx.at)
3 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <stdint.h>
23
24#include "libavutil/common.h"
25#include "libavutil/libm.h"
26#include "libavutil/samplefmt.h"
27#include "avresample.h"
28#include "internal.h"
29#include "audio_data.h"
30#include "audio_mix.h"
31
32/* channel positions */
33#define FRONT_LEFT 0
34#define FRONT_RIGHT 1
35#define FRONT_CENTER 2
36#define LOW_FREQUENCY 3
37#define BACK_LEFT 4
38#define BACK_RIGHT 5
39#define FRONT_LEFT_OF_CENTER 6
40#define FRONT_RIGHT_OF_CENTER 7
41#define BACK_CENTER 8
42#define SIDE_LEFT 9
43#define SIDE_RIGHT 10
44#define TOP_CENTER 11
45#define TOP_FRONT_LEFT 12
46#define TOP_FRONT_CENTER 13
47#define TOP_FRONT_RIGHT 14
48#define TOP_BACK_LEFT 15
49#define TOP_BACK_CENTER 16
50#define TOP_BACK_RIGHT 17
51#define STEREO_LEFT 29
52#define STEREO_RIGHT 30
53#define WIDE_LEFT 31
54#define WIDE_RIGHT 32
55#define SURROUND_DIRECT_LEFT 33
56#define SURROUND_DIRECT_RIGHT 34
57#define LOW_FREQUENCY_2 35
58
59#define SQRT3_2 1.22474487139158904909 /* sqrt(3/2) */
60
61static av_always_inline int even(uint64_t layout)
62{
63 return (!layout || !!(layout & (layout - 1)));
64}
65
66static int sane_layout(uint64_t layout)
67{
68 /* check that there is at least 1 front speaker */
69 if (!(layout & AV_CH_LAYOUT_SURROUND))
70 return 0;
71
72 /* check for left/right symmetry */
73 if (!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)) ||
74 !even(layout & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)) ||
75 !even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)) ||
76 !even(layout & (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)) ||
77 !even(layout & (AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT)) ||
78 !even(layout & (AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT)) ||
79 !even(layout & (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT)) ||
80 !even(layout & (AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT)) ||
81 !even(layout & (AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT)))
82 return 0;
83
84 return 1;
85}
86
87int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
88 double center_mix_level, double surround_mix_level,
89 double lfe_mix_level, int normalize,
90 double *matrix_out, int stride,
91 enum AVMatrixEncoding matrix_encoding)
92{
93 int i, j, out_i, out_j;
94 double matrix[64][64] = {{0}};
95 int64_t unaccounted;
96 double maxcoef = 0;
97 int in_channels, out_channels;
98
99 if ((out_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == AV_CH_LAYOUT_STEREO_DOWNMIX) {
100 out_layout = AV_CH_LAYOUT_STEREO;
101 }
102
103 unaccounted = in_layout & ~out_layout;
104
105 in_channels = av_get_channel_layout_nb_channels( in_layout);
106 out_channels = av_get_channel_layout_nb_channels(out_layout);
107
108 memset(matrix_out, 0, out_channels * stride * sizeof(*matrix_out));
109
110 /* check if layouts are supported */
111 if (!in_layout || in_channels > AVRESAMPLE_MAX_CHANNELS)
112 return AVERROR(EINVAL);
113 if (!out_layout || out_channels > AVRESAMPLE_MAX_CHANNELS)
114 return AVERROR(EINVAL);
115
116 /* check if layouts are unbalanced or abnormal */
117 if (!sane_layout(in_layout) || !sane_layout(out_layout))
118 return AVERROR_PATCHWELCOME;
119
120 /* route matching input/output channels */
121 for (i = 0; i < 64; i++) {
122 if (in_layout & out_layout & (1ULL << i))
123 matrix[i][i] = 1.0;
124 }
125
126 /* mix front center to front left/right */
127 if (unaccounted & AV_CH_FRONT_CENTER) {
128 if ((out_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO) {
129 if ((in_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO) {
130 matrix[FRONT_LEFT ][FRONT_CENTER] += center_mix_level;
131 matrix[FRONT_RIGHT][FRONT_CENTER] += center_mix_level;
132 } else {
133 matrix[FRONT_LEFT ][FRONT_CENTER] += M_SQRT1_2;
134 matrix[FRONT_RIGHT][FRONT_CENTER] += M_SQRT1_2;
135 }
136 } else
137 return AVERROR_PATCHWELCOME;
138 }
139 /* mix front left/right to center */
140 if (unaccounted & AV_CH_LAYOUT_STEREO) {
141 if (out_layout & AV_CH_FRONT_CENTER) {
142 matrix[FRONT_CENTER][FRONT_LEFT ] += M_SQRT1_2;
143 matrix[FRONT_CENTER][FRONT_RIGHT] += M_SQRT1_2;
144 /* mix left/right/center to center */
145 if (in_layout & AV_CH_FRONT_CENTER)
146 matrix[FRONT_CENTER][FRONT_CENTER] = center_mix_level * M_SQRT2;
147 } else
148 return AVERROR_PATCHWELCOME;
149 }
150 /* mix back center to back, side, or front */
151 if (unaccounted & AV_CH_BACK_CENTER) {
152 if (out_layout & AV_CH_BACK_LEFT) {
153 matrix[BACK_LEFT ][BACK_CENTER] += M_SQRT1_2;
154 matrix[BACK_RIGHT][BACK_CENTER] += M_SQRT1_2;
155 } else if (out_layout & AV_CH_SIDE_LEFT) {
156 matrix[SIDE_LEFT ][BACK_CENTER] += M_SQRT1_2;
157 matrix[SIDE_RIGHT][BACK_CENTER] += M_SQRT1_2;
158 } else if (out_layout & AV_CH_FRONT_LEFT) {
159 if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
160 matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
161 if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
162 matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level * M_SQRT1_2;
163 matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
164 } else {
165 matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level;
166 matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level;
167 }
168 } else {
169 matrix[FRONT_LEFT ][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
170 matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
171 }
172 } else if (out_layout & AV_CH_FRONT_CENTER) {
173 matrix[FRONT_CENTER][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
174 } else
175 return AVERROR_PATCHWELCOME;
176 }
177 /* mix back left/right to back center, side, or front */
178 if (unaccounted & AV_CH_BACK_LEFT) {
179 if (out_layout & AV_CH_BACK_CENTER) {
180 matrix[BACK_CENTER][BACK_LEFT ] += M_SQRT1_2;
181 matrix[BACK_CENTER][BACK_RIGHT] += M_SQRT1_2;
182 } else if (out_layout & AV_CH_SIDE_LEFT) {
183 /* if side channels do not exist in the input, just copy back
184 channels to side channels, otherwise mix back into side */
185 if (in_layout & AV_CH_SIDE_LEFT) {
186 matrix[SIDE_LEFT ][BACK_LEFT ] += M_SQRT1_2;
187 matrix[SIDE_RIGHT][BACK_RIGHT] += M_SQRT1_2;
188 } else {
189 matrix[SIDE_LEFT ][BACK_LEFT ] += 1.0;
190 matrix[SIDE_RIGHT][BACK_RIGHT] += 1.0;
191 }
192 } else if (out_layout & AV_CH_FRONT_LEFT) {
193 if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
194 matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2;
195 matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
196 matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
197 matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
198 } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
199 matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * SQRT3_2;
200 matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
201 matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
202 matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * SQRT3_2;
203 } else {
204 matrix[FRONT_LEFT ][BACK_LEFT ] += surround_mix_level;
205 matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
206 }
207 } else if (out_layout & AV_CH_FRONT_CENTER) {
208 matrix[FRONT_CENTER][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
209 matrix[FRONT_CENTER][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
210 } else
211 return AVERROR_PATCHWELCOME;
212 }
213 /* mix side left/right into back or front */
214 if (unaccounted & AV_CH_SIDE_LEFT) {
215 if (out_layout & AV_CH_BACK_LEFT) {
216 /* if back channels do not exist in the input, just copy side
217 channels to back channels, otherwise mix side into back */
218 if (in_layout & AV_CH_BACK_LEFT) {
219 matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
220 matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
221 } else {
222 matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
223 matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
224 }
225 } else if (out_layout & AV_CH_BACK_CENTER) {
226 matrix[BACK_CENTER][SIDE_LEFT ] += M_SQRT1_2;
227 matrix[BACK_CENTER][SIDE_RIGHT] += M_SQRT1_2;
228 } else if (out_layout & AV_CH_FRONT_LEFT) {
229 if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
230 matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2;
231 matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
232 matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
233 matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
234 } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
235 matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * SQRT3_2;
236 matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
237 matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
238 matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * SQRT3_2;
239 } else {
240 matrix[FRONT_LEFT ][SIDE_LEFT ] += surround_mix_level;
241 matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
242 }
243 } else if (out_layout & AV_CH_FRONT_CENTER) {
244 matrix[FRONT_CENTER][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
245 matrix[FRONT_CENTER][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
246 } else
247 return AVERROR_PATCHWELCOME;
248 }
249 /* mix left-of-center/right-of-center into front left/right or center */
250 if (unaccounted & AV_CH_FRONT_LEFT_OF_CENTER) {
251 if (out_layout & AV_CH_FRONT_LEFT) {
252 matrix[FRONT_LEFT ][FRONT_LEFT_OF_CENTER ] += 1.0;
253 matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER] += 1.0;
254 } else if (out_layout & AV_CH_FRONT_CENTER) {
255 matrix[FRONT_CENTER][FRONT_LEFT_OF_CENTER ] += M_SQRT1_2;
256 matrix[FRONT_CENTER][FRONT_RIGHT_OF_CENTER] += M_SQRT1_2;
257 } else
258 return AVERROR_PATCHWELCOME;
259 }
260 /* mix LFE into front left/right or center */
261 if (unaccounted & AV_CH_LOW_FREQUENCY) {
262 if (out_layout & AV_CH_FRONT_CENTER) {
263 matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level;
264 } else if (out_layout & AV_CH_FRONT_LEFT) {
265 matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
266 matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
267 } else
268 return AVERROR_PATCHWELCOME;
269 }
270
271 /* transfer internal matrix to output matrix and calculate maximum
272 per-channel coefficient sum */
273 for (out_i = i = 0; out_i < out_channels && i < 64; i++) {
274 double sum = 0;
275 for (out_j = j = 0; out_j < in_channels && j < 64; j++) {
276 matrix_out[out_i * stride + out_j] = matrix[i][j];
277 sum += fabs(matrix[i][j]);
278 if (in_layout & (1ULL << j))
279 out_j++;
280 }
281 maxcoef = FFMAX(maxcoef, sum);
282 if (out_layout & (1ULL << i))
283 out_i++;
284 }
285
286 /* normalize */
287 if (normalize && maxcoef > 1.0) {
288 for (i = 0; i < out_channels; i++)
289 for (j = 0; j < in_channels; j++)
290 matrix_out[i * stride + j] /= maxcoef;
291 }
292
293 return 0;
294}
libavresample/avresample.h+0−595
@@ -1,595 +0,0 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifndef AVRESAMPLE_AVRESAMPLE_H
22#define AVRESAMPLE_AVRESAMPLE_H
23
24/**
25 * @file
26 * @ingroup lavr
27 * external API header
28 */
29
30/**
31 * @defgroup lavr libavresample
32 * @{
33 *
34 * Libavresample (lavr) is a library that handles audio resampling, sample
35 * format conversion and mixing.
36 *
37 * Interaction with lavr is done through AVAudioResampleContext, which is
38 * allocated with avresample_alloc_context(). It is opaque, so all parameters
39 * must be set with the @ref avoptions API.
40 *
41 * For example the following code will setup conversion from planar float sample
42 * format to interleaved signed 16-bit integer, downsampling from 48kHz to
43 * 44.1kHz and downmixing from 5.1 channels to stereo (using the default mixing
44 * matrix):
45 * @code
46 * AVAudioResampleContext *avr = avresample_alloc_context();
47 * av_opt_set_int(avr, "in_channel_layout", AV_CH_LAYOUT_5POINT1, 0);
48 * av_opt_set_int(avr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
49 * av_opt_set_int(avr, "in_sample_rate", 48000, 0);
50 * av_opt_set_int(avr, "out_sample_rate", 44100, 0);
51 * av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
52 * av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
53 * @endcode
54 *
55 * Once the context is initialized, it must be opened with avresample_open(). If
56 * you need to change the conversion parameters, you must close the context with
57 * avresample_close(), change the parameters as described above, then reopen it
58 * again.
59 *
60 * The conversion itself is done by repeatedly calling avresample_convert().
61 * Note that the samples may get buffered in two places in lavr. The first one
62 * is the output FIFO, where the samples end up if the output buffer is not
63 * large enough. The data stored in there may be retrieved at any time with
64 * avresample_read(). The second place is the resampling delay buffer,
65 * applicable only when resampling is done. The samples in it require more input
66 * before they can be processed. Their current amount is returned by
67 * avresample_get_delay(). At the end of conversion the resampling buffer can be
68 * flushed by calling avresample_convert() with NULL input.
69 *
70 * The following code demonstrates the conversion loop assuming the parameters
71 * from above and caller-defined functions get_input() and handle_output():
72 * @code
73 * uint8_t **input;
74 * int in_linesize, in_samples;
75 *
76 * while (get_input(&input, &in_linesize, &in_samples)) {
77 * uint8_t *output
78 * int out_linesize;
79 * int out_samples = avresample_get_out_samples(avr, in_samples);
80 *
81 * av_samples_alloc(&output, &out_linesize, 2, out_samples,
82 * AV_SAMPLE_FMT_S16, 0);
83 * out_samples = avresample_convert(avr, &output, out_linesize, out_samples,
84 * input, in_linesize, in_samples);
85 * handle_output(output, out_linesize, out_samples);
86 * av_freep(&output);
87 * }
88 * @endcode
89 *
90 * When the conversion is finished and the FIFOs are flushed if required, the
91 * conversion context and everything associated with it must be freed with
92 * avresample_free().
93 */
94
95#include "libavutil/avutil.h"
96#include "libavutil/channel_layout.h"
97#include "libavutil/dict.h"
98#include "libavutil/frame.h"
99#include "libavutil/log.h"
100#include "libavutil/mathematics.h"
101
102#include "libavresample/version.h"
103
104#define AVRESAMPLE_MAX_CHANNELS 32
105
106typedef struct AVAudioResampleContext AVAudioResampleContext;
107
108/**
109 * @deprecated use libswresample
110 *
111 * Mixing Coefficient Types */
112enum attribute_deprecated AVMixCoeffType {
113 AV_MIX_COEFF_TYPE_Q8, /** 16-bit 8.8 fixed-point */
114 AV_MIX_COEFF_TYPE_Q15, /** 32-bit 17.15 fixed-point */
115 AV_MIX_COEFF_TYPE_FLT, /** floating-point */
116 AV_MIX_COEFF_TYPE_NB, /** Number of coeff types. Not part of ABI */
117};
118
119/**
120 * @deprecated use libswresample
121 *
122 * Resampling Filter Types */
123enum attribute_deprecated AVResampleFilterType {
124 AV_RESAMPLE_FILTER_TYPE_CUBIC, /**< Cubic */
125 AV_RESAMPLE_FILTER_TYPE_BLACKMAN_NUTTALL, /**< Blackman Nuttall Windowed Sinc */
126 AV_RESAMPLE_FILTER_TYPE_KAISER, /**< Kaiser Windowed Sinc */
127};
128
129/**
130 * @deprecated use libswresample
131 */
132enum attribute_deprecated AVResampleDitherMethod {
133 AV_RESAMPLE_DITHER_NONE, /**< Do not use dithering */
134 AV_RESAMPLE_DITHER_RECTANGULAR, /**< Rectangular Dither */
135 AV_RESAMPLE_DITHER_TRIANGULAR, /**< Triangular Dither*/
136 AV_RESAMPLE_DITHER_TRIANGULAR_HP, /**< Triangular Dither with High Pass */
137 AV_RESAMPLE_DITHER_TRIANGULAR_NS, /**< Triangular Dither with Noise Shaping */
138 AV_RESAMPLE_DITHER_NB, /**< Number of dither types. Not part of ABI. */
139};
140
141/**
142 *
143 * @deprecated use libswresample
144 *
145 * Return the LIBAVRESAMPLE_VERSION_INT constant.
146 */
147attribute_deprecated
148unsigned avresample_version(void);
149
150/**
151 *
152 * @deprecated use libswresample
153 *
154 * Return the libavresample build-time configuration.
155 * @return configure string
156 */
157attribute_deprecated
158const char *avresample_configuration(void);
159
160/**
161 *
162 * @deprecated use libswresample
163 *
164 * Return the libavresample license.
165 */
166attribute_deprecated
167const char *avresample_license(void);
168
169/**
170 *
171 * @deprecated use libswresample
172 *
173 * Get the AVClass for AVAudioResampleContext.
174 *
175 * Can be used in combination with AV_OPT_SEARCH_FAKE_OBJ for examining options
176 * without allocating a context.
177 *
178 * @see av_opt_find().
179 *
180 * @return AVClass for AVAudioResampleContext
181 */
182attribute_deprecated
183const AVClass *avresample_get_class(void);
184
185/**
186 *
187 * @deprecated use libswresample
188 *
189 * Allocate AVAudioResampleContext and set options.
190 *
191 * @return allocated audio resample context, or NULL on failure
192 */
193attribute_deprecated
194AVAudioResampleContext *avresample_alloc_context(void);
195
196/**
197 *
198 * @deprecated use libswresample
199 *
200 * Initialize AVAudioResampleContext.
201 * @note The context must be configured using the AVOption API.
202 * @note The fields "in_channel_layout", "out_channel_layout",
203 * "in_sample_rate", "out_sample_rate", "in_sample_fmt",
204 * "out_sample_fmt" must be set.
205 *
206 * @see av_opt_set_int()
207 * @see av_opt_set_dict()
208 * @see av_get_default_channel_layout()
209 *
210 * @param avr audio resample context
211 * @return 0 on success, negative AVERROR code on failure
212 */
213attribute_deprecated
214int avresample_open(AVAudioResampleContext *avr);
215
216/**
217 *
218 * @deprecated use libswresample
219 *
220 * Check whether an AVAudioResampleContext is open or closed.
221 *
222 * @param avr AVAudioResampleContext to check
223 * @return 1 if avr is open, 0 if avr is closed.
224 */
225attribute_deprecated
226int avresample_is_open(AVAudioResampleContext *avr);
227
228/**
229 *
230 * @deprecated use libswresample
231 *
232 * Close AVAudioResampleContext.
233 *
234 * This closes the context, but it does not change the parameters. The context
235 * can be reopened with avresample_open(). It does, however, clear the output
236 * FIFO and any remaining leftover samples in the resampling delay buffer. If
237 * there was a custom matrix being used, that is also cleared.
238 *
239 * @see avresample_convert()
240 * @see avresample_set_matrix()
241 *
242 * @param avr audio resample context
243 */
244attribute_deprecated
245void avresample_close(AVAudioResampleContext *avr);
246
247/**
248 *
249 * @deprecated use libswresample
250 *
251 * Free AVAudioResampleContext and associated AVOption values.
252 *
253 * This also calls avresample_close() before freeing.
254 *
255 * @param avr audio resample context
256 */
257attribute_deprecated
258void avresample_free(AVAudioResampleContext **avr);
259
260/**
261 *
262 * @deprecated use libswresample
263 *
264 * Generate a channel mixing matrix.
265 *
266 * This function is the one used internally by libavresample for building the
267 * default mixing matrix. It is made public just as a utility function for
268 * building custom matrices.
269 *
270 * @param in_layout input channel layout
271 * @param out_layout output channel layout
272 * @param center_mix_level mix level for the center channel
273 * @param surround_mix_level mix level for the surround channel(s)
274 * @param lfe_mix_level mix level for the low-frequency effects channel
275 * @param normalize if 1, coefficients will be normalized to prevent
276 * overflow. if 0, coefficients will not be
277 * normalized.
278 * @param[out] matrix mixing coefficients; matrix[i + stride * o] is
279 * the weight of input channel i in output channel o.
280 * @param stride distance between adjacent input channels in the
281 * matrix array
282 * @param matrix_encoding matrixed stereo downmix mode (e.g. dplii)
283 * @return 0 on success, negative AVERROR code on failure
284 */
285attribute_deprecated
286int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
287 double center_mix_level, double surround_mix_level,
288 double lfe_mix_level, int normalize, double *matrix,
289 int stride, enum AVMatrixEncoding matrix_encoding);
290
291/**
292 *
293 * @deprecated use libswresample
294 *
295 * Get the current channel mixing matrix.
296 *
297 * If no custom matrix has been previously set or the AVAudioResampleContext is
298 * not open, an error is returned.
299 *
300 * @param avr audio resample context
301 * @param matrix mixing coefficients; matrix[i + stride * o] is the weight of
302 * input channel i in output channel o.
303 * @param stride distance between adjacent input channels in the matrix array
304 * @return 0 on success, negative AVERROR code on failure
305 */
306attribute_deprecated
307int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix,
308 int stride);
309
310/**
311 *
312 * @deprecated use libswresample
313 *
314 * Set channel mixing matrix.
315 *
316 * Allows for setting a custom mixing matrix, overriding the default matrix
317 * generated internally during avresample_open(). This function can be called
318 * anytime on an allocated context, either before or after calling
319 * avresample_open(), as long as the channel layouts have been set.
320 * avresample_convert() always uses the current matrix.
321 * Calling avresample_close() on the context will clear the current matrix.
322 *
323 * @see avresample_close()
324 *
325 * @param avr audio resample context
326 * @param matrix mixing coefficients; matrix[i + stride * o] is the weight of
327 * input channel i in output channel o.
328 * @param stride distance between adjacent input channels in the matrix array
329 * @return 0 on success, negative AVERROR code on failure
330 */
331attribute_deprecated
332int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix,
333 int stride);
334
335/**
336 *
337 * @deprecated use libswresample
338 *
339 * Set a customized input channel mapping.
340 *
341 * This function can only be called when the allocated context is not open.
342 * Also, the input channel layout must have already been set.
343 *
344 * Calling avresample_close() on the context will clear the channel mapping.
345 *
346 * The map for each input channel specifies the channel index in the source to
347 * use for that particular channel, or -1 to mute the channel. Source channels
348 * can be duplicated by using the same index for multiple input channels.
349 *
350 * Examples:
351 *
352 * Reordering 5.1 AAC order (C,L,R,Ls,Rs,LFE) to FFmpeg order (L,R,C,LFE,Ls,Rs):
353 * { 1, 2, 0, 5, 3, 4 }
354 *
355 * Muting the 3rd channel in 4-channel input:
356 * { 0, 1, -1, 3 }
357 *
358 * Duplicating the left channel of stereo input:
359 * { 0, 0 }
360 *
361 * @param avr audio resample context
362 * @param channel_map customized input channel mapping
363 * @return 0 on success, negative AVERROR code on failure
364 */
365attribute_deprecated
366int avresample_set_channel_mapping(AVAudioResampleContext *avr,
367 const int *channel_map);
368
369/**
370 *
371 * @deprecated use libswresample
372 *
373 * Set compensation for resampling.
374 *
375 * This can be called anytime after avresample_open(). If resampling is not
376 * automatically enabled because of a sample rate conversion, the
377 * "force_resampling" option must have been set to 1 when opening the context
378 * in order to use resampling compensation.
379 *
380 * @param avr audio resample context
381 * @param sample_delta compensation delta, in samples
382 * @param compensation_distance compensation distance, in samples
383 * @return 0 on success, negative AVERROR code on failure
384 */
385attribute_deprecated
386int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta,
387 int compensation_distance);
388
389/**
390 *
391 * @deprecated use libswresample
392 *
393 * Provide the upper bound on the number of samples the configured
394 * conversion would output.
395 *
396 * @param avr audio resample context
397 * @param in_nb_samples number of input samples
398 *
399 * @return number of samples or AVERROR(EINVAL) if the value
400 * would exceed INT_MAX
401 */
402attribute_deprecated
403int avresample_get_out_samples(AVAudioResampleContext *avr, int in_nb_samples);
404
405/**
406 *
407 * @deprecated use libswresample
408 *
409 * Convert input samples and write them to the output FIFO.
410 *
411 * The upper bound on the number of output samples can be obtained through
412 * avresample_get_out_samples().
413 *
414 * The output data can be NULL or have fewer allocated samples than required.
415 * In this case, any remaining samples not written to the output will be added
416 * to an internal FIFO buffer, to be returned at the next call to this function
417 * or to avresample_read().
418 *
419 * If converting sample rate, there may be data remaining in the internal
420 * resampling delay buffer. avresample_get_delay() tells the number of remaining
421 * samples. To get this data as output, call avresample_convert() with NULL
422 * input.
423 *
424 * At the end of the conversion process, there may be data remaining in the
425 * internal FIFO buffer. avresample_available() tells the number of remaining
426 * samples. To get this data as output, either call avresample_convert() with
427 * NULL input or call avresample_read().
428 *
429 * @see avresample_get_out_samples()
430 * @see avresample_read()
431 * @see avresample_get_delay()
432 *
433 * @param avr audio resample context
434 * @param output output data pointers
435 * @param out_plane_size output plane size, in bytes.
436 * This can be 0 if unknown, but that will lead to
437 * optimized functions not being used directly on the
438 * output, which could slow down some conversions.
439 * @param out_samples maximum number of samples that the output buffer can hold
440 * @param input input data pointers
441 * @param in_plane_size input plane size, in bytes
442 * This can be 0 if unknown, but that will lead to
443 * optimized functions not being used directly on the
444 * input, which could slow down some conversions.
445 * @param in_samples number of input samples to convert
446 * @return number of samples written to the output buffer,
447 * not including converted samples added to the internal
448 * output FIFO
449 */
450attribute_deprecated
451int avresample_convert(AVAudioResampleContext *avr, uint8_t **output,
452 int out_plane_size, int out_samples,
453 uint8_t * const *input, int in_plane_size,
454 int in_samples);
455
456/**
457 *
458 * @deprecated use libswresample
459 *
460 * Return the number of samples currently in the resampling delay buffer.
461 *
462 * When resampling, there may be a delay between the input and output. Any
463 * unconverted samples in each call are stored internally in a delay buffer.
464 * This function allows the user to determine the current number of samples in
465 * the delay buffer, which can be useful for synchronization.
466 *
467 * @see avresample_convert()
468 *
469 * @param avr audio resample context
470 * @return number of samples currently in the resampling delay buffer
471 */
472attribute_deprecated
473int avresample_get_delay(AVAudioResampleContext *avr);
474
475/**
476 *
477 * @deprecated use libswresample
478 *
479 * Return the number of available samples in the output FIFO.
480 *
481 * During conversion, if the user does not specify an output buffer or
482 * specifies an output buffer that is smaller than what is needed, remaining
483 * samples that are not written to the output are stored to an internal FIFO
484 * buffer. The samples in the FIFO can be read with avresample_read() or
485 * avresample_convert().
486 *
487 * @see avresample_read()
488 * @see avresample_convert()
489 *
490 * @param avr audio resample context
491 * @return number of samples available for reading
492 */
493attribute_deprecated
494int avresample_available(AVAudioResampleContext *avr);
495
496/**
497 *
498 * @deprecated use libswresample
499 *
500 * Read samples from the output FIFO.
501 *
502 * During conversion, if the user does not specify an output buffer or
503 * specifies an output buffer that is smaller than what is needed, remaining
504 * samples that are not written to the output are stored to an internal FIFO
505 * buffer. This function can be used to read samples from that internal FIFO.
506 *
507 * @see avresample_available()
508 * @see avresample_convert()
509 *
510 * @param avr audio resample context
511 * @param output output data pointers. May be NULL, in which case
512 * nb_samples of data is discarded from output FIFO.
513 * @param nb_samples number of samples to read from the FIFO
514 * @return the number of samples written to output
515 */
516attribute_deprecated
517int avresample_read(AVAudioResampleContext *avr, uint8_t **output, int nb_samples);
518
519/**
520 *
521 * @deprecated use libswresample
522 *
523 * Convert the samples in the input AVFrame and write them to the output AVFrame.
524 *
525 * Input and output AVFrames must have channel_layout, sample_rate and format set.
526 *
527 * The upper bound on the number of output samples is obtained through
528 * avresample_get_out_samples().
529 *
530 * If the output AVFrame does not have the data pointers allocated the nb_samples
531 * field will be set using avresample_get_out_samples() and av_frame_get_buffer()
532 * is called to allocate the frame.
533 *
534 * The output AVFrame can be NULL or have fewer allocated samples than required.
535 * In this case, any remaining samples not written to the output will be added
536 * to an internal FIFO buffer, to be returned at the next call to this function
537 * or to avresample_convert() or to avresample_read().
538 *
539 * If converting sample rate, there may be data remaining in the internal
540 * resampling delay buffer. avresample_get_delay() tells the number of
541 * remaining samples. To get this data as output, call this function or
542 * avresample_convert() with NULL input.
543 *
544 * At the end of the conversion process, there may be data remaining in the
545 * internal FIFO buffer. avresample_available() tells the number of remaining
546 * samples. To get this data as output, either call this function or
547 * avresample_convert() with NULL input or call avresample_read().
548 *
549 * If the AVAudioResampleContext configuration does not match the output and
550 * input AVFrame settings the conversion does not take place and depending on
551 * which AVFrame is not matching AVERROR_OUTPUT_CHANGED, AVERROR_INPUT_CHANGED
552 * or AVERROR_OUTPUT_CHANGED|AVERROR_INPUT_CHANGED is returned.
553 *
554 * @see avresample_get_out_samples()
555 * @see avresample_available()
556 * @see avresample_convert()
557 * @see avresample_read()
558 * @see avresample_get_delay()
559 *
560 * @param avr audio resample context
561 * @param output output AVFrame
562 * @param input input AVFrame
563 * @return 0 on success, AVERROR on failure or nonmatching
564 * configuration.
565 */
566attribute_deprecated
567int avresample_convert_frame(AVAudioResampleContext *avr,
568 AVFrame *output, AVFrame *input);
569
570/**
571 *
572 * @deprecated use libswresample
573 *
574 * Configure or reconfigure the AVAudioResampleContext using the information
575 * provided by the AVFrames.
576 *
577 * The original resampling context is reset even on failure.
578 * The function calls avresample_close() internally if the context is open.
579 *
580 * @see avresample_open();
581 * @see avresample_close();
582 *
583 * @param avr audio resample context
584 * @param out output AVFrame
585 * @param in input AVFrame
586 * @return 0 on success, AVERROR on failure.
587 */
588attribute_deprecated
589int avresample_config(AVAudioResampleContext *avr, AVFrame *out, AVFrame *in);
590
591/**
592 * @}
593 */
594
595#endif /* AVRESAMPLE_AVRESAMPLE_H */
libavresample/avresampleres.rc+0−55
@@ -1,55 +0,0 @@
1/*
2 * Windows resource file for libavresample
3 *
4 * Copyright (C) 2012 James Almer
5 * Copyright (C) 2013 Tiancheng "Timothy" Gu
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <windows.h>
25#include "libavresample/version.h"
26#include "libavutil/ffversion.h"
27#include "config.h"
28
291 VERSIONINFO
30FILEVERSION LIBAVRESAMPLE_VERSION_MAJOR, LIBAVRESAMPLE_VERSION_MINOR, LIBAVRESAMPLE_VERSION_MICRO, 0
31PRODUCTVERSION LIBAVRESAMPLE_VERSION_MAJOR, LIBAVRESAMPLE_VERSION_MINOR, LIBAVRESAMPLE_VERSION_MICRO, 0
32FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
33FILEOS VOS_NT_WINDOWS32
34FILETYPE VFT_DLL
35{
36 BLOCK "StringFileInfo"
37 {
38 BLOCK "040904B0"
39 {
40 VALUE "CompanyName", "FFmpeg Project"
41 VALUE "FileDescription", "Libav audio resampling library"
42 VALUE "FileVersion", AV_STRINGIFY(LIBAVRESAMPLE_VERSION)
43 VALUE "InternalName", "libavresample"
44 VALUE "LegalCopyright", "Copyright (C) 2000-" AV_STRINGIFY(CONFIG_THIS_YEAR) " FFmpeg Project"
45 VALUE "OriginalFilename", "avresample" BUILDSUF "-" AV_STRINGIFY(LIBAVRESAMPLE_VERSION_MAJOR) SLIBSUF
46 VALUE "ProductName", "FFmpeg"
47 VALUE "ProductVersion", FFMPEG_VERSION
48 }
49 }
50
51 BLOCK "VarFileInfo"
52 {
53 VALUE "Translation", 0x0409, 0x04B0
54 }
55}
libavresample/dither.c+0−440
@@ -1,440 +0,0 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * Triangular with Noise Shaping is based on opusfile.
5 * Copyright (c) 1994-2012 by the Xiph.Org Foundation and contributors
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24/**
25 * @file
26 * Dithered Audio Sample Quantization
27 *
28 * Converts from dbl, flt, or s32 to s16 using dithering.
29 */
30
31#include <math.h>
32#include <stdint.h>
33
34#include "libavutil/attributes.h"
35#include "libavutil/common.h"
36#include "libavutil/lfg.h"
37#include "libavutil/mem.h"
38#include "libavutil/samplefmt.h"
39#include "audio_convert.h"
40#include "dither.h"
41#include "internal.h"
42
43typedef struct DitherState {
44 int mute;
45 unsigned int seed;
46 AVLFG lfg;
47 float *noise_buf;
48 int noise_buf_size;
49 int noise_buf_ptr;
50 float dither_a[4];
51 float dither_b[4];
52} DitherState;
53
54struct DitherContext {
55 DitherDSPContext ddsp;
56 enum AVResampleDitherMethod method;
57 int apply_map;
58 ChannelMapInfo *ch_map_info;
59
60 int mute_dither_threshold; // threshold for disabling dither
61 int mute_reset_threshold; // threshold for resetting noise shaping
62 const float *ns_coef_b; // noise shaping coeffs
63 const float *ns_coef_a; // noise shaping coeffs
64
65 int channels;
66 DitherState *state; // dither states for each channel
67
68 AudioData *flt_data; // input data in fltp
69 AudioData *s16_data; // dithered output in s16p
70 AudioConvert *ac_in; // converter for input to fltp
71 AudioConvert *ac_out; // converter for s16p to s16 (if needed)
72
73 void (*quantize)(int16_t *dst, const float *src, float *dither, int len);
74 int samples_align;
75};
76
77/* mute threshold, in seconds */
78#define MUTE_THRESHOLD_SEC 0.000333
79
80/* scale factor for 16-bit output.
81 The signal is attenuated slightly to avoid clipping */
82#define S16_SCALE 32753.0f
83
84/* scale to convert lfg from INT_MIN/INT_MAX to -0.5/0.5 */
85#define LFG_SCALE (1.0f / (2.0f * INT32_MAX))
86
87/* noise shaping coefficients */
88
89static const float ns_48_coef_b[4] = {
90 2.2374f, -0.7339f, -0.1251f, -0.6033f
91};
92
93static const float ns_48_coef_a[4] = {
94 0.9030f, 0.0116f, -0.5853f, -0.2571f
95};
96
97static const float ns_44_coef_b[4] = {
98 2.2061f, -0.4707f, -0.2534f, -0.6213f
99};
100
101static const float ns_44_coef_a[4] = {
102 1.0587f, 0.0676f, -0.6054f, -0.2738f
103};
104
105static void dither_int_to_float_rectangular_c(float *dst, int *src, int len)
106{
107 int i;
108 for (i = 0; i < len; i++)
109 dst[i] = src[i] * LFG_SCALE;
110}
111
112static void dither_int_to_float_triangular_c(float *dst, int *src0, int len)
113{
114 int i;
115 int *src1 = src0 + len;
116
117 for (i = 0; i < len; i++) {
118 float r = src0[i] * LFG_SCALE;
119 r += src1[i] * LFG_SCALE;
120 dst[i] = r;
121 }
122}
123
124static void quantize_c(int16_t *dst, const float *src, float *dither, int len)
125{
126 int i;
127 for (i = 0; i < len; i++)
128 dst[i] = av_clip_int16(lrintf(src[i] * S16_SCALE + dither[i]));
129}
130
131#define SQRT_1_6 0.40824829046386301723f
132
133static void dither_highpass_filter(float *src, int len)
134{
135 int i;
136
137 /* filter is from libswresample in FFmpeg */
138 for (i = 0; i < len - 2; i++)
139 src[i] = (-src[i] + 2 * src[i + 1] - src[i + 2]) * SQRT_1_6;
140}
141
142static int generate_dither_noise(DitherContext *c, DitherState *state,
143 int min_samples)
144{
145 int i;
146 int nb_samples = FFALIGN(min_samples, 16) + 16;
147 int buf_samples = nb_samples *
148 (c->method == AV_RESAMPLE_DITHER_RECTANGULAR ? 1 : 2);
149 unsigned int *noise_buf_ui;
150
151 av_freep(&state->noise_buf);
152 state->noise_buf_size = state->noise_buf_ptr = 0;
153
154 state->noise_buf = av_malloc(buf_samples * sizeof(*state->noise_buf));
155 if (!state->noise_buf)
156 return AVERROR(ENOMEM);
157 state->noise_buf_size = FFALIGN(min_samples, 16);
158 noise_buf_ui = (unsigned int *)state->noise_buf;
159
160 av_lfg_init(&state->lfg, state->seed);
161 for (i = 0; i < buf_samples; i++)
162 noise_buf_ui[i] = av_lfg_get(&state->lfg);
163
164 c->ddsp.dither_int_to_float(state->noise_buf, noise_buf_ui, nb_samples);
165
166 if (c->method == AV_RESAMPLE_DITHER_TRIANGULAR_HP)
167 dither_highpass_filter(state->noise_buf, nb_samples);
168
169 return 0;
170}
171
172static void quantize_triangular_ns(DitherContext *c, DitherState *state,
173 int16_t *dst, const float *src,
174 int nb_samples)
175{
176 int i, j;
177 float *dither = &state->noise_buf[state->noise_buf_ptr];
178
179 if (state->mute > c->mute_reset_threshold)
180 memset(state->dither_a, 0, sizeof(state->dither_a));
181
182 for (i = 0; i < nb_samples; i++) {
183 float err = 0;
184 float sample = src[i] * S16_SCALE;
185
186 for (j = 0; j < 4; j++) {
187 err += c->ns_coef_b[j] * state->dither_b[j] -
188 c->ns_coef_a[j] * state->dither_a[j];
189 }
190 for (j = 3; j > 0; j--) {
191 state->dither_a[j] = state->dither_a[j - 1];
192 state->dither_b[j] = state->dither_b[j - 1];
193 }
194 state->dither_a[0] = err;
195 sample -= err;
196
197 if (state->mute > c->mute_dither_threshold) {
198 dst[i] = av_clip_int16(lrintf(sample));
199 state->dither_b[0] = 0;
200 } else {
201 dst[i] = av_clip_int16(lrintf(sample + dither[i]));
202 state->dither_b[0] = av_clipf(dst[i] - sample, -1.5f, 1.5f);
203 }
204
205 state->mute++;
206 if (src[i])
207 state->mute = 0;
208 }
209}
210
211static int convert_samples(DitherContext *c, int16_t **dst, float * const *src,
212 int channels, int nb_samples)
213{
214 int ch, ret;
215 int aligned_samples = FFALIGN(nb_samples, 16);
216
217 for (ch = 0; ch < channels; ch++) {
218 DitherState *state = &c->state[ch];
219
220 if (state->noise_buf_size < aligned_samples) {
221 ret = generate_dither_noise(c, state, nb_samples);
222 if (ret < 0)
223 return ret;
224 } else if (state->noise_buf_size - state->noise_buf_ptr < aligned_samples) {
225 state->noise_buf_ptr = 0;
226 }
227
228 if (c->method == AV_RESAMPLE_DITHER_TRIANGULAR_NS) {
229 quantize_triangular_ns(c, state, dst[ch], src[ch], nb_samples);
230 } else {
231 c->quantize(dst[ch], src[ch],
232 &state->noise_buf[state->noise_buf_ptr],
233 FFALIGN(nb_samples, c->samples_align));
234 }
235
236 state->noise_buf_ptr += aligned_samples;
237 }
238
239 return 0;
240}
241
242int ff_convert_dither(DitherContext *c, AudioData *dst, AudioData *src)
243{
244 int ret;
245 AudioData *flt_data;
246
247 /* output directly to dst if it is planar */
248 if (dst->sample_fmt == AV_SAMPLE_FMT_S16P)
249 c->s16_data = dst;
250 else {
251 /* make sure s16_data is large enough for the output */
252 ret = ff_audio_data_realloc(c->s16_data, src->nb_samples);
253 if (ret < 0)
254 return ret;
255 }
256
257 if (src->sample_fmt != AV_SAMPLE_FMT_FLTP || c->apply_map) {
258 /* make sure flt_data is large enough for the input */
259 ret = ff_audio_data_realloc(c->flt_data, src->nb_samples);
260 if (ret < 0)
261 return ret;
262 flt_data = c->flt_data;
263 }
264
265 if (src->sample_fmt != AV_SAMPLE_FMT_FLTP) {
266 /* convert input samples to fltp and scale to s16 range */
267 ret = ff_audio_convert(c->ac_in, flt_data, src);
268 if (ret < 0)
269 return ret;
270 } else if (c->apply_map) {
271 ret = ff_audio_data_copy(flt_data, src, c->ch_map_info);
272 if (ret < 0)
273 return ret;
274 } else {
275 flt_data = src;
276 }
277
278 /* check alignment and padding constraints */
279 if (c->method != AV_RESAMPLE_DITHER_TRIANGULAR_NS) {
280 int ptr_align = FFMIN(flt_data->ptr_align, c->s16_data->ptr_align);
281 int samples_align = FFMIN(flt_data->samples_align, c->s16_data->samples_align);
282 int aligned_len = FFALIGN(src->nb_samples, c->ddsp.samples_align);
283
284 if (!(ptr_align % c->ddsp.ptr_align) && samples_align >= aligned_len) {
285 c->quantize = c->ddsp.quantize;
286 c->samples_align = c->ddsp.samples_align;
287 } else {
288 c->quantize = quantize_c;
289 c->samples_align = 1;
290 }
291 }
292
293 ret = convert_samples(c, (int16_t **)c->s16_data->data,
294 (float * const *)flt_data->data, src->channels,
295 src->nb_samples);
296 if (ret < 0)
297 return ret;
298
299 c->s16_data->nb_samples = src->nb_samples;
300
301 /* interleave output to dst if needed */
302 if (dst->sample_fmt == AV_SAMPLE_FMT_S16) {
303 ret = ff_audio_convert(c->ac_out, dst, c->s16_data);
304 if (ret < 0)
305 return ret;
306 } else
307 c->s16_data = NULL;
308
309 return 0;
310}
311
312void ff_dither_free(DitherContext **cp)
313{
314 DitherContext *c = *cp;
315 int ch;
316
317 if (!c)
318 return;
319 ff_audio_data_free(&c->flt_data);
320 ff_audio_data_free(&c->s16_data);
321 ff_audio_convert_free(&c->ac_in);
322 ff_audio_convert_free(&c->ac_out);
323 for (ch = 0; ch < c->channels; ch++)
324 av_free(c->state[ch].noise_buf);
325 av_free(c->state);
326 av_freep(cp);
327}
328
329static av_cold void dither_init(DitherDSPContext *ddsp,
330 enum AVResampleDitherMethod method)
331{
332 ddsp->quantize = quantize_c;
333 ddsp->ptr_align = 1;
334 ddsp->samples_align = 1;
335
336 if (method == AV_RESAMPLE_DITHER_RECTANGULAR)
337 ddsp->dither_int_to_float = dither_int_to_float_rectangular_c;
338 else
339 ddsp->dither_int_to_float = dither_int_to_float_triangular_c;
340
341 if (ARCH_X86)
342 ff_dither_init_x86(ddsp, method);
343}
344
345DitherContext *ff_dither_alloc(AVAudioResampleContext *avr,
346 enum AVSampleFormat out_fmt,
347 enum AVSampleFormat in_fmt,
348 int channels, int sample_rate, int apply_map)
349{
350 AVLFG seed_gen;
351 DitherContext *c;
352 int ch;
353
354 if (av_get_packed_sample_fmt(out_fmt) != AV_SAMPLE_FMT_S16 ||
355 av_get_bytes_per_sample(in_fmt) <= 2) {
356 av_log(avr, AV_LOG_ERROR, "dithering %s to %s is not supported\n",
357 av_get_sample_fmt_name(in_fmt), av_get_sample_fmt_name(out_fmt));
358 return NULL;
359 }
360
361 c = av_mallocz(sizeof(*c));
362 if (!c)
363 return NULL;
364
365 c->apply_map = apply_map;
366 if (apply_map)
367 c->ch_map_info = &avr->ch_map_info;
368
369 if (avr->dither_method == AV_RESAMPLE_DITHER_TRIANGULAR_NS &&
370 sample_rate != 48000 && sample_rate != 44100) {
371 av_log(avr, AV_LOG_WARNING, "sample rate must be 48000 or 44100 Hz "
372 "for triangular_ns dither. using triangular_hp instead.\n");
373 avr->dither_method = AV_RESAMPLE_DITHER_TRIANGULAR_HP;
374 }
375 c->method = avr->dither_method;
376 dither_init(&c->ddsp, c->method);
377
378 if (c->method == AV_RESAMPLE_DITHER_TRIANGULAR_NS) {
379 if (sample_rate == 48000) {
380 c->ns_coef_b = ns_48_coef_b;
381 c->ns_coef_a = ns_48_coef_a;
382 } else {
383 c->ns_coef_b = ns_44_coef_b;
384 c->ns_coef_a = ns_44_coef_a;
385 }
386 }
387
388 /* Either s16 or s16p output format is allowed, but s16p is used
389 internally, so we need to use a temp buffer and interleave if the output
390 format is s16 */
391 if (out_fmt != AV_SAMPLE_FMT_S16P) {
392 c->s16_data = ff_audio_data_alloc(channels, 1024, AV_SAMPLE_FMT_S16P,
393 "dither s16 buffer");
394 if (!c->s16_data)
395 goto fail;
396
397 c->ac_out = ff_audio_convert_alloc(avr, out_fmt, AV_SAMPLE_FMT_S16P,
398 channels, sample_rate, 0);
399 if (!c->ac_out)
400 goto fail;
401 }
402
403 if (in_fmt != AV_SAMPLE_FMT_FLTP || c->apply_map) {
404 c->flt_data = ff_audio_data_alloc(channels, 1024, AV_SAMPLE_FMT_FLTP,
405 "dither flt buffer");
406 if (!c->flt_data)
407 goto fail;
408 }
409 if (in_fmt != AV_SAMPLE_FMT_FLTP) {
410 c->ac_in = ff_audio_convert_alloc(avr, AV_SAMPLE_FMT_FLTP, in_fmt,
411 channels, sample_rate, c->apply_map);
412 if (!c->ac_in)
413 goto fail;
414 }
415
416 c->state = av_mallocz(channels * sizeof(*c->state));
417 if (!c->state)
418 goto fail;
419 c->channels = channels;
420
421 /* calculate thresholds for turning off dithering during periods of
422 silence to avoid replacing digital silence with quiet dither noise */
423 c->mute_dither_threshold = lrintf(sample_rate * MUTE_THRESHOLD_SEC);
424 c->mute_reset_threshold = c->mute_dither_threshold * 4;
425
426 /* initialize dither states */
427 av_lfg_init(&seed_gen, 0xC0FFEE);
428 for (ch = 0; ch < channels; ch++) {
429 DitherState *state = &c->state[ch];
430 state->mute = c->mute_reset_threshold + 1;
431 state->seed = av_lfg_get(&seed_gen);
432 generate_dither_noise(c, state, FFMAX(32768, sample_rate / 2));
433 }
434
435 return c;
436
437fail:
438 ff_dither_free(&c);
439 return NULL;
440}
libavresample/dither.h+0−93
@@ -1,93 +0,0 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifndef AVRESAMPLE_DITHER_H
22#define AVRESAMPLE_DITHER_H
23
24#include "avresample.h"
25#include "audio_data.h"
26
27typedef struct DitherContext DitherContext;
28
29typedef struct DitherDSPContext {
30 /**
31 * Convert samples from flt to s16 with added dither noise.
32 *
33 * @param dst destination float array, range -0.5 to 0.5
34 * @param src source int array, range INT_MIN to INT_MAX.
35 * @param dither float dither noise array
36 * @param len number of samples
37 */
38 void (*quantize)(int16_t *dst, const float *src, float *dither, int len);
39
40 int ptr_align; ///< src and dst constraints for quantize()
41 int samples_align; ///< len constraints for quantize()
42
43 /**
44 * Convert dither noise from int to float with triangular distribution.
45 *
46 * @param dst destination float array, range -0.5 to 0.5
47 * constraints: 32-byte aligned
48 * @param src0 source int array, range INT_MIN to INT_MAX.
49 * the array size is len * 2
50 * constraints: 32-byte aligned
51 * @param len number of output noise samples
52 * constraints: multiple of 16
53 */
54 void (*dither_int_to_float)(float *dst, int *src0, int len);
55} DitherDSPContext;
56
57/**
58 * Allocate and initialize a DitherContext.
59 *
60 * The parameters in the AVAudioResampleContext are used to initialize the
61 * DitherContext.
62 *
63 * @param avr AVAudioResampleContext
64 * @return newly-allocated DitherContext
65 */
66DitherContext *ff_dither_alloc(AVAudioResampleContext *avr,
67 enum AVSampleFormat out_fmt,
68 enum AVSampleFormat in_fmt,
69 int channels, int sample_rate, int apply_map);
70
71/**
72 * Free a DitherContext.
73 *
74 * @param c DitherContext
75 */
76void ff_dither_free(DitherContext **c);
77
78/**
79 * Convert audio sample format with dithering.
80 *
81 * @param c DitherContext
82 * @param dst destination audio data
83 * @param src source audio data
84 * @return 0 if ok, negative AVERROR code on failure
85 */
86int ff_convert_dither(DitherContext *c, AudioData *dst, AudioData *src);
87
88/* arch-specific initialization functions */
89
90void ff_dither_init_x86(DitherDSPContext *ddsp,
91 enum AVResampleDitherMethod method);
92
93#endif /* AVRESAMPLE_DITHER_H */
libavresample/internal.h+0−116
@@ -1,116 +0,0 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifndef AVRESAMPLE_INTERNAL_H
22#define AVRESAMPLE_INTERNAL_H
23
24#include "libavutil/audio_fifo.h"
25#include "libavutil/log.h"
26#include "libavutil/opt.h"
27#include "libavutil/samplefmt.h"
28#include "avresample.h"
29
30typedef struct AudioData AudioData;
31typedef struct AudioConvert AudioConvert;
32typedef struct AudioMix AudioMix;
33typedef struct ResampleContext ResampleContext;
34
35enum RemapPoint {
36 REMAP_NONE,
37 REMAP_IN_COPY,
38 REMAP_IN_CONVERT,
39 REMAP_OUT_COPY,
40 REMAP_OUT_CONVERT,
41};
42
43typedef struct ChannelMapInfo {
44 int channel_map[AVRESAMPLE_MAX_CHANNELS]; /**< source index of each output channel, -1 if not remapped */
45 int do_remap; /**< remap needed */
46 int channel_copy[AVRESAMPLE_MAX_CHANNELS]; /**< dest index to copy from */
47 int do_copy; /**< copy needed */
48 int channel_zero[AVRESAMPLE_MAX_CHANNELS]; /**< dest index to zero */
49 int do_zero; /**< zeroing needed */
50 int input_map[AVRESAMPLE_MAX_CHANNELS]; /**< dest index of each input channel */
51} ChannelMapInfo;
52
53struct AVAudioResampleContext {
54 const AVClass *av_class; /**< AVClass for logging and AVOptions */
55
56 uint64_t in_channel_layout; /**< input channel layout */
57 enum AVSampleFormat in_sample_fmt; /**< input sample format */
58 int in_sample_rate; /**< input sample rate */
59 uint64_t out_channel_layout; /**< output channel layout */
60 enum AVSampleFormat out_sample_fmt; /**< output sample format */
61 int out_sample_rate; /**< output sample rate */
62 enum AVSampleFormat internal_sample_fmt; /**< internal sample format */
63 enum AVMixCoeffType mix_coeff_type; /**< mixing coefficient type */
64 double center_mix_level; /**< center mix level */
65 double surround_mix_level; /**< surround mix level */
66 double lfe_mix_level; /**< lfe mix level */
67 int normalize_mix_level; /**< enable mix level normalization */
68 int force_resampling; /**< force resampling */
69 int filter_size; /**< length of each FIR filter in the resampling filterbank relative to the cutoff frequency */
70 int phase_shift; /**< log2 of the number of entries in the resampling polyphase filterbank */
71 int linear_interp; /**< if 1 then the resampling FIR filter will be linearly interpolated */
72 double cutoff; /**< resampling cutoff frequency. 1.0 corresponds to half the output sample rate */
73 enum AVResampleFilterType filter_type; /**< resampling filter type */
74 int kaiser_beta; /**< beta value for Kaiser window (only applicable if filter_type == AV_FILTER_TYPE_KAISER) */
75 enum AVResampleDitherMethod dither_method; /**< dither method */
76
77 int in_channels; /**< number of input channels */
78 int out_channels; /**< number of output channels */
79 int resample_channels; /**< number of channels used for resampling */
80 int downmix_needed; /**< downmixing is needed */
81 int upmix_needed; /**< upmixing is needed */
82 int mixing_needed; /**< either upmixing or downmixing is needed */
83 int resample_needed; /**< resampling is needed */
84 int in_convert_needed; /**< input sample format conversion is needed */
85 int out_convert_needed; /**< output sample format conversion is needed */
86 int in_copy_needed; /**< input data copy is needed */
87
88 AudioData *in_buffer; /**< buffer for converted input */
89 AudioData *resample_out_buffer; /**< buffer for output from resampler */
90 AudioData *out_buffer; /**< buffer for converted output */
91 AVAudioFifo *out_fifo; /**< FIFO for output samples */
92
93 AudioConvert *ac_in; /**< input sample format conversion context */
94 AudioConvert *ac_out; /**< output sample format conversion context */
95 ResampleContext *resample; /**< resampling context */
96 AudioMix *am; /**< channel mixing context */
97 enum AVMatrixEncoding matrix_encoding; /**< matrixed stereo encoding */
98
99 /**
100 * mix matrix
101 * only used if avresample_set_matrix() is called before avresample_open()
102 */
103 double *mix_matrix;
104
105 int use_channel_map;
106 enum RemapPoint remap_point;
107 ChannelMapInfo ch_map_info;
108};
109
110
111void ff_audio_resample_init_aarch64(ResampleContext *c,
112 enum AVSampleFormat sample_fmt);
113void ff_audio_resample_init_arm(ResampleContext *c,
114 enum AVSampleFormat sample_fmt);
115
116#endif /* AVRESAMPLE_INTERNAL_H */
libavresample/libavresample.v+0−6
@@ -1,6 +0,0 @@
1LIBAVRESAMPLE_MAJOR {
2 global:
3 av*;
4 local:
5 *;
6};
libavresample/options.c+0−113
@@ -1,113 +0,0 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <stdint.h>
22
23#include "libavutil/mathematics.h"
24#include "libavutil/mem.h"
25#include "libavutil/opt.h"
26#include "avresample.h"
27#include "internal.h"
28#include "audio_mix.h"
29
30/**
31 * @file
32 * Options definition for AVAudioResampleContext.
33 */
34
35#define OFFSET(x) offsetof(AVAudioResampleContext, x)
36#define PARAM AV_OPT_FLAG_AUDIO_PARAM
37
38static const AVOption avresample_options[] = {
39 { "in_channel_layout", "Input Channel Layout", OFFSET(in_channel_layout), AV_OPT_TYPE_INT64, { .i64 = 0 }, INT64_MIN, INT64_MAX, PARAM },
40 { "in_sample_fmt", "Input Sample Format", OFFSET(in_sample_fmt), AV_OPT_TYPE_INT, { .i64 = AV_SAMPLE_FMT_S16 }, AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NB-1, PARAM },
41 { "in_sample_rate", "Input Sample Rate", OFFSET(in_sample_rate), AV_OPT_TYPE_INT, { .i64 = 48000 }, 1, INT_MAX, PARAM },
42 { "out_channel_layout", "Output Channel Layout", OFFSET(out_channel_layout), AV_OPT_TYPE_INT64, { .i64 = 0 }, INT64_MIN, INT64_MAX, PARAM },
43 { "out_sample_fmt", "Output Sample Format", OFFSET(out_sample_fmt), AV_OPT_TYPE_INT, { .i64 = AV_SAMPLE_FMT_S16 }, AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NB-1, PARAM },
44 { "out_sample_rate", "Output Sample Rate", OFFSET(out_sample_rate), AV_OPT_TYPE_INT, { .i64 = 48000 }, 1, INT_MAX, PARAM },
45 { "internal_sample_fmt", "Internal Sample Format", OFFSET(internal_sample_fmt), AV_OPT_TYPE_INT, { .i64 = AV_SAMPLE_FMT_NONE }, AV_SAMPLE_FMT_NONE, AV_SAMPLE_FMT_NB-1, PARAM, "internal_sample_fmt" },
46 {"u8" , "8-bit unsigned integer", 0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_U8 }, INT_MIN, INT_MAX, PARAM, "internal_sample_fmt"},
47 {"s16", "16-bit signed integer", 0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_S16 }, INT_MIN, INT_MAX, PARAM, "internal_sample_fmt"},
48 {"s32", "32-bit signed integer", 0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_S32 }, INT_MIN, INT_MAX, PARAM, "internal_sample_fmt"},
49 {"flt", "32-bit float", 0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_FLT }, INT_MIN, INT_MAX, PARAM, "internal_sample_fmt"},
50 {"dbl", "64-bit double", 0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_DBL }, INT_MIN, INT_MAX, PARAM, "internal_sample_fmt"},
51 {"u8p" , "8-bit unsigned integer planar", 0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_U8P }, INT_MIN, INT_MAX, PARAM, "internal_sample_fmt"},
52 {"s16p", "16-bit signed integer planar", 0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_S16P }, INT_MIN, INT_MAX, PARAM, "internal_sample_fmt"},
53 {"s32p", "32-bit signed integer planar", 0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_S32P }, INT_MIN, INT_MAX, PARAM, "internal_sample_fmt"},
54 {"fltp", "32-bit float planar", 0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_FLTP }, INT_MIN, INT_MAX, PARAM, "internal_sample_fmt"},
55 {"dblp", "64-bit double planar", 0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_DBLP }, INT_MIN, INT_MAX, PARAM, "internal_sample_fmt"},
56 { "mix_coeff_type", "Mixing Coefficient Type", OFFSET(mix_coeff_type), AV_OPT_TYPE_INT, { .i64 = AV_MIX_COEFF_TYPE_FLT }, AV_MIX_COEFF_TYPE_Q8, AV_MIX_COEFF_TYPE_NB-1, PARAM, "mix_coeff_type" },
57 { "q8", "16-bit 8.8 Fixed-Point", 0, AV_OPT_TYPE_CONST, { .i64 = AV_MIX_COEFF_TYPE_Q8 }, INT_MIN, INT_MAX, PARAM, "mix_coeff_type" },
58 { "q15", "32-bit 17.15 Fixed-Point", 0, AV_OPT_TYPE_CONST, { .i64 = AV_MIX_COEFF_TYPE_Q15 }, INT_MIN, INT_MAX, PARAM, "mix_coeff_type" },
59 { "flt", "Floating-Point", 0, AV_OPT_TYPE_CONST, { .i64 = AV_MIX_COEFF_TYPE_FLT }, INT_MIN, INT_MAX, PARAM, "mix_coeff_type" },
60 { "center_mix_level", "Center Mix Level", OFFSET(center_mix_level), AV_OPT_TYPE_DOUBLE, { .dbl = M_SQRT1_2 }, -32.0, 32.0, PARAM },
61 { "surround_mix_level", "Surround Mix Level", OFFSET(surround_mix_level), AV_OPT_TYPE_DOUBLE, { .dbl = M_SQRT1_2 }, -32.0, 32.0, PARAM },
62 { "lfe_mix_level", "LFE Mix Level", OFFSET(lfe_mix_level), AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, -32.0, 32.0, PARAM },
63 { "normalize_mix_level", "Normalize Mix Level", OFFSET(normalize_mix_level), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, PARAM },
64 { "force_resampling", "Force Resampling", OFFSET(force_resampling), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, PARAM },
65 { "filter_size", "Resampling Filter Size", OFFSET(filter_size), AV_OPT_TYPE_INT, { .i64 = 16 }, 0, 32, /* ??? */ PARAM },
66 { "phase_shift", "Resampling Phase Shift", OFFSET(phase_shift), AV_OPT_TYPE_INT, { .i64 = 10 }, 0, 30, /* ??? */ PARAM },
67 { "linear_interp", "Use Linear Interpolation", OFFSET(linear_interp), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, PARAM },
68 { "cutoff", "Cutoff Frequency Ratio", OFFSET(cutoff), AV_OPT_TYPE_DOUBLE, { .dbl = 0.8 }, 0.0, 1.0, PARAM },
69 /* duplicate option in order to work with avconv */
70 { "resample_cutoff", "Cutoff Frequency Ratio", OFFSET(cutoff), AV_OPT_TYPE_DOUBLE, { .dbl = 0.8 }, 0.0, 1.0, PARAM },
71 { "matrix_encoding", "Matrixed Stereo Encoding", OFFSET(matrix_encoding), AV_OPT_TYPE_INT, {.i64 = AV_MATRIX_ENCODING_NONE}, AV_MATRIX_ENCODING_NONE, AV_MATRIX_ENCODING_NB-1, PARAM, "matrix_encoding" },
72 { "none", "None", 0, AV_OPT_TYPE_CONST, { .i64 = AV_MATRIX_ENCODING_NONE }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" },
73 { "dolby", "Dolby", 0, AV_OPT_TYPE_CONST, { .i64 = AV_MATRIX_ENCODING_DOLBY }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" },
74 { "dplii", "Dolby Pro Logic II", 0, AV_OPT_TYPE_CONST, { .i64 = AV_MATRIX_ENCODING_DPLII }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" },
75 { "filter_type", "Filter Type", OFFSET(filter_type), AV_OPT_TYPE_INT, { .i64 = AV_RESAMPLE_FILTER_TYPE_KAISER }, AV_RESAMPLE_FILTER_TYPE_CUBIC, AV_RESAMPLE_FILTER_TYPE_KAISER, PARAM, "filter_type" },
76 { "cubic", "Cubic", 0, AV_OPT_TYPE_CONST, { .i64 = AV_RESAMPLE_FILTER_TYPE_CUBIC }, INT_MIN, INT_MAX, PARAM, "filter_type" },
77 { "blackman_nuttall", "Blackman Nuttall Windowed Sinc", 0, AV_OPT_TYPE_CONST, { .i64 = AV_RESAMPLE_FILTER_TYPE_BLACKMAN_NUTTALL }, INT_MIN, INT_MAX, PARAM, "filter_type" },
78 { "kaiser", "Kaiser Windowed Sinc", 0, AV_OPT_TYPE_CONST, { .i64 = AV_RESAMPLE_FILTER_TYPE_KAISER }, INT_MIN, INT_MAX, PARAM, "filter_type" },
79 { "kaiser_beta", "Kaiser Window Beta", OFFSET(kaiser_beta), AV_OPT_TYPE_INT, { .i64 = 9 }, 2, 16, PARAM },
80 { "dither_method", "Dither Method", OFFSET(dither_method), AV_OPT_TYPE_INT, { .i64 = AV_RESAMPLE_DITHER_NONE }, 0, AV_RESAMPLE_DITHER_NB-1, PARAM, "dither_method"},
81 {"none", "No Dithering", 0, AV_OPT_TYPE_CONST, { .i64 = AV_RESAMPLE_DITHER_NONE }, INT_MIN, INT_MAX, PARAM, "dither_method"},
82 {"rectangular", "Rectangular Dither", 0, AV_OPT_TYPE_CONST, { .i64 = AV_RESAMPLE_DITHER_RECTANGULAR }, INT_MIN, INT_MAX, PARAM, "dither_method"},
83 {"triangular", "Triangular Dither", 0, AV_OPT_TYPE_CONST, { .i64 = AV_RESAMPLE_DITHER_TRIANGULAR }, INT_MIN, INT_MAX, PARAM, "dither_method"},
84 {"triangular_hp", "Triangular Dither With High Pass", 0, AV_OPT_TYPE_CONST, { .i64 = AV_RESAMPLE_DITHER_TRIANGULAR_HP }, INT_MIN, INT_MAX, PARAM, "dither_method"},
85 {"triangular_ns", "Triangular Dither With Noise Shaping", 0, AV_OPT_TYPE_CONST, { .i64 = AV_RESAMPLE_DITHER_TRIANGULAR_NS }, INT_MIN, INT_MAX, PARAM, "dither_method"},
86 { NULL },
87};
88
89static const AVClass av_resample_context_class = {
90 .class_name = "AVAudioResampleContext",
91 .item_name = av_default_item_name,
92 .option = avresample_options,
93 .version = LIBAVUTIL_VERSION_INT,
94};
95
96AVAudioResampleContext *avresample_alloc_context(void)
97{
98 AVAudioResampleContext *avr;
99
100 avr = av_mallocz(sizeof(*avr));
101 if (!avr)
102 return NULL;
103
104 avr->av_class = &av_resample_context_class;
105 av_opt_set_defaults(avr);
106
107 return avr;
108}
109
110const AVClass *avresample_get_class(void)
111{
112 return &av_resample_context_class;
113}
libavresample/resample.c+0−446
@@ -1,446 +0,0 @@
1/*
2 * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
3 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "libavutil/common.h"
23#include "libavutil/libm.h"
24#include "libavutil/log.h"
25#include "internal.h"
26#include "resample.h"
27#include "audio_data.h"
28
29
30/* double template */
31#define CONFIG_RESAMPLE_DBL
32#include "resample_template.c"
33#undef CONFIG_RESAMPLE_DBL
34
35/* float template */
36#define CONFIG_RESAMPLE_FLT
37#include "resample_template.c"
38#undef CONFIG_RESAMPLE_FLT
39
40/* s32 template */
41#define CONFIG_RESAMPLE_S32
42#include "resample_template.c"
43#undef CONFIG_RESAMPLE_S32
44
45/* s16 template */
46#include "resample_template.c"
47
48
49/* 0th order modified Bessel function of the first kind. */
50static double bessel(double x)
51{
52 double v = 1;
53 double lastv = 0;
54 double t = 1;
55 int i;
56
57 x = x * x / 4;
58 for (i = 1; v != lastv; i++) {
59 lastv = v;
60 t *= x / (i * i);
61 v += t;
62 }
63 return v;
64}
65
66/* Build a polyphase filterbank. */
67static int build_filter(ResampleContext *c, double factor)
68{
69 int ph, i;
70 double x, y, w;
71 double *tab;
72 int tap_count = c->filter_length;
73 int phase_count = 1 << c->phase_shift;
74 const int center = (tap_count - 1) / 2;
75
76 tab = av_malloc(tap_count * sizeof(*tab));
77 if (!tab)
78 return AVERROR(ENOMEM);
79
80 for (ph = 0; ph < phase_count; ph++) {
81 double norm = 0;
82 for (i = 0; i < tap_count; i++) {
83 x = M_PI * ((double)(i - center) - (double)ph / phase_count) * factor;
84 if (x == 0) y = 1.0;
85 else y = sin(x) / x;
86 switch (c->filter_type) {
87 case AV_RESAMPLE_FILTER_TYPE_CUBIC: {
88 const float d = -0.5; //first order derivative = -0.5
89 x = fabs(((double)(i - center) - (double)ph / phase_count) * factor);
90 if (x < 1.0) y = 1 - 3 * x*x + 2 * x*x*x + d * ( -x*x + x*x*x);
91 else y = d * (-4 + 8 * x - 5 * x*x + x*x*x);
92 break;
93 }
94 case AV_RESAMPLE_FILTER_TYPE_BLACKMAN_NUTTALL:
95 w = 2.0 * x / (factor * tap_count) + M_PI;
96 y *= 0.3635819 - 0.4891775 * cos( w) +
97 0.1365995 * cos(2 * w) -
98 0.0106411 * cos(3 * w);
99 break;
100 case AV_RESAMPLE_FILTER_TYPE_KAISER:
101 w = 2.0 * x / (factor * tap_count * M_PI);
102 y *= bessel(c->kaiser_beta * sqrt(FFMAX(1 - w * w, 0)));
103 break;
104 }
105
106 tab[i] = y;
107 norm += y;
108 }
109 /* normalize so that an uniform color remains the same */
110 for (i = 0; i < tap_count; i++)
111 tab[i] = tab[i] / norm;
112
113 c->set_filter(c->filter_bank, tab, ph, tap_count);
114 }
115
116 av_free(tab);
117 return 0;
118}
119
120ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr)
121{
122 ResampleContext *c;
123 int out_rate = avr->out_sample_rate;
124 int in_rate = avr->in_sample_rate;
125 double factor = FFMIN(out_rate * avr->cutoff / in_rate, 1.0);
126 int phase_count = 1 << avr->phase_shift;
127 int felem_size;
128
129 if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P &&
130 avr->internal_sample_fmt != AV_SAMPLE_FMT_S32P &&
131 avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP &&
132 avr->internal_sample_fmt != AV_SAMPLE_FMT_DBLP) {
133 av_log(avr, AV_LOG_ERROR, "Unsupported internal format for "
134 "resampling: %s\n",
135 av_get_sample_fmt_name(avr->internal_sample_fmt));
136 return NULL;
137 }
138 c = av_mallocz(sizeof(*c));
139 if (!c)
140 return NULL;
141
142 c->avr = avr;
143 c->phase_shift = avr->phase_shift;
144 c->phase_mask = phase_count - 1;
145 c->linear = avr->linear_interp;
146 c->filter_length = FFMAX((int)ceil(avr->filter_size / factor), 1);
147 c->filter_type = avr->filter_type;
148 c->kaiser_beta = avr->kaiser_beta;
149
150 switch (avr->internal_sample_fmt) {
151 case AV_SAMPLE_FMT_DBLP:
152 c->resample_one = c->linear ? resample_linear_dbl : resample_one_dbl;
153 c->resample_nearest = resample_nearest_dbl;
154 c->set_filter = set_filter_dbl;
155 break;
156 case AV_SAMPLE_FMT_FLTP:
157 c->resample_one = c->linear ? resample_linear_flt : resample_one_flt;
158 c->resample_nearest = resample_nearest_flt;
159 c->set_filter = set_filter_flt;
160 break;
161 case AV_SAMPLE_FMT_S32P:
162 c->resample_one = c->linear ? resample_linear_s32 : resample_one_s32;
163 c->resample_nearest = resample_nearest_s32;
164 c->set_filter = set_filter_s32;
165 break;
166 case AV_SAMPLE_FMT_S16P:
167 c->resample_one = c->linear ? resample_linear_s16 : resample_one_s16;
168 c->resample_nearest = resample_nearest_s16;
169 c->set_filter = set_filter_s16;
170 break;
171 }
172
173 if (ARCH_AARCH64)
174 ff_audio_resample_init_aarch64(c, avr->internal_sample_fmt);
175 if (ARCH_ARM)
176 ff_audio_resample_init_arm(c, avr->internal_sample_fmt);
177
178 felem_size = av_get_bytes_per_sample(avr->internal_sample_fmt);
179 c->filter_bank = av_mallocz(c->filter_length * (phase_count + 1) * felem_size);
180 if (!c->filter_bank)
181 goto error;
182
183 if (build_filter(c, factor) < 0)
184 goto error;
185
186 memcpy(&c->filter_bank[(c->filter_length * phase_count + 1) * felem_size],
187 c->filter_bank, (c->filter_length - 1) * felem_size);
188 memcpy(&c->filter_bank[c->filter_length * phase_count * felem_size],
189 &c->filter_bank[(c->filter_length - 1) * felem_size], felem_size);
190
191 c->compensation_distance = 0;
192 if (!av_reduce(&c->src_incr, &c->dst_incr, out_rate,
193 in_rate * (int64_t)phase_count, INT32_MAX / 2))
194 goto error;
195 c->ideal_dst_incr = c->dst_incr;
196
197 c->padding_size = (c->filter_length - 1) / 2;
198 c->initial_padding_filled = 0;
199 c->index = 0;
200 c->frac = 0;
201
202 /* allocate internal buffer */
203 c->buffer = ff_audio_data_alloc(avr->resample_channels, c->padding_size,
204 avr->internal_sample_fmt,
205 "resample buffer");
206 if (!c->buffer)
207 goto error;
208 c->buffer->nb_samples = c->padding_size;
209 c->initial_padding_samples = c->padding_size;
210
211 av_log(avr, AV_LOG_DEBUG, "resample: %s from %d Hz to %d Hz\n",
212 av_get_sample_fmt_name(avr->internal_sample_fmt),
213 avr->in_sample_rate, avr->out_sample_rate);
214
215 return c;
216
217error:
218 ff_audio_data_free(&c->buffer);
219 av_free(c->filter_bank);
220 av_free(c);
221 return NULL;
222}
223
224void ff_audio_resample_free(ResampleContext **c)
225{
226 if (!*c)
227 return;
228 ff_audio_data_free(&(*c)->buffer);
229 av_free((*c)->filter_bank);
230 av_freep(c);
231}
232
233int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta,
234 int compensation_distance)
235{
236 ResampleContext *c;
237
238 if (compensation_distance < 0)
239 return AVERROR(EINVAL);
240 if (!compensation_distance && sample_delta)
241 return AVERROR(EINVAL);
242
243 if (!avr->resample_needed) {
244 av_log(avr, AV_LOG_ERROR, "Unable to set resampling compensation\n");
245 return AVERROR(EINVAL);
246 }
247 c = avr->resample;
248 c->compensation_distance = compensation_distance;
249 if (compensation_distance) {
250 c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr *
251 (int64_t)sample_delta / compensation_distance;
252 } else {
253 c->dst_incr = c->ideal_dst_incr;
254 }
255
256 return 0;
257}
258
259static int resample(ResampleContext *c, void *dst, const void *src,
260 int *consumed, int src_size, int dst_size, int update_ctx,
261 int nearest_neighbour)
262{
263 int dst_index;
264 unsigned int index = c->index;
265 int frac = c->frac;
266 int dst_incr_frac = c->dst_incr % c->src_incr;
267 int dst_incr = c->dst_incr / c->src_incr;
268 int compensation_distance = c->compensation_distance;
269
270 if (!dst != !src)
271 return AVERROR(EINVAL);
272
273 if (nearest_neighbour) {
274 uint64_t index2 = ((uint64_t)index) << 32;
275 int64_t incr = (1LL << 32) * c->dst_incr / c->src_incr;
276 dst_size = FFMIN(dst_size,
277 (src_size-1-index) * (int64_t)c->src_incr /
278 c->dst_incr);
279
280 if (dst) {
281 for(dst_index = 0; dst_index < dst_size; dst_index++) {
282 c->resample_nearest(dst, dst_index, src, index2 >> 32);
283 index2 += incr;
284 }
285 } else {
286 dst_index = dst_size;
287 }
288 index += dst_index * dst_incr;
289 index += (frac + dst_index * (int64_t)dst_incr_frac) / c->src_incr;
290 frac = (frac + dst_index * (int64_t)dst_incr_frac) % c->src_incr;
291 } else {
292 for (dst_index = 0; dst_index < dst_size; dst_index++) {
293 int sample_index = index >> c->phase_shift;
294
295 if (sample_index + c->filter_length > src_size)
296 break;
297
298 if (dst)
299 c->resample_one(c, dst, dst_index, src, index, frac);
300
301 frac += dst_incr_frac;
302 index += dst_incr;
303 if (frac >= c->src_incr) {
304 frac -= c->src_incr;
305 index++;
306 }
307 if (dst_index + 1 == compensation_distance) {
308 compensation_distance = 0;
309 dst_incr_frac = c->ideal_dst_incr % c->src_incr;
310 dst_incr = c->ideal_dst_incr / c->src_incr;
311 }
312 }
313 }
314 if (consumed)
315 *consumed = index >> c->phase_shift;
316
317 if (update_ctx) {
318 index &= c->phase_mask;
319
320 if (compensation_distance) {
321 compensation_distance -= dst_index;
322 if (compensation_distance <= 0)
323 return AVERROR_BUG;
324 }
325 c->frac = frac;
326 c->index = index;
327 c->dst_incr = dst_incr_frac + c->src_incr*dst_incr;
328 c->compensation_distance = compensation_distance;
329 }
330
331 return dst_index;
332}
333
334int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src)
335{
336 int ch, in_samples, in_leftover, consumed = 0, out_samples = 0;
337 int ret = AVERROR(EINVAL);
338 int nearest_neighbour = (c->compensation_distance == 0 &&
339 c->filter_length == 1 &&
340 c->phase_shift == 0);
341
342 in_samples = src ? src->nb_samples : 0;
343 in_leftover = c->buffer->nb_samples;
344
345 /* add input samples to the internal buffer */
346 if (src) {
347 ret = ff_audio_data_combine(c->buffer, in_leftover, src, 0, in_samples);
348 if (ret < 0)
349 return ret;
350 } else if (in_leftover <= c->final_padding_samples) {
351 /* no remaining samples to flush */
352 return 0;
353 }
354
355 if (!c->initial_padding_filled) {
356 int bps = av_get_bytes_per_sample(c->avr->internal_sample_fmt);
357 int i;
358
359 if (src && c->buffer->nb_samples < 2 * c->padding_size)
360 return 0;
361
362 for (i = 0; i < c->padding_size; i++)
363 for (ch = 0; ch < c->buffer->channels; ch++) {
364 if (c->buffer->nb_samples > 2 * c->padding_size - i) {
365 memcpy(c->buffer->data[ch] + bps * i,
366 c->buffer->data[ch] + bps * (2 * c->padding_size - i), bps);
367 } else {
368 memset(c->buffer->data[ch] + bps * i, 0, bps);
369 }
370 }
371 c->initial_padding_filled = 1;
372 }
373
374 if (!src && !c->final_padding_filled) {
375 int bps = av_get_bytes_per_sample(c->avr->internal_sample_fmt);
376 int i;
377
378 ret = ff_audio_data_realloc(c->buffer,
379 FFMAX(in_samples, in_leftover) +
380 c->padding_size);
381 if (ret < 0) {
382 av_log(c->avr, AV_LOG_ERROR, "Error reallocating resampling buffer\n");
383 return AVERROR(ENOMEM);
384 }
385
386 for (i = 0; i < c->padding_size; i++)
387 for (ch = 0; ch < c->buffer->channels; ch++) {
388 if (in_leftover > i) {
389 memcpy(c->buffer->data[ch] + bps * (in_leftover + i),
390 c->buffer->data[ch] + bps * (in_leftover - i - 1),
391 bps);
392 } else {
393 memset(c->buffer->data[ch] + bps * (in_leftover + i),
394 0, bps);
395 }
396 }
397 c->buffer->nb_samples += c->padding_size;
398 c->final_padding_samples = c->padding_size;
399 c->final_padding_filled = 1;
400 }
401
402
403 /* calculate output size and reallocate output buffer if needed */
404 /* TODO: try to calculate this without the dummy resample() run */
405 if (!dst->read_only && dst->allow_realloc) {
406 out_samples = resample(c, NULL, NULL, NULL, c->buffer->nb_samples,
407 INT_MAX, 0, nearest_neighbour);
408 ret = ff_audio_data_realloc(dst, out_samples);
409 if (ret < 0) {
410 av_log(c->avr, AV_LOG_ERROR, "error reallocating output\n");
411 return ret;
412 }
413 }
414
415 /* resample each channel plane */
416 for (ch = 0; ch < c->buffer->channels; ch++) {
417 out_samples = resample(c, (void *)dst->data[ch],
418 (const void *)c->buffer->data[ch], &consumed,
419 c->buffer->nb_samples, dst->allocated_samples,
420 ch + 1 == c->buffer->channels, nearest_neighbour);
421 }
422 if (out_samples < 0) {
423 av_log(c->avr, AV_LOG_ERROR, "error during resampling\n");
424 return out_samples;
425 }
426
427 /* drain consumed samples from the internal buffer */
428 ff_audio_data_drain(c->buffer, consumed);
429 c->initial_padding_samples = FFMAX(c->initial_padding_samples - consumed, 0);
430
431 av_log(c->avr, AV_LOG_TRACE, "resampled %d in + %d leftover to %d out + %d leftover\n",
432 in_samples, in_leftover, out_samples, c->buffer->nb_samples);
433
434 dst->nb_samples = out_samples;
435 return 0;
436}
437
438int avresample_get_delay(AVAudioResampleContext *avr)
439{
440 ResampleContext *c = avr->resample;
441
442 if (!avr->resample_needed || !avr->resample)
443 return 0;
444
445 return FFMAX(c->buffer->nb_samples - c->padding_size, 0);
446}
libavresample/resample.h+0−96
@@ -1,96 +0,0 @@
1/*
2 * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifndef AVRESAMPLE_RESAMPLE_H
22#define AVRESAMPLE_RESAMPLE_H
23
24#include "avresample.h"
25#include "internal.h"
26#include "audio_data.h"
27
28struct ResampleContext {
29 AVAudioResampleContext *avr;
30 AudioData *buffer;
31 uint8_t *filter_bank;
32 int filter_length;
33 int ideal_dst_incr;
34 int dst_incr;
35 unsigned int index;
36 int frac;
37 int src_incr;
38 int compensation_distance;
39 int phase_shift;
40 int phase_mask;
41 int linear;
42 enum AVResampleFilterType filter_type;
43 int kaiser_beta;
44 void (*set_filter)(void *filter, double *tab, int phase, int tap_count);
45 void (*resample_one)(struct ResampleContext *c, void *dst0,
46 int dst_index, const void *src0,
47 unsigned int index, int frac);
48 void (*resample_nearest)(void *dst0, int dst_index,
49 const void *src0, unsigned int index);
50 int padding_size;
51 int initial_padding_filled;
52 int initial_padding_samples;
53 int final_padding_filled;
54 int final_padding_samples;
55};
56
57/**
58 * Allocate and initialize a ResampleContext.
59 *
60 * The parameters in the AVAudioResampleContext are used to initialize the
61 * ResampleContext.
62 *
63 * @param avr AVAudioResampleContext
64 * @return newly-allocated ResampleContext
65 */
66ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr);
67
68/**
69 * Free a ResampleContext.
70 *
71 * @param c ResampleContext
72 */
73void ff_audio_resample_free(ResampleContext **c);
74
75/**
76 * Resample audio data.
77 *
78 * Changes the sample rate.
79 *
80 * @par
81 * All samples in the source data may not be consumed depending on the
82 * resampling parameters and the size of the output buffer. The unconsumed
83 * samples are automatically added to the start of the source in the next call.
84 * If the destination data can be reallocated, that may be done in this function
85 * in order to fit all available output. If it cannot be reallocated, fewer
86 * input samples will be consumed in order to have the output fit in the
87 * destination data buffers.
88 *
89 * @param c ResampleContext
90 * @param dst destination audio data
91 * @param src source audio data
92 * @return 0 on success, negative AVERROR code on failure
93 */
94int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src);
95
96#endif /* AVRESAMPLE_RESAMPLE_H */
libavresample/resample_template.c+0−118
@@ -1,118 +0,0 @@
1/*
2 * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <math.h>
22#include <stdint.h>
23
24#include "libavutil/common.h"
25#include "internal.h"
26
27#if defined(CONFIG_RESAMPLE_DBL)
28#define SET_TYPE(func) func ## _dbl
29#define FELEM double
30#define FELEM2 double
31#define FELEML double
32#define OUT(d, v) d = v
33#define DBL_TO_FELEM(d, v) d = v
34#elif defined(CONFIG_RESAMPLE_FLT)
35#define SET_TYPE(func) func ## _flt
36#define FELEM float
37#define FELEM2 float
38#define FELEML float
39#define OUT(d, v) d = v
40#define DBL_TO_FELEM(d, v) d = v
41#elif defined(CONFIG_RESAMPLE_S32)
42#define SET_TYPE(func) func ## _s32
43#define FELEM int32_t
44#define FELEM2 int64_t
45#define FELEML int64_t
46#define OUT(d, v) d = av_clipl_int32((v + (1 << 29)) >> 30)
47#define DBL_TO_FELEM(d, v) d = av_clipl_int32(llrint(v * (1 << 30)));
48#else
49#define SET_TYPE(func) func ## _s16
50#define FELEM int16_t
51#define FELEM2 int32_t
52#define FELEML int64_t
53#define OUT(d, v) d = av_clip_int16((v + (1 << 14)) >> 15)
54#define DBL_TO_FELEM(d, v) d = av_clip_int16(lrint(v * (1 << 15)))
55#endif
56
57static void SET_TYPE(resample_nearest)(void *dst0, int dst_index, const void *src0, unsigned int index)
58{
59 FELEM *dst = dst0;
60 const FELEM *src = src0;
61 dst[dst_index] = src[index];
62}
63
64static void SET_TYPE(resample_linear)(ResampleContext *c, void *dst0, int dst_index,
65 const void *src0, unsigned int index, int frac)
66{
67 FELEM *dst = dst0;
68 const FELEM *src = src0;
69 int i;
70 unsigned int sample_index = index >> c->phase_shift;
71 FELEM2 val = 0;
72 FELEM *filter = ((FELEM *)c->filter_bank) +
73 c->filter_length * (index & c->phase_mask);
74 FELEM2 v2 = 0;
75
76 for (i = 0; i < c->filter_length; i++) {
77 val += src[sample_index + i] * (FELEM2)filter[i];
78 v2 += src[sample_index + i] * (FELEM2)filter[i + c->filter_length];
79 }
80 val += (v2 - val) * (FELEML)frac / c->src_incr;
81
82 OUT(dst[dst_index], val);
83}
84
85static void SET_TYPE(resample_one)(ResampleContext *c,
86 void *dst0, int dst_index, const void *src0,
87 unsigned int index, int frac)
88{
89 FELEM *dst = dst0;
90 const FELEM *src = src0;
91 int i;
92 unsigned int sample_index = index >> c->phase_shift;
93 FELEM2 val = 0;
94 FELEM *filter = ((FELEM *)c->filter_bank) +
95 c->filter_length * (index & c->phase_mask);
96
97 for (i = 0; i < c->filter_length; i++)
98 val += src[sample_index + i] * (FELEM2)filter[i];
99
100 OUT(dst[dst_index], val);
101}
102
103static void SET_TYPE(set_filter)(void *filter0, double *tab, int phase,
104 int tap_count)
105{
106 int i;
107 FELEM *filter = ((FELEM *)filter0) + phase * tap_count;
108 for (i = 0; i < tap_count; i++) {
109 DBL_TO_FELEM(filter[i], tab[i]);
110 }
111}
112
113#undef SET_TYPE
114#undef FELEM
115#undef FELEM2
116#undef FELEML
117#undef OUT
118#undef DBL_TO_FELEM
libavresample/tests/.gitignore+0−1
@@ -1 +0,0 @@
1/avresample
libavresample/tests/avresample.c+0−342
@@ -1,342 +0,0 @@
1/*
2 * Copyright (c) 2002 Fabrice Bellard
3 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <stdint.h>
23#include <stdio.h>
24
25#include "libavutil/avstring.h"
26#include "libavutil/common.h"
27#include "libavutil/lfg.h"
28#include "libavutil/libm.h"
29#include "libavutil/log.h"
30#include "libavutil/mem.h"
31#include "libavutil/opt.h"
32#include "libavutil/samplefmt.h"
33
34#include "libavresample/avresample.h"
35
36static double dbl_rand(AVLFG *lfg)
37{
38 return 2.0 * (av_lfg_get(lfg) / (double)UINT_MAX) - 1.0;
39}
40
41#define PUT_FUNC(name, fmt, type, expr) \
42static void put_sample_ ## name(void **data, enum AVSampleFormat sample_fmt,\
43 int channels, int sample, int ch, \
44 double v_dbl) \
45{ \
46 type v = expr; \
47 type **out = (type **)data; \
48 if (av_sample_fmt_is_planar(sample_fmt)) \
49 out[ch][sample] = v; \
50 else \
51 out[0][sample * channels + ch] = v; \
52}
53
54PUT_FUNC(u8, AV_SAMPLE_FMT_U8, uint8_t, av_clip_uint8 ( lrint(v_dbl * (1 << 7)) + 128))
55PUT_FUNC(s16, AV_SAMPLE_FMT_S16, int16_t, av_clip_int16 ( lrint(v_dbl * (1 << 15))))
56PUT_FUNC(s32, AV_SAMPLE_FMT_S32, int32_t, av_clipl_int32(llrint(v_dbl * (1U << 31))))
57PUT_FUNC(flt, AV_SAMPLE_FMT_FLT, float, v_dbl)
58PUT_FUNC(dbl, AV_SAMPLE_FMT_DBL, double, v_dbl)
59
60static void put_sample(void **data, enum AVSampleFormat sample_fmt,
61 int channels, int sample, int ch, double v_dbl)
62{
63 switch (av_get_packed_sample_fmt(sample_fmt)) {
64 case AV_SAMPLE_FMT_U8:
65 put_sample_u8(data, sample_fmt, channels, sample, ch, v_dbl);
66 break;
67 case AV_SAMPLE_FMT_S16:
68 put_sample_s16(data, sample_fmt, channels, sample, ch, v_dbl);
69 break;
70 case AV_SAMPLE_FMT_S32:
71 put_sample_s32(data, sample_fmt, channels, sample, ch, v_dbl);
72 break;
73 case AV_SAMPLE_FMT_FLT:
74 put_sample_flt(data, sample_fmt, channels, sample, ch, v_dbl);
75 break;
76 case AV_SAMPLE_FMT_DBL:
77 put_sample_dbl(data, sample_fmt, channels, sample, ch, v_dbl);
78 break;
79 }
80}
81
82static void audiogen(AVLFG *rnd, void **data, enum AVSampleFormat sample_fmt,
83 int channels, int sample_rate, int nb_samples)
84{
85 int i, ch, k;
86 double v, f, a, ampa;
87 double tabf1[AVRESAMPLE_MAX_CHANNELS];
88 double tabf2[AVRESAMPLE_MAX_CHANNELS];
89 double taba[AVRESAMPLE_MAX_CHANNELS];
90
91#define PUT_SAMPLE put_sample(data, sample_fmt, channels, k, ch, v);
92
93 k = 0;
94
95 /* 1 second of single freq sine at 1000 Hz */
96 a = 0;
97 for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
98 v = sin(a) * 0.30;
99 for (ch = 0; ch < channels; ch++)
100 PUT_SAMPLE
101 a += M_PI * 1000.0 * 2.0 / sample_rate;
102 }
103
104 /* 1 second of varying frequency between 100 and 10000 Hz */
105 a = 0;
106 for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
107 v = sin(a) * 0.30;
108 for (ch = 0; ch < channels; ch++)
109 PUT_SAMPLE
110 f = 100.0 + (((10000.0 - 100.0) * i) / sample_rate);
111 a += M_PI * f * 2.0 / sample_rate;
112 }
113
114 /* 0.5 second of low amplitude white noise */
115 for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
116 v = dbl_rand(rnd) * 0.30;
117 for (ch = 0; ch < channels; ch++)
118 PUT_SAMPLE
119 }
120
121 /* 0.5 second of high amplitude white noise */
122 for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
123 v = dbl_rand(rnd);
124 for (ch = 0; ch < channels; ch++)
125 PUT_SAMPLE
126 }
127
128 /* 1 second of unrelated ramps for each channel */
129 for (ch = 0; ch < channels; ch++) {
130 taba[ch] = 0;
131 tabf1[ch] = 100 + av_lfg_get(rnd) % 5000;
132 tabf2[ch] = 100 + av_lfg_get(rnd) % 5000;
133 }
134 for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
135 for (ch = 0; ch < channels; ch++) {
136 v = sin(taba[ch]) * 0.30;
137 PUT_SAMPLE
138 f = tabf1[ch] + (((tabf2[ch] - tabf1[ch]) * i) / sample_rate);
139 taba[ch] += M_PI * f * 2.0 / sample_rate;
140 }
141 }
142
143 /* 2 seconds of 500 Hz with varying volume */
144 a = 0;
145 ampa = 0;
146 for (i = 0; i < 2 * sample_rate && k < nb_samples; i++, k++) {
147 for (ch = 0; ch < channels; ch++) {
148 double amp = (1.0 + sin(ampa)) * 0.15;
149 if (ch & 1)
150 amp = 0.30 - amp;
151 v = sin(a) * amp;
152 PUT_SAMPLE
153 a += M_PI * 500.0 * 2.0 / sample_rate;
154 ampa += M_PI * 2.0 / sample_rate;
155 }
156 }
157}
158
159/* formats, rates, and layouts are ordered for priority in testing.
160 e.g. 'avresample-test 4 2 2' will test all input/output combinations of
161 S16/FLTP/S16P/FLT, 48000/44100, and stereo/mono */
162
163static const enum AVSampleFormat formats[] = {
164 AV_SAMPLE_FMT_S16,
165 AV_SAMPLE_FMT_FLTP,
166 AV_SAMPLE_FMT_S16P,
167 AV_SAMPLE_FMT_FLT,
168 AV_SAMPLE_FMT_S32P,
169 AV_SAMPLE_FMT_S32,
170 AV_SAMPLE_FMT_U8P,
171 AV_SAMPLE_FMT_U8,
172 AV_SAMPLE_FMT_DBLP,
173 AV_SAMPLE_FMT_DBL,
174};
175
176static const int rates[] = {
177 48000,
178 44100,
179 16000
180};
181
182static const uint64_t layouts[] = {
183 AV_CH_LAYOUT_STEREO,
184 AV_CH_LAYOUT_MONO,
185 AV_CH_LAYOUT_5POINT1,
186 AV_CH_LAYOUT_7POINT1,
187};
188
189int main(int argc, char **argv)
190{
191 AVAudioResampleContext *s;
192 AVLFG rnd;
193 int ret = 0;
194 uint8_t *in_buf = NULL;
195 uint8_t *out_buf = NULL;
196 unsigned int in_buf_size;
197 unsigned int out_buf_size;
198 uint8_t *in_data[AVRESAMPLE_MAX_CHANNELS] = { 0 };
199 uint8_t *out_data[AVRESAMPLE_MAX_CHANNELS] = { 0 };
200 int in_linesize;
201 int out_linesize;
202 uint64_t in_ch_layout;
203 int in_channels;
204 enum AVSampleFormat in_fmt;
205 int in_rate;
206 uint64_t out_ch_layout;
207 int out_channels;
208 enum AVSampleFormat out_fmt;
209 int out_rate;
210 int num_formats, num_rates, num_layouts;
211 int i, j, k, l, m, n;
212
213 num_formats = 2;
214 num_rates = 2;
215 num_layouts = 2;
216 if (argc > 1) {
217 if (!av_strncasecmp(argv[1], "-h", 3)) {
218 av_log(NULL, AV_LOG_INFO, "Usage: avresample-test [<num formats> "
219 "[<num sample rates> [<num channel layouts>]]]\n"
220 "Default is 2 2 2\n");
221 return 0;
222 }
223 num_formats = strtol(argv[1], NULL, 0);
224 num_formats = av_clip(num_formats, 1, FF_ARRAY_ELEMS(formats));
225 }
226 if (argc > 2) {
227 num_rates = strtol(argv[2], NULL, 0);
228 num_rates = av_clip(num_rates, 1, FF_ARRAY_ELEMS(rates));
229 }
230 if (argc > 3) {
231 num_layouts = strtol(argv[3], NULL, 0);
232 num_layouts = av_clip(num_layouts, 1, FF_ARRAY_ELEMS(layouts));
233 }
234
235 av_log_set_level(AV_LOG_DEBUG);
236
237 av_lfg_init(&rnd, 0xC0FFEE);
238
239 in_buf_size = av_samples_get_buffer_size(&in_linesize, 8, 48000 * 6,
240 AV_SAMPLE_FMT_DBLP, 0);
241 out_buf_size = in_buf_size;
242
243 in_buf = av_malloc(in_buf_size);
244 if (!in_buf)
245 goto end;
246 out_buf = av_malloc(out_buf_size);
247 if (!out_buf)
248 goto end;
249
250 s = avresample_alloc_context();
251 if (!s) {
252 av_log(NULL, AV_LOG_ERROR, "Error allocating AVAudioResampleContext\n");
253 ret = 1;
254 goto end;
255 }
256
257 for (i = 0; i < num_formats; i++) {
258 in_fmt = formats[i];
259 for (k = 0; k < num_layouts; k++) {
260 in_ch_layout = layouts[k];
261 in_channels = av_get_channel_layout_nb_channels(in_ch_layout);
262 for (m = 0; m < num_rates; m++) {
263 in_rate = rates[m];
264
265 ret = av_samples_fill_arrays(in_data, &in_linesize, in_buf,
266 in_channels, in_rate * 6,
267 in_fmt, 0);
268 if (ret < 0) {
269 av_log(s, AV_LOG_ERROR, "failed in_data fill arrays\n");
270 goto end;
271 }
272 audiogen(&rnd, (void **)in_data, in_fmt, in_channels, in_rate, in_rate * 6);
273
274 for (j = 0; j < num_formats; j++) {
275 out_fmt = formats[j];
276 for (l = 0; l < num_layouts; l++) {
277 out_ch_layout = layouts[l];
278 out_channels = av_get_channel_layout_nb_channels(out_ch_layout);
279 for (n = 0; n < num_rates; n++) {
280 out_rate = rates[n];
281
282 av_log(NULL, AV_LOG_INFO, "%s to %s, %d to %d channels, %d Hz to %d Hz\n",
283 av_get_sample_fmt_name(in_fmt), av_get_sample_fmt_name(out_fmt),
284 in_channels, out_channels, in_rate, out_rate);
285
286 ret = av_samples_fill_arrays(out_data, &out_linesize,
287 out_buf, out_channels,
288 out_rate * 6, out_fmt, 0);
289 if (ret < 0) {
290 av_log(s, AV_LOG_ERROR, "failed out_data fill arrays\n");
291 goto end;
292 }
293
294 av_opt_set_int(s, "in_channel_layout", in_ch_layout, 0);
295 av_opt_set_int(s, "in_sample_fmt", in_fmt, 0);
296 av_opt_set_int(s, "in_sample_rate", in_rate, 0);
297 av_opt_set_int(s, "out_channel_layout", out_ch_layout, 0);
298 av_opt_set_int(s, "out_sample_fmt", out_fmt, 0);
299 av_opt_set_int(s, "out_sample_rate", out_rate, 0);
300
301 av_opt_set_int(s, "internal_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
302
303 ret = avresample_open(s);
304 if (ret < 0) {
305 av_log(s, AV_LOG_ERROR, "Error opening context\n");
306 goto end;
307 }
308
309 ret = avresample_convert(s, out_data, out_linesize, out_rate * 6,
310 in_data, in_linesize, in_rate * 6);
311 if (ret < 0) {
312 char errbuf[256];
313 av_strerror(ret, errbuf, sizeof(errbuf));
314 av_log(NULL, AV_LOG_ERROR, "%s\n", errbuf);
315 goto end;
316 }
317 av_log(NULL, AV_LOG_INFO, "Converted %d samples to %d samples\n",
318 in_rate * 6, ret);
319 if (avresample_get_delay(s) > 0)
320 av_log(NULL, AV_LOG_INFO, "%d delay samples not converted\n",
321 avresample_get_delay(s));
322 if (avresample_available(s) > 0)
323 av_log(NULL, AV_LOG_INFO, "%d samples available for output\n",
324 avresample_available(s));
325 av_log(NULL, AV_LOG_INFO, "\n");
326
327 avresample_close(s);
328 }
329 }
330 }
331 }
332 }
333 }
334
335 ret = 0;
336
337end:
338 av_freep(&in_buf);
339 av_freep(&out_buf);
340 avresample_free(&s);
341 return ret;
342}
libavresample/utils.c+0−793
@@ -1,793 +0,0 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "libavutil/common.h"
22#include "libavutil/dict.h"
23// #include "libavutil/error.h"
24#include "libavutil/frame.h"
25#include "libavutil/log.h"
26#include "libavutil/mem.h"
27#include "libavutil/opt.h"
28
29#include "avresample.h"
30#include "internal.h"
31#include "audio_data.h"
32#include "audio_convert.h"
33#include "audio_mix.h"
34#include "resample.h"
35
36int avresample_open(AVAudioResampleContext *avr)
37{
38 int ret;
39
40 if (avresample_is_open(avr)) {
41 av_log(avr, AV_LOG_ERROR, "The resampling context is already open.\n");
42 return AVERROR(EINVAL);
43 }
44
45 /* set channel mixing parameters */
46 avr->in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
47 if (avr->in_channels <= 0 || avr->in_channels > AVRESAMPLE_MAX_CHANNELS) {
48 av_log(avr, AV_LOG_ERROR, "Invalid input channel layout: %"PRIu64"\n",
49 avr->in_channel_layout);
50 return AVERROR(EINVAL);
51 }
52 avr->out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
53 if (avr->out_channels <= 0 || avr->out_channels > AVRESAMPLE_MAX_CHANNELS) {
54 av_log(avr, AV_LOG_ERROR, "Invalid output channel layout: %"PRIu64"\n",
55 avr->out_channel_layout);
56 return AVERROR(EINVAL);
57 }
58 avr->resample_channels = FFMIN(avr->in_channels, avr->out_channels);
59 avr->downmix_needed = avr->in_channels > avr->out_channels;
60 avr->upmix_needed = avr->out_channels > avr->in_channels ||
61 (!avr->downmix_needed && (avr->mix_matrix ||
62 avr->in_channel_layout != avr->out_channel_layout));
63 avr->mixing_needed = avr->downmix_needed || avr->upmix_needed;
64
65 /* set resampling parameters */
66 avr->resample_needed = avr->in_sample_rate != avr->out_sample_rate ||
67 avr->force_resampling;
68
69 /* select internal sample format if not specified by the user */
70 if (avr->internal_sample_fmt == AV_SAMPLE_FMT_NONE &&
71 (avr->mixing_needed || avr->resample_needed)) {
72 enum AVSampleFormat in_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt);
73 enum AVSampleFormat out_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);
74 int max_bps = FFMAX(av_get_bytes_per_sample(in_fmt),
75 av_get_bytes_per_sample(out_fmt));
76 if (max_bps <= 2) {
77 avr->internal_sample_fmt = AV_SAMPLE_FMT_S16P;
78 } else if (avr->mixing_needed) {
79 avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP;
80 } else {
81 if (max_bps <= 4) {
82 if (in_fmt == AV_SAMPLE_FMT_S32P ||
83 out_fmt == AV_SAMPLE_FMT_S32P) {
84 if (in_fmt == AV_SAMPLE_FMT_FLTP ||
85 out_fmt == AV_SAMPLE_FMT_FLTP) {
86 /* if one is s32 and the other is flt, use dbl */
87 avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP;
88 } else {
89 /* if one is s32 and the other is s32, s16, or u8, use s32 */
90 avr->internal_sample_fmt = AV_SAMPLE_FMT_S32P;
91 }
92 } else {
93 /* if one is flt and the other is flt, s16 or u8, use flt */
94 avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP;
95 }
96 } else {
97 /* if either is dbl, use dbl */
98 avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP;
99 }
100 }
101 av_log(avr, AV_LOG_DEBUG, "Using %s as internal sample format\n",
102 av_get_sample_fmt_name(avr->internal_sample_fmt));
103 }
104
105 /* we may need to add an extra conversion in order to remap channels if
106 the output format is not planar */
107 if (avr->use_channel_map && !avr->mixing_needed && !avr->resample_needed &&
108 !ff_sample_fmt_is_planar(avr->out_sample_fmt, avr->out_channels)) {
109 avr->internal_sample_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);
110 }
111
112 /* set sample format conversion parameters */
113 if (avr->resample_needed || avr->mixing_needed)
114 avr->in_convert_needed = avr->in_sample_fmt != avr->internal_sample_fmt;
115 else
116 avr->in_convert_needed = avr->use_channel_map &&
117 !ff_sample_fmt_is_planar(avr->out_sample_fmt, avr->out_channels);
118
119 if (avr->resample_needed || avr->mixing_needed || avr->in_convert_needed)
120 avr->out_convert_needed = avr->internal_sample_fmt != avr->out_sample_fmt;
121 else
122 avr->out_convert_needed = avr->in_sample_fmt != avr->out_sample_fmt;
123
124 avr->in_copy_needed = !avr->in_convert_needed && (avr->mixing_needed ||
125 (avr->use_channel_map && avr->resample_needed));
126
127 if (avr->use_channel_map) {
128 if (avr->in_copy_needed) {
129 avr->remap_point = REMAP_IN_COPY;
130 av_log(avr, AV_LOG_TRACE, "remap channels during in_copy\n");
131 } else if (avr->in_convert_needed) {
132 avr->remap_point = REMAP_IN_CONVERT;
133 av_log(avr, AV_LOG_TRACE, "remap channels during in_convert\n");
134 } else if (avr->out_convert_needed) {
135 avr->remap_point = REMAP_OUT_CONVERT;
136 av_log(avr, AV_LOG_TRACE, "remap channels during out_convert\n");
137 } else {
138 avr->remap_point = REMAP_OUT_COPY;
139 av_log(avr, AV_LOG_TRACE, "remap channels during out_copy\n");
140 }
141
142#ifdef DEBUG
143 {
144 int ch;
145 av_log(avr, AV_LOG_TRACE, "output map: ");
146 if (avr->ch_map_info.do_remap)
147 for (ch = 0; ch < avr->in_channels; ch++)
148 av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.channel_map[ch]);
149 else
150 av_log(avr, AV_LOG_TRACE, "n/a");
151 av_log(avr, AV_LOG_TRACE, "\n");
152 av_log(avr, AV_LOG_TRACE, "copy map: ");
153 if (avr->ch_map_info.do_copy)
154 for (ch = 0; ch < avr->in_channels; ch++)
155 av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.channel_copy[ch]);
156 else
157 av_log(avr, AV_LOG_TRACE, "n/a");
158 av_log(avr, AV_LOG_TRACE, "\n");
159 av_log(avr, AV_LOG_TRACE, "zero map: ");
160 if (avr->ch_map_info.do_zero)
161 for (ch = 0; ch < avr->in_channels; ch++)
162 av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.channel_zero[ch]);
163 else
164 av_log(avr, AV_LOG_TRACE, "n/a");
165 av_log(avr, AV_LOG_TRACE, "\n");
166 av_log(avr, AV_LOG_TRACE, "input map: ");
167 for (ch = 0; ch < avr->in_channels; ch++)
168 av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.input_map[ch]);
169 av_log(avr, AV_LOG_TRACE, "\n");
170 }
171#endif
172 } else
173 avr->remap_point = REMAP_NONE;
174
175 /* allocate buffers */
176 if (avr->in_copy_needed || avr->in_convert_needed) {
177 avr->in_buffer = ff_audio_data_alloc(FFMAX(avr->in_channels, avr->out_channels),
178 0, avr->internal_sample_fmt,
179 "in_buffer");
180 if (!avr->in_buffer) {
181 ret = AVERROR(EINVAL);
182 goto error;
183 }
184 }
185 if (avr->resample_needed) {
186 avr->resample_out_buffer = ff_audio_data_alloc(avr->out_channels,
187 1024, avr->internal_sample_fmt,
188 "resample_out_buffer");
189 if (!avr->resample_out_buffer) {
190 ret = AVERROR(EINVAL);
191 goto error;
192 }
193 }
194 if (avr->out_convert_needed) {
195 avr->out_buffer = ff_audio_data_alloc(avr->out_channels, 0,
196 avr->out_sample_fmt, "out_buffer");
197 if (!avr->out_buffer) {
198 ret = AVERROR(EINVAL);
199 goto error;
200 }
201 }
202 avr->out_fifo = av_audio_fifo_alloc(avr->out_sample_fmt, avr->out_channels,
203 1024);
204 if (!avr->out_fifo) {
205 ret = AVERROR(ENOMEM);
206 goto error;
207 }
208
209 /* setup contexts */
210 if (avr->in_convert_needed) {
211 avr->ac_in = ff_audio_convert_alloc(avr, avr->internal_sample_fmt,
212 avr->in_sample_fmt, avr->in_channels,
213 avr->in_sample_rate,
214 avr->remap_point == REMAP_IN_CONVERT);
215 if (!avr->ac_in) {
216 ret = AVERROR(ENOMEM);
217 goto error;
218 }
219 }
220 if (avr->out_convert_needed) {
221 enum AVSampleFormat src_fmt;
222 if (avr->in_convert_needed)
223 src_fmt = avr->internal_sample_fmt;
224 else
225 src_fmt = avr->in_sample_fmt;
226 avr->ac_out = ff_audio_convert_alloc(avr, avr->out_sample_fmt, src_fmt,
227 avr->out_channels,
228 avr->out_sample_rate,
229 avr->remap_point == REMAP_OUT_CONVERT);
230 if (!avr->ac_out) {
231 ret = AVERROR(ENOMEM);
232 goto error;
233 }
234 }
235 if (avr->resample_needed) {
236 avr->resample = ff_audio_resample_init(avr);
237 if (!avr->resample) {
238 ret = AVERROR(ENOMEM);
239 goto error;
240 }
241 }
242 if (avr->mixing_needed) {
243 avr->am = ff_audio_mix_alloc(avr);
244 if (!avr->am) {
245 ret = AVERROR(ENOMEM);
246 goto error;
247 }
248 }
249
250 return 0;
251
252error:
253 avresample_close(avr);
254 return ret;
255}
256
257int avresample_is_open(AVAudioResampleContext *avr)
258{
259 return !!avr->out_fifo;
260}
261
262void avresample_close(AVAudioResampleContext *avr)
263{
264 ff_audio_data_free(&avr->in_buffer);
265 ff_audio_data_free(&avr->resample_out_buffer);
266 ff_audio_data_free(&avr->out_buffer);
267 av_audio_fifo_free(avr->out_fifo);
268 avr->out_fifo = NULL;
269 ff_audio_convert_free(&avr->ac_in);
270 ff_audio_convert_free(&avr->ac_out);
271 ff_audio_resample_free(&avr->resample);
272 ff_audio_mix_free(&avr->am);
273 av_freep(&avr->mix_matrix);
274
275 avr->use_channel_map = 0;
276}
277
278void avresample_free(AVAudioResampleContext **avr)
279{
280 if (!*avr)
281 return;
282 avresample_close(*avr);
283 av_opt_free(*avr);
284 av_freep(avr);
285}
286
287static int handle_buffered_output(AVAudioResampleContext *avr,
288 AudioData *output, AudioData *converted)
289{
290 int ret;
291
292 if (!output || av_audio_fifo_size(avr->out_fifo) > 0 ||
293 (converted && output->allocated_samples < converted->nb_samples)) {
294 if (converted) {
295 /* if there are any samples in the output FIFO or if the
296 user-supplied output buffer is not large enough for all samples,
297 we add to the output FIFO */
298 av_log(avr, AV_LOG_TRACE, "[FIFO] add %s to out_fifo\n", converted->name);
299 ret = ff_audio_data_add_to_fifo(avr->out_fifo, converted, 0,
300 converted->nb_samples);
301 if (ret < 0)
302 return ret;
303 }
304
305 /* if the user specified an output buffer, read samples from the output
306 FIFO to the user output */
307 if (output && output->allocated_samples > 0) {
308 av_log(avr, AV_LOG_TRACE, "[FIFO] read from out_fifo to output\n");
309 av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
310 return ff_audio_data_read_from_fifo(avr->out_fifo, output,
311 output->allocated_samples);
312 }
313 } else if (converted) {
314 /* copy directly to output if it is large enough or there is not any
315 data in the output FIFO */
316 av_log(avr, AV_LOG_TRACE, "[copy] %s to output\n", converted->name);
317 output->nb_samples = 0;
318 ret = ff_audio_data_copy(output, converted,
319 avr->remap_point == REMAP_OUT_COPY ?
320 &avr->ch_map_info : NULL);
321 if (ret < 0)
322 return ret;
323 av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
324 return output->nb_samples;
325 }
326 av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
327 return 0;
328}
329
330int attribute_align_arg avresample_convert(AVAudioResampleContext *avr,
331 uint8_t **output, int out_plane_size,
332 int out_samples,
333 uint8_t * const *input,
334 int in_plane_size, int in_samples)
335{
336 AudioData input_buffer;
337 AudioData output_buffer;
338 AudioData *current_buffer;
339 int ret, direct_output;
340
341 /* reset internal buffers */
342 if (avr->in_buffer) {
343 avr->in_buffer->nb_samples = 0;
344 ff_audio_data_set_channels(avr->in_buffer,
345 avr->in_buffer->allocated_channels);
346 }
347 if (avr->resample_out_buffer) {
348 avr->resample_out_buffer->nb_samples = 0;
349 ff_audio_data_set_channels(avr->resample_out_buffer,
350 avr->resample_out_buffer->allocated_channels);
351 }
352 if (avr->out_buffer) {
353 avr->out_buffer->nb_samples = 0;
354 ff_audio_data_set_channels(avr->out_buffer,
355 avr->out_buffer->allocated_channels);
356 }
357
358 av_log(avr, AV_LOG_TRACE, "[start conversion]\n");
359
360 /* initialize output_buffer with output data */
361 direct_output = output && av_audio_fifo_size(avr->out_fifo) == 0;
362 if (output) {
363 ret = ff_audio_data_init(&output_buffer, output, out_plane_size,
364 avr->out_channels, out_samples,
365 avr->out_sample_fmt, 0, "output");
366 if (ret < 0)
367 return ret;
368 output_buffer.nb_samples = 0;
369 }
370
371 if (input) {
372 /* initialize input_buffer with input data */
373 ret = ff_audio_data_init(&input_buffer, input, in_plane_size,
374 avr->in_channels, in_samples,
375 avr->in_sample_fmt, 1, "input");
376 if (ret < 0)
377 return ret;
378 current_buffer = &input_buffer;
379
380 if (avr->upmix_needed && !avr->in_convert_needed && !avr->resample_needed &&
381 !avr->out_convert_needed && direct_output && out_samples >= in_samples) {
382 /* in some rare cases we can copy input to output and upmix
383 directly in the output buffer */
384 av_log(avr, AV_LOG_TRACE, "[copy] %s to output\n", current_buffer->name);
385 ret = ff_audio_data_copy(&output_buffer, current_buffer,
386 avr->remap_point == REMAP_OUT_COPY ?
387 &avr->ch_map_info : NULL);
388 if (ret < 0)
389 return ret;
390 current_buffer = &output_buffer;
391 } else if (avr->remap_point == REMAP_OUT_COPY &&
392 (!direct_output || out_samples < in_samples)) {
393 /* if remapping channels during output copy, we may need to
394 * use an intermediate buffer in order to remap before adding
395 * samples to the output fifo */
396 av_log(avr, AV_LOG_TRACE, "[copy] %s to out_buffer\n", current_buffer->name);
397 ret = ff_audio_data_copy(avr->out_buffer, current_buffer,
398 &avr->ch_map_info);
399 if (ret < 0)
400 return ret;
401 current_buffer = avr->out_buffer;
402 } else if (avr->in_copy_needed || avr->in_convert_needed) {
403 /* if needed, copy or convert input to in_buffer, and downmix if
404 applicable */
405 if (avr->in_convert_needed) {
406 ret = ff_audio_data_realloc(avr->in_buffer,
407 current_buffer->nb_samples);
408 if (ret < 0)
409 return ret;
410 av_log(avr, AV_LOG_TRACE, "[convert] %s to in_buffer\n", current_buffer->name);
411 ret = ff_audio_convert(avr->ac_in, avr->in_buffer,
412 current_buffer);
413 if (ret < 0)
414 return ret;
415 } else {
416 av_log(avr, AV_LOG_TRACE, "[copy] %s to in_buffer\n", current_buffer->name);
417 ret = ff_audio_data_copy(avr->in_buffer, current_buffer,
418 avr->remap_point == REMAP_IN_COPY ?
419 &avr->ch_map_info : NULL);
420 if (ret < 0)
421 return ret;
422 }
423 ff_audio_data_set_channels(avr->in_buffer, avr->in_channels);
424 if (avr->downmix_needed) {
425 av_log(avr, AV_LOG_TRACE, "[downmix] in_buffer\n");
426 ret = ff_audio_mix(avr->am, avr->in_buffer);
427 if (ret < 0)
428 return ret;
429 }
430 current_buffer = avr->in_buffer;
431 }
432 } else {
433 /* flush resampling buffer and/or output FIFO if input is NULL */
434 if (!avr->resample_needed)
435 return handle_buffered_output(avr, output ? &output_buffer : NULL,
436 NULL);
437 current_buffer = NULL;
438 }
439
440 if (avr->resample_needed) {
441 AudioData *resample_out;
442
443 if (!avr->out_convert_needed && direct_output && out_samples > 0)
444 resample_out = &output_buffer;
445 else
446 resample_out = avr->resample_out_buffer;
447 av_log(avr, AV_LOG_TRACE, "[resample] %s to %s\n",
448 current_buffer ? current_buffer->name : "null",
449 resample_out->name);
450 ret = ff_audio_resample(avr->resample, resample_out,
451 current_buffer);
452 if (ret < 0)
453 return ret;
454
455 /* if resampling did not produce any samples, just return 0 */
456 if (resample_out->nb_samples == 0) {
457 av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
458 return 0;
459 }
460
461 current_buffer = resample_out;
462 }
463
464 if (avr->upmix_needed) {
465 av_log(avr, AV_LOG_TRACE, "[upmix] %s\n", current_buffer->name);
466 ret = ff_audio_mix(avr->am, current_buffer);
467 if (ret < 0)
468 return ret;
469 }
470
471 /* if we resampled or upmixed directly to output, return here */
472 if (current_buffer == &output_buffer) {
473 av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
474 return current_buffer->nb_samples;
475 }
476
477 if (avr->out_convert_needed) {
478 if (direct_output && out_samples >= current_buffer->nb_samples) {
479 /* convert directly to output */
480 av_log(avr, AV_LOG_TRACE, "[convert] %s to output\n", current_buffer->name);
481 ret = ff_audio_convert(avr->ac_out, &output_buffer, current_buffer);
482 if (ret < 0)
483 return ret;
484
485 av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
486 return output_buffer.nb_samples;
487 } else {
488 ret = ff_audio_data_realloc(avr->out_buffer,
489 current_buffer->nb_samples);
490 if (ret < 0)
491 return ret;
492 av_log(avr, AV_LOG_TRACE, "[convert] %s to out_buffer\n", current_buffer->name);
493 ret = ff_audio_convert(avr->ac_out, avr->out_buffer,
494 current_buffer);
495 if (ret < 0)
496 return ret;
497 current_buffer = avr->out_buffer;
498 }
499 }
500
501 return handle_buffered_output(avr, output ? &output_buffer : NULL,
502 current_buffer);
503}
504
505int avresample_config(AVAudioResampleContext *avr, AVFrame *out, AVFrame *in)
506{
507 if (avresample_is_open(avr)) {
508 avresample_close(avr);
509 }
510
511 if (in) {
512 avr->in_channel_layout = in->channel_layout;
513 avr->in_sample_rate = in->sample_rate;
514 avr->in_sample_fmt = in->format;
515 }
516
517 if (out) {
518 avr->out_channel_layout = out->channel_layout;
519 avr->out_sample_rate = out->sample_rate;
520 avr->out_sample_fmt = out->format;
521 }
522
523 return 0;
524}
525
526static int config_changed(AVAudioResampleContext *avr,
527 AVFrame *out, AVFrame *in)
528{
529 int ret = 0;
530
531 if (in) {
532 if (avr->in_channel_layout != in->channel_layout ||
533 avr->in_sample_rate != in->sample_rate ||
534 avr->in_sample_fmt != in->format) {
535 ret |= AVERROR_INPUT_CHANGED;
536 }
537 }
538
539 if (out) {
540 if (avr->out_channel_layout != out->channel_layout ||
541 avr->out_sample_rate != out->sample_rate ||
542 avr->out_sample_fmt != out->format) {
543 ret |= AVERROR_OUTPUT_CHANGED;
544 }
545 }
546
547 return ret;
548}
549
550static inline int convert_frame(AVAudioResampleContext *avr,
551 AVFrame *out, AVFrame *in)
552{
553 int ret;
554 uint8_t **out_data = NULL, **in_data = NULL;
555 int out_linesize = 0, in_linesize = 0;
556 int out_nb_samples = 0, in_nb_samples = 0;
557
558 if (out) {
559 out_data = out->extended_data;
560 out_linesize = out->linesize[0];
561 out_nb_samples = out->nb_samples;
562 }
563
564 if (in) {
565 in_data = in->extended_data;
566 in_linesize = in->linesize[0];
567 in_nb_samples = in->nb_samples;
568 }
569
570 ret = avresample_convert(avr, out_data, out_linesize,
571 out_nb_samples,
572 in_data, in_linesize,
573 in_nb_samples);
574
575 if (ret < 0) {
576 if (out)
577 out->nb_samples = 0;
578 return ret;
579 }
580
581 if (out)
582 out->nb_samples = ret;
583
584 return 0;
585}
586
587static inline int available_samples(AVFrame *out)
588{
589 int samples;
590 int bytes_per_sample = av_get_bytes_per_sample(out->format);
591 if (!bytes_per_sample)
592 return AVERROR(EINVAL);
593
594 samples = out->linesize[0] / bytes_per_sample;
595 if (av_sample_fmt_is_planar(out->format)) {
596 return samples;
597 } else {
598 int channels = av_get_channel_layout_nb_channels(out->channel_layout);
599 return samples / channels;
600 }
601}
602
603int avresample_convert_frame(AVAudioResampleContext *avr,
604 AVFrame *out, AVFrame *in)
605{
606 int ret, setup = 0;
607
608 if (!avresample_is_open(avr)) {
609 if ((ret = avresample_config(avr, out, in)) < 0)
610 return ret;
611 if ((ret = avresample_open(avr)) < 0)
612 return ret;
613 setup = 1;
614 } else {
615 // return as is or reconfigure for input changes?
616 if ((ret = config_changed(avr, out, in)))
617 return ret;
618 }
619
620 if (out) {
621 if (!out->linesize[0]) {
622 out->nb_samples = avresample_get_out_samples(avr, in->nb_samples);
623 if ((ret = av_frame_get_buffer(out, 0)) < 0) {
624 if (setup)
625 avresample_close(avr);
626 return ret;
627 }
628 } else {
629 if (!out->nb_samples)
630 out->nb_samples = available_samples(out);
631 }
632 }
633
634 return convert_frame(avr, out, in);
635}
636
637int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix,
638 int stride)
639{
640 int in_channels, out_channels, i, o;
641
642 if (avr->am)
643 return ff_audio_mix_get_matrix(avr->am, matrix, stride);
644
645 in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
646 out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
647
648 if ( in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS ||
649 out_channels <= 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
650 av_log(avr, AV_LOG_ERROR, "Invalid channel layouts\n");
651 return AVERROR(EINVAL);
652 }
653
654 if (!avr->mix_matrix) {
655 av_log(avr, AV_LOG_ERROR, "matrix is not set\n");
656 return AVERROR(EINVAL);
657 }
658
659 for (o = 0; o < out_channels; o++)
660 for (i = 0; i < in_channels; i++)
661 matrix[o * stride + i] = avr->mix_matrix[o * in_channels + i];
662
663 return 0;
664}
665
666int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix,
667 int stride)
668{
669 int in_channels, out_channels, i, o;
670
671 if (avr->am)
672 return ff_audio_mix_set_matrix(avr->am, matrix, stride);
673
674 in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
675 out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
676
677 if ( in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS ||
678 out_channels <= 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
679 av_log(avr, AV_LOG_ERROR, "Invalid channel layouts\n");
680 return AVERROR(EINVAL);
681 }
682
683 if (avr->mix_matrix)
684 av_freep(&avr->mix_matrix);
685 avr->mix_matrix = av_malloc(in_channels * out_channels *
686 sizeof(*avr->mix_matrix));
687 if (!avr->mix_matrix)
688 return AVERROR(ENOMEM);
689
690 for (o = 0; o < out_channels; o++)
691 for (i = 0; i < in_channels; i++)
692 avr->mix_matrix[o * in_channels + i] = matrix[o * stride + i];
693
694 return 0;
695}
696
697int avresample_set_channel_mapping(AVAudioResampleContext *avr,
698 const int *channel_map)
699{
700 ChannelMapInfo *info = &avr->ch_map_info;
701 int in_channels, ch, i;
702
703 in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
704 if (in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS) {
705 av_log(avr, AV_LOG_ERROR, "Invalid input channel layout\n");
706 return AVERROR(EINVAL);
707 }
708
709 memset(info, 0, sizeof(*info));
710 memset(info->input_map, -1, sizeof(info->input_map));
711
712 for (ch = 0; ch < in_channels; ch++) {
713 if (channel_map[ch] >= in_channels) {
714 av_log(avr, AV_LOG_ERROR, "Invalid channel map\n");
715 return AVERROR(EINVAL);
716 }
717 if (channel_map[ch] < 0) {
718 info->channel_zero[ch] = 1;
719 info->channel_map[ch] = -1;
720 info->do_zero = 1;
721 } else if (info->input_map[channel_map[ch]] >= 0) {
722 info->channel_copy[ch] = info->input_map[channel_map[ch]];
723 info->channel_map[ch] = -1;
724 info->do_copy = 1;
725 } else {
726 info->channel_map[ch] = channel_map[ch];
727 info->input_map[channel_map[ch]] = ch;
728 info->do_remap = 1;
729 }
730 }
731 /* Fill-in unmapped input channels with unmapped output channels.
732 This is used when remapping during conversion from interleaved to
733 planar format. */
734 for (ch = 0, i = 0; ch < in_channels && i < in_channels; ch++, i++) {
735 while (ch < in_channels && info->input_map[ch] >= 0)
736 ch++;
737 while (i < in_channels && info->channel_map[i] >= 0)
738 i++;
739 if (ch >= in_channels || i >= in_channels)
740 break;
741 info->input_map[ch] = i;
742 }
743
744 avr->use_channel_map = 1;
745 return 0;
746}
747
748int avresample_available(AVAudioResampleContext *avr)
749{
750 return av_audio_fifo_size(avr->out_fifo);
751}
752
753int avresample_get_out_samples(AVAudioResampleContext *avr, int in_nb_samples)
754{
755 int64_t samples = avresample_get_delay(avr) + (int64_t)in_nb_samples;
756
757 if (avr->resample_needed) {
758 samples = av_rescale_rnd(samples,
759 avr->out_sample_rate,
760 avr->in_sample_rate,
761 AV_ROUND_UP);
762 }
763
764 samples += avresample_available(avr);
765
766 if (samples > INT_MAX)
767 return AVERROR(EINVAL);
768
769 return samples;
770}
771
772int avresample_read(AVAudioResampleContext *avr, uint8_t **output, int nb_samples)
773{
774 if (!output)
775 return av_audio_fifo_drain(avr->out_fifo, nb_samples);
776 return av_audio_fifo_read(avr->out_fifo, (void**)output, nb_samples);
777}
778
779unsigned avresample_version(void)
780{
781 return LIBAVRESAMPLE_VERSION_INT;
782}
783
784const char *avresample_license(void)
785{
786#define LICENSE_PREFIX "libavresample license: "
787 return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
788}
789
790const char *avresample_configuration(void)
791{
792 return FFMPEG_CONFIGURATION;
793}
libavresample/version.h+0−50
@@ -1,50 +0,0 @@
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#ifndef AVRESAMPLE_VERSION_H
20#define AVRESAMPLE_VERSION_H
21
22/**
23 * @file
24 * @ingroup lavr
25 * Libavresample version macros.
26 */
27
28#include "libavutil/version.h"
29
30#define LIBAVRESAMPLE_VERSION_MAJOR 4
31#define LIBAVRESAMPLE_VERSION_MINOR 0
32#define LIBAVRESAMPLE_VERSION_MICRO 0
33
34#define LIBAVRESAMPLE_VERSION_INT AV_VERSION_INT(LIBAVRESAMPLE_VERSION_MAJOR, \
35 LIBAVRESAMPLE_VERSION_MINOR, \
36 LIBAVRESAMPLE_VERSION_MICRO)
37#define LIBAVRESAMPLE_VERSION AV_VERSION(LIBAVRESAMPLE_VERSION_MAJOR, \
38 LIBAVRESAMPLE_VERSION_MINOR, \
39 LIBAVRESAMPLE_VERSION_MICRO)
40#define LIBAVRESAMPLE_BUILD LIBAVRESAMPLE_VERSION_INT
41
42#define LIBAVRESAMPLE_IDENT "Lavr" AV_STRINGIFY(LIBAVRESAMPLE_VERSION)
43
44/**
45 * FF_API_* defines may be placed below to indicate public API that will be
46 * dropped at a future version bump. The defines themselves are not part of
47 * the public API and may change, break or disappear at any time.
48 */
49
50#endif /* AVRESAMPLE_VERSION_H */
libavresample/x86/Makefile+0−9
@@ -1,9 +0,0 @@
1OBJS += x86/audio_convert_init.o \
2 x86/audio_mix_init.o \
3 x86/dither_init.o \
4
5OBJS-$(CONFIG_XMM_CLOBBER_TEST) += x86/w64xmmtest.o
6
7X86ASM-OBJS += x86/audio_convert.o \
8 x86/audio_mix.o \
9 x86/dither.o \
libavresample/x86/audio_convert.asm+0−1261
@@ -1,1261 +0,0 @@
1;******************************************************************************
2;* x86 optimized Format Conversion Utils
3;* Copyright (c) 2008 Loren Merritt
4;* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
5;*
6;* This file is part of FFmpeg.
7;*
8;* FFmpeg is free software; you can redistribute it and/or
9;* modify it under the terms of the GNU Lesser General Public
10;* License as published by the Free Software Foundation; either
11;* version 2.1 of the License, or (at your option) any later version.
12;*
13;* FFmpeg is distributed in the hope that it will be useful,
14;* but WITHOUT ANY WARRANTY; without even the implied warranty of
15;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16;* Lesser General Public License for more details.
17;*
18;* You should have received a copy of the GNU Lesser General Public
19;* License along with FFmpeg; if not, write to the Free Software
20;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21;******************************************************************************
22
23%include "libavutil/x86/x86util.asm"
24%include "util.asm"
25
26SECTION_RODATA 32
27
28pf_s32_inv_scale: times 8 dd 0x30000000
29pf_s32_scale: times 8 dd 0x4f000000
30pf_s32_clip: times 8 dd 0x4effffff
31pf_s16_inv_scale: times 4 dd 0x38000000
32pf_s16_scale: times 4 dd 0x47000000
33pb_shuf_unpack_even: db -1, -1, 0, 1, -1, -1, 2, 3, -1, -1, 8, 9, -1, -1, 10, 11
34pb_shuf_unpack_odd: db -1, -1, 4, 5, -1, -1, 6, 7, -1, -1, 12, 13, -1, -1, 14, 15
35pb_interleave_words: SHUFFLE_MASK_W 0, 4, 1, 5, 2, 6, 3, 7
36pb_deinterleave_words: SHUFFLE_MASK_W 0, 2, 4, 6, 1, 3, 5, 7
37pw_zero_even: times 4 dw 0x0000, 0xffff
38
39SECTION .text
40
41;------------------------------------------------------------------------------
42; void ff_conv_s16_to_s32(int32_t *dst, const int16_t *src, int len);
43;------------------------------------------------------------------------------
44
45INIT_XMM sse2
46cglobal conv_s16_to_s32, 3,3,3, dst, src, len
47 lea lenq, [2*lend]
48 lea dstq, [dstq+2*lenq]
49 add srcq, lenq
50 neg lenq
51.loop:
52 mova m2, [srcq+lenq]
53 pxor m0, m0
54 pxor m1, m1
55 punpcklwd m0, m2
56 punpckhwd m1, m2
57 mova [dstq+2*lenq ], m0
58 mova [dstq+2*lenq+mmsize], m1
59 add lenq, mmsize
60 jl .loop
61 REP_RET
62
63;------------------------------------------------------------------------------
64; void ff_conv_s16_to_flt(float *dst, const int16_t *src, int len);
65;------------------------------------------------------------------------------
66
67%macro CONV_S16_TO_FLT 0
68cglobal conv_s16_to_flt, 3,3,3, dst, src, len
69 lea lenq, [2*lend]
70 add srcq, lenq
71 lea dstq, [dstq + 2*lenq]
72 neg lenq
73 mova m2, [pf_s16_inv_scale]
74 ALIGN 16
75.loop:
76 mova m0, [srcq+lenq]
77 S16_TO_S32_SX 0, 1
78 cvtdq2ps m0, m0
79 cvtdq2ps m1, m1
80 mulps m0, m2
81 mulps m1, m2
82 mova [dstq+2*lenq ], m0
83 mova [dstq+2*lenq+mmsize], m1
84 add lenq, mmsize
85 jl .loop
86 REP_RET
87%endmacro
88
89INIT_XMM sse2
90CONV_S16_TO_FLT
91INIT_XMM sse4
92CONV_S16_TO_FLT
93
94;------------------------------------------------------------------------------
95; void ff_conv_s32_to_s16(int16_t *dst, const int32_t *src, int len);
96;------------------------------------------------------------------------------
97
98%macro CONV_S32_TO_S16 0
99cglobal conv_s32_to_s16, 3,3,4, dst, src, len
100 lea lenq, [2*lend]
101 lea srcq, [srcq+2*lenq]
102 add dstq, lenq
103 neg lenq
104.loop:
105 mova m0, [srcq+2*lenq ]
106 mova m1, [srcq+2*lenq+ mmsize]
107 mova m2, [srcq+2*lenq+2*mmsize]
108 mova m3, [srcq+2*lenq+3*mmsize]
109 psrad m0, 16
110 psrad m1, 16
111 psrad m2, 16
112 psrad m3, 16
113 packssdw m0, m1
114 packssdw m2, m3
115 mova [dstq+lenq ], m0
116 mova [dstq+lenq+mmsize], m2
117 add lenq, mmsize*2
118 jl .loop
119%if mmsize == 8
120 emms
121 RET
122%else
123 REP_RET
124%endif
125%endmacro
126
127INIT_MMX mmx
128CONV_S32_TO_S16
129INIT_XMM sse2
130CONV_S32_TO_S16
131
132;------------------------------------------------------------------------------
133; void ff_conv_s32_to_flt(float *dst, const int32_t *src, int len);
134;------------------------------------------------------------------------------
135
136%macro CONV_S32_TO_FLT 0
137cglobal conv_s32_to_flt, 3,3,3, dst, src, len
138 lea lenq, [4*lend]
139 add srcq, lenq
140 add dstq, lenq
141 neg lenq
142 mova m0, [pf_s32_inv_scale]
143 ALIGN 16
144.loop:
145 cvtdq2ps m1, [srcq+lenq ]
146 cvtdq2ps m2, [srcq+lenq+mmsize]
147 mulps m1, m1, m0
148 mulps m2, m2, m0
149 mova [dstq+lenq ], m1
150 mova [dstq+lenq+mmsize], m2
151 add lenq, mmsize*2
152 jl .loop
153 REP_RET
154%endmacro
155
156INIT_XMM sse2
157CONV_S32_TO_FLT
158%if HAVE_AVX_EXTERNAL
159INIT_YMM avx
160CONV_S32_TO_FLT
161%endif
162
163;------------------------------------------------------------------------------
164; void ff_conv_flt_to_s16(int16_t *dst, const float *src, int len);
165;------------------------------------------------------------------------------
166
167INIT_XMM sse2
168cglobal conv_flt_to_s16, 3,3,5, dst, src, len
169 lea lenq, [2*lend]
170 lea srcq, [srcq+2*lenq]
171 add dstq, lenq
172 neg lenq
173 mova m4, [pf_s16_scale]
174.loop:
175 mova m0, [srcq+2*lenq ]
176 mova m1, [srcq+2*lenq+1*mmsize]
177 mova m2, [srcq+2*lenq+2*mmsize]
178 mova m3, [srcq+2*lenq+3*mmsize]
179 mulps m0, m4
180 mulps m1, m4
181 mulps m2, m4
182 mulps m3, m4
183 cvtps2dq m0, m0
184 cvtps2dq m1, m1
185 cvtps2dq m2, m2
186 cvtps2dq m3, m3
187 packssdw m0, m1
188 packssdw m2, m3
189 mova [dstq+lenq ], m0
190 mova [dstq+lenq+mmsize], m2
191 add lenq, mmsize*2
192 jl .loop
193 REP_RET
194
195;------------------------------------------------------------------------------
196; void ff_conv_flt_to_s32(int32_t *dst, const float *src, int len);
197;------------------------------------------------------------------------------
198
199%macro CONV_FLT_TO_S32 0
200cglobal conv_flt_to_s32, 3,3,6, dst, src, len
201 lea lenq, [lend*4]
202 add srcq, lenq
203 add dstq, lenq
204 neg lenq
205 mova m4, [pf_s32_scale]
206 mova m5, [pf_s32_clip]
207.loop:
208 mulps m0, m4, [srcq+lenq ]
209 mulps m1, m4, [srcq+lenq+1*mmsize]
210 mulps m2, m4, [srcq+lenq+2*mmsize]
211 mulps m3, m4, [srcq+lenq+3*mmsize]
212 minps m0, m0, m5
213 minps m1, m1, m5
214 minps m2, m2, m5
215 minps m3, m3, m5
216 cvtps2dq m0, m0
217 cvtps2dq m1, m1
218 cvtps2dq m2, m2
219 cvtps2dq m3, m3
220 mova [dstq+lenq ], m0
221 mova [dstq+lenq+1*mmsize], m1
222 mova [dstq+lenq+2*mmsize], m2
223 mova [dstq+lenq+3*mmsize], m3
224 add lenq, mmsize*4
225 jl .loop
226 REP_RET
227%endmacro
228
229INIT_XMM sse2
230CONV_FLT_TO_S32
231%if HAVE_AVX_EXTERNAL
232INIT_YMM avx
233CONV_FLT_TO_S32
234%endif
235
236;------------------------------------------------------------------------------
237; void ff_conv_s16p_to_s16_2ch(int16_t *dst, int16_t *const *src, int len,
238; int channels);
239;------------------------------------------------------------------------------
240
241%macro CONV_S16P_TO_S16_2CH 0
242cglobal conv_s16p_to_s16_2ch, 3,4,5, dst, src0, len, src1
243 mov src1q, [src0q+gprsize]
244 mov src0q, [src0q ]
245 lea lenq, [2*lend]
246 add src0q, lenq
247 add src1q, lenq
248 lea dstq, [dstq+2*lenq]
249 neg lenq
250.loop:
251 mova m0, [src0q+lenq ]
252 mova m1, [src1q+lenq ]
253 mova m2, [src0q+lenq+mmsize]
254 mova m3, [src1q+lenq+mmsize]
255 SBUTTERFLY2 wd, 0, 1, 4
256 SBUTTERFLY2 wd, 2, 3, 4
257 mova [dstq+2*lenq+0*mmsize], m0
258 mova [dstq+2*lenq+1*mmsize], m1
259 mova [dstq+2*lenq+2*mmsize], m2
260 mova [dstq+2*lenq+3*mmsize], m3
261 add lenq, 2*mmsize
262 jl .loop
263 REP_RET
264%endmacro
265
266INIT_XMM sse2
267CONV_S16P_TO_S16_2CH
268%if HAVE_AVX_EXTERNAL
269INIT_XMM avx
270CONV_S16P_TO_S16_2CH
271%endif
272
273;------------------------------------------------------------------------------
274; void ff_conv_s16p_to_s16_6ch(int16_t *dst, int16_t *const *src, int len,
275; int channels);
276;------------------------------------------------------------------------------
277
278;------------------------------------------------------------------------------
279; NOTE: In the 6-channel functions, len could be used as an index on x86-64
280; instead of just a counter, which would avoid incrementing the
281; pointers, but the extra complexity and amount of code is not worth
282; the small gain. On x86-32 there are not enough registers to use len
283; as an index without keeping two of the pointers on the stack and
284; loading them in each iteration.
285;------------------------------------------------------------------------------
286
287%macro CONV_S16P_TO_S16_6CH 0
288%if ARCH_X86_64
289cglobal conv_s16p_to_s16_6ch, 3,8,7, dst, src0, len, src1, src2, src3, src4, src5
290%else
291cglobal conv_s16p_to_s16_6ch, 2,7,7, dst, src0, src1, src2, src3, src4, src5
292%define lend dword r2m
293%endif
294 mov src1q, [src0q+1*gprsize]
295 mov src2q, [src0q+2*gprsize]
296 mov src3q, [src0q+3*gprsize]
297 mov src4q, [src0q+4*gprsize]
298 mov src5q, [src0q+5*gprsize]
299 mov src0q, [src0q]
300 sub src1q, src0q
301 sub src2q, src0q
302 sub src3q, src0q
303 sub src4q, src0q
304 sub src5q, src0q
305.loop:
306%if cpuflag(sse2slow)
307 movq m0, [src0q ] ; m0 = 0, 6, 12, 18, x, x, x, x
308 movq m1, [src0q+src1q] ; m1 = 1, 7, 13, 19, x, x, x, x
309 movq m2, [src0q+src2q] ; m2 = 2, 8, 14, 20, x, x, x, x
310 movq m3, [src0q+src3q] ; m3 = 3, 9, 15, 21, x, x, x, x
311 movq m4, [src0q+src4q] ; m4 = 4, 10, 16, 22, x, x, x, x
312 movq m5, [src0q+src5q] ; m5 = 5, 11, 17, 23, x, x, x, x
313 ; unpack words:
314 punpcklwd m0, m1 ; m0 = 0, 1, 6, 7, 12, 13, 18, 19
315 punpcklwd m2, m3 ; m2 = 4, 5, 10, 11, 16, 17, 22, 23
316 punpcklwd m4, m5 ; m4 = 2, 3, 8, 9, 14, 15, 20, 21
317 ; blend dwords
318 shufps m1, m0, m2, q2020 ; m1 = 0, 1, 12, 13, 2, 3, 14, 15
319 shufps m0, m4, q2031 ; m0 = 6, 7, 18, 19, 4, 5, 16, 17
320 shufps m2, m4, q3131 ; m2 = 8, 9, 20, 21, 10, 11, 22, 23
321 ; shuffle dwords
322 pshufd m0, m0, q1302 ; m0 = 4, 5, 6, 7, 16, 17, 18, 19
323 pshufd m1, m1, q3120 ; m1 = 0, 1, 2, 3, 12, 13, 14, 15
324 pshufd m2, m2, q3120 ; m2 = 8, 9, 10, 11, 20, 21, 22, 23
325 movq [dstq+0*mmsize/2], m1
326 movq [dstq+1*mmsize/2], m0
327 movq [dstq+2*mmsize/2], m2
328 movhps [dstq+3*mmsize/2], m1
329 movhps [dstq+4*mmsize/2], m0
330 movhps [dstq+5*mmsize/2], m2
331 add src0q, mmsize/2
332 add dstq, mmsize*3
333 sub lend, mmsize/4
334%else
335 mova m0, [src0q ] ; m0 = 0, 6, 12, 18, 24, 30, 36, 42
336 mova m1, [src0q+src1q] ; m1 = 1, 7, 13, 19, 25, 31, 37, 43
337 mova m2, [src0q+src2q] ; m2 = 2, 8, 14, 20, 26, 32, 38, 44
338 mova m3, [src0q+src3q] ; m3 = 3, 9, 15, 21, 27, 33, 39, 45
339 mova m4, [src0q+src4q] ; m4 = 4, 10, 16, 22, 28, 34, 40, 46
340 mova m5, [src0q+src5q] ; m5 = 5, 11, 17, 23, 29, 35, 41, 47
341 ; unpack words:
342 SBUTTERFLY2 wd, 0, 1, 6 ; m0 = 0, 1, 6, 7, 12, 13, 18, 19
343 ; m1 = 24, 25, 30, 31, 36, 37, 42, 43
344 SBUTTERFLY2 wd, 2, 3, 6 ; m2 = 2, 3, 8, 9, 14, 15, 20, 21
345 ; m3 = 26, 27, 32, 33, 38, 39, 44, 45
346 SBUTTERFLY2 wd, 4, 5, 6 ; m4 = 4, 5, 10, 11, 16, 17, 22, 23
347 ; m5 = 28, 29, 34, 35, 40, 41, 46, 47
348 ; blend dwords
349 shufps m6, m0, m2, q2020 ; m6 = 0, 1, 12, 13, 2, 3, 14, 15
350 shufps m0, m4, q2031 ; m0 = 6, 7, 18, 19, 4, 5, 16, 17
351 shufps m2, m4, q3131 ; m2 = 8, 9, 20, 21, 10, 11, 22, 23
352 SWAP 4,6 ; m4 = 0, 1, 12, 13, 2, 3, 14, 15
353 shufps m6, m1, m3, q2020 ; m6 = 24, 25, 36, 37, 26, 27, 38, 39
354 shufps m1, m5, q2031 ; m1 = 30, 31, 42, 43, 28, 29, 40, 41
355 shufps m3, m5, q3131 ; m3 = 32, 33, 44, 45, 34, 35, 46, 47
356 SWAP 5,6 ; m5 = 24, 25, 36, 37, 26, 27, 38, 39
357 ; shuffle dwords
358 pshufd m0, m0, q1302 ; m0 = 4, 5, 6, 7, 16, 17, 18, 19
359 pshufd m2, m2, q3120 ; m2 = 8, 9, 10, 11, 20, 21, 22, 23
360 pshufd m4, m4, q3120 ; m4 = 0, 1, 2, 3, 12, 13, 14, 15
361 pshufd m1, m1, q1302 ; m1 = 28, 29, 30, 31, 40, 41, 42, 43
362 pshufd m3, m3, q3120 ; m3 = 32, 33, 34, 35, 44, 45, 46, 47
363 pshufd m5, m5, q3120 ; m5 = 24, 25, 26, 27, 36, 37, 38, 39
364 ; shuffle qwords
365 punpcklqdq m6, m4, m0 ; m6 = 0, 1, 2, 3, 4, 5, 6, 7
366 punpckhqdq m0, m2 ; m0 = 16, 17, 18, 19, 20, 21, 22, 23
367 shufps m2, m4, q3210 ; m2 = 8, 9, 10, 11, 12, 13, 14, 15
368 SWAP 4,6 ; m4 = 0, 1, 2, 3, 4, 5, 6, 7
369 punpcklqdq m6, m5, m1 ; m6 = 24, 25, 26, 27, 28, 29, 30, 31
370 punpckhqdq m1, m3 ; m1 = 40, 41, 42, 43, 44, 45, 46, 47
371 shufps m3, m5, q3210 ; m3 = 32, 33, 34, 35, 36, 37, 38, 39
372 SWAP 5,6 ; m5 = 24, 25, 26, 27, 28, 29, 30, 31
373 mova [dstq+0*mmsize], m4
374 mova [dstq+1*mmsize], m2
375 mova [dstq+2*mmsize], m0
376 mova [dstq+3*mmsize], m5
377 mova [dstq+4*mmsize], m3
378 mova [dstq+5*mmsize], m1
379 add src0q, mmsize
380 add dstq, mmsize*6
381 sub lend, mmsize/2
382%endif
383 jg .loop
384 REP_RET
385%endmacro
386
387INIT_XMM sse2
388CONV_S16P_TO_S16_6CH
389INIT_XMM sse2slow
390CONV_S16P_TO_S16_6CH
391%if HAVE_AVX_EXTERNAL
392INIT_XMM avx
393CONV_S16P_TO_S16_6CH
394%endif
395
396;------------------------------------------------------------------------------
397; void ff_conv_s16p_to_flt_2ch(float *dst, int16_t *const *src, int len,
398; int channels);
399;------------------------------------------------------------------------------
400
401%macro CONV_S16P_TO_FLT_2CH 0
402cglobal conv_s16p_to_flt_2ch, 3,4,6, dst, src0, len, src1
403 lea lenq, [2*lend]
404 mov src1q, [src0q+gprsize]
405 mov src0q, [src0q ]
406 lea dstq, [dstq+4*lenq]
407 add src0q, lenq
408 add src1q, lenq
409 neg lenq
410 mova m5, [pf_s32_inv_scale]
411.loop:
412 mova m2, [src0q+lenq] ; m2 = 0, 2, 4, 6, 8, 10, 12, 14
413 mova m4, [src1q+lenq] ; m4 = 1, 3, 5, 7, 9, 11, 13, 15
414 SBUTTERFLY2 wd, 2, 4, 3 ; m2 = 0, 1, 2, 3, 4, 5, 6, 7
415 ; m4 = 8, 9, 10, 11, 12, 13, 14, 15
416 pxor m3, m3
417 punpcklwd m0, m3, m2 ; m0 = 0, 1, 2, 3
418 punpckhwd m1, m3, m2 ; m1 = 4, 5, 6, 7
419 punpcklwd m2, m3, m4 ; m2 = 8, 9, 10, 11
420 punpckhwd m3, m4 ; m3 = 12, 13, 14, 15
421 cvtdq2ps m0, m0
422 cvtdq2ps m1, m1
423 cvtdq2ps m2, m2
424 cvtdq2ps m3, m3
425 mulps m0, m5
426 mulps m1, m5
427 mulps m2, m5
428 mulps m3, m5
429 mova [dstq+4*lenq ], m0
430 mova [dstq+4*lenq+ mmsize], m1
431 mova [dstq+4*lenq+2*mmsize], m2
432 mova [dstq+4*lenq+3*mmsize], m3
433 add lenq, mmsize
434 jl .loop
435 REP_RET
436%endmacro
437
438INIT_XMM sse2
439CONV_S16P_TO_FLT_2CH
440%if HAVE_AVX_EXTERNAL
441INIT_XMM avx
442CONV_S16P_TO_FLT_2CH
443%endif
444
445;------------------------------------------------------------------------------
446; void ff_conv_s16p_to_flt_6ch(float *dst, int16_t *const *src, int len,
447; int channels);
448;------------------------------------------------------------------------------
449
450%macro CONV_S16P_TO_FLT_6CH 0
451%if ARCH_X86_64
452cglobal conv_s16p_to_flt_6ch, 3,8,8, dst, src, len, src1, src2, src3, src4, src5
453%else
454cglobal conv_s16p_to_flt_6ch, 2,7,8, dst, src, src1, src2, src3, src4, src5
455%define lend dword r2m
456%endif
457 mov src1q, [srcq+1*gprsize]
458 mov src2q, [srcq+2*gprsize]
459 mov src3q, [srcq+3*gprsize]
460 mov src4q, [srcq+4*gprsize]
461 mov src5q, [srcq+5*gprsize]
462 mov srcq, [srcq]
463 sub src1q, srcq
464 sub src2q, srcq
465 sub src3q, srcq
466 sub src4q, srcq
467 sub src5q, srcq
468 mova m7, [pf_s32_inv_scale]
469%if cpuflag(ssse3)
470 %define unpack_even m6
471 mova m6, [pb_shuf_unpack_even]
472%if ARCH_X86_64
473 %define unpack_odd m8
474 mova m8, [pb_shuf_unpack_odd]
475%else
476 %define unpack_odd [pb_shuf_unpack_odd]
477%endif
478%endif
479.loop:
480 movq m0, [srcq ] ; m0 = 0, 6, 12, 18, x, x, x, x
481 movq m1, [srcq+src1q] ; m1 = 1, 7, 13, 19, x, x, x, x
482 movq m2, [srcq+src2q] ; m2 = 2, 8, 14, 20, x, x, x, x
483 movq m3, [srcq+src3q] ; m3 = 3, 9, 15, 21, x, x, x, x
484 movq m4, [srcq+src4q] ; m4 = 4, 10, 16, 22, x, x, x, x
485 movq m5, [srcq+src5q] ; m5 = 5, 11, 17, 23, x, x, x, x
486 ; unpack words:
487 punpcklwd m0, m1 ; m0 = 0, 1, 6, 7, 12, 13, 18, 19
488 punpcklwd m2, m3 ; m2 = 2, 3, 8, 9, 14, 15, 20, 21
489 punpcklwd m4, m5 ; m4 = 4, 5, 10, 11, 16, 17, 22, 23
490 ; blend dwords
491 shufps m1, m4, m0, q3120 ; m1 = 4, 5, 16, 17, 6, 7, 18, 19
492 shufps m0, m2, q2020 ; m0 = 0, 1, 12, 13, 2, 3, 14, 15
493 shufps m2, m4, q3131 ; m2 = 8, 9, 20, 21, 10, 11, 22, 23
494%if cpuflag(ssse3)
495 pshufb m3, m0, unpack_odd ; m3 = 12, 13, 14, 15
496 pshufb m0, unpack_even ; m0 = 0, 1, 2, 3
497 pshufb m4, m1, unpack_odd ; m4 = 16, 17, 18, 19
498 pshufb m1, unpack_even ; m1 = 4, 5, 6, 7
499 pshufb m5, m2, unpack_odd ; m5 = 20, 21, 22, 23
500 pshufb m2, unpack_even ; m2 = 8, 9, 10, 11
501%else
502 ; shuffle dwords
503 pshufd m0, m0, q3120 ; m0 = 0, 1, 2, 3, 12, 13, 14, 15
504 pshufd m1, m1, q3120 ; m1 = 4, 5, 6, 7, 16, 17, 18, 19
505 pshufd m2, m2, q3120 ; m2 = 8, 9, 10, 11, 20, 21, 22, 23
506 pxor m6, m6 ; convert s16 in m0-m2 to s32 in m0-m5
507 punpcklwd m3, m6, m0 ; m3 = 0, 1, 2, 3
508 punpckhwd m4, m6, m0 ; m4 = 12, 13, 14, 15
509 punpcklwd m0, m6, m1 ; m0 = 4, 5, 6, 7
510 punpckhwd m5, m6, m1 ; m5 = 16, 17, 18, 19
511 punpcklwd m1, m6, m2 ; m1 = 8, 9, 10, 11
512 punpckhwd m6, m2 ; m6 = 20, 21, 22, 23
513 SWAP 6,2,1,0,3,4,5 ; swap registers 3,0,1,4,5,6 to 0,1,2,3,4,5
514%endif
515 cvtdq2ps m0, m0 ; convert s32 to float
516 cvtdq2ps m1, m1
517 cvtdq2ps m2, m2
518 cvtdq2ps m3, m3
519 cvtdq2ps m4, m4
520 cvtdq2ps m5, m5
521 mulps m0, m7 ; scale float from s32 range to [-1.0,1.0]
522 mulps m1, m7
523 mulps m2, m7
524 mulps m3, m7
525 mulps m4, m7
526 mulps m5, m7
527 mova [dstq ], m0
528 mova [dstq+ mmsize], m1
529 mova [dstq+2*mmsize], m2
530 mova [dstq+3*mmsize], m3
531 mova [dstq+4*mmsize], m4
532 mova [dstq+5*mmsize], m5
533 add srcq, mmsize/2
534 add dstq, mmsize*6
535 sub lend, mmsize/4
536 jg .loop
537 REP_RET
538%endmacro
539
540INIT_XMM sse2
541CONV_S16P_TO_FLT_6CH
542INIT_XMM ssse3
543CONV_S16P_TO_FLT_6CH
544%if HAVE_AVX_EXTERNAL
545INIT_XMM avx
546CONV_S16P_TO_FLT_6CH
547%endif
548
549;------------------------------------------------------------------------------
550; void ff_conv_fltp_to_s16_2ch(int16_t *dst, float *const *src, int len,
551; int channels);
552;------------------------------------------------------------------------------
553
554%macro CONV_FLTP_TO_S16_2CH 0
555cglobal conv_fltp_to_s16_2ch, 3,4,3, dst, src0, len, src1
556 lea lenq, [4*lend]
557 mov src1q, [src0q+gprsize]
558 mov src0q, [src0q ]
559 add dstq, lenq
560 add src0q, lenq
561 add src1q, lenq
562 neg lenq
563 mova m2, [pf_s16_scale]
564%if cpuflag(ssse3)
565 mova m3, [pb_interleave_words]
566%endif
567.loop:
568 mulps m0, m2, [src0q+lenq] ; m0 = 0, 2, 4, 6
569 mulps m1, m2, [src1q+lenq] ; m1 = 1, 3, 5, 7
570 cvtps2dq m0, m0
571 cvtps2dq m1, m1
572%if cpuflag(ssse3)
573 packssdw m0, m1 ; m0 = 0, 2, 4, 6, 1, 3, 5, 7
574 pshufb m0, m3 ; m0 = 0, 1, 2, 3, 4, 5, 6, 7
575%else
576 packssdw m0, m0 ; m0 = 0, 2, 4, 6, x, x, x, x
577 packssdw m1, m1 ; m1 = 1, 3, 5, 7, x, x, x, x
578 punpcklwd m0, m1 ; m0 = 0, 1, 2, 3, 4, 5, 6, 7
579%endif
580 mova [dstq+lenq], m0
581 add lenq, mmsize
582 jl .loop
583 REP_RET
584%endmacro
585
586INIT_XMM sse2
587CONV_FLTP_TO_S16_2CH
588INIT_XMM ssse3
589CONV_FLTP_TO_S16_2CH
590
591;------------------------------------------------------------------------------
592; void ff_conv_fltp_to_s16_6ch(int16_t *dst, float *const *src, int len,
593; int channels);
594;------------------------------------------------------------------------------
595
596%macro CONV_FLTP_TO_S16_6CH 0
597%if ARCH_X86_64
598cglobal conv_fltp_to_s16_6ch, 3,8,7, dst, src, len, src1, src2, src3, src4, src5
599%else
600cglobal conv_fltp_to_s16_6ch, 2,7,7, dst, src, src1, src2, src3, src4, src5
601%define lend dword r2m
602%endif
603 mov src1q, [srcq+1*gprsize]
604 mov src2q, [srcq+2*gprsize]
605 mov src3q, [srcq+3*gprsize]
606 mov src4q, [srcq+4*gprsize]
607 mov src5q, [srcq+5*gprsize]
608 mov srcq, [srcq]
609 sub src1q, srcq
610 sub src2q, srcq
611 sub src3q, srcq
612 sub src4q, srcq
613 sub src5q, srcq
614 movaps xmm6, [pf_s16_scale]
615.loop:
616%if cpuflag(sse2)
617 mulps m0, m6, [srcq ]
618 mulps m1, m6, [srcq+src1q]
619 mulps m2, m6, [srcq+src2q]
620 mulps m3, m6, [srcq+src3q]
621 mulps m4, m6, [srcq+src4q]
622 mulps m5, m6, [srcq+src5q]
623 cvtps2dq m0, m0
624 cvtps2dq m1, m1
625 cvtps2dq m2, m2
626 cvtps2dq m3, m3
627 cvtps2dq m4, m4
628 cvtps2dq m5, m5
629 packssdw m0, m3 ; m0 = 0, 6, 12, 18, 3, 9, 15, 21
630 packssdw m1, m4 ; m1 = 1, 7, 13, 19, 4, 10, 16, 22
631 packssdw m2, m5 ; m2 = 2, 8, 14, 20, 5, 11, 17, 23
632 ; unpack words:
633 movhlps m3, m0 ; m3 = 3, 9, 15, 21, x, x, x, x
634 punpcklwd m0, m1 ; m0 = 0, 1, 6, 7, 12, 13, 18, 19
635 punpckhwd m1, m2 ; m1 = 4, 5, 10, 11, 16, 17, 22, 23
636 punpcklwd m2, m3 ; m2 = 2, 3, 8, 9, 14, 15, 20, 21
637 ; blend dwords:
638 shufps m3, m0, m2, q2020 ; m3 = 0, 1, 12, 13, 2, 3, 14, 15
639 shufps m0, m1, q2031 ; m0 = 6, 7, 18, 19, 4, 5, 16, 17
640 shufps m2, m1, q3131 ; m2 = 8, 9, 20, 21, 10, 11, 22, 23
641 ; shuffle dwords:
642 shufps m1, m2, m3, q3120 ; m1 = 8, 9, 10, 11, 12, 13, 14, 15
643 shufps m3, m0, q0220 ; m3 = 0, 1, 2, 3, 4, 5, 6, 7
644 shufps m0, m2, q3113 ; m0 = 16, 17, 18, 19, 20, 21, 22, 23
645 mova [dstq+0*mmsize], m3
646 mova [dstq+1*mmsize], m1
647 mova [dstq+2*mmsize], m0
648%else ; sse
649 movlps xmm0, [srcq ]
650 movlps xmm1, [srcq+src1q]
651 movlps xmm2, [srcq+src2q]
652 movlps xmm3, [srcq+src3q]
653 movlps xmm4, [srcq+src4q]
654 movlps xmm5, [srcq+src5q]
655 mulps xmm0, xmm6
656 mulps xmm1, xmm6
657 mulps xmm2, xmm6
658 mulps xmm3, xmm6
659 mulps xmm4, xmm6
660 mulps xmm5, xmm6
661 cvtps2pi mm0, xmm0
662 cvtps2pi mm1, xmm1
663 cvtps2pi mm2, xmm2
664 cvtps2pi mm3, xmm3
665 cvtps2pi mm4, xmm4
666 cvtps2pi mm5, xmm5
667 packssdw mm0, mm3 ; m0 = 0, 6, 3, 9
668 packssdw mm1, mm4 ; m1 = 1, 7, 4, 10
669 packssdw mm2, mm5 ; m2 = 2, 8, 5, 11
670 ; unpack words
671 pshufw mm3, mm0, q1032 ; m3 = 3, 9, 0, 6
672 punpcklwd mm0, mm1 ; m0 = 0, 1, 6, 7
673 punpckhwd mm1, mm2 ; m1 = 4, 5, 10, 11
674 punpcklwd mm2, mm3 ; m2 = 2, 3, 8, 9
675 ; unpack dwords
676 pshufw mm3, mm0, q1032 ; m3 = 6, 7, 0, 1
677 punpckldq mm0, mm2 ; m0 = 0, 1, 2, 3 (final)
678 punpckhdq mm2, mm1 ; m2 = 8, 9, 10, 11 (final)
679 punpckldq mm1, mm3 ; m1 = 4, 5, 6, 7 (final)
680 mova [dstq+0*mmsize], mm0
681 mova [dstq+1*mmsize], mm1
682 mova [dstq+2*mmsize], mm2
683%endif
684 add srcq, mmsize
685 add dstq, mmsize*3
686 sub lend, mmsize/4
687 jg .loop
688%if mmsize == 8
689 emms
690 RET
691%else
692 REP_RET
693%endif
694%endmacro
695
696INIT_MMX sse
697CONV_FLTP_TO_S16_6CH
698INIT_XMM sse2
699CONV_FLTP_TO_S16_6CH
700%if HAVE_AVX_EXTERNAL
701INIT_XMM avx
702CONV_FLTP_TO_S16_6CH
703%endif
704
705;------------------------------------------------------------------------------
706; void ff_conv_fltp_to_flt_2ch(float *dst, float *const *src, int len,
707; int channels);
708;------------------------------------------------------------------------------
709
710%macro CONV_FLTP_TO_FLT_2CH 0
711cglobal conv_fltp_to_flt_2ch, 3,4,5, dst, src0, len, src1
712 mov src1q, [src0q+gprsize]
713 mov src0q, [src0q]
714 lea lenq, [4*lend]
715 add src0q, lenq
716 add src1q, lenq
717 lea dstq, [dstq+2*lenq]
718 neg lenq
719.loop:
720 mova m0, [src0q+lenq ]
721 mova m1, [src1q+lenq ]
722 mova m2, [src0q+lenq+mmsize]
723 mova m3, [src1q+lenq+mmsize]
724 SBUTTERFLYPS 0, 1, 4
725 SBUTTERFLYPS 2, 3, 4
726 mova [dstq+2*lenq+0*mmsize], m0
727 mova [dstq+2*lenq+1*mmsize], m1
728 mova [dstq+2*lenq+2*mmsize], m2
729 mova [dstq+2*lenq+3*mmsize], m3
730 add lenq, 2*mmsize
731 jl .loop
732 REP_RET
733%endmacro
734
735INIT_XMM sse
736CONV_FLTP_TO_FLT_2CH
737%if HAVE_AVX_EXTERNAL
738INIT_XMM avx
739CONV_FLTP_TO_FLT_2CH
740%endif
741
742;-----------------------------------------------------------------------------
743; void ff_conv_fltp_to_flt_6ch(float *dst, float *const *src, int len,
744; int channels);
745;-----------------------------------------------------------------------------
746
747%macro CONV_FLTP_TO_FLT_6CH 0
748cglobal conv_fltp_to_flt_6ch, 2,8,7, dst, src, src1, src2, src3, src4, src5, len
749%if ARCH_X86_64
750 mov lend, r2d
751%else
752 %define lend dword r2m
753%endif
754 mov src1q, [srcq+1*gprsize]
755 mov src2q, [srcq+2*gprsize]
756 mov src3q, [srcq+3*gprsize]
757 mov src4q, [srcq+4*gprsize]
758 mov src5q, [srcq+5*gprsize]
759 mov srcq, [srcq]
760 sub src1q, srcq
761 sub src2q, srcq
762 sub src3q, srcq
763 sub src4q, srcq
764 sub src5q, srcq
765.loop:
766 mova m0, [srcq ]
767 mova m1, [srcq+src1q]
768 mova m2, [srcq+src2q]
769 mova m3, [srcq+src3q]
770 mova m4, [srcq+src4q]
771 mova m5, [srcq+src5q]
772%if cpuflag(sse4)
773 SBUTTERFLYPS 0, 1, 6
774 SBUTTERFLYPS 2, 3, 6
775 SBUTTERFLYPS 4, 5, 6
776
777 blendps m6, m4, m0, 1100b
778 movlhps m0, m2
779 movhlps m4, m2
780 blendps m2, m5, m1, 1100b
781 movlhps m1, m3
782 movhlps m5, m3
783
784 movaps [dstq ], m0
785 movaps [dstq+16], m6
786 movaps [dstq+32], m4
787 movaps [dstq+48], m1
788 movaps [dstq+64], m2
789 movaps [dstq+80], m5
790%else ; mmx
791 SBUTTERFLY dq, 0, 1, 6
792 SBUTTERFLY dq, 2, 3, 6
793 SBUTTERFLY dq, 4, 5, 6
794
795 movq [dstq ], m0
796 movq [dstq+ 8], m2
797 movq [dstq+16], m4
798 movq [dstq+24], m1
799 movq [dstq+32], m3
800 movq [dstq+40], m5
801%endif
802 add srcq, mmsize
803 add dstq, mmsize*6
804 sub lend, mmsize/4
805 jg .loop
806%if mmsize == 8
807 emms
808 RET
809%else
810 REP_RET
811%endif
812%endmacro
813
814INIT_MMX mmx
815CONV_FLTP_TO_FLT_6CH
816INIT_XMM sse4
817CONV_FLTP_TO_FLT_6CH
818%if HAVE_AVX_EXTERNAL
819INIT_XMM avx
820CONV_FLTP_TO_FLT_6CH
821%endif
822
823;------------------------------------------------------------------------------
824; void ff_conv_s16_to_s16p_2ch(int16_t *const *dst, int16_t *src, int len,
825; int channels);
826;------------------------------------------------------------------------------
827
828%macro CONV_S16_TO_S16P_2CH 0
829cglobal conv_s16_to_s16p_2ch, 3,4,4, dst0, src, len, dst1
830 lea lenq, [2*lend]
831 mov dst1q, [dst0q+gprsize]
832 mov dst0q, [dst0q ]
833 lea srcq, [srcq+2*lenq]
834 add dst0q, lenq
835 add dst1q, lenq
836 neg lenq
837%if cpuflag(ssse3)
838 mova m3, [pb_deinterleave_words]
839%endif
840.loop:
841 mova m0, [srcq+2*lenq ] ; m0 = 0, 1, 2, 3, 4, 5, 6, 7
842 mova m1, [srcq+2*lenq+mmsize] ; m1 = 8, 9, 10, 11, 12, 13, 14, 15
843%if cpuflag(ssse3)
844 pshufb m0, m3 ; m0 = 0, 2, 4, 6, 1, 3, 5, 7
845 pshufb m1, m3 ; m1 = 8, 10, 12, 14, 9, 11, 13, 15
846 SBUTTERFLY2 qdq, 0, 1, 2 ; m0 = 0, 2, 4, 6, 8, 10, 12, 14
847 ; m1 = 1, 3, 5, 7, 9, 11, 13, 15
848%else ; sse2
849 pshuflw m0, m0, q3120 ; m0 = 0, 2, 1, 3, 4, 5, 6, 7
850 pshufhw m0, m0, q3120 ; m0 = 0, 2, 1, 3, 4, 6, 5, 7
851 pshuflw m1, m1, q3120 ; m1 = 8, 10, 9, 11, 12, 13, 14, 15
852 pshufhw m1, m1, q3120 ; m1 = 8, 10, 9, 11, 12, 14, 13, 15
853 DEINT2_PS 0, 1, 2 ; m0 = 0, 2, 4, 6, 8, 10, 12, 14
854 ; m1 = 1, 3, 5, 7, 9, 11, 13, 15
855%endif
856 mova [dst0q+lenq], m0
857 mova [dst1q+lenq], m1
858 add lenq, mmsize
859 jl .loop
860 REP_RET
861%endmacro
862
863INIT_XMM sse2
864CONV_S16_TO_S16P_2CH
865INIT_XMM ssse3
866CONV_S16_TO_S16P_2CH
867%if HAVE_AVX_EXTERNAL
868INIT_XMM avx
869CONV_S16_TO_S16P_2CH
870%endif
871
872;------------------------------------------------------------------------------
873; void ff_conv_s16_to_s16p_6ch(int16_t *const *dst, int16_t *src, int len,
874; int channels);
875;------------------------------------------------------------------------------
876
877%macro CONV_S16_TO_S16P_6CH 0
878%if ARCH_X86_64
879cglobal conv_s16_to_s16p_6ch, 3,8,5, dst, src, len, dst1, dst2, dst3, dst4, dst5
880%else
881cglobal conv_s16_to_s16p_6ch, 2,7,5, dst, src, dst1, dst2, dst3, dst4, dst5
882%define lend dword r2m
883%endif
884 mov dst1q, [dstq+ gprsize]
885 mov dst2q, [dstq+2*gprsize]
886 mov dst3q, [dstq+3*gprsize]
887 mov dst4q, [dstq+4*gprsize]
888 mov dst5q, [dstq+5*gprsize]
889 mov dstq, [dstq ]
890 sub dst1q, dstq
891 sub dst2q, dstq
892 sub dst3q, dstq
893 sub dst4q, dstq
894 sub dst5q, dstq
895.loop:
896 mova m0, [srcq+0*mmsize] ; m0 = 0, 1, 2, 3, 4, 5, 6, 7
897 mova m3, [srcq+1*mmsize] ; m3 = 8, 9, 10, 11, 12, 13, 14, 15
898 mova m2, [srcq+2*mmsize] ; m2 = 16, 17, 18, 19, 20, 21, 22, 23
899 PALIGNR m1, m3, m0, 12, m4 ; m1 = 6, 7, 8, 9, 10, 11, x, x
900 shufps m3, m2, q1032 ; m3 = 12, 13, 14, 15, 16, 17, 18, 19
901 psrldq m2, 4 ; m2 = 18, 19, 20, 21, 22, 23, x, x
902 SBUTTERFLY2 wd, 0, 1, 4 ; m0 = 0, 6, 1, 7, 2, 8, 3, 9
903 ; m1 = 4, 10, 5, 11, x, x, x, x
904 SBUTTERFLY2 wd, 3, 2, 4 ; m3 = 12, 18, 13, 19, 14, 20, 15, 21
905 ; m2 = 16, 22, 17, 23, x, x, x, x
906 SBUTTERFLY2 dq, 0, 3, 4 ; m0 = 0, 6, 12, 18, 1, 7, 13, 19
907 ; m3 = 2, 8, 14, 20, 3, 9, 15, 21
908 punpckldq m1, m2 ; m1 = 4, 10, 16, 22, 5, 11, 17, 23
909 movq [dstq ], m0
910 movhps [dstq+dst1q], m0
911 movq [dstq+dst2q], m3
912 movhps [dstq+dst3q], m3
913 movq [dstq+dst4q], m1
914 movhps [dstq+dst5q], m1
915 add srcq, mmsize*3
916 add dstq, mmsize/2
917 sub lend, mmsize/4
918 jg .loop
919 REP_RET
920%endmacro
921
922INIT_XMM sse2
923CONV_S16_TO_S16P_6CH
924INIT_XMM ssse3
925CONV_S16_TO_S16P_6CH
926%if HAVE_AVX_EXTERNAL
927INIT_XMM avx
928CONV_S16_TO_S16P_6CH
929%endif
930
931;------------------------------------------------------------------------------
932; void ff_conv_s16_to_fltp_2ch(float *const *dst, int16_t *src, int len,
933; int channels);
934;------------------------------------------------------------------------------
935
936%macro CONV_S16_TO_FLTP_2CH 0
937cglobal conv_s16_to_fltp_2ch, 3,4,5, dst0, src, len, dst1
938 lea lenq, [4*lend]
939 mov dst1q, [dst0q+gprsize]
940 mov dst0q, [dst0q ]
941 add srcq, lenq
942 add dst0q, lenq
943 add dst1q, lenq
944 neg lenq
945 mova m3, [pf_s32_inv_scale]
946 mova m4, [pw_zero_even]
947.loop:
948 mova m1, [srcq+lenq]
949 pslld m0, m1, 16
950 pand m1, m4
951 cvtdq2ps m0, m0
952 cvtdq2ps m1, m1
953 mulps m0, m0, m3
954 mulps m1, m1, m3
955 mova [dst0q+lenq], m0
956 mova [dst1q+lenq], m1
957 add lenq, mmsize
958 jl .loop
959 REP_RET
960%endmacro
961
962INIT_XMM sse2
963CONV_S16_TO_FLTP_2CH
964%if HAVE_AVX_EXTERNAL
965INIT_XMM avx
966CONV_S16_TO_FLTP_2CH
967%endif
968
969;------------------------------------------------------------------------------
970; void ff_conv_s16_to_fltp_6ch(float *const *dst, int16_t *src, int len,
971; int channels);
972;------------------------------------------------------------------------------
973
974%macro CONV_S16_TO_FLTP_6CH 0
975%if ARCH_X86_64
976cglobal conv_s16_to_fltp_6ch, 3,8,7, dst, src, len, dst1, dst2, dst3, dst4, dst5
977%else
978cglobal conv_s16_to_fltp_6ch, 2,7,7, dst, src, dst1, dst2, dst3, dst4, dst5
979%define lend dword r2m
980%endif
981 mov dst1q, [dstq+ gprsize]
982 mov dst2q, [dstq+2*gprsize]
983 mov dst3q, [dstq+3*gprsize]
984 mov dst4q, [dstq+4*gprsize]
985 mov dst5q, [dstq+5*gprsize]
986 mov dstq, [dstq ]
987 sub dst1q, dstq
988 sub dst2q, dstq
989 sub dst3q, dstq
990 sub dst4q, dstq
991 sub dst5q, dstq
992 mova m6, [pf_s16_inv_scale]
993.loop:
994 mova m0, [srcq+0*mmsize] ; m0 = 0, 1, 2, 3, 4, 5, 6, 7
995 mova m3, [srcq+1*mmsize] ; m3 = 8, 9, 10, 11, 12, 13, 14, 15
996 mova m2, [srcq+2*mmsize] ; m2 = 16, 17, 18, 19, 20, 21, 22, 23
997 PALIGNR m1, m3, m0, 12, m4 ; m1 = 6, 7, 8, 9, 10, 11, x, x
998 shufps m3, m2, q1032 ; m3 = 12, 13, 14, 15, 16, 17, 18, 19
999 psrldq m2, 4 ; m2 = 18, 19, 20, 21, 22, 23, x, x
1000 SBUTTERFLY2 wd, 0, 1, 4 ; m0 = 0, 6, 1, 7, 2, 8, 3, 9
1001 ; m1 = 4, 10, 5, 11, x, x, x, x
1002 SBUTTERFLY2 wd, 3, 2, 4 ; m3 = 12, 18, 13, 19, 14, 20, 15, 21
1003 ; m2 = 16, 22, 17, 23, x, x, x, x
1004 SBUTTERFLY2 dq, 0, 3, 4 ; m0 = 0, 6, 12, 18, 1, 7, 13, 19
1005 ; m3 = 2, 8, 14, 20, 3, 9, 15, 21
1006 punpckldq m1, m2 ; m1 = 4, 10, 16, 22, 5, 11, 17, 23
1007 S16_TO_S32_SX 0, 2 ; m0 = 0, 6, 12, 18
1008 ; m2 = 1, 7, 13, 19
1009 S16_TO_S32_SX 3, 4 ; m3 = 2, 8, 14, 20
1010 ; m4 = 3, 9, 15, 21
1011 S16_TO_S32_SX 1, 5 ; m1 = 4, 10, 16, 22
1012 ; m5 = 5, 11, 17, 23
1013 SWAP 1,2,3,4
1014 cvtdq2ps m0, m0
1015 cvtdq2ps m1, m1
1016 cvtdq2ps m2, m2
1017 cvtdq2ps m3, m3
1018 cvtdq2ps m4, m4
1019 cvtdq2ps m5, m5
1020 mulps m0, m6
1021 mulps m1, m6
1022 mulps m2, m6
1023 mulps m3, m6
1024 mulps m4, m6
1025 mulps m5, m6
1026 mova [dstq ], m0
1027 mova [dstq+dst1q], m1
1028 mova [dstq+dst2q], m2
1029 mova [dstq+dst3q], m3
1030 mova [dstq+dst4q], m4
1031 mova [dstq+dst5q], m5
1032 add srcq, mmsize*3
1033 add dstq, mmsize
1034 sub lend, mmsize/4
1035 jg .loop
1036 REP_RET
1037%endmacro
1038
1039INIT_XMM sse2
1040CONV_S16_TO_FLTP_6CH
1041INIT_XMM ssse3
1042CONV_S16_TO_FLTP_6CH
1043INIT_XMM sse4
1044CONV_S16_TO_FLTP_6CH
1045%if HAVE_AVX_EXTERNAL
1046INIT_XMM avx
1047CONV_S16_TO_FLTP_6CH
1048%endif
1049
1050;------------------------------------------------------------------------------
1051; void ff_conv_flt_to_s16p_2ch(int16_t *const *dst, float *src, int len,
1052; int channels);
1053;------------------------------------------------------------------------------
1054
1055%macro CONV_FLT_TO_S16P_2CH 0
1056cglobal conv_flt_to_s16p_2ch, 3,4,6, dst0, src, len, dst1
1057 lea lenq, [2*lend]
1058 mov dst1q, [dst0q+gprsize]
1059 mov dst0q, [dst0q ]
1060 lea srcq, [srcq+4*lenq]
1061 add dst0q, lenq
1062 add dst1q, lenq
1063 neg lenq
1064 mova m5, [pf_s16_scale]
1065.loop:
1066 mova m0, [srcq+4*lenq ]
1067 mova m1, [srcq+4*lenq+ mmsize]
1068 mova m2, [srcq+4*lenq+2*mmsize]
1069 mova m3, [srcq+4*lenq+3*mmsize]
1070 DEINT2_PS 0, 1, 4
1071 DEINT2_PS 2, 3, 4
1072 mulps m0, m0, m5
1073 mulps m1, m1, m5
1074 mulps m2, m2, m5
1075 mulps m3, m3, m5
1076 cvtps2dq m0, m0
1077 cvtps2dq m1, m1
1078 cvtps2dq m2, m2
1079 cvtps2dq m3, m3
1080 packssdw m0, m2
1081 packssdw m1, m3
1082 mova [dst0q+lenq], m0
1083 mova [dst1q+lenq], m1
1084 add lenq, mmsize
1085 jl .loop
1086 REP_RET
1087%endmacro
1088
1089INIT_XMM sse2
1090CONV_FLT_TO_S16P_2CH
1091%if HAVE_AVX_EXTERNAL
1092INIT_XMM avx
1093CONV_FLT_TO_S16P_2CH
1094%endif
1095
1096;------------------------------------------------------------------------------
1097; void ff_conv_flt_to_s16p_6ch(int16_t *const *dst, float *src, int len,
1098; int channels);
1099;------------------------------------------------------------------------------
1100
1101%macro CONV_FLT_TO_S16P_6CH 0
1102%if ARCH_X86_64
1103cglobal conv_flt_to_s16p_6ch, 3,8,7, dst, src, len, dst1, dst2, dst3, dst4, dst5
1104%else
1105cglobal conv_flt_to_s16p_6ch, 2,7,7, dst, src, dst1, dst2, dst3, dst4, dst5
1106%define lend dword r2m
1107%endif
1108 mov dst1q, [dstq+ gprsize]
1109 mov dst2q, [dstq+2*gprsize]
1110 mov dst3q, [dstq+3*gprsize]
1111 mov dst4q, [dstq+4*gprsize]
1112 mov dst5q, [dstq+5*gprsize]
1113 mov dstq, [dstq ]
1114 sub dst1q, dstq
1115 sub dst2q, dstq
1116 sub dst3q, dstq
1117 sub dst4q, dstq
1118 sub dst5q, dstq
1119 mova m6, [pf_s16_scale]
1120.loop:
1121 mulps m0, m6, [srcq+0*mmsize]
1122 mulps m3, m6, [srcq+1*mmsize]
1123 mulps m1, m6, [srcq+2*mmsize]
1124 mulps m4, m6, [srcq+3*mmsize]
1125 mulps m2, m6, [srcq+4*mmsize]
1126 mulps m5, m6, [srcq+5*mmsize]
1127 cvtps2dq m0, m0
1128 cvtps2dq m1, m1
1129 cvtps2dq m2, m2
1130 cvtps2dq m3, m3
1131 cvtps2dq m4, m4
1132 cvtps2dq m5, m5
1133 packssdw m0, m3 ; m0 = 0, 1, 2, 3, 4, 5, 6, 7
1134 packssdw m1, m4 ; m1 = 8, 9, 10, 11, 12, 13, 14, 15
1135 packssdw m2, m5 ; m2 = 16, 17, 18, 19, 20, 21, 22, 23
1136 PALIGNR m3, m1, m0, 12, m4 ; m3 = 6, 7, 8, 9, 10, 11, x, x
1137 shufps m1, m2, q1032 ; m1 = 12, 13, 14, 15, 16, 17, 18, 19
1138 psrldq m2, 4 ; m2 = 18, 19, 20, 21, 22, 23, x, x
1139 SBUTTERFLY2 wd, 0, 3, 4 ; m0 = 0, 6, 1, 7, 2, 8, 3, 9
1140 ; m3 = 4, 10, 5, 11, x, x, x, x
1141 SBUTTERFLY2 wd, 1, 2, 4 ; m1 = 12, 18, 13, 19, 14, 20, 15, 21
1142 ; m2 = 16, 22, 17, 23, x, x, x, x
1143 SBUTTERFLY2 dq, 0, 1, 4 ; m0 = 0, 6, 12, 18, 1, 7, 13, 19
1144 ; m1 = 2, 8, 14, 20, 3, 9, 15, 21
1145 punpckldq m3, m2 ; m3 = 4, 10, 16, 22, 5, 11, 17, 23
1146 movq [dstq ], m0
1147 movhps [dstq+dst1q], m0
1148 movq [dstq+dst2q], m1
1149 movhps [dstq+dst3q], m1
1150 movq [dstq+dst4q], m3
1151 movhps [dstq+dst5q], m3
1152 add srcq, mmsize*6
1153 add dstq, mmsize/2
1154 sub lend, mmsize/4
1155 jg .loop
1156 REP_RET
1157%endmacro
1158
1159INIT_XMM sse2
1160CONV_FLT_TO_S16P_6CH
1161INIT_XMM ssse3
1162CONV_FLT_TO_S16P_6CH
1163%if HAVE_AVX_EXTERNAL
1164INIT_XMM avx
1165CONV_FLT_TO_S16P_6CH
1166%endif
1167
1168;------------------------------------------------------------------------------
1169; void ff_conv_flt_to_fltp_2ch(float *const *dst, float *src, int len,
1170; int channels);
1171;------------------------------------------------------------------------------
1172
1173%macro CONV_FLT_TO_FLTP_2CH 0
1174cglobal conv_flt_to_fltp_2ch, 3,4,3, dst0, src, len, dst1
1175 lea lenq, [4*lend]
1176 mov dst1q, [dst0q+gprsize]
1177 mov dst0q, [dst0q ]
1178 lea srcq, [srcq+2*lenq]
1179 add dst0q, lenq
1180 add dst1q, lenq
1181 neg lenq
1182.loop:
1183 mova m0, [srcq+2*lenq ]
1184 mova m1, [srcq+2*lenq+mmsize]
1185 DEINT2_PS 0, 1, 2
1186 mova [dst0q+lenq], m0
1187 mova [dst1q+lenq], m1
1188 add lenq, mmsize
1189 jl .loop
1190 REP_RET
1191%endmacro
1192
1193INIT_XMM sse
1194CONV_FLT_TO_FLTP_2CH
1195%if HAVE_AVX_EXTERNAL
1196INIT_XMM avx
1197CONV_FLT_TO_FLTP_2CH
1198%endif
1199
1200;------------------------------------------------------------------------------
1201; void ff_conv_flt_to_fltp_6ch(float *const *dst, float *src, int len,
1202; int channels);
1203;------------------------------------------------------------------------------
1204
1205%macro CONV_FLT_TO_FLTP_6CH 0
1206%if ARCH_X86_64
1207cglobal conv_flt_to_fltp_6ch, 3,8,7, dst, src, len, dst1, dst2, dst3, dst4, dst5
1208%else
1209cglobal conv_flt_to_fltp_6ch, 2,7,7, dst, src, dst1, dst2, dst3, dst4, dst5
1210%define lend dword r2m
1211%endif
1212 mov dst1q, [dstq+ gprsize]
1213 mov dst2q, [dstq+2*gprsize]
1214 mov dst3q, [dstq+3*gprsize]
1215 mov dst4q, [dstq+4*gprsize]
1216 mov dst5q, [dstq+5*gprsize]
1217 mov dstq, [dstq ]
1218 sub dst1q, dstq
1219 sub dst2q, dstq
1220 sub dst3q, dstq
1221 sub dst4q, dstq
1222 sub dst5q, dstq
1223.loop:
1224 mova m0, [srcq+0*mmsize] ; m0 = 0, 1, 2, 3
1225 mova m1, [srcq+1*mmsize] ; m1 = 4, 5, 6, 7
1226 mova m2, [srcq+2*mmsize] ; m2 = 8, 9, 10, 11
1227 mova m3, [srcq+3*mmsize] ; m3 = 12, 13, 14, 15
1228 mova m4, [srcq+4*mmsize] ; m4 = 16, 17, 18, 19
1229 mova m5, [srcq+5*mmsize] ; m5 = 20, 21, 22, 23
1230
1231 SBUTTERFLY2 dq, 0, 3, 6 ; m0 = 0, 12, 1, 13
1232 ; m3 = 2, 14, 3, 15
1233 SBUTTERFLY2 dq, 1, 4, 6 ; m1 = 4, 16, 5, 17
1234 ; m4 = 6, 18, 7, 19
1235 SBUTTERFLY2 dq, 2, 5, 6 ; m2 = 8, 20, 9, 21
1236 ; m5 = 10, 22, 11, 23
1237 SBUTTERFLY2 dq, 0, 4, 6 ; m0 = 0, 6, 12, 18
1238 ; m4 = 1, 7, 13, 19
1239 SBUTTERFLY2 dq, 3, 2, 6 ; m3 = 2, 8, 14, 20
1240 ; m2 = 3, 9, 15, 21
1241 SBUTTERFLY2 dq, 1, 5, 6 ; m1 = 4, 10, 16, 22
1242 ; m5 = 5, 11, 17, 23
1243 mova [dstq ], m0
1244 mova [dstq+dst1q], m4
1245 mova [dstq+dst2q], m3
1246 mova [dstq+dst3q], m2
1247 mova [dstq+dst4q], m1
1248 mova [dstq+dst5q], m5
1249 add srcq, mmsize*6
1250 add dstq, mmsize
1251 sub lend, mmsize/4
1252 jg .loop
1253 REP_RET
1254%endmacro
1255
1256INIT_XMM sse2
1257CONV_FLT_TO_FLTP_6CH
1258%if HAVE_AVX_EXTERNAL
1259INIT_XMM avx
1260CONV_FLT_TO_FLTP_6CH
1261%endif
libavresample/x86/audio_convert_init.c+0−265
@@ -1,265 +0,0 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "config.h"
22#include "libavutil/cpu.h"
23#include "libavutil/x86/cpu.h"
24#include "libavresample/audio_convert.h"
25
26/* flat conversions */
27
28void ff_conv_s16_to_s32_sse2(int16_t *dst, const int32_t *src, int len);
29
30void ff_conv_s16_to_flt_sse2(float *dst, const int16_t *src, int len);
31void ff_conv_s16_to_flt_sse4(float *dst, const int16_t *src, int len);
32
33void ff_conv_s32_to_s16_mmx (int16_t *dst, const int32_t *src, int len);
34void ff_conv_s32_to_s16_sse2(int16_t *dst, const int32_t *src, int len);
35
36void ff_conv_s32_to_flt_sse2(float *dst, const int32_t *src, int len);
37void ff_conv_s32_to_flt_avx (float *dst, const int32_t *src, int len);
38
39void ff_conv_flt_to_s16_sse2(int16_t *dst, const float *src, int len);
40
41void ff_conv_flt_to_s32_sse2(int32_t *dst, const float *src, int len);
42void ff_conv_flt_to_s32_avx (int32_t *dst, const float *src, int len);
43
44/* interleave conversions */
45
46void ff_conv_s16p_to_s16_2ch_sse2(int16_t *dst, int16_t *const *src,
47 int len, int channels);
48void ff_conv_s16p_to_s16_2ch_avx (int16_t *dst, int16_t *const *src,
49 int len, int channels);
50
51void ff_conv_s16p_to_s16_6ch_sse2(int16_t *dst, int16_t *const *src,
52 int len, int channels);
53void ff_conv_s16p_to_s16_6ch_sse2slow(int16_t *dst, int16_t *const *src,
54 int len, int channels);
55void ff_conv_s16p_to_s16_6ch_avx (int16_t *dst, int16_t *const *src,
56 int len, int channels);
57
58void ff_conv_s16p_to_flt_2ch_sse2(float *dst, int16_t *const *src,
59 int len, int channels);
60void ff_conv_s16p_to_flt_2ch_avx (float *dst, int16_t *const *src,
61 int len, int channels);
62
63void ff_conv_s16p_to_flt_6ch_sse2 (float *dst, int16_t *const *src,
64 int len, int channels);
65void ff_conv_s16p_to_flt_6ch_ssse3(float *dst, int16_t *const *src,
66 int len, int channels);
67void ff_conv_s16p_to_flt_6ch_avx (float *dst, int16_t *const *src,
68 int len, int channels);
69
70void ff_conv_fltp_to_s16_2ch_sse2 (int16_t *dst, float *const *src,
71 int len, int channels);
72void ff_conv_fltp_to_s16_2ch_ssse3(int16_t *dst, float *const *src,
73 int len, int channels);
74
75void ff_conv_fltp_to_s16_6ch_sse (int16_t *dst, float *const *src,
76 int len, int channels);
77void ff_conv_fltp_to_s16_6ch_sse2(int16_t *dst, float *const *src,
78 int len, int channels);
79void ff_conv_fltp_to_s16_6ch_avx (int16_t *dst, float *const *src,
80 int len, int channels);
81
82void ff_conv_fltp_to_flt_2ch_sse(float *dst, float *const *src, int len,
83 int channels);
84void ff_conv_fltp_to_flt_2ch_avx(float *dst, float *const *src, int len,
85 int channels);
86
87void ff_conv_fltp_to_flt_6ch_mmx (float *dst, float *const *src, int len,
88 int channels);
89void ff_conv_fltp_to_flt_6ch_sse4(float *dst, float *const *src, int len,
90 int channels);
91void ff_conv_fltp_to_flt_6ch_avx (float *dst, float *const *src, int len,
92 int channels);
93
94/* deinterleave conversions */
95
96void ff_conv_s16_to_s16p_2ch_sse2(int16_t *const *dst, int16_t *src,
97 int len, int channels);
98void ff_conv_s16_to_s16p_2ch_ssse3(int16_t *const *dst, int16_t *src,
99 int len, int channels);
100void ff_conv_s16_to_s16p_2ch_avx (int16_t *const *dst, int16_t *src,
101 int len, int channels);
102
103void ff_conv_s16_to_s16p_6ch_sse2 (int16_t *const *dst, int16_t *src,
104 int len, int channels);
105void ff_conv_s16_to_s16p_6ch_ssse3(int16_t *const *dst, int16_t *src,
106 int len, int channels);
107void ff_conv_s16_to_s16p_6ch_avx (int16_t *const *dst, int16_t *src,
108 int len, int channels);
109
110void ff_conv_s16_to_fltp_2ch_sse2(float *const *dst, int16_t *src,
111 int len, int channels);
112void ff_conv_s16_to_fltp_2ch_avx (float *const *dst, int16_t *src,
113 int len, int channels);
114
115void ff_conv_s16_to_fltp_6ch_sse2 (float *const *dst, int16_t *src,
116 int len, int channels);
117void ff_conv_s16_to_fltp_6ch_ssse3(float *const *dst, int16_t *src,
118 int len, int channels);
119void ff_conv_s16_to_fltp_6ch_sse4 (float *const *dst, int16_t *src,
120 int len, int channels);
121void ff_conv_s16_to_fltp_6ch_avx (float *const *dst, int16_t *src,
122 int len, int channels);
123
124void ff_conv_flt_to_s16p_2ch_sse2(int16_t *const *dst, float *src,
125 int len, int channels);
126void ff_conv_flt_to_s16p_2ch_avx (int16_t *const *dst, float *src,
127 int len, int channels);
128
129void ff_conv_flt_to_s16p_6ch_sse2 (int16_t *const *dst, float *src,
130 int len, int channels);
131void ff_conv_flt_to_s16p_6ch_ssse3(int16_t *const *dst, float *src,
132 int len, int channels);
133void ff_conv_flt_to_s16p_6ch_avx (int16_t *const *dst, float *src,
134 int len, int channels);
135
136void ff_conv_flt_to_fltp_2ch_sse(float *const *dst, float *src, int len,
137 int channels);
138void ff_conv_flt_to_fltp_2ch_avx(float *const *dst, float *src, int len,
139 int channels);
140
141void ff_conv_flt_to_fltp_6ch_sse2(float *const *dst, float *src, int len,
142 int channels);
143void ff_conv_flt_to_fltp_6ch_avx (float *const *dst, float *src, int len,
144 int channels);
145
146av_cold void ff_audio_convert_init_x86(AudioConvert *ac)
147{
148 int cpu_flags = av_get_cpu_flags();
149
150 if (EXTERNAL_MMX(cpu_flags)) {
151 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32,
152 0, 1, 8, "MMX", ff_conv_s32_to_s16_mmx);
153 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
154 6, 1, 4, "MMX", ff_conv_fltp_to_flt_6ch_mmx);
155 }
156 if (EXTERNAL_SSE(cpu_flags)) {
157 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLTP,
158 6, 1, 2, "SSE", ff_conv_fltp_to_s16_6ch_sse);
159 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
160 2, 16, 8, "SSE", ff_conv_fltp_to_flt_2ch_sse);
161 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT,
162 2, 16, 4, "SSE", ff_conv_flt_to_fltp_2ch_sse);
163 }
164 if (EXTERNAL_SSE2(cpu_flags)) {
165 if (!(cpu_flags & AV_CPU_FLAG_SSE2SLOW)) {
166 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32,
167 0, 16, 16, "SSE2", ff_conv_s32_to_s16_sse2);
168 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P,
169 6, 16, 8, "SSE2", ff_conv_s16p_to_s16_6ch_sse2);
170 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLTP,
171 6, 16, 4, "SSE2", ff_conv_fltp_to_s16_6ch_sse2);
172 } else {
173 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P,
174 6, 1, 4, "SSE2SLOW", ff_conv_s16p_to_s16_6ch_sse2slow);
175 }
176 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16,
177 0, 16, 8, "SSE2", ff_conv_s16_to_s32_sse2);
178 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16,
179 0, 16, 8, "SSE2", ff_conv_s16_to_flt_sse2);
180 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32,
181 0, 16, 8, "SSE2", ff_conv_s32_to_flt_sse2);
182 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT,
183 0, 16, 16, "SSE2", ff_conv_flt_to_s16_sse2);
184 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT,
185 0, 16, 16, "SSE2", ff_conv_flt_to_s32_sse2);
186 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P,
187 2, 16, 16, "SSE2", ff_conv_s16p_to_s16_2ch_sse2);
188 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16P,
189 2, 16, 8, "SSE2", ff_conv_s16p_to_flt_2ch_sse2);
190 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16P,
191 6, 16, 4, "SSE2", ff_conv_s16p_to_flt_6ch_sse2);
192 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLTP,
193 2, 16, 4, "SSE2", ff_conv_fltp_to_s16_2ch_sse2);
194 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16,
195 2, 16, 8, "SSE2", ff_conv_s16_to_s16p_2ch_sse2);
196 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16,
197 6, 16, 4, "SSE2", ff_conv_s16_to_s16p_6ch_sse2);
198 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_S16,
199 2, 16, 8, "SSE2", ff_conv_s16_to_fltp_2ch_sse2);
200 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_S16,
201 6, 16, 4, "SSE2", ff_conv_s16_to_fltp_6ch_sse2);
202 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_FLT,
203 2, 16, 8, "SSE2", ff_conv_flt_to_s16p_2ch_sse2);
204 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_FLT,
205 6, 16, 4, "SSE2", ff_conv_flt_to_s16p_6ch_sse2);
206 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT,
207 6, 16, 4, "SSE2", ff_conv_flt_to_fltp_6ch_sse2);
208 }
209 if (EXTERNAL_SSSE3(cpu_flags)) {
210 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16P,
211 6, 16, 4, "SSSE3", ff_conv_s16p_to_flt_6ch_ssse3);
212 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLTP,
213 2, 16, 4, "SSSE3", ff_conv_fltp_to_s16_2ch_ssse3);
214 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16,
215 2, 16, 8, "SSSE3", ff_conv_s16_to_s16p_2ch_ssse3);
216 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16,
217 6, 16, 4, "SSSE3", ff_conv_s16_to_s16p_6ch_ssse3);
218 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_S16,
219 6, 16, 4, "SSSE3", ff_conv_s16_to_fltp_6ch_ssse3);
220 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_FLT,
221 6, 16, 4, "SSSE3", ff_conv_flt_to_s16p_6ch_ssse3);
222 }
223 if (EXTERNAL_SSE4(cpu_flags)) {
224 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16,
225 0, 16, 8, "SSE4", ff_conv_s16_to_flt_sse4);
226 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
227 6, 16, 4, "SSE4", ff_conv_fltp_to_flt_6ch_sse4);
228 }
229 if (EXTERNAL_AVX_FAST(cpu_flags)) {
230 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32,
231 0, 32, 16, "AVX", ff_conv_s32_to_flt_avx);
232 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT,
233 0, 32, 32, "AVX", ff_conv_flt_to_s32_avx);
234 }
235 if (EXTERNAL_AVX(cpu_flags)) {
236 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P,
237 2, 16, 16, "AVX", ff_conv_s16p_to_s16_2ch_avx);
238 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P,
239 6, 16, 8, "AVX", ff_conv_s16p_to_s16_6ch_avx);
240 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16P,
241 2, 16, 8, "AVX", ff_conv_s16p_to_flt_2ch_avx);
242 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16P,
243 6, 16, 4, "AVX", ff_conv_s16p_to_flt_6ch_avx);
244 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLTP,
245 6, 16, 4, "AVX", ff_conv_fltp_to_s16_6ch_avx);
246 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
247 6, 16, 4, "AVX", ff_conv_fltp_to_flt_6ch_avx);
248 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16,
249 2, 16, 8, "AVX", ff_conv_s16_to_s16p_2ch_avx);
250 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16,
251 6, 16, 4, "AVX", ff_conv_s16_to_s16p_6ch_avx);
252 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_S16,
253 2, 16, 8, "AVX", ff_conv_s16_to_fltp_2ch_avx);
254 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_S16,
255 6, 16, 4, "AVX", ff_conv_s16_to_fltp_6ch_avx);
256 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_FLT,
257 2, 16, 8, "AVX", ff_conv_flt_to_s16p_2ch_avx);
258 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_FLT,
259 6, 16, 4, "AVX", ff_conv_flt_to_s16p_6ch_avx);
260 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT,
261 2, 16, 4, "AVX", ff_conv_flt_to_fltp_2ch_avx);
262 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT,
263 6, 16, 4, "AVX", ff_conv_flt_to_fltp_6ch_avx);
264 }
265}
libavresample/x86/audio_mix.asm+0−511
@@ -1,511 +0,0 @@
1;******************************************************************************
2;* x86 optimized channel mixing
3;* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4;*
5;* This file is part of FFmpeg.
6;*
7;* FFmpeg is free software; you can redistribute it and/or
8;* modify it under the terms of the GNU Lesser General Public
9;* License as published by the Free Software Foundation; either
10;* version 2.1 of the License, or (at your option) any later version.
11;*
12;* FFmpeg is distributed in the hope that it will be useful,
13;* but WITHOUT ANY WARRANTY; without even the implied warranty of
14;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15;* Lesser General Public License for more details.
16;*
17;* You should have received a copy of the GNU Lesser General Public
18;* License along with FFmpeg; if not, write to the Free Software
19;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20;******************************************************************************
21
22%include "libavutil/x86/x86util.asm"
23%include "util.asm"
24
25SECTION .text
26
27;-----------------------------------------------------------------------------
28; void ff_mix_2_to_1_fltp_flt(float **src, float **matrix, int len,
29; int out_ch, int in_ch);
30;-----------------------------------------------------------------------------
31
32%macro MIX_2_TO_1_FLTP_FLT 0
33cglobal mix_2_to_1_fltp_flt, 3,4,6, src, matrix, len, src1
34 mov src1q, [srcq+gprsize]
35 mov srcq, [srcq ]
36 sub src1q, srcq
37 mov matrixq, [matrixq ]
38 VBROADCASTSS m4, [matrixq ]
39 VBROADCASTSS m5, [matrixq+4]
40 ALIGN 16
41.loop:
42 mulps m0, m4, [srcq ]
43 mulps m1, m5, [srcq+src1q ]
44 mulps m2, m4, [srcq+ mmsize]
45 mulps m3, m5, [srcq+src1q+mmsize]
46 addps m0, m0, m1
47 addps m2, m2, m3
48 mova [srcq ], m0
49 mova [srcq+mmsize], m2
50 add srcq, mmsize*2
51 sub lend, mmsize*2/4
52 jg .loop
53 REP_RET
54%endmacro
55
56INIT_XMM sse
57MIX_2_TO_1_FLTP_FLT
58%if HAVE_AVX_EXTERNAL
59INIT_YMM avx
60MIX_2_TO_1_FLTP_FLT
61%endif
62
63;-----------------------------------------------------------------------------
64; void ff_mix_2_to_1_s16p_flt(int16_t **src, float **matrix, int len,
65; int out_ch, int in_ch);
66;-----------------------------------------------------------------------------
67
68%macro MIX_2_TO_1_S16P_FLT 0
69cglobal mix_2_to_1_s16p_flt, 3,4,6, src, matrix, len, src1
70 mov src1q, [srcq+gprsize]
71 mov srcq, [srcq]
72 sub src1q, srcq
73 mov matrixq, [matrixq ]
74 VBROADCASTSS m4, [matrixq ]
75 VBROADCASTSS m5, [matrixq+4]
76 ALIGN 16
77.loop:
78 mova m0, [srcq ]
79 mova m2, [srcq+src1q]
80 S16_TO_S32_SX 0, 1
81 S16_TO_S32_SX 2, 3
82 cvtdq2ps m0, m0
83 cvtdq2ps m1, m1
84 cvtdq2ps m2, m2
85 cvtdq2ps m3, m3
86 mulps m0, m4
87 mulps m1, m4
88 mulps m2, m5
89 mulps m3, m5
90 addps m0, m2
91 addps m1, m3
92 cvtps2dq m0, m0
93 cvtps2dq m1, m1
94 packssdw m0, m1
95 mova [srcq], m0
96 add srcq, mmsize
97 sub lend, mmsize/2
98 jg .loop
99 REP_RET
100%endmacro
101
102INIT_XMM sse2
103MIX_2_TO_1_S16P_FLT
104INIT_XMM sse4
105MIX_2_TO_1_S16P_FLT
106
107;-----------------------------------------------------------------------------
108; void ff_mix_2_to_1_s16p_q8(int16_t **src, int16_t **matrix, int len,
109; int out_ch, int in_ch);
110;-----------------------------------------------------------------------------
111
112INIT_XMM sse2
113cglobal mix_2_to_1_s16p_q8, 3,4,6, src, matrix, len, src1
114 mov src1q, [srcq+gprsize]
115 mov srcq, [srcq]
116 sub src1q, srcq
117 mov matrixq, [matrixq]
118 movd m4, [matrixq]
119 movd m5, [matrixq]
120 SPLATW m4, m4, 0
121 SPLATW m5, m5, 1
122 pxor m0, m0
123 punpcklwd m4, m0
124 punpcklwd m5, m0
125 ALIGN 16
126.loop:
127 mova m0, [srcq ]
128 mova m2, [srcq+src1q]
129 punpckhwd m1, m0, m0
130 punpcklwd m0, m0
131 punpckhwd m3, m2, m2
132 punpcklwd m2, m2
133 pmaddwd m0, m4
134 pmaddwd m1, m4
135 pmaddwd m2, m5
136 pmaddwd m3, m5
137 paddd m0, m2
138 paddd m1, m3
139 psrad m0, 8
140 psrad m1, 8
141 packssdw m0, m1
142 mova [srcq], m0
143 add srcq, mmsize
144 sub lend, mmsize/2
145 jg .loop
146 REP_RET
147
148;-----------------------------------------------------------------------------
149; void ff_mix_1_to_2_fltp_flt(float **src, float **matrix, int len,
150; int out_ch, int in_ch);
151;-----------------------------------------------------------------------------
152
153%macro MIX_1_TO_2_FLTP_FLT 0
154cglobal mix_1_to_2_fltp_flt, 3,5,4, src0, matrix0, len, src1, matrix1
155 mov src1q, [src0q+gprsize]
156 mov src0q, [src0q]
157 sub src1q, src0q
158 mov matrix1q, [matrix0q+gprsize]
159 mov matrix0q, [matrix0q]
160 VBROADCASTSS m2, [matrix0q]
161 VBROADCASTSS m3, [matrix1q]
162 ALIGN 16
163.loop:
164 mova m0, [src0q]
165 mulps m1, m0, m3
166 mulps m0, m0, m2
167 mova [src0q ], m0
168 mova [src0q+src1q], m1
169 add src0q, mmsize
170 sub lend, mmsize/4
171 jg .loop
172 REP_RET
173%endmacro
174
175INIT_XMM sse
176MIX_1_TO_2_FLTP_FLT
177%if HAVE_AVX_EXTERNAL
178INIT_YMM avx
179MIX_1_TO_2_FLTP_FLT
180%endif
181
182;-----------------------------------------------------------------------------
183; void ff_mix_1_to_2_s16p_flt(int16_t **src, float **matrix, int len,
184; int out_ch, int in_ch);
185;-----------------------------------------------------------------------------
186
187%macro MIX_1_TO_2_S16P_FLT 0
188cglobal mix_1_to_2_s16p_flt, 3,5,6, src0, matrix0, len, src1, matrix1
189 mov src1q, [src0q+gprsize]
190 mov src0q, [src0q]
191 sub src1q, src0q
192 mov matrix1q, [matrix0q+gprsize]
193 mov matrix0q, [matrix0q]
194 VBROADCASTSS m4, [matrix0q]
195 VBROADCASTSS m5, [matrix1q]
196 ALIGN 16
197.loop:
198 mova m0, [src0q]
199 S16_TO_S32_SX 0, 2
200 cvtdq2ps m0, m0
201 cvtdq2ps m2, m2
202 mulps m1, m0, m5
203 mulps m0, m0, m4
204 mulps m3, m2, m5
205 mulps m2, m2, m4
206 cvtps2dq m0, m0
207 cvtps2dq m1, m1
208 cvtps2dq m2, m2
209 cvtps2dq m3, m3
210 packssdw m0, m2
211 packssdw m1, m3
212 mova [src0q ], m0
213 mova [src0q+src1q], m1
214 add src0q, mmsize
215 sub lend, mmsize/2
216 jg .loop
217 REP_RET
218%endmacro
219
220INIT_XMM sse2
221MIX_1_TO_2_S16P_FLT
222INIT_XMM sse4
223MIX_1_TO_2_S16P_FLT
224%if HAVE_AVX_EXTERNAL
225INIT_XMM avx
226MIX_1_TO_2_S16P_FLT
227%endif
228
229;-----------------------------------------------------------------------------
230; void ff_mix_3_8_to_1_2_fltp/s16p_flt(float/int16_t **src, float **matrix,
231; int len, int out_ch, int in_ch);
232;-----------------------------------------------------------------------------
233
234%macro MIX_3_8_TO_1_2_FLT 3 ; %1 = in channels, %2 = out channels, %3 = s16p or fltp
235; define some names to make the code clearer
236%assign in_channels %1
237%assign out_channels %2
238%assign stereo out_channels - 1
239%ifidn %3, s16p
240 %assign is_s16 1
241%else
242 %assign is_s16 0
243%endif
244
245; determine how many matrix elements must go on the stack vs. mmregs
246%assign matrix_elements in_channels * out_channels
247%if is_s16
248 %if stereo
249 %assign needed_mmregs 7
250 %else
251 %assign needed_mmregs 5
252 %endif
253%else
254 %if stereo
255 %assign needed_mmregs 4
256 %else
257 %assign needed_mmregs 3
258 %endif
259%endif
260%assign matrix_elements_mm num_mmregs - needed_mmregs
261%if matrix_elements < matrix_elements_mm
262 %assign matrix_elements_mm matrix_elements
263%endif
264%if matrix_elements_mm < matrix_elements
265 %assign matrix_elements_stack matrix_elements - matrix_elements_mm
266%else
267 %assign matrix_elements_stack 0
268%endif
269%assign matrix_stack_size matrix_elements_stack * mmsize
270
271%assign needed_stack_size -1 * matrix_stack_size
272%if ARCH_X86_32 && in_channels >= 7
273%assign needed_stack_size needed_stack_size - 16
274%endif
275
276cglobal mix_%1_to_%2_%3_flt, 3,in_channels+2,needed_mmregs+matrix_elements_mm, needed_stack_size, src0, src1, len, src2, src3, src4, src5, src6, src7
277
278; define src pointers on stack if needed
279%if matrix_elements_stack > 0 && ARCH_X86_32 && in_channels >= 7
280 %define src5m [rsp+matrix_stack_size+0]
281 %define src6m [rsp+matrix_stack_size+4]
282 %define src7m [rsp+matrix_stack_size+8]
283%endif
284
285; load matrix pointers
286%define matrix0q r1q
287%define matrix1q r3q
288%if stereo
289 mov matrix1q, [matrix0q+gprsize]
290%endif
291 mov matrix0q, [matrix0q]
292
293; define matrix coeff names
294%assign %%i 0
295%assign %%j needed_mmregs
296%rep in_channels
297 %if %%i >= matrix_elements_mm
298 CAT_XDEFINE mx_stack_0_, %%i, 1
299 CAT_XDEFINE mx_0_, %%i, [rsp+(%%i-matrix_elements_mm)*mmsize]
300 %else
301 CAT_XDEFINE mx_stack_0_, %%i, 0
302 CAT_XDEFINE mx_0_, %%i, m %+ %%j
303 %assign %%j %%j+1
304 %endif
305 %assign %%i %%i+1
306%endrep
307%if stereo
308%assign %%i 0
309%rep in_channels
310 %if in_channels + %%i >= matrix_elements_mm
311 CAT_XDEFINE mx_stack_1_, %%i, 1
312 CAT_XDEFINE mx_1_, %%i, [rsp+(in_channels+%%i-matrix_elements_mm)*mmsize]
313 %else
314 CAT_XDEFINE mx_stack_1_, %%i, 0
315 CAT_XDEFINE mx_1_, %%i, m %+ %%j
316 %assign %%j %%j+1
317 %endif
318 %assign %%i %%i+1
319%endrep
320%endif
321
322; load/splat matrix coeffs
323%assign %%i 0
324%rep in_channels
325 %if mx_stack_0_ %+ %%i
326 VBROADCASTSS m0, [matrix0q+4*%%i]
327 mova mx_0_ %+ %%i, m0
328 %else
329 VBROADCASTSS mx_0_ %+ %%i, [matrix0q+4*%%i]
330 %endif
331 %if stereo
332 %if mx_stack_1_ %+ %%i
333 VBROADCASTSS m0, [matrix1q+4*%%i]
334 mova mx_1_ %+ %%i, m0
335 %else
336 VBROADCASTSS mx_1_ %+ %%i, [matrix1q+4*%%i]
337 %endif
338 %endif
339 %assign %%i %%i+1
340%endrep
341
342; load channel pointers to registers as offsets from the first channel pointer
343%if ARCH_X86_64
344 movsxd lenq, r2d
345%endif
346 shl lenq, 2-is_s16
347%assign %%i 1
348%rep (in_channels - 1)
349 %if ARCH_X86_32 && in_channels >= 7 && %%i >= 5
350 mov src5q, [src0q+%%i*gprsize]
351 add src5q, lenq
352 mov src %+ %%i %+ m, src5q
353 %else
354 mov src %+ %%i %+ q, [src0q+%%i*gprsize]
355 add src %+ %%i %+ q, lenq
356 %endif
357 %assign %%i %%i+1
358%endrep
359 mov src0q, [src0q]
360 add src0q, lenq
361 neg lenq
362.loop:
363; for x86-32 with 7-8 channels we do not have enough gp registers for all src
364; pointers, so we have to load some of them from the stack each time
365%define copy_src_from_stack ARCH_X86_32 && in_channels >= 7 && %%i >= 5
366%if is_s16
367 ; mix with s16p input
368 mova m0, [src0q+lenq]
369 S16_TO_S32_SX 0, 1
370 cvtdq2ps m0, m0
371 cvtdq2ps m1, m1
372 %if stereo
373 mulps m2, m0, mx_1_0
374 mulps m3, m1, mx_1_0
375 %endif
376 mulps m0, m0, mx_0_0
377 mulps m1, m1, mx_0_0
378%assign %%i 1
379%rep (in_channels - 1)
380 %if copy_src_from_stack
381 %define src_ptr src5q
382 %else
383 %define src_ptr src %+ %%i %+ q
384 %endif
385 %if stereo
386 %if copy_src_from_stack
387 mov src_ptr, src %+ %%i %+ m
388 %endif
389 mova m4, [src_ptr+lenq]
390 S16_TO_S32_SX 4, 5
391 cvtdq2ps m4, m4
392 cvtdq2ps m5, m5
393 FMULADD_PS m2, m4, mx_1_ %+ %%i, m2, m6
394 FMULADD_PS m3, m5, mx_1_ %+ %%i, m3, m6
395 FMULADD_PS m0, m4, mx_0_ %+ %%i, m0, m4
396 FMULADD_PS m1, m5, mx_0_ %+ %%i, m1, m5
397 %else
398 %if copy_src_from_stack
399 mov src_ptr, src %+ %%i %+ m
400 %endif
401 mova m2, [src_ptr+lenq]
402 S16_TO_S32_SX 2, 3
403 cvtdq2ps m2, m2
404 cvtdq2ps m3, m3
405 FMULADD_PS m0, m2, mx_0_ %+ %%i, m0, m4
406 FMULADD_PS m1, m3, mx_0_ %+ %%i, m1, m4
407 %endif
408 %assign %%i %%i+1
409%endrep
410 %if stereo
411 cvtps2dq m2, m2
412 cvtps2dq m3, m3
413 packssdw m2, m3
414 mova [src1q+lenq], m2
415 %endif
416 cvtps2dq m0, m0
417 cvtps2dq m1, m1
418 packssdw m0, m1
419 mova [src0q+lenq], m0
420%else
421 ; mix with fltp input
422 %if stereo || mx_stack_0_0
423 mova m0, [src0q+lenq]
424 %endif
425 %if stereo
426 mulps m1, m0, mx_1_0
427 %endif
428 %if stereo || mx_stack_0_0
429 mulps m0, m0, mx_0_0
430 %else
431 mulps m0, mx_0_0, [src0q+lenq]
432 %endif
433%assign %%i 1
434%rep (in_channels - 1)
435 %if copy_src_from_stack
436 %define src_ptr src5q
437 mov src_ptr, src %+ %%i %+ m
438 %else
439 %define src_ptr src %+ %%i %+ q
440 %endif
441 ; avoid extra load for mono if matrix is in a mm register
442 %if stereo || mx_stack_0_ %+ %%i
443 mova m2, [src_ptr+lenq]
444 %endif
445 %if stereo
446 FMULADD_PS m1, m2, mx_1_ %+ %%i, m1, m3
447 %endif
448 %if stereo || mx_stack_0_ %+ %%i
449 FMULADD_PS m0, m2, mx_0_ %+ %%i, m0, m2
450 %else
451 FMULADD_PS m0, mx_0_ %+ %%i, [src_ptr+lenq], m0, m1
452 %endif
453 %assign %%i %%i+1
454%endrep
455 mova [src0q+lenq], m0
456 %if stereo
457 mova [src1q+lenq], m1
458 %endif
459%endif
460
461 add lenq, mmsize
462 jl .loop
463; zero ymm high halves
464%if mmsize == 32
465 vzeroupper
466%endif
467 RET
468%endmacro
469
470%macro MIX_3_8_TO_1_2_FLT_FUNCS 0
471%assign %%i 3
472%rep 6
473 INIT_XMM sse
474 MIX_3_8_TO_1_2_FLT %%i, 1, fltp
475 MIX_3_8_TO_1_2_FLT %%i, 2, fltp
476 INIT_XMM sse2
477 MIX_3_8_TO_1_2_FLT %%i, 1, s16p
478 MIX_3_8_TO_1_2_FLT %%i, 2, s16p
479 INIT_XMM sse4
480 MIX_3_8_TO_1_2_FLT %%i, 1, s16p
481 MIX_3_8_TO_1_2_FLT %%i, 2, s16p
482 ; do not use ymm AVX or FMA4 in x86-32 for 6 or more channels due to stack alignment issues
483 %if HAVE_AVX_EXTERNAL
484 %if ARCH_X86_64 || %%i < 6
485 INIT_YMM avx
486 %else
487 INIT_XMM avx
488 %endif
489 MIX_3_8_TO_1_2_FLT %%i, 1, fltp
490 MIX_3_8_TO_1_2_FLT %%i, 2, fltp
491 INIT_XMM avx
492 MIX_3_8_TO_1_2_FLT %%i, 1, s16p
493 MIX_3_8_TO_1_2_FLT %%i, 2, s16p
494 %endif
495 %if HAVE_FMA4_EXTERNAL
496 %if ARCH_X86_64 || %%i < 6
497 INIT_YMM fma4
498 %else
499 INIT_XMM fma4
500 %endif
501 MIX_3_8_TO_1_2_FLT %%i, 1, fltp
502 MIX_3_8_TO_1_2_FLT %%i, 2, fltp
503 INIT_XMM fma4
504 MIX_3_8_TO_1_2_FLT %%i, 1, s16p
505 MIX_3_8_TO_1_2_FLT %%i, 2, s16p
506 %endif
507 %assign %%i %%i+1
508%endrep
509%endmacro
510
511MIX_3_8_TO_1_2_FLT_FUNCS
libavresample/x86/audio_mix_init.c+0−215
@@ -1,215 +0,0 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "config.h"
22#include "libavutil/cpu.h"
23#include "libavutil/x86/cpu.h"
24#include "libavresample/audio_mix.h"
25
26void ff_mix_2_to_1_fltp_flt_sse(float **src, float **matrix, int len,
27 int out_ch, int in_ch);
28void ff_mix_2_to_1_fltp_flt_avx(float **src, float **matrix, int len,
29 int out_ch, int in_ch);
30
31void ff_mix_2_to_1_s16p_flt_sse2(int16_t **src, float **matrix, int len,
32 int out_ch, int in_ch);
33void ff_mix_2_to_1_s16p_flt_sse4(int16_t **src, float **matrix, int len,
34 int out_ch, int in_ch);
35
36void ff_mix_2_to_1_s16p_q8_sse2(int16_t **src, int16_t **matrix,
37 int len, int out_ch, int in_ch);
38
39void ff_mix_1_to_2_fltp_flt_sse(float **src, float **matrix, int len,
40 int out_ch, int in_ch);
41void ff_mix_1_to_2_fltp_flt_avx(float **src, float **matrix, int len,
42 int out_ch, int in_ch);
43
44void ff_mix_1_to_2_s16p_flt_sse2(int16_t **src, float **matrix, int len,
45 int out_ch, int in_ch);
46void ff_mix_1_to_2_s16p_flt_sse4(int16_t **src, float **matrix, int len,
47 int out_ch, int in_ch);
48void ff_mix_1_to_2_s16p_flt_avx (int16_t **src, float **matrix, int len,
49 int out_ch, int in_ch);
50
51#define DEFINE_MIX_3_8_TO_1_2(chan) \
52void ff_mix_ ## chan ## _to_1_fltp_flt_sse(float **src, \
53 float **matrix, int len, \
54 int out_ch, int in_ch); \
55void ff_mix_ ## chan ## _to_2_fltp_flt_sse(float **src, \
56 float **matrix, int len, \
57 int out_ch, int in_ch); \
58 \
59void ff_mix_ ## chan ## _to_1_s16p_flt_sse2(int16_t **src, \
60 float **matrix, int len, \
61 int out_ch, int in_ch); \
62void ff_mix_ ## chan ## _to_2_s16p_flt_sse2(int16_t **src, \
63 float **matrix, int len, \
64 int out_ch, int in_ch); \
65 \
66void ff_mix_ ## chan ## _to_1_s16p_flt_sse4(int16_t **src, \
67 float **matrix, int len, \
68 int out_ch, int in_ch); \
69void ff_mix_ ## chan ## _to_2_s16p_flt_sse4(int16_t **src, \
70 float **matrix, int len, \
71 int out_ch, int in_ch); \
72 \
73void ff_mix_ ## chan ## _to_1_fltp_flt_avx(float **src, \
74 float **matrix, int len, \
75 int out_ch, int in_ch); \
76void ff_mix_ ## chan ## _to_2_fltp_flt_avx(float **src, \
77 float **matrix, int len, \
78 int out_ch, int in_ch); \
79 \
80void ff_mix_ ## chan ## _to_1_s16p_flt_avx(int16_t **src, \
81 float **matrix, int len, \
82 int out_ch, int in_ch); \
83void ff_mix_ ## chan ## _to_2_s16p_flt_avx(int16_t **src, \
84 float **matrix, int len, \
85 int out_ch, int in_ch); \
86 \
87void ff_mix_ ## chan ## _to_1_fltp_flt_fma4(float **src, \
88 float **matrix, int len, \
89 int out_ch, int in_ch); \
90void ff_mix_ ## chan ## _to_2_fltp_flt_fma4(float **src, \
91 float **matrix, int len, \
92 int out_ch, int in_ch); \
93 \
94void ff_mix_ ## chan ## _to_1_s16p_flt_fma4(int16_t **src, \
95 float **matrix, int len, \
96 int out_ch, int in_ch); \
97void ff_mix_ ## chan ## _to_2_s16p_flt_fma4(int16_t **src, \
98 float **matrix, int len, \
99 int out_ch, int in_ch);
100
101DEFINE_MIX_3_8_TO_1_2(3)
102DEFINE_MIX_3_8_TO_1_2(4)
103DEFINE_MIX_3_8_TO_1_2(5)
104DEFINE_MIX_3_8_TO_1_2(6)
105DEFINE_MIX_3_8_TO_1_2(7)
106DEFINE_MIX_3_8_TO_1_2(8)
107
108#define SET_MIX_3_8_TO_1_2(chan) \
109 if (EXTERNAL_SSE(cpu_flags)) { \
110 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,\
111 chan, 1, 16, 4, "SSE", \
112 ff_mix_ ## chan ## _to_1_fltp_flt_sse); \
113 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,\
114 chan, 2, 16, 4, "SSE", \
115 ff_mix_## chan ##_to_2_fltp_flt_sse); \
116 } \
117 if (EXTERNAL_SSE2(cpu_flags)) { \
118 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,\
119 chan, 1, 16, 8, "SSE2", \
120 ff_mix_ ## chan ## _to_1_s16p_flt_sse2); \
121 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,\
122 chan, 2, 16, 8, "SSE2", \
123 ff_mix_ ## chan ## _to_2_s16p_flt_sse2); \
124 } \
125 if (EXTERNAL_SSE4(cpu_flags)) { \
126 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,\
127 chan, 1, 16, 8, "SSE4", \
128 ff_mix_ ## chan ## _to_1_s16p_flt_sse4); \
129 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,\
130 chan, 2, 16, 8, "SSE4", \
131 ff_mix_ ## chan ## _to_2_s16p_flt_sse4); \
132 } \
133 if (EXTERNAL_AVX(cpu_flags)) { \
134 int ptr_align = 32; \
135 int smp_align = 8; \
136 if (ARCH_X86_32 || chan >= 6) { \
137 ptr_align = 16; \
138 smp_align = 4; \
139 } \
140 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,\
141 chan, 1, ptr_align, smp_align, "AVX", \
142 ff_mix_ ## chan ## _to_1_fltp_flt_avx); \
143 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,\
144 chan, 2, ptr_align, smp_align, "AVX", \
145 ff_mix_ ## chan ## _to_2_fltp_flt_avx); \
146 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,\
147 chan, 1, 16, 8, "AVX", \
148 ff_mix_ ## chan ## _to_1_s16p_flt_avx); \
149 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,\
150 chan, 2, 16, 8, "AVX", \
151 ff_mix_ ## chan ## _to_2_s16p_flt_avx); \
152 } \
153 if (EXTERNAL_FMA4(cpu_flags)) { \
154 int ptr_align = 32; \
155 int smp_align = 8; \
156 if (ARCH_X86_32 || chan >= 6) { \
157 ptr_align = 16; \
158 smp_align = 4; \
159 } \
160 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,\
161 chan, 1, ptr_align, smp_align, "FMA4", \
162 ff_mix_ ## chan ## _to_1_fltp_flt_fma4); \
163 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,\
164 chan, 2, ptr_align, smp_align, "FMA4", \
165 ff_mix_ ## chan ## _to_2_fltp_flt_fma4); \
166 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,\
167 chan, 1, 16, 8, "FMA4", \
168 ff_mix_ ## chan ## _to_1_s16p_flt_fma4); \
169 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,\
170 chan, 2, 16, 8, "FMA4", \
171 ff_mix_ ## chan ## _to_2_s16p_flt_fma4); \
172 }
173
174av_cold void ff_audio_mix_init_x86(AudioMix *am)
175{
176 int cpu_flags = av_get_cpu_flags();
177
178 if (EXTERNAL_SSE(cpu_flags)) {
179 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
180 2, 1, 16, 8, "SSE", ff_mix_2_to_1_fltp_flt_sse);
181 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
182 1, 2, 16, 4, "SSE", ff_mix_1_to_2_fltp_flt_sse);
183 }
184 if (EXTERNAL_SSE2(cpu_flags)) {
185 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
186 2, 1, 16, 8, "SSE2", ff_mix_2_to_1_s16p_flt_sse2);
187 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q8,
188 2, 1, 16, 8, "SSE2", ff_mix_2_to_1_s16p_q8_sse2);
189 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
190 1, 2, 16, 8, "SSE2", ff_mix_1_to_2_s16p_flt_sse2);
191 }
192 if (EXTERNAL_SSE4(cpu_flags)) {
193 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
194 2, 1, 16, 8, "SSE4", ff_mix_2_to_1_s16p_flt_sse4);
195 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
196 1, 2, 16, 8, "SSE4", ff_mix_1_to_2_s16p_flt_sse4);
197 }
198 if (EXTERNAL_AVX_FAST(cpu_flags)) {
199 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
200 2, 1, 32, 16, "AVX", ff_mix_2_to_1_fltp_flt_avx);
201 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
202 1, 2, 32, 8, "AVX", ff_mix_1_to_2_fltp_flt_avx);
203 }
204 if (EXTERNAL_AVX(cpu_flags)) {
205 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
206 1, 2, 16, 8, "AVX", ff_mix_1_to_2_s16p_flt_avx);
207 }
208
209 SET_MIX_3_8_TO_1_2(3)
210 SET_MIX_3_8_TO_1_2(4)
211 SET_MIX_3_8_TO_1_2(5)
212 SET_MIX_3_8_TO_1_2(6)
213 SET_MIX_3_8_TO_1_2(7)
214 SET_MIX_3_8_TO_1_2(8)
215}
libavresample/x86/dither.asm+0−117
@@ -1,117 +0,0 @@
1;******************************************************************************
2;* x86 optimized dithering format conversion
3;* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4;*
5;* This file is part of FFmpeg.
6;*
7;* FFmpeg is free software; you can redistribute it and/or
8;* modify it under the terms of the GNU Lesser General Public
9;* License as published by the Free Software Foundation; either
10;* version 2.1 of the License, or (at your option) any later version.
11;*
12;* FFmpeg is distributed in the hope that it will be useful,
13;* but WITHOUT ANY WARRANTY; without even the implied warranty of
14;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15;* Lesser General Public License for more details.
16;*
17;* You should have received a copy of the GNU Lesser General Public
18;* License along with FFmpeg; if not, write to the Free Software
19;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20;******************************************************************************
21
22%include "libavutil/x86/x86util.asm"
23
24SECTION_RODATA 32
25
26; 1.0f / (2.0f * INT32_MAX)
27pf_dither_scale: times 8 dd 2.32830643762e-10
28
29pf_s16_scale: times 4 dd 32753.0
30
31SECTION .text
32
33;------------------------------------------------------------------------------
34; void ff_quantize(int16_t *dst, float *src, float *dither, int len);
35;------------------------------------------------------------------------------
36
37INIT_XMM sse2
38cglobal quantize, 4,4,3, dst, src, dither, len
39 lea lenq, [2*lend]
40 add dstq, lenq
41 lea srcq, [srcq+2*lenq]
42 lea ditherq, [ditherq+2*lenq]
43 neg lenq
44 mova m2, [pf_s16_scale]
45.loop:
46 mulps m0, m2, [srcq+2*lenq]
47 mulps m1, m2, [srcq+2*lenq+mmsize]
48 addps m0, [ditherq+2*lenq]
49 addps m1, [ditherq+2*lenq+mmsize]
50 cvtps2dq m0, m0
51 cvtps2dq m1, m1
52 packssdw m0, m1
53 mova [dstq+lenq], m0
54 add lenq, mmsize
55 jl .loop
56 REP_RET
57
58;------------------------------------------------------------------------------
59; void ff_dither_int_to_float_rectangular(float *dst, int *src, int len)
60;------------------------------------------------------------------------------
61
62%macro DITHER_INT_TO_FLOAT_RECTANGULAR 0
63cglobal dither_int_to_float_rectangular, 3,3,3, dst, src, len
64 lea lenq, [4*lend]
65 add srcq, lenq
66 add dstq, lenq
67 neg lenq
68 mova m0, [pf_dither_scale]
69.loop:
70 cvtdq2ps m1, [srcq+lenq]
71 cvtdq2ps m2, [srcq+lenq+mmsize]
72 mulps m1, m1, m0
73 mulps m2, m2, m0
74 mova [dstq+lenq], m1
75 mova [dstq+lenq+mmsize], m2
76 add lenq, 2*mmsize
77 jl .loop
78 REP_RET
79%endmacro
80
81INIT_XMM sse2
82DITHER_INT_TO_FLOAT_RECTANGULAR
83INIT_YMM avx
84DITHER_INT_TO_FLOAT_RECTANGULAR
85
86;------------------------------------------------------------------------------
87; void ff_dither_int_to_float_triangular(float *dst, int *src0, int len)
88;------------------------------------------------------------------------------
89
90%macro DITHER_INT_TO_FLOAT_TRIANGULAR 0
91cglobal dither_int_to_float_triangular, 3,4,5, dst, src0, len, src1
92 lea lenq, [4*lend]
93 lea src1q, [src0q+2*lenq]
94 add src0q, lenq
95 add dstq, lenq
96 neg lenq
97 mova m0, [pf_dither_scale]
98.loop:
99 cvtdq2ps m1, [src0q+lenq]
100 cvtdq2ps m2, [src0q+lenq+mmsize]
101 cvtdq2ps m3, [src1q+lenq]
102 cvtdq2ps m4, [src1q+lenq+mmsize]
103 addps m1, m1, m3
104 addps m2, m2, m4
105 mulps m1, m1, m0
106 mulps m2, m2, m0
107 mova [dstq+lenq], m1
108 mova [dstq+lenq+mmsize], m2
109 add lenq, 2*mmsize
110 jl .loop
111 REP_RET
112%endmacro
113
114INIT_XMM sse2
115DITHER_INT_TO_FLOAT_TRIANGULAR
116INIT_YMM avx
117DITHER_INT_TO_FLOAT_TRIANGULAR
libavresample/x86/dither_init.c+0−60
@@ -1,60 +0,0 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "config.h"
22#include "libavutil/cpu.h"
23#include "libavutil/x86/cpu.h"
24#include "libavresample/dither.h"
25
26void ff_quantize_sse2(int16_t *dst, const float *src, float *dither, int len);
27
28void ff_dither_int_to_float_rectangular_sse2(float *dst, int *src, int len);
29void ff_dither_int_to_float_rectangular_avx(float *dst, int *src, int len);
30
31void ff_dither_int_to_float_triangular_sse2(float *dst, int *src0, int len);
32void ff_dither_int_to_float_triangular_avx(float *dst, int *src0, int len);
33
34av_cold void ff_dither_init_x86(DitherDSPContext *ddsp,
35 enum AVResampleDitherMethod method)
36{
37 int cpu_flags = av_get_cpu_flags();
38
39 if (EXTERNAL_SSE2(cpu_flags)) {
40 ddsp->quantize = ff_quantize_sse2;
41 ddsp->ptr_align = 16;
42 ddsp->samples_align = 8;
43 }
44
45 if (method == AV_RESAMPLE_DITHER_RECTANGULAR) {
46 if (EXTERNAL_SSE2(cpu_flags)) {
47 ddsp->dither_int_to_float = ff_dither_int_to_float_rectangular_sse2;
48 }
49 if (EXTERNAL_AVX_FAST(cpu_flags)) {
50 ddsp->dither_int_to_float = ff_dither_int_to_float_rectangular_avx;
51 }
52 } else {
53 if (EXTERNAL_SSE2(cpu_flags)) {
54 ddsp->dither_int_to_float = ff_dither_int_to_float_triangular_sse2;
55 }
56 if (EXTERNAL_AVX_FAST(cpu_flags)) {
57 ddsp->dither_int_to_float = ff_dither_int_to_float_triangular_avx;
58 }
59 }
60}
libavresample/x86/util.asm+0−41
@@ -1,41 +0,0 @@
1;******************************************************************************
2;* x86 utility macros for libavresample
3;* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4;*
5;* This file is part of FFmpeg.
6;*
7;* FFmpeg is free software; you can redistribute it and/or
8;* modify it under the terms of the GNU Lesser General Public
9;* License as published by the Free Software Foundation; either
10;* version 2.1 of the License, or (at your option) any later version.
11;*
12;* FFmpeg is distributed in the hope that it will be useful,
13;* but WITHOUT ANY WARRANTY; without even the implied warranty of
14;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15;* Lesser General Public License for more details.
16;*
17;* You should have received a copy of the GNU Lesser General Public
18;* License along with FFmpeg; if not, write to the Free Software
19;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20;******************************************************************************
21
22%macro S16_TO_S32_SX 2 ; src/low dst, high dst
23%if cpuflag(sse4)
24 pmovsxwd m%2, m%1
25 psrldq m%1, 8
26 pmovsxwd m%1, m%1
27 SWAP %1, %2
28%else
29 mova m%2, m%1
30 punpckhwd m%2, m%2
31 punpcklwd m%1, m%1
32 psrad m%2, 16
33 psrad m%1, 16
34%endif
35%endmacro
36
37%macro DEINT2_PS 3 ; src0/even dst, src1/odd dst, temp
38 shufps m%3, m%1, m%2, q3131
39 shufps m%1, m%2, q2020
40 SWAP %2,%3
41%endmacro
libavresample/x86/w64xmmtest.c+0−31
@@ -1,31 +0,0 @@
1/*
2 * check XMM registers for clobbers on Win64
3 * Copyright (c) 2013 Martin Storsjo
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "libavresample/avresample.h"
23#include "libavutil/x86/w64xmmtest.h"
24
25wrap(avresample_convert(AVAudioResampleContext *avr, uint8_t **output,
26 int out_plane_size, int out_samples, uint8_t **input,
27 int in_plane_size, int in_samples))
28{
29 testxmmclobbers(avresample_convert, avr, output, out_plane_size,
30 out_samples, input, in_plane_size, in_samples);
31}
tests/Makefile+0−1
@@ -157,7 +157,6 @@ include $(SRC_PATH)/tests/fate/indeo.mak · 156 unmodified lines
157include $(SRC_PATH)/tests/fate/libavcodec.mak157include $(SRC_PATH)/tests/fate/libavcodec.mak
158include $(SRC_PATH)/tests/fate/libavdevice.mak158include $(SRC_PATH)/tests/fate/libavdevice.mak
159include $(SRC_PATH)/tests/fate/libavformat.mak159include $(SRC_PATH)/tests/fate/libavformat.mak
160include $(SRC_PATH)/tests/fate/libavresample.mak
161include $(SRC_PATH)/tests/fate/libavutil.mak160include $(SRC_PATH)/tests/fate/libavutil.mak
162include $(SRC_PATH)/tests/fate/libswresample.mak161include $(SRC_PATH)/tests/fate/libswresample.mak
163include $(SRC_PATH)/tests/fate/libswscale.mak162include $(SRC_PATH)/tests/fate/libswscale.mak
tests/fate.sh+0−1
@@ -48,7 +48,6 @@ configure()( · 47 unmodified lines
48 --samples="${samples}" \48 --samples="${samples}" \
49 --enable-gpl \49 --enable-gpl \
50 --enable-memory-poisoning \50 --enable-memory-poisoning \
51 --enable-avresample \
52 ${ignore_tests:+--ignore-tests="$ignore_tests"} \51 ${ignore_tests:+--ignore-tests="$ignore_tests"} \
53 ${arch:+--arch=$arch} \52 ${arch:+--arch=$arch} \
54 ${cpu:+--cpu="$cpu"} \53 ${cpu:+--cpu="$cpu"} \
tests/fate/libavresample.mak+0−68
@@ -1,68 +0,0 @@
1CROSS_TEST = $(foreach I,$(1), \
2 $(foreach J,$(1), \
3 $(if $(filter-out $(I),$(J)), \
4 $(eval $(call $(2),$(I),$(J),$(3),$(4),$(5))), \
5 )))
6
7MIX_CHANNELS = 1 2 3 4 5 6 7 8
8
9define MIX
10FATE_LAVR_MIX += fate-lavr-mix-$(3)-$(1)-$(2)
11fate-lavr-mix-$(3)-$(1)-$(2): tests/data/asynth-44100-$(1).wav
12fate-lavr-mix-$(3)-$(1)-$(2): CMD = ffmpeg -i $(TARGET_PATH)/tests/data/asynth-44100-$(1).wav -ac $(2) -mix_coeff_type $(3) -internal_sample_fmt $(4) -f s16le -af atrim=end_sample=1024 -
13fate-lavr-mix-$(3)-$(1)-$(2): CMP = oneoff
14fate-lavr-mix-$(3)-$(1)-$(2): REF = $(SAMPLES)/lavr/lavr-mix-$(3)-$(1)-$(2)
15endef
16
17$(call CROSS_TEST,$(MIX_CHANNELS),MIX,q8,s16p)
18$(call CROSS_TEST,$(MIX_CHANNELS),MIX,q15,s16p)
19$(call CROSS_TEST,$(MIX_CHANNELS),MIX,flt,fltp)
20
21# test output zeroing with skipped corresponding input
22FATE_LAVR_MIX-$(call FILTERDEMDECENCMUX, CHANNELMAP RESAMPLE, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-lavr-mix-output-zero
23fate-lavr-mix-output-zero: tests/data/filtergraphs/lavr_mix_output_zero tests/data/asynth-44100-4.wav
24fate-lavr-mix-output-zero: CMP = oneoff
25fate-lavr-mix-output-zero: CMD = ffmpeg -i $(TARGET_PATH)/tests/data/asynth-44100-4.wav -filter_script $(TARGET_PATH)/tests/data/filtergraphs/lavr_mix_output_zero -f s16le -
26fate-lavr-mix-output-zero: REF = $(SAMPLES)/lavr/lavr-mix-output-zero
27
28FATE_LAVR_MIX-$(call FILTERDEMDECENCMUX, RESAMPLE, WAV, PCM_S16LE, PCM_S16LE, WAV) += $(FATE_LAVR_MIX)
29fate-lavr-mix: $(FATE_LAVR_MIX-yes)
30#FATE_LAVR += $(FATE_LAVR_MIX-yes)
31
32SAMPLERATES = 2626 8000 44100 48000 96000
33
34define RESAMPLE
35FATE_LAVR_RESAMPLE += fate-lavr-resample-$(3)-$(1)-$(2)
36fate-lavr-resample-$(3)-$(1)-$(2): tests/data/asynth-$(1)-1.wav
37fate-lavr-resample-$(3)-$(1)-$(2): CMD = ffmpeg -i $(TARGET_PATH)/tests/data/asynth-$(1)-1.wav -ar $(2) -internal_sample_fmt $(3) -f $(4) -af atrim=end_sample=10240 -
38fate-lavr-resample-$(3)-$(1)-$(2): CMP = oneoff
39fate-lavr-resample-$(3)-$(1)-$(2): CMP_UNIT = $(5)
40fate-lavr-resample-$(3)-$(1)-$(2): FUZZ = 6
41fate-lavr-resample-$(3)-$(1)-$(2): REF = $(SAMPLES)/lavr/lavr-resample-$(3)-$(1)-$(2)-v3
42endef
43
44$(call CROSS_TEST,$(SAMPLERATES),RESAMPLE,s16p,s16le,s16)
45$(call CROSS_TEST,$(SAMPLERATES),RESAMPLE,s32p,s32le,s16)
46$(call CROSS_TEST,$(SAMPLERATES),RESAMPLE,fltp,f32le,f32)
47$(call CROSS_TEST,$(SAMPLERATES),RESAMPLE,dblp,f64le,f64)
48
49FATE_LAVR_RESAMPLE += fate-lavr-resample-linear
50fate-lavr-resample-linear: tests/data/asynth-44100-1.wav
51fate-lavr-resample-linear: CMD = ffmpeg -i $(TARGET_PATH)/tests/data/asynth-44100-1.wav -ar 48000 -filter_size 32 -linear_interp 1 -f s16le -af atrim=end_sample=10240 -
52fate-lavr-resample-linear: CMP = oneoff
53fate-lavr-resample-linear: CMP_UNIT = s16
54fate-lavr-resample-linear: REF = $(SAMPLES)/lavr/lavr-resample-linear
55
56FATE_LAVR_RESAMPLE += fate-lavr-resample-nearest
57fate-lavr-resample-nearest: tests/data/asynth-48000-1.wav
58fate-lavr-resample-nearest: CMD = ffmpeg -i $(TARGET_PATH)/tests/data/asynth-48000-1.wav -ar 44100 -filter_size 0 -phase_shift 0 -f s16le -af atrim=end_sample=10240 -
59fate-lavr-resample-nearest: CMP = oneoff
60fate-lavr-resample-nearest: CMP_UNIT = s16
61fate-lavr-resample-nearest: REF = $(SAMPLES)/lavr/lavr-resample-nearest
62
63FATE_LAVR_RESAMPLE-$(call FILTERDEMDECENCMUX, RESAMPLE, WAV, PCM_S16LE, PCM_S16LE, WAV) += $(FATE_LAVR_RESAMPLE)
64fate-lavr-resample: $(FATE_LAVR_RESAMPLE-yes)
65#FATE_LAVR += $(FATE_LAVR_RESAMPLE-yes)
66
67FATE_SAMPLES_AVCONV += $(FATE_LAVR)
68fate-lavr: $(FATE_LAVR)
tools/gen-rc+0−1
@@ -43,7 +43,6 @@ EOF · 42 unmodified lines
43# gen-rc libavdevice "FFmpeg device handling library"43# gen-rc libavdevice "FFmpeg device handling library"
44# gen-rc libavfilter "FFmpeg audio/video filtering library"44# gen-rc libavfilter "FFmpeg audio/video filtering library"
45# gen-rc libpostproc "FFmpeg postprocessing library"45# gen-rc libpostproc "FFmpeg postprocessing library"
46# gen-rc libavresample "Libav audio resampling library"
47# gen-rc libswscale "FFmpeg image rescaling library"46# gen-rc libswscale "FFmpeg image rescaling library"
48# gen-rc libswresample "FFmpeg audio resampling library"47# gen-rc libswresample "FFmpeg audio resampling library"
49 48
tools/target_dec_fuzzer.c+1−1
@@ -30,7 +30,7 @@ · 29 unmodified lines
30 * build the fuzz target.30 * build the fuzz target.
31 Choose the value of FFMPEG_CODEC (e.g. AV_CODEC_ID_DVD_SUBTITLE) and31 Choose the value of FFMPEG_CODEC (e.g. AV_CODEC_ID_DVD_SUBTITLE) and
32 choose one of FUZZ_FFMPEG_VIDEO, FUZZ_FFMPEG_AUDIO, FUZZ_FFMPEG_SUBTITLE.32 choose one of FUZZ_FFMPEG_VIDEO, FUZZ_FFMPEG_AUDIO, FUZZ_FFMPEG_SUBTITLE.
33 clang -fsanitize=address -fsanitize-coverage=trace-pc-guard,trace-cmp tools/target_dec_fuzzer.c -o target_dec_fuzzer -I. -DFFMPEG_CODEC=AV_CODEC_ID_MPEG1VIDEO -DFUZZ_FFMPEG_VIDEO ../../libfuzzer/libFuzzer.a -Llibavcodec -Llibavdevice -Llibavfilter -Llibavformat -Llibavresample -Llibavutil -Llibpostproc -Llibswscale -Llibswresample -Wl,--as-needed -Wl,-z,noexecstack -Wl,--warn-common -Wl,-rpath-link=:libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil:libavresample -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -ldl -lxcb -lxcb-shm -lxcb -lxcb-xfixes -lxcb -lxcb-shape -lxcb -lX11 -lasound -lm -lbz2 -lz -pthread33 clang -fsanitize=address -fsanitize-coverage=trace-pc-guard,trace-cmp tools/target_dec_fuzzer.c -o target_dec_fuzzer -I. -DFFMPEG_CODEC=AV_CODEC_ID_MPEG1VIDEO -DFUZZ_FFMPEG_VIDEO ../../libfuzzer/libFuzzer.a -Llibavcodec -Llibavdevice -Llibavfilter -Llibavformat -Llibavutil -Llibpostproc -Llibswscale -Llibswresample -Wl,--as-needed -Wl,-z,noexecstack -Wl,--warn-common -Wl,-rpath-link=:libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -ldl -lxcb -lxcb-shm -lxcb -lxcb-xfixes -lxcb -lxcb-shape -lxcb -lX11 -lasound -lm -lbz2 -lz -pthread
34 * create a corpus directory and put some samples there (empty dir is ok too):34 * create a corpus directory and put some samples there (empty dir is ok too):
35 mkdir CORPUS && cp some-files CORPUS35 mkdir CORPUS && cp some-files CORPUS
36 36

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

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

Repository code

Go to file
t