Deprecated in c29038f3041a4080342b2e333c1967d136749c0f. The resample filter based upon this library has been removed as well.
Unified · Split
| @@ -23,7 +23,6 @@ FFLIBS-$(CONFIG_AVDEVICE) += avdevice · 22 unmodified lines | ||
| 23 | 23 | FFLIBS-$(CONFIG_AVFILTER) += avfilter |
| 24 | 24 | FFLIBS-$(CONFIG_AVFORMAT) += avformat |
| 25 | 25 | FFLIBS-$(CONFIG_AVCODEC) += avcodec |
| 26 | −FFLIBS-$(CONFIG_AVRESAMPLE) += avresample | |
| 27 | 26 | FFLIBS-$(CONFIG_POSTPROC) += postproc |
| 28 | 27 | FFLIBS-$(CONFIG_SWRESAMPLE) += swresample |
| 29 | 28 | FFLIBS-$(CONFIG_SWSCALE) += swscale |
| @@ -132,7 +132,6 @@ Component options: · 131 unmodified lines | ||
| 132 | 132 | --disable-swscale disable libswscale build |
| 133 | 133 | --disable-postproc disable libpostproc build |
| 134 | 134 | --disable-avfilter disable libavfilter build |
| 135 | − --enable-avresample enable libavresample build (deprecated) [no] | |
| 136 | 135 | --disable-pthreads disable pthreads [autodetect] |
| 137 | 136 | --disable-w32threads disable Win32 threads [autodetect] |
| 138 | 137 | --disable-os2threads disable OS/2 threads [autodetect] |
| @@ -1901,7 +1900,6 @@ LIBRARY_LIST=" · 1762 unmodified lines | ||
| 1901 | 1900 | avformat |
| 1902 | 1901 | avcodec |
| 1903 | 1902 | swresample |
| 1904 | − avresample | |
| 1905 | 1903 | avutil |
| 1906 | 1904 | " |
| 1907 | 1905 | |
| @@ -3609,7 +3607,6 @@ program_opencl_filter_deps="opencl" · 1701 unmodified lines | ||
| 3609 | 3607 | pullup_filter_deps="gpl" |
| 3610 | 3608 | removelogo_filter_deps="avcodec avformat swscale" |
| 3611 | 3609 | repeatfields_filter_deps="gpl" |
| 3612 | −resample_filter_deps="avresample" | |
| 3613 | 3610 | roberts_opencl_filter_deps="opencl" |
| 3614 | 3611 | rubberband_filter_deps="librubberband" |
| 3615 | 3612 | sab_filter_deps="gpl swscale" |
| @@ -3711,8 +3708,6 @@ avfilter_deps="avutil" · 95 unmodified lines | ||
| 3711 | 3708 | avfilter_suggest="libm" |
| 3712 | 3709 | avformat_deps="avcodec avutil" |
| 3713 | 3710 | avformat_suggest="libm network zlib" |
| 3714 | −avresample_deps="avutil" | |
| 3715 | −avresample_suggest="libm" | |
| 3716 | 3711 | avutil_suggest="clock_gettime ffnvcodec libm libdrm libmfx opencl user32 vaapi vulkan videotoolbox corefoundation corevideo coremedia bcrypt" |
| 3717 | 3712 | postproc_deps="avutil gpl" |
| 3718 | 3713 | postproc_suggest="libm" |
| @@ -3795,7 +3790,7 @@ intrinsics="none" · 76 unmodified lines | ||
| 3795 | 3790 | enable $PROGRAM_LIST |
| 3796 | 3791 | enable $DOCUMENT_LIST |
| 3797 | 3792 | enable $EXAMPLE_LIST |
| 3798 | −enable $(filter_out avresample $LIBRARY_LIST) | |
| 3793 | +enable $LIBRARY_LIST | |
| 3799 | 3794 | enable stripping |
| 3800 | 3795 | |
| 3801 | 3796 | enable asm |
| @@ -6845,7 +6840,7 @@ EOF · 3043 unmodified lines | ||
| 6845 | 6840 | |
| 6846 | 6841 | # add some linker flags |
| 6847 | 6842 | check_ldflags -Wl,--warn-common |
| 6848 | −check_ldflags -Wl,-rpath-link=:libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil:libavresample | |
| 6843 | +check_ldflags -Wl,-rpath-link=:libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil | |
| 6849 | 6844 | enabled rpath && add_ldexeflags -Wl,-rpath,$libdir && add_ldsoflags -Wl,-rpath,$libdir |
| 6850 | 6845 | test_ldflags -Wl,-Bsymbolic && append SHFLAGS -Wl,-Bsymbolic |
| 6851 | 6846 | |
| @@ -6860,8 +6855,7 @@ enabled neon_clobber_test && · 8 unmodified lines | ||
| 6860 | 6855 | -Wl,--wrap,avcodec_receive_packet \ |
| 6861 | 6856 | -Wl,--wrap,avcodec_send_frame \ |
| 6862 | 6857 | -Wl,--wrap,avcodec_receive_frame \ |
| 6863 | − -Wl,--wrap,swr_convert \ | |
| 6864 | − -Wl,--wrap,avresample_convert || | |
| 6858 | + -Wl,--wrap,swr_convert || | |
| 6865 | 6859 | disable neon_clobber_test |
| 6866 | 6860 | |
| 6867 | 6861 | enabled xmm_clobber_test && |
| @@ -6873,7 +6867,6 @@ enabled xmm_clobber_test && · 5 unmodified lines | ||
| 6873 | 6867 | -Wl,--wrap,avcodec_send_frame \ |
| 6874 | 6868 | -Wl,--wrap,avcodec_receive_frame \ |
| 6875 | 6869 | -Wl,--wrap,swr_convert \ |
| 6876 | − -Wl,--wrap,avresample_convert \ | |
| 6877 | 6870 | -Wl,--wrap,sws_scale || |
| 6878 | 6871 | disable xmm_clobber_test |
| 6879 | 6872 | |
| @@ -7098,7 +7091,6 @@ check_deps $CONFIG_LIST \ · 218 unmodified lines | ||
| 7098 | 7091 | $ALL_COMPONENTS \ |
| 7099 | 7092 | |
| 7100 | 7093 | enabled 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" |
| 7101 | −enabled avresample && warn "Building with deprecated library libavresample" | |
| 7102 | 7094 | |
| 7103 | 7095 | case $target_os in |
| 7104 | 7096 | haiku) |
| @@ -7214,7 +7206,6 @@ enabled movie_filter && prepend avfilter_deps "avformat avcodec" · 109 unmodified lines | ||
| 7214 | 7206 | enabled pan_filter && prepend avfilter_deps "swresample" |
| 7215 | 7207 | enabled pp_filter && prepend avfilter_deps "postproc" |
| 7216 | 7208 | enabled removelogo_filter && prepend avfilter_deps "avformat avcodec swscale" |
| 7217 | −enabled resample_filter && prepend avfilter_deps "avresample" | |
| 7218 | 7209 | enabled sab_filter && prepend avfilter_deps "swscale" |
| 7219 | 7210 | enabled scale_filter && prepend avfilter_deps "swscale" |
| 7220 | 7211 | enabled scale2ref_filter && prepend avfilter_deps "swscale" |
| @@ -7707,7 +7698,6 @@ extralibs_avcodec="$avcodec_extralibs" · 486 unmodified lines | ||
| 7707 | 7698 | extralibs_avformat="$avformat_extralibs" |
| 7708 | 7699 | extralibs_avdevice="$avdevice_extralibs" |
| 7709 | 7700 | extralibs_avfilter="$avfilter_extralibs" |
| 7710 | −extralibs_avresample="$avresample_extralibs" | |
| 7711 | 7701 | extralibs_postproc="$postproc_extralibs" |
| 7712 | 7702 | extralibs_swscale="$swscale_extralibs" |
| 7713 | 7703 | extralibs_swresample="$swresample_extralibs" |
| @@ -6,7 +6,6 @@ libavcodec: 2017-10-21 · 5 unmodified lines | ||
| 6 | 6 | libavdevice: 2017-10-21 |
| 7 | 7 | libavfilter: 2017-10-21 |
| 8 | 8 | libavformat: 2017-10-21 |
| 9 | −libavresample: 2017-10-21 | |
| 10 | 9 | libpostproc: 2017-10-21 |
| 11 | 10 | libswresample: 2017-10-21 |
| 12 | 11 | libswscale: 2017-10-21 |
| @@ -26,7 +26,7 @@ $(foreach VAR,$(SILENT),$(eval override $(VAR) = @$($(VAR)))) · 25 unmodified lines | ||
| 26 | 26 | $(eval INSTALL = @$(call ECHO,INSTALL,$$(^:$(SRC_DIR)/%=%)); $(INSTALL)) |
| 27 | 27 | endif |
| 28 | 28 | |
| 29 | −ALLFFLIBS = avcodec avdevice avfilter avformat avresample avutil postproc swscale swresample | |
| 29 | +ALLFFLIBS = avcodec avdevice avfilter avformat avutil postproc swscale swresample | |
| 30 | 30 | |
| 31 | 31 | # NASM requires -I path terminated with / |
| 32 | 32 | IFLAGS := -I. -I$(SRC_LINK)/ |
| @@ -34,7 +34,6 @@ · 33 unmodified lines | ||
| 34 | 34 | #include "libavformat/avformat.h" |
| 35 | 35 | #include "libavfilter/avfilter.h" |
| 36 | 36 | #include "libavdevice/avdevice.h" |
| 37 | −#include "libavresample/avresample.h" | |
| 38 | 37 | #include "libswscale/swscale.h" |
| 39 | 38 | #include "libswresample/swresample.h" |
| 40 | 39 | #include "libpostproc/postprocess.h" |
| @@ -545,9 +544,6 @@ int opt_default(void *optctx, const char *opt, const char *arg) · 504 unmodified lines | ||
| 545 | 544 | char opt_stripped[128]; |
| 546 | 545 | const char *p; |
| 547 | 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 | 547 | #if CONFIG_SWSCALE |
| 552 | 548 | const AVClass *sc = sws_get_class(); |
| 553 | 549 | #endif |
| @@ -617,13 +613,6 @@ int opt_default(void *optctx, const char *opt, const char *arg) · 63 unmodified lines | ||
| 617 | 613 | consumed = 1; |
| 618 | 614 | } |
| 619 | 615 | #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 | 617 | if (consumed) |
| 629 | 618 | return 0; |
| @@ -1134,7 +1123,6 @@ static void print_all_libs_info(int flags, int level) · 504 unmodified lines | ||
| 1134 | 1123 | PRINT_LIB_INFO(avformat, AVFORMAT, flags, level); |
| 1135 | 1124 | PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level); |
| 1136 | 1125 | PRINT_LIB_INFO(avfilter, AVFILTER, flags, level); |
| 1137 | − PRINT_LIB_INFO(avresample, AVRESAMPLE, flags, level); | |
| 1138 | 1126 | PRINT_LIB_INFO(swscale, SWSCALE, flags, level); |
| 1139 | 1127 | PRINT_LIB_INFO(swresample, SWRESAMPLE, flags, level); |
| 1140 | 1128 | PRINT_LIB_INFO(postproc, POSTPROC, flags, level); |
| @@ -26,8 +26,6 @@ · 25 unmodified lines | ||
| 26 | 26 | #include "libavfilter/buffersink.h" |
| 27 | 27 | #include "libavfilter/buffersrc.h" |
| 28 | 28 | |
| 29 | −#include "libavresample/avresample.h" | |
| 30 | − | |
| 31 | 29 | #include "libavutil/avassert.h" |
| 32 | 30 | #include "libavutil/avstring.h" |
| 33 | 31 | #include "libavutil/bprint.h" |
| @@ -135,7 +135,6 @@ OBJS-$(CONFIG_LV2_FILTER) += af_lv2.o · 134 unmodified lines | ||
| 135 | 135 | OBJS-$(CONFIG_MCOMPAND_FILTER) += af_mcompand.o |
| 136 | 136 | OBJS-$(CONFIG_PAN_FILTER) += af_pan.o |
| 137 | 137 | OBJS-$(CONFIG_REPLAYGAIN_FILTER) += af_replaygain.o |
| 138 | −OBJS-$(CONFIG_RESAMPLE_FILTER) += af_resample.o | |
| 139 | 138 | OBJS-$(CONFIG_RUBBERBAND_FILTER) += af_rubberband.o |
| 140 | 139 | OBJS-$(CONFIG_SIDECHAINCOMPRESS_FILTER) += af_sidechaincompress.o |
| 141 | 140 | OBJS-$(CONFIG_SIDECHAINGATE_FILTER) += af_agate.o |
| @@ -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 | − | |
| 38 | −typedef 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 | − | |
| 51 | −static 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 | − | |
| 78 | −static 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 | − | |
| 89 | −static 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 | − | |
| 116 | −static 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 | − | |
| 186 | −static 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 | − | |
| 223 | −static 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 | − | |
| 298 | −fail: | |
| 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 | |
| 310 | −static const AVClass *resample_child_class_next(const AVClass *prev) | |
| 311 | −{ | |
| 312 | − return prev ? NULL : avresample_get_class(); | |
| 313 | −} | |
| 314 | −#endif | |
| 315 | − | |
| 316 | −static 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 | − | |
| 323 | −static void *resample_child_next(void *obj, void *prev) | |
| 324 | −{ | |
| 325 | − ResampleContext *s = obj; | |
| 326 | − return prev ? NULL : s->avr; | |
| 327 | −} | |
| 328 | − | |
| 329 | −static 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 | − | |
| 340 | −static 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 | − | |
| 349 | −static 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 | − | |
| 359 | −AVFilter 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 | −}; | |
| @@ -129,7 +129,6 @@ extern AVFilter ff_af_lv2; · 128 unmodified lines | ||
| 129 | 129 | extern AVFilter ff_af_mcompand; |
| 130 | 130 | extern AVFilter ff_af_pan; |
| 131 | 131 | extern AVFilter ff_af_replaygain; |
| 132 | −extern AVFilter ff_af_resample; | |
| 133 | 132 | extern AVFilter ff_af_rubberband; |
| 134 | 133 | extern AVFilter ff_af_sidechaincompress; |
| 135 | 134 | extern AVFilter ff_af_sidechaingate; |
| @@ -1,19 +0,0 @@ | ||
| 1 | −NAME = avresample | |
| 2 | −DESC = Libav audio resampling library | |
| 3 | − | |
| 4 | −HEADERS = avresample.h \ | |
| 5 | − version.h \ | |
| 6 | − | |
| 7 | −OBJS = audio_convert.o \ | |
| 8 | − audio_data.o \ | |
| 9 | − audio_mix.o \ | |
| 10 | − audio_mix_matrix.o \ | |
| 11 | − dither.o \ | |
| 12 | − options.o \ | |
| 13 | − resample.o \ | |
| 14 | − utils.o \ | |
| 15 | − | |
| 16 | −# Windows resource file | |
| 17 | −SLIBOBJS-$(HAVE_GNU_WINDRES) += avresampleres.o | |
| 18 | − | |
| 19 | −TESTPROGS = avresample | |
| @@ -1,7 +0,0 @@ | ||
| 1 | −OBJS += aarch64/audio_convert_init.o \ | |
| 2 | − aarch64/resample_init.o \ | |
| 3 | − | |
| 4 | −OBJS-$(CONFIG_NEON_CLOBBER_TEST) += aarch64/neontest.o | |
| 5 | − | |
| 6 | −NEON-OBJS += aarch64/audio_convert_neon.o \ | |
| 7 | − aarch64/resample_neon.o \ | |
| @@ -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 */ | |
| @@ -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 | − | |
| 28 | −void ff_conv_flt_to_s16_neon(int16_t *dst, const float *src, int len); | |
| 29 | −void ff_conv_fltp_to_s16_neon(int16_t *dst, float *const *src, | |
| 30 | − int len, int channels); | |
| 31 | −void ff_conv_fltp_to_s16_2ch_neon(int16_t *dst, float *const *src, | |
| 32 | − int len, int channels); | |
| 33 | − | |
| 34 | −av_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 | −} | |
| @@ -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 | − | |
| 25 | −function 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 | |
| 34 | −1: 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 | |
| 52 | −2: 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 | |
| 63 | −3: sqrshrn v4.4h, v4.4s, #16 | |
| 64 | − sqrshrn2 v4.8h, v5.4s, #16 | |
| 65 | − st1 {v4.8h}, [x0] | |
| 66 | − ret | |
| 67 | −endfunc | |
| 68 | − | |
| 69 | −function 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 | |
| 83 | −1: 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 | |
| 111 | −2: 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 | |
| 126 | −3: sri v6.4s, v4.4s, #16 | |
| 127 | − sri v7.4s, v5.4s, #16 | |
| 128 | − st1 {v6.4s,v7.4s}, [x0] | |
| 129 | − ret | |
| 130 | −endfunc | |
| 131 | − | |
| 132 | −function 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) | |
| 138 | −1: | |
| 139 | − cmp w3, #4 | |
| 140 | − lsl x12, x3, #1 | |
| 141 | − b.lt 4f | |
| 142 | − | |
| 143 | −5: // 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 | |
| 156 | −6: | |
| 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 | |
| 192 | −7: | |
| 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 | − | |
| 203 | −4: // 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 | |
| 239 | −6: | |
| 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 | |
| 279 | −6: | |
| 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 | |
| 289 | −7: | |
| 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 | |
| 300 | −8: | |
| 301 | − subs w3, w3, #2 | |
| 302 | − add x0, x0, #4 | |
| 303 | − b.eq end | |
| 304 | − | |
| 305 | −4: // 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 | |
| 315 | −6: | |
| 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 | |
| 334 | −7: | |
| 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 | |
| 345 | −8: | |
| 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 | |
| 361 | −end: | |
| 362 | − ret | |
| 363 | −endfunc | |
| @@ -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 | − | |
| 25 | −wrap(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 | −} | |
| @@ -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 | − | |
| 30 | −AV_CHECK_OFFSET(struct ResampleContext, filter_bank, FILTER_BANK); | |
| 31 | −AV_CHECK_OFFSET(struct ResampleContext, filter_length, FILTER_LENGTH); | |
| 32 | −AV_CHECK_OFFSET(struct ResampleContext, phase_shift, PHASE_SHIFT); | |
| 33 | −AV_CHECK_OFFSET(struct ResampleContext, phase_mask, PHASE_MASK); | |
| 34 | − | |
| 35 | −void ff_resample_one_dbl_neon(struct ResampleContext *c, void *dst0, | |
| 36 | − int dst_index, const void *src0, | |
| 37 | − unsigned int index, int frac); | |
| 38 | −void ff_resample_one_flt_neon(struct ResampleContext *c, void *dst0, | |
| 39 | − int dst_index, const void *src0, | |
| 40 | − unsigned int index, int frac); | |
| 41 | −void ff_resample_one_s16_neon(struct ResampleContext *c, void *dst0, | |
| 42 | − int dst_index, const void *src0, | |
| 43 | − unsigned int index, int frac); | |
| 44 | −void ff_resample_one_s32_neon(struct ResampleContext *c, void *dst0, | |
| 45 | − int dst_index, const void *src0, | |
| 46 | − unsigned int index, int frac); | |
| 47 | − | |
| 48 | −av_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 | −} | |
| @@ -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 | |
| 31 | −function 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 | |
| 43 | −8: // 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 | |
| 49 | −7: | |
| 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 | |
| 67 | −6: | |
| 68 | − M_MLA v0, v21, v25, v1 | |
| 69 | − M_MLA2 v1, v23, v27 | |
| 70 | − STORE_ONE 0, x1, x2, v1 | |
| 71 | − ret | |
| 72 | −5: | |
| 73 | − movi v0.16b, #0 | |
| 74 | − movi v1.16b, #0 | |
| 75 | −4: // 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 | |
| 85 | −2: // 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 | |
| 93 | −1: // remaining filter_length 1 | |
| 94 | − LOAD1 6, x3 | |
| 95 | − LOAD1 7, x9 | |
| 96 | − M_MLA v0, v6, v7 | |
| 97 | −0: | |
| 98 | − STORE_ONE 0, x1, x2, v1 | |
| 99 | − ret | |
| 100 | −endfunc | |
| 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 | − | |
| 144 | −resample_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 | − | |
| 171 | −resample_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 | − | |
| 199 | −resample_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 | − | |
| 233 | −resample_one s32 | |
| @@ -1,7 +0,0 @@ | ||
| 1 | −OBJS += arm/audio_convert_init.o \ | |
| 2 | − arm/resample_init.o | |
| 3 | − | |
| 4 | −OBJS-$(CONFIG_NEON_CLOBBER_TEST) += arm/neontest.o | |
| 5 | − | |
| 6 | −NEON-OBJS += arm/audio_convert_neon.o \ | |
| 7 | − arm/resample_neon.o | |
| @@ -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 */ | |
| @@ -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 | − | |
| 28 | −void ff_conv_flt_to_s16_neon(int16_t *dst, const float *src, int len); | |
| 29 | −void ff_conv_fltp_to_s16_neon(int16_t *dst, float *const *src, | |
| 30 | − int len, int channels); | |
| 31 | −void ff_conv_fltp_to_s16_2ch_neon(int16_t *dst, float *const *src, | |
| 32 | − int len, int channels); | |
| 33 | − | |
| 34 | −av_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 | −} | |
| @@ -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 | − | |
| 24 | −function 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 | |
| 33 | −1: 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 | |
| 51 | −2: 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 | |
| 62 | −3: vqrshrn.s32 d4, q8, #16 | |
| 63 | − vqrshrn.s32 d5, q9, #16 | |
| 64 | − vst1.16 {q2}, [r0,:128]! | |
| 65 | − bx lr | |
| 66 | −endfunc | |
| 67 | − | |
| 68 | −function 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 | |
| 82 | −1: 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 | |
| 110 | −2: 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 | |
| 126 | −3: vsri.32 q10, q8, #16 | |
| 127 | − vsri.32 q11, q9, #16 | |
| 128 | − vst1.16 {q10-q11},[r0,:128]! | |
| 129 | − bx lr | |
| 130 | −endfunc | |
| 131 | − | |
| 132 | −function 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 | |
| 145 | −5: 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 | |
| 156 | −6: 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 | |
| 191 | −7: 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 | |
| 203 | −4: 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 | |
| 240 | −6: 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 | |
| 283 | −6: 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 | |
| 292 | −7: 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 | |
| 304 | −8: subs r3, r3, #2 | |
| 305 | − add r0, r0, #4 | |
| 306 | − it eq | |
| 307 | − popeq {r4-r8, pc} | |
| 308 | − | |
| 309 | − @ 1 channel | |
| 310 | −4: 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 | |
| 319 | −6: 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 | |
| 337 | −7: 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} | |
| 347 | −8: 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 | |
| 363 | −endfunc | |
| @@ -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 | − | |
| 25 | −wrap(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 | −} | |
| @@ -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 | − | |
| 32 | −AV_CHECK_OFFSET(struct ResampleContext, filter_bank, FILTER_BANK); | |
| 33 | −AV_CHECK_OFFSET(struct ResampleContext, filter_length, FILTER_LENGTH); | |
| 34 | −AV_CHECK_OFFSET(struct ResampleContext, src_incr, SRC_INCR); | |
| 35 | −AV_CHECK_OFFSET(struct ResampleContext, phase_shift, PHASE_SHIFT); | |
| 36 | −AV_CHECK_OFFSET(struct ResampleContext, phase_mask, PHASE_MASK); | |
| 37 | − | |
| 38 | −void ff_resample_one_flt_neon(struct ResampleContext *c, void *dst0, | |
| 39 | − int dst_index, const void *src0, | |
| 40 | − unsigned int index, int frac); | |
| 41 | −void ff_resample_one_s16_neon(struct ResampleContext *c, void *dst0, | |
| 42 | − int dst_index, const void *src0, | |
| 43 | − unsigned int index, int frac); | |
| 44 | −void ff_resample_one_s32_neon(struct ResampleContext *c, void *dst0, | |
| 45 | − int dst_index, const void *src0, | |
| 46 | − unsigned int index, int frac); | |
| 47 | − | |
| 48 | −void ff_resample_linear_flt_neon(struct ResampleContext *c, void *dst0, | |
| 49 | − int dst_index, const void *src0, | |
| 50 | − unsigned int index, int frac); | |
| 51 | − | |
| 52 | −av_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 | −} | |
| @@ -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 | |
| 26 | −function 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 | |
| 45 | −8: | |
| 46 | − subs r5, r5, #8 | |
| 47 | − LOAD4 | |
| 48 | − MUL4 | |
| 49 | −7: | |
| 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 | |
| 59 | −6: | |
| 60 | − MLA4 | |
| 61 | − STORE | |
| 62 | − pop {r4, r5} | |
| 63 | − bx lr | |
| 64 | −5: | |
| 65 | − INIT4 | |
| 66 | −4: /* 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 | |
| 73 | −2: /* 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 | |
| 80 | −1: /* remaining filter_length 1 */ | |
| 81 | − LOAD1 | |
| 82 | − MLA1 | |
| 83 | −0: | |
| 84 | − STORE | |
| 85 | − pop {r4, r5} | |
| 86 | − bx lr | |
| 87 | −endfunc | |
| 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 | − | |
| 138 | −resample_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 | − | |
| 180 | −resample_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 | − | |
| 221 | −resample_one s16, 1 | |
| 222 | − | |
| 223 | − | |
| 224 | −.macro resample_linear fmt, es=2 | |
| 225 | −function 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 | |
| 246 | −8: | |
| 247 | − subs r5, r5, #8 | |
| 248 | − LOAD4 | |
| 249 | − MUL4 | |
| 250 | −7: | |
| 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 | |
| 260 | −6: | |
| 261 | − MLA4 | |
| 262 | − STORE | |
| 263 | − pop {r4, r5} | |
| 264 | − bx lr | |
| 265 | −5: | |
| 266 | − INIT4 | |
| 267 | −4: /* 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 | |
| 274 | −2: /* 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 | |
| 281 | −1: /* remaining filter_length 1 */ | |
| 282 | − LOAD1 | |
| 283 | − MLA1 | |
| 284 | −0: | |
| 285 | − STORE | |
| 286 | − pop {r4, r5} | |
| 287 | − bx lr | |
| 288 | −endfunc | |
| 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 | − | |
| 358 | −resample_linear flt, 2 | |
| @@ -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 | − | |
| 34 | −enum ConvFuncType { | |
| 35 | − CONV_FUNC_TYPE_FLAT, | |
| 36 | − CONV_FUNC_TYPE_INTERLEAVE, | |
| 37 | − CONV_FUNC_TYPE_DEINTERLEAVE, | |
| 38 | −}; | |
| 39 | − | |
| 40 | −typedef void (conv_func_flat)(uint8_t *out, const uint8_t *in, int len); | |
| 41 | − | |
| 42 | −typedef void (conv_func_interleave)(uint8_t *out, uint8_t *const *in, | |
| 43 | − int len, int channels); | |
| 44 | − | |
| 45 | −typedef void (conv_func_deinterleave)(uint8_t **out, const uint8_t *in, int len, | |
| 46 | − int channels); | |
| 47 | − | |
| 48 | −struct 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 | − | |
| 70 | −void 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) \ | |
| 144 | −static 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) \ | |
| 156 | −static 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) \ | |
| 172 | −static 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) \ | |
| 188 | −CONV_FUNC_FLAT( ofmt, otype, ifmt, itype, expr) \ | |
| 189 | −CONV_FUNC_INTERLEAVE( ofmt, otype, ifmt ## P, itype, expr) \ | |
| 190 | −CONV_FUNC_DEINTERLEAVE(ofmt ## P, otype, ifmt, itype, expr) | |
| 191 | − | |
| 192 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_U8, uint8_t, *(const uint8_t *)pi) | |
| 193 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) << 8) | |
| 194 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) << 24) | |
| 195 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) * (1.0f / (1 << 7))) | |
| 196 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) * (1.0 / (1 << 7))) | |
| 197 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t, (*(const int16_t *)pi >> 8) + 0x80) | |
| 198 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi) | |
| 199 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi << 16) | |
| 200 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi * (1.0f / (1 << 15))) | |
| 201 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi * (1.0 / (1 << 15))) | |
| 202 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t, (*(const int32_t *)pi >> 24) + 0x80) | |
| 203 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi >> 16) | |
| 204 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi) | |
| 205 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi * (1.0f / (1U << 31))) | |
| 206 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi * (1.0 / (1U << 31))) | |
| 207 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8( lrintf(*(const float *)pi * (1 << 7)) + 0x80)) | |
| 208 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16( lrintf(*(const float *)pi * (1 << 15)))) | |
| 209 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *)pi * (1U << 31)))) | |
| 210 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_FLT, float, *(const float *)pi) | |
| 211 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_FLT, float, *(const float *)pi) | |
| 212 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8( lrint(*(const double *)pi * (1 << 7)) + 0x80)) | |
| 213 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16( lrint(*(const double *)pi * (1 << 15)))) | |
| 214 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *)pi * (1U << 31)))) | |
| 215 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_DBL, double, *(const double *)pi) | |
| 216 | −CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_DBL, double, *(const double *)pi) | |
| 217 | − | |
| 218 | −#define SET_CONV_FUNC_GROUP(ofmt, ifmt) \ | |
| 219 | −ff_audio_convert_set_func(ac, ofmt, ifmt, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt, ifmt)); \ | |
| 220 | −ff_audio_convert_set_func(ac, ofmt ## P, ifmt, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt ## P, ifmt)); \ | |
| 221 | −ff_audio_convert_set_func(ac, ofmt, ifmt ## P, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt, ifmt ## P)); | |
| 222 | − | |
| 223 | −static 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 | − | |
| 252 | −void ff_audio_convert_free(AudioConvert **ac) | |
| 253 | −{ | |
| 254 | − if (!*ac) | |
| 255 | − return; | |
| 256 | − ff_dither_free(&(*ac)->dc); | |
| 257 | − av_freep(ac); | |
| 258 | −} | |
| 259 | − | |
| 260 | −AudioConvert *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 | − | |
| 314 | −int 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 | −} | |
| @@ -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 | − */ | |
| 48 | −void ff_audio_convert_set_func(AudioConvert *ac, enum AVSampleFormat out_fmt, | |
| 49 | − enum AVSampleFormat in_fmt, int channels, | |
| 50 | − int ptr_align, int samples_align, | |
| 51 | − const char *descr, void *conv); | |
| 52 | − | |
| 53 | −/** | |
| 54 | − * Allocate and initialize AudioConvert context for sample format conversion. | |
| 55 | − * | |
| 56 | − * @param avr AVAudioResampleContext | |
| 57 | − * @param out_fmt output sample format | |
| 58 | − * @param in_fmt input sample format | |
| 59 | − * @param channels number of channels | |
| 60 | − * @param sample_rate sample rate (used for dithering) | |
| 61 | − * @param apply_map apply channel map during conversion | |
| 62 | − * @return newly-allocated AudioConvert context | |
| 63 | − */ | |
| 64 | −AudioConvert *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 | − */ | |
| 77 | −void 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 | − */ | |
| 95 | −int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in); | |
| 96 | − | |
| 97 | −/* arch-specific initialization functions */ | |
| 98 | − | |
| 99 | −void ff_audio_convert_init_aarch64(AudioConvert *ac); | |
| 100 | −void ff_audio_convert_init_arm(AudioConvert *ac); | |
| 101 | −void ff_audio_convert_init_x86(AudioConvert *ac); | |
| 102 | − | |
| 103 | −#endif /* AVRESAMPLE_AUDIO_CONVERT_H */ | |
| @@ -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 | − | |
| 27 | −static 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 | − */ | |
| 36 | −static 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 | − | |
| 51 | −int 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 | − | |
| 59 | −int 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 | − | |
| 73 | −int 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 | − | |
| 119 | −AudioData *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 | − | |
| 162 | −int 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 | − | |
| 217 | −void ff_audio_data_free(AudioData **a) | |
| 218 | −{ | |
| 219 | − if (!*a) | |
| 220 | − return; | |
| 221 | − av_free((*a)->buffer); | |
| 222 | − av_freep(a); | |
| 223 | −} | |
| 224 | − | |
| 225 | −int 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 | − | |
| 278 | −int 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 | − | |
| 334 | −void 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 | − | |
| 351 | −int 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 | − | |
| 366 | −int 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 | −} | |
| @@ -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 | − | |
| 32 | −int ff_sample_fmt_is_planar(enum AVSampleFormat sample_fmt, int channels); | |
| 33 | − | |
| 34 | −/** | |
| 35 | − * Audio buffer used for intermediate storage between conversion phases. | |
| 36 | − */ | |
| 37 | −struct 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 | − | |
| 58 | −int 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 | − */ | |
| 79 | −int 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 | − */ | |
| 95 | −AudioData *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 | − */ | |
| 108 | −int 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 | − */ | |
| 117 | −void 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 | − */ | |
| 127 | −int 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 | − */ | |
| 141 | −int 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 | − */ | |
| 152 | −void 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 | − */ | |
| 164 | −int 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 | − */ | |
| 176 | −int ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples); | |
| 177 | − | |
| 178 | −#endif /* AVRESAMPLE_AUDIO_DATA_H */ | |
| @@ -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 | − | |
| 31 | −static const char * const coeff_type_names[] = { "q8", "q15", "flt" }; | |
| 32 | − | |
| 33 | −struct AudioMix { | |
| 34 | − AVAudioResampleContext *avr; | |
| 35 | − enum AVSampleFormat fmt; | |
| 36 | − enum AVMixCoeffType coeff_type; | |
| 37 | − uint64_t in_layout; | |
| 38 | − uint64_t out_layout; | |
| 39 | − int in_channels; | |
| 40 | − int out_channels; | |
| 41 | − | |
| 42 | − int ptr_align; | |
| 43 | − int samples_align; | |
| 44 | − int has_optimized_func; | |
| 45 | − const char *func_descr; | |
| 46 | − const char *func_descr_generic; | |
| 47 | − mix_func *mix; | |
| 48 | − mix_func *mix_generic; | |
| 49 | − | |
| 50 | − 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 | − | |
| 61 | −void 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) \ | |
| 102 | −static 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 | − | |
| 119 | −MIX_FUNC_GENERIC(FLTP, FLT, float, float, float, sum) | |
| 120 | −MIX_FUNC_GENERIC(S16P, FLT, int16_t, float, float, av_clip_int16(lrintf(sum))) | |
| 121 | −MIX_FUNC_GENERIC(S16P, Q15, int16_t, int32_t, int64_t, av_clip_int16(sum >> 15)) | |
| 122 | −MIX_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 | − | |
| 126 | −static 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 | − | |
| 148 | −static 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 | − | |
| 170 | −static 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 | − | |
| 192 | −static 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 | − | |
| 225 | −static 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 | − | |
| 259 | −static 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 | − | |
| 285 | −static 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 | − | |
| 341 | −AudioMix *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 | − | |
| 404 | −error: | |
| 405 | − av_free(am); | |
| 406 | − return NULL; | |
| 407 | −} | |
| 408 | − | |
| 409 | −void 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 | − | |
| 428 | −int 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 | − | |
| 483 | −int 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 | − | |
| 530 | −static 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 | − | |
| 653 | −int 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 | −} | |
| @@ -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 | − | |
| 31 | −typedef 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 | − */ | |
| 54 | −void 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 | − */ | |
| 68 | −AudioMix *ff_audio_mix_alloc(AVAudioResampleContext *avr); | |
| 69 | − | |
| 70 | −/** | |
| 71 | − * Free an AudioMix context. | |
| 72 | − */ | |
| 73 | −void ff_audio_mix_free(AudioMix **am); | |
| 74 | − | |
| 75 | −/** | |
| 76 | − * Apply channel mixing to audio data using the current mixing matrix. | |
| 77 | − */ | |
| 78 | −int ff_audio_mix(AudioMix *am, AudioData *src); | |
| 79 | − | |
| 80 | −/** | |
| 81 | − * Get the current mixing matrix. | |
| 82 | − */ | |
| 83 | −int ff_audio_mix_get_matrix(AudioMix *am, double *matrix, int stride); | |
| 84 | − | |
| 85 | −/** | |
| 86 | − * Set the current mixing matrix. | |
| 87 | − */ | |
| 88 | −int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride); | |
| 89 | − | |
| 90 | −/* arch-specific initialization functions */ | |
| 91 | − | |
| 92 | −void ff_audio_mix_init_x86(AudioMix *am); | |
| 93 | − | |
| 94 | −#endif /* AVRESAMPLE_AUDIO_MIX_H */ | |
| @@ -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 | − | |
| 61 | −static av_always_inline int even(uint64_t layout) | |
| 62 | −{ | |
| 63 | − return (!layout || !!(layout & (layout - 1))); | |
| 64 | −} | |
| 65 | − | |
| 66 | −static 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 | − | |
| 87 | −int 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 | −} | |
| @@ -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 | − | |
| 106 | −typedef struct AVAudioResampleContext AVAudioResampleContext; | |
| 107 | − | |
| 108 | −/** | |
| 109 | − * @deprecated use libswresample | |
| 110 | − * | |
| 111 | − * Mixing Coefficient Types */ | |
| 112 | −enum 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 */ | |
| 123 | −enum 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 | − */ | |
| 132 | −enum 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 | − */ | |
| 147 | −attribute_deprecated | |
| 148 | −unsigned avresample_version(void); | |
| 149 | − | |
| 150 | −/** | |
| 151 | − * | |
| 152 | − * @deprecated use libswresample | |
| 153 | − * | |
| 154 | − * Return the libavresample build-time configuration. | |
| 155 | − * @return configure string | |
| 156 | − */ | |
| 157 | −attribute_deprecated | |
| 158 | −const char *avresample_configuration(void); | |
| 159 | − | |
| 160 | −/** | |
| 161 | − * | |
| 162 | − * @deprecated use libswresample | |
| 163 | − * | |
| 164 | − * Return the libavresample license. | |
| 165 | − */ | |
| 166 | −attribute_deprecated | |
| 167 | −const 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 | − */ | |
| 182 | −attribute_deprecated | |
| 183 | −const 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 | − */ | |
| 193 | −attribute_deprecated | |
| 194 | −AVAudioResampleContext *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 | − */ | |
| 213 | −attribute_deprecated | |
| 214 | −int 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 | − */ | |
| 225 | −attribute_deprecated | |
| 226 | −int 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 | − */ | |
| 244 | −attribute_deprecated | |
| 245 | −void 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 | − */ | |
| 257 | −attribute_deprecated | |
| 258 | −void 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 | − */ | |
| 285 | −attribute_deprecated | |
| 286 | −int 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 | − */ | |
| 306 | −attribute_deprecated | |
| 307 | −int 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 | − */ | |
| 331 | −attribute_deprecated | |
| 332 | −int 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 | − */ | |
| 365 | −attribute_deprecated | |
| 366 | −int 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 | − */ | |
| 385 | −attribute_deprecated | |
| 386 | −int 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 | − */ | |
| 402 | −attribute_deprecated | |
| 403 | −int 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 | − */ | |
| 450 | −attribute_deprecated | |
| 451 | −int 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 | − */ | |
| 472 | −attribute_deprecated | |
| 473 | −int 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 | − */ | |
| 493 | −attribute_deprecated | |
| 494 | −int 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 | − */ | |
| 516 | −attribute_deprecated | |
| 517 | −int 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 | − */ | |
| 566 | −attribute_deprecated | |
| 567 | −int 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 | − */ | |
| 588 | −attribute_deprecated | |
| 589 | −int avresample_config(AVAudioResampleContext *avr, AVFrame *out, AVFrame *in); | |
| 590 | − | |
| 591 | −/** | |
| 592 | − * @} | |
| 593 | − */ | |
| 594 | − | |
| 595 | −#endif /* AVRESAMPLE_AVRESAMPLE_H */ | |
| @@ -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 | − | |
| 29 | −1 VERSIONINFO | |
| 30 | −FILEVERSION LIBAVRESAMPLE_VERSION_MAJOR, LIBAVRESAMPLE_VERSION_MINOR, LIBAVRESAMPLE_VERSION_MICRO, 0 | |
| 31 | −PRODUCTVERSION LIBAVRESAMPLE_VERSION_MAJOR, LIBAVRESAMPLE_VERSION_MINOR, LIBAVRESAMPLE_VERSION_MICRO, 0 | |
| 32 | −FILEFLAGSMASK VS_FFI_FILEFLAGSMASK | |
| 33 | −FILEOS VOS_NT_WINDOWS32 | |
| 34 | −FILETYPE 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 | −} | |
| @@ -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 | − | |
| 43 | −typedef 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 | − | |
| 54 | −struct 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 | − | |
| 89 | −static const float ns_48_coef_b[4] = { | |
| 90 | − 2.2374f, -0.7339f, -0.1251f, -0.6033f | |
| 91 | −}; | |
| 92 | − | |
| 93 | −static const float ns_48_coef_a[4] = { | |
| 94 | − 0.9030f, 0.0116f, -0.5853f, -0.2571f | |
| 95 | −}; | |
| 96 | − | |
| 97 | −static const float ns_44_coef_b[4] = { | |
| 98 | − 2.2061f, -0.4707f, -0.2534f, -0.6213f | |
| 99 | −}; | |
| 100 | − | |
| 101 | −static const float ns_44_coef_a[4] = { | |
| 102 | − 1.0587f, 0.0676f, -0.6054f, -0.2738f | |
| 103 | −}; | |
| 104 | − | |
| 105 | −static 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 | − | |
| 112 | −static 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 | − | |
| 124 | −static 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 | − | |
| 133 | −static 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 | − | |
| 142 | −static 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 | − | |
| 172 | −static 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 | − | |
| 211 | −static 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 | − | |
| 242 | −int 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 | − | |
| 312 | −void 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 | − | |
| 329 | −static 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 | − | |
| 345 | −DitherContext *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 | − | |
| 437 | −fail: | |
| 438 | − ff_dither_free(&c); | |
| 439 | − return NULL; | |
| 440 | −} | |
| @@ -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 | − | |
| 27 | −typedef struct DitherContext DitherContext; | |
| 28 | − | |
| 29 | −typedef 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 | − */ | |
| 66 | −DitherContext *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 | − */ | |
| 76 | −void 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 | − */ | |
| 86 | −int ff_convert_dither(DitherContext *c, AudioData *dst, AudioData *src); | |
| 87 | − | |
| 88 | −/* arch-specific initialization functions */ | |
| 89 | − | |
| 90 | −void ff_dither_init_x86(DitherDSPContext *ddsp, | |
| 91 | − enum AVResampleDitherMethod method); | |
| 92 | − | |
| 93 | −#endif /* AVRESAMPLE_DITHER_H */ | |
| @@ -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 | − | |
| 30 | −typedef struct AudioData AudioData; | |
| 31 | −typedef struct AudioConvert AudioConvert; | |
| 32 | −typedef struct AudioMix AudioMix; | |
| 33 | −typedef struct ResampleContext ResampleContext; | |
| 34 | − | |
| 35 | −enum RemapPoint { | |
| 36 | − REMAP_NONE, | |
| 37 | − REMAP_IN_COPY, | |
| 38 | − REMAP_IN_CONVERT, | |
| 39 | − REMAP_OUT_COPY, | |
| 40 | − REMAP_OUT_CONVERT, | |
| 41 | −}; | |
| 42 | − | |
| 43 | −typedef 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 | − | |
| 53 | −struct 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 | − | |
| 111 | −void ff_audio_resample_init_aarch64(ResampleContext *c, | |
| 112 | − enum AVSampleFormat sample_fmt); | |
| 113 | −void ff_audio_resample_init_arm(ResampleContext *c, | |
| 114 | − enum AVSampleFormat sample_fmt); | |
| 115 | − | |
| 116 | −#endif /* AVRESAMPLE_INTERNAL_H */ | |
| @@ -1,6 +0,0 @@ | ||
| 1 | −LIBAVRESAMPLE_MAJOR { | |
| 2 | − global: | |
| 3 | − av*; | |
| 4 | − local: | |
| 5 | − *; | |
| 6 | −}; | |
| @@ -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 | − | |
| 38 | −static 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 | − | |
| 89 | −static 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 | − | |
| 96 | −AVAudioResampleContext *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 | − | |
| 110 | −const AVClass *avresample_get_class(void) | |
| 111 | −{ | |
| 112 | − return &av_resample_context_class; | |
| 113 | −} | |
| @@ -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. */ | |
| 50 | −static 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. */ | |
| 67 | −static 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 | − | |
| 120 | −ResampleContext *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 | − | |
| 217 | −error: | |
| 218 | − ff_audio_data_free(&c->buffer); | |
| 219 | − av_free(c->filter_bank); | |
| 220 | − av_free(c); | |
| 221 | − return NULL; | |
| 222 | −} | |
| 223 | − | |
| 224 | −void 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 | − | |
| 233 | −int 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 | − | |
| 259 | −static 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 | − | |
| 334 | −int 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 | − | |
| 438 | −int 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 | −} | |
| @@ -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 | − | |
| 28 | −struct 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 | − */ | |
| 66 | −ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr); | |
| 67 | − | |
| 68 | −/** | |
| 69 | − * Free a ResampleContext. | |
| 70 | − * | |
| 71 | − * @param c ResampleContext | |
| 72 | − */ | |
| 73 | −void 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 | − */ | |
| 94 | −int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src); | |
| 95 | − | |
| 96 | −#endif /* AVRESAMPLE_RESAMPLE_H */ | |
| @@ -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 | − | |
| 57 | −static 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 | − | |
| 64 | −static 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 | − | |
| 85 | −static 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 | − | |
| 103 | −static 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 | |
| @@ -1 +0,0 @@ | ||
| 1 | −/avresample | |
| @@ -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 | − | |
| 36 | −static 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) \ | |
| 42 | −static 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 | − | |
| 54 | −PUT_FUNC(u8, AV_SAMPLE_FMT_U8, uint8_t, av_clip_uint8 ( lrint(v_dbl * (1 << 7)) + 128)) | |
| 55 | −PUT_FUNC(s16, AV_SAMPLE_FMT_S16, int16_t, av_clip_int16 ( lrint(v_dbl * (1 << 15)))) | |
| 56 | −PUT_FUNC(s32, AV_SAMPLE_FMT_S32, int32_t, av_clipl_int32(llrint(v_dbl * (1U << 31)))) | |
| 57 | −PUT_FUNC(flt, AV_SAMPLE_FMT_FLT, float, v_dbl) | |
| 58 | −PUT_FUNC(dbl, AV_SAMPLE_FMT_DBL, double, v_dbl) | |
| 59 | − | |
| 60 | −static 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 | − | |
| 82 | −static 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 | − | |
| 163 | −static 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 | − | |
| 176 | −static const int rates[] = { | |
| 177 | − 48000, | |
| 178 | − 44100, | |
| 179 | − 16000 | |
| 180 | −}; | |
| 181 | − | |
| 182 | −static 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 | − | |
| 189 | −int 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 | − | |
| 337 | −end: | |
| 338 | − av_freep(&in_buf); | |
| 339 | − av_freep(&out_buf); | |
| 340 | − avresample_free(&s); | |
| 341 | − return ret; | |
| 342 | −} | |
| @@ -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 | − | |
| 36 | −int 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 | − | |
| 252 | −error: | |
| 253 | − avresample_close(avr); | |
| 254 | − return ret; | |
| 255 | −} | |
| 256 | − | |
| 257 | −int avresample_is_open(AVAudioResampleContext *avr) | |
| 258 | −{ | |
| 259 | − return !!avr->out_fifo; | |
| 260 | −} | |
| 261 | − | |
| 262 | −void 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 | − | |
| 278 | −void 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 | − | |
| 287 | −static 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 | − | |
| 330 | −int 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 | − | |
| 505 | −int 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 | − | |
| 526 | −static 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 | − | |
| 550 | −static 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 | − | |
| 587 | −static 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 | − | |
| 603 | −int 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 | − | |
| 637 | −int 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 | − | |
| 666 | −int 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 | − | |
| 697 | −int 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 | − | |
| 748 | −int avresample_available(AVAudioResampleContext *avr) | |
| 749 | −{ | |
| 750 | − return av_audio_fifo_size(avr->out_fifo); | |
| 751 | −} | |
| 752 | − | |
| 753 | −int 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 | − | |
| 772 | −int 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 | − | |
| 779 | −unsigned avresample_version(void) | |
| 780 | −{ | |
| 781 | − return LIBAVRESAMPLE_VERSION_INT; | |
| 782 | −} | |
| 783 | − | |
| 784 | −const char *avresample_license(void) | |
| 785 | −{ | |
| 786 | −#define LICENSE_PREFIX "libavresample license: " | |
| 787 | − return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; | |
| 788 | −} | |
| 789 | − | |
| 790 | −const char *avresample_configuration(void) | |
| 791 | −{ | |
| 792 | − return FFMPEG_CONFIGURATION; | |
| 793 | −} | |
| @@ -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 */ | |
| @@ -1,9 +0,0 @@ | ||
| 1 | −OBJS += x86/audio_convert_init.o \ | |
| 2 | − x86/audio_mix_init.o \ | |
| 3 | − x86/dither_init.o \ | |
| 4 | − | |
| 5 | −OBJS-$(CONFIG_XMM_CLOBBER_TEST) += x86/w64xmmtest.o | |
| 6 | − | |
| 7 | −X86ASM-OBJS += x86/audio_convert.o \ | |
| 8 | − x86/audio_mix.o \ | |
| 9 | − x86/dither.o \ | |
| @@ -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 | − | |
| 26 | −SECTION_RODATA 32 | |
| 27 | − | |
| 28 | −pf_s32_inv_scale: times 8 dd 0x30000000 | |
| 29 | −pf_s32_scale: times 8 dd 0x4f000000 | |
| 30 | −pf_s32_clip: times 8 dd 0x4effffff | |
| 31 | −pf_s16_inv_scale: times 4 dd 0x38000000 | |
| 32 | −pf_s16_scale: times 4 dd 0x47000000 | |
| 33 | −pb_shuf_unpack_even: db -1, -1, 0, 1, -1, -1, 2, 3, -1, -1, 8, 9, -1, -1, 10, 11 | |
| 34 | −pb_shuf_unpack_odd: db -1, -1, 4, 5, -1, -1, 6, 7, -1, -1, 12, 13, -1, -1, 14, 15 | |
| 35 | −pb_interleave_words: SHUFFLE_MASK_W 0, 4, 1, 5, 2, 6, 3, 7 | |
| 36 | −pb_deinterleave_words: SHUFFLE_MASK_W 0, 2, 4, 6, 1, 3, 5, 7 | |
| 37 | −pw_zero_even: times 4 dw 0x0000, 0xffff | |
| 38 | − | |
| 39 | −SECTION .text | |
| 40 | − | |
| 41 | −;------------------------------------------------------------------------------ | |
| 42 | −; void ff_conv_s16_to_s32(int32_t *dst, const int16_t *src, int len); | |
| 43 | −;------------------------------------------------------------------------------ | |
| 44 | − | |
| 45 | −INIT_XMM sse2 | |
| 46 | −cglobal 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 | |
| 68 | −cglobal 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 | − | |
| 89 | −INIT_XMM sse2 | |
| 90 | −CONV_S16_TO_FLT | |
| 91 | −INIT_XMM sse4 | |
| 92 | −CONV_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 | |
| 99 | −cglobal 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 | − | |
| 127 | −INIT_MMX mmx | |
| 128 | −CONV_S32_TO_S16 | |
| 129 | −INIT_XMM sse2 | |
| 130 | −CONV_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 | |
| 137 | −cglobal 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 | − | |
| 156 | −INIT_XMM sse2 | |
| 157 | −CONV_S32_TO_FLT | |
| 158 | −%if HAVE_AVX_EXTERNAL | |
| 159 | −INIT_YMM avx | |
| 160 | −CONV_S32_TO_FLT | |
| 161 | −%endif | |
| 162 | − | |
| 163 | −;------------------------------------------------------------------------------ | |
| 164 | −; void ff_conv_flt_to_s16(int16_t *dst, const float *src, int len); | |
| 165 | −;------------------------------------------------------------------------------ | |
| 166 | − | |
| 167 | −INIT_XMM sse2 | |
| 168 | −cglobal 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 | |
| 200 | −cglobal 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 | − | |
| 229 | −INIT_XMM sse2 | |
| 230 | −CONV_FLT_TO_S32 | |
| 231 | −%if HAVE_AVX_EXTERNAL | |
| 232 | −INIT_YMM avx | |
| 233 | −CONV_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 | |
| 242 | −cglobal 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 | − | |
| 266 | −INIT_XMM sse2 | |
| 267 | −CONV_S16P_TO_S16_2CH | |
| 268 | −%if HAVE_AVX_EXTERNAL | |
| 269 | −INIT_XMM avx | |
| 270 | −CONV_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 | |
| 289 | −cglobal conv_s16p_to_s16_6ch, 3,8,7, dst, src0, len, src1, src2, src3, src4, src5 | |
| 290 | −%else | |
| 291 | −cglobal 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 | − | |
| 387 | −INIT_XMM sse2 | |
| 388 | −CONV_S16P_TO_S16_6CH | |
| 389 | −INIT_XMM sse2slow | |
| 390 | −CONV_S16P_TO_S16_6CH | |
| 391 | −%if HAVE_AVX_EXTERNAL | |
| 392 | −INIT_XMM avx | |
| 393 | −CONV_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 | |
| 402 | −cglobal 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 | − | |
| 438 | −INIT_XMM sse2 | |
| 439 | −CONV_S16P_TO_FLT_2CH | |
| 440 | −%if HAVE_AVX_EXTERNAL | |
| 441 | −INIT_XMM avx | |
| 442 | −CONV_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 | |
| 452 | −cglobal conv_s16p_to_flt_6ch, 3,8,8, dst, src, len, src1, src2, src3, src4, src5 | |
| 453 | −%else | |
| 454 | −cglobal 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 | − | |
| 540 | −INIT_XMM sse2 | |
| 541 | −CONV_S16P_TO_FLT_6CH | |
| 542 | −INIT_XMM ssse3 | |
| 543 | −CONV_S16P_TO_FLT_6CH | |
| 544 | −%if HAVE_AVX_EXTERNAL | |
| 545 | −INIT_XMM avx | |
| 546 | −CONV_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 | |
| 555 | −cglobal 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 | − | |
| 586 | −INIT_XMM sse2 | |
| 587 | −CONV_FLTP_TO_S16_2CH | |
| 588 | −INIT_XMM ssse3 | |
| 589 | −CONV_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 | |
| 598 | −cglobal conv_fltp_to_s16_6ch, 3,8,7, dst, src, len, src1, src2, src3, src4, src5 | |
| 599 | −%else | |
| 600 | −cglobal 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 | − | |
| 696 | −INIT_MMX sse | |
| 697 | −CONV_FLTP_TO_S16_6CH | |
| 698 | −INIT_XMM sse2 | |
| 699 | −CONV_FLTP_TO_S16_6CH | |
| 700 | −%if HAVE_AVX_EXTERNAL | |
| 701 | −INIT_XMM avx | |
| 702 | −CONV_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 | |
| 711 | −cglobal 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 | − | |
| 735 | −INIT_XMM sse | |
| 736 | −CONV_FLTP_TO_FLT_2CH | |
| 737 | −%if HAVE_AVX_EXTERNAL | |
| 738 | −INIT_XMM avx | |
| 739 | −CONV_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 | |
| 748 | −cglobal 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 | − | |
| 814 | −INIT_MMX mmx | |
| 815 | −CONV_FLTP_TO_FLT_6CH | |
| 816 | −INIT_XMM sse4 | |
| 817 | −CONV_FLTP_TO_FLT_6CH | |
| 818 | −%if HAVE_AVX_EXTERNAL | |
| 819 | −INIT_XMM avx | |
| 820 | −CONV_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 | |
| 829 | −cglobal 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 | − | |
| 863 | −INIT_XMM sse2 | |
| 864 | −CONV_S16_TO_S16P_2CH | |
| 865 | −INIT_XMM ssse3 | |
| 866 | −CONV_S16_TO_S16P_2CH | |
| 867 | −%if HAVE_AVX_EXTERNAL | |
| 868 | −INIT_XMM avx | |
| 869 | −CONV_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 | |
| 879 | −cglobal conv_s16_to_s16p_6ch, 3,8,5, dst, src, len, dst1, dst2, dst3, dst4, dst5 | |
| 880 | −%else | |
| 881 | −cglobal 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 | − | |
| 922 | −INIT_XMM sse2 | |
| 923 | −CONV_S16_TO_S16P_6CH | |
| 924 | −INIT_XMM ssse3 | |
| 925 | −CONV_S16_TO_S16P_6CH | |
| 926 | −%if HAVE_AVX_EXTERNAL | |
| 927 | −INIT_XMM avx | |
| 928 | −CONV_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 | |
| 937 | −cglobal 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 | − | |
| 962 | −INIT_XMM sse2 | |
| 963 | −CONV_S16_TO_FLTP_2CH | |
| 964 | −%if HAVE_AVX_EXTERNAL | |
| 965 | −INIT_XMM avx | |
| 966 | −CONV_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 | |
| 976 | −cglobal conv_s16_to_fltp_6ch, 3,8,7, dst, src, len, dst1, dst2, dst3, dst4, dst5 | |
| 977 | −%else | |
| 978 | −cglobal 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 | − | |
| 1039 | −INIT_XMM sse2 | |
| 1040 | −CONV_S16_TO_FLTP_6CH | |
| 1041 | −INIT_XMM ssse3 | |
| 1042 | −CONV_S16_TO_FLTP_6CH | |
| 1043 | −INIT_XMM sse4 | |
| 1044 | −CONV_S16_TO_FLTP_6CH | |
| 1045 | −%if HAVE_AVX_EXTERNAL | |
| 1046 | −INIT_XMM avx | |
| 1047 | −CONV_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 | |
| 1056 | −cglobal 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 | − | |
| 1089 | −INIT_XMM sse2 | |
| 1090 | −CONV_FLT_TO_S16P_2CH | |
| 1091 | −%if HAVE_AVX_EXTERNAL | |
| 1092 | −INIT_XMM avx | |
| 1093 | −CONV_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 | |
| 1103 | −cglobal conv_flt_to_s16p_6ch, 3,8,7, dst, src, len, dst1, dst2, dst3, dst4, dst5 | |
| 1104 | −%else | |
| 1105 | −cglobal 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 | − | |
| 1159 | −INIT_XMM sse2 | |
| 1160 | −CONV_FLT_TO_S16P_6CH | |
| 1161 | −INIT_XMM ssse3 | |
| 1162 | −CONV_FLT_TO_S16P_6CH | |
| 1163 | −%if HAVE_AVX_EXTERNAL | |
| 1164 | −INIT_XMM avx | |
| 1165 | −CONV_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 | |
| 1174 | −cglobal 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 | − | |
| 1193 | −INIT_XMM sse | |
| 1194 | −CONV_FLT_TO_FLTP_2CH | |
| 1195 | −%if HAVE_AVX_EXTERNAL | |
| 1196 | −INIT_XMM avx | |
| 1197 | −CONV_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 | |
| 1207 | −cglobal conv_flt_to_fltp_6ch, 3,8,7, dst, src, len, dst1, dst2, dst3, dst4, dst5 | |
| 1208 | −%else | |
| 1209 | −cglobal 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 | − | |
| 1256 | −INIT_XMM sse2 | |
| 1257 | −CONV_FLT_TO_FLTP_6CH | |
| 1258 | −%if HAVE_AVX_EXTERNAL | |
| 1259 | −INIT_XMM avx | |
| 1260 | −CONV_FLT_TO_FLTP_6CH | |
| 1261 | −%endif | |
| @@ -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 | − | |
| 28 | −void ff_conv_s16_to_s32_sse2(int16_t *dst, const int32_t *src, int len); | |
| 29 | − | |
| 30 | −void ff_conv_s16_to_flt_sse2(float *dst, const int16_t *src, int len); | |
| 31 | −void ff_conv_s16_to_flt_sse4(float *dst, const int16_t *src, int len); | |
| 32 | − | |
| 33 | −void ff_conv_s32_to_s16_mmx (int16_t *dst, const int32_t *src, int len); | |
| 34 | −void ff_conv_s32_to_s16_sse2(int16_t *dst, const int32_t *src, int len); | |
| 35 | − | |
| 36 | −void ff_conv_s32_to_flt_sse2(float *dst, const int32_t *src, int len); | |
| 37 | −void ff_conv_s32_to_flt_avx (float *dst, const int32_t *src, int len); | |
| 38 | − | |
| 39 | −void ff_conv_flt_to_s16_sse2(int16_t *dst, const float *src, int len); | |
| 40 | − | |
| 41 | −void ff_conv_flt_to_s32_sse2(int32_t *dst, const float *src, int len); | |
| 42 | −void ff_conv_flt_to_s32_avx (int32_t *dst, const float *src, int len); | |
| 43 | − | |
| 44 | −/* interleave conversions */ | |
| 45 | − | |
| 46 | −void ff_conv_s16p_to_s16_2ch_sse2(int16_t *dst, int16_t *const *src, | |
| 47 | − int len, int channels); | |
| 48 | −void ff_conv_s16p_to_s16_2ch_avx (int16_t *dst, int16_t *const *src, | |
| 49 | − int len, int channels); | |
| 50 | − | |
| 51 | −void ff_conv_s16p_to_s16_6ch_sse2(int16_t *dst, int16_t *const *src, | |
| 52 | − int len, int channels); | |
| 53 | −void ff_conv_s16p_to_s16_6ch_sse2slow(int16_t *dst, int16_t *const *src, | |
| 54 | − int len, int channels); | |
| 55 | −void ff_conv_s16p_to_s16_6ch_avx (int16_t *dst, int16_t *const *src, | |
| 56 | − int len, int channels); | |
| 57 | − | |
| 58 | −void ff_conv_s16p_to_flt_2ch_sse2(float *dst, int16_t *const *src, | |
| 59 | − int len, int channels); | |
| 60 | −void ff_conv_s16p_to_flt_2ch_avx (float *dst, int16_t *const *src, | |
| 61 | − int len, int channels); | |
| 62 | − | |
| 63 | −void ff_conv_s16p_to_flt_6ch_sse2 (float *dst, int16_t *const *src, | |
| 64 | − int len, int channels); | |
| 65 | −void ff_conv_s16p_to_flt_6ch_ssse3(float *dst, int16_t *const *src, | |
| 66 | − int len, int channels); | |
| 67 | −void ff_conv_s16p_to_flt_6ch_avx (float *dst, int16_t *const *src, | |
| 68 | − int len, int channels); | |
| 69 | − | |
| 70 | −void ff_conv_fltp_to_s16_2ch_sse2 (int16_t *dst, float *const *src, | |
| 71 | − int len, int channels); | |
| 72 | −void ff_conv_fltp_to_s16_2ch_ssse3(int16_t *dst, float *const *src, | |
| 73 | − int len, int channels); | |
| 74 | − | |
| 75 | −void ff_conv_fltp_to_s16_6ch_sse (int16_t *dst, float *const *src, | |
| 76 | − int len, int channels); | |
| 77 | −void ff_conv_fltp_to_s16_6ch_sse2(int16_t *dst, float *const *src, | |
| 78 | − int len, int channels); | |
| 79 | −void ff_conv_fltp_to_s16_6ch_avx (int16_t *dst, float *const *src, | |
| 80 | − int len, int channels); | |
| 81 | − | |
| 82 | −void ff_conv_fltp_to_flt_2ch_sse(float *dst, float *const *src, int len, | |
| 83 | − int channels); | |
| 84 | −void ff_conv_fltp_to_flt_2ch_avx(float *dst, float *const *src, int len, | |
| 85 | − int channels); | |
| 86 | − | |
| 87 | −void ff_conv_fltp_to_flt_6ch_mmx (float *dst, float *const *src, int len, | |
| 88 | − int channels); | |
| 89 | −void ff_conv_fltp_to_flt_6ch_sse4(float *dst, float *const *src, int len, | |
| 90 | − int channels); | |
| 91 | −void ff_conv_fltp_to_flt_6ch_avx (float *dst, float *const *src, int len, | |
| 92 | − int channels); | |
| 93 | − | |
| 94 | −/* deinterleave conversions */ | |
| 95 | − | |
| 96 | −void ff_conv_s16_to_s16p_2ch_sse2(int16_t *const *dst, int16_t *src, | |
| 97 | − int len, int channels); | |
| 98 | −void ff_conv_s16_to_s16p_2ch_ssse3(int16_t *const *dst, int16_t *src, | |
| 99 | − int len, int channels); | |
| 100 | −void ff_conv_s16_to_s16p_2ch_avx (int16_t *const *dst, int16_t *src, | |
| 101 | − int len, int channels); | |
| 102 | − | |
| 103 | −void ff_conv_s16_to_s16p_6ch_sse2 (int16_t *const *dst, int16_t *src, | |
| 104 | − int len, int channels); | |
| 105 | −void ff_conv_s16_to_s16p_6ch_ssse3(int16_t *const *dst, int16_t *src, | |
| 106 | − int len, int channels); | |
| 107 | −void ff_conv_s16_to_s16p_6ch_avx (int16_t *const *dst, int16_t *src, | |
| 108 | − int len, int channels); | |
| 109 | − | |
| 110 | −void ff_conv_s16_to_fltp_2ch_sse2(float *const *dst, int16_t *src, | |
| 111 | − int len, int channels); | |
| 112 | −void ff_conv_s16_to_fltp_2ch_avx (float *const *dst, int16_t *src, | |
| 113 | − int len, int channels); | |
| 114 | − | |
| 115 | −void ff_conv_s16_to_fltp_6ch_sse2 (float *const *dst, int16_t *src, | |
| 116 | − int len, int channels); | |
| 117 | −void ff_conv_s16_to_fltp_6ch_ssse3(float *const *dst, int16_t *src, | |
| 118 | − int len, int channels); | |
| 119 | −void ff_conv_s16_to_fltp_6ch_sse4 (float *const *dst, int16_t *src, | |
| 120 | − int len, int channels); | |
| 121 | −void ff_conv_s16_to_fltp_6ch_avx (float *const *dst, int16_t *src, | |
| 122 | − int len, int channels); | |
| 123 | − | |
| 124 | −void ff_conv_flt_to_s16p_2ch_sse2(int16_t *const *dst, float *src, | |
| 125 | − int len, int channels); | |
| 126 | −void ff_conv_flt_to_s16p_2ch_avx (int16_t *const *dst, float *src, | |
| 127 | − int len, int channels); | |
| 128 | − | |
| 129 | −void ff_conv_flt_to_s16p_6ch_sse2 (int16_t *const *dst, float *src, | |
| 130 | − int len, int channels); | |
| 131 | −void ff_conv_flt_to_s16p_6ch_ssse3(int16_t *const *dst, float *src, | |
| 132 | − int len, int channels); | |
| 133 | −void ff_conv_flt_to_s16p_6ch_avx (int16_t *const *dst, float *src, | |
| 134 | − int len, int channels); | |
| 135 | − | |
| 136 | −void ff_conv_flt_to_fltp_2ch_sse(float *const *dst, float *src, int len, | |
| 137 | − int channels); | |
| 138 | −void ff_conv_flt_to_fltp_2ch_avx(float *const *dst, float *src, int len, | |
| 139 | − int channels); | |
| 140 | − | |
| 141 | −void ff_conv_flt_to_fltp_6ch_sse2(float *const *dst, float *src, int len, | |
| 142 | − int channels); | |
| 143 | −void ff_conv_flt_to_fltp_6ch_avx (float *const *dst, float *src, int len, | |
| 144 | − int channels); | |
| 145 | − | |
| 146 | −av_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 | −} | |
| @@ -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 | − | |
| 25 | −SECTION .text | |
| 26 | − | |
| 27 | −;----------------------------------------------------------------------------- | |
| 28 | −; void ff_mix_2_to_1_fltp_flt(float **src, float **matrix, int len, | |
| 29 | −; int out_ch, int in_ch); | |
| 30 | −;----------------------------------------------------------------------------- | |
| 31 | − | |
| 32 | −%macro MIX_2_TO_1_FLTP_FLT 0 | |
| 33 | −cglobal mix_2_to_1_fltp_flt, 3,4,6, src, matrix, len, src1 | |
| 34 | − mov src1q, [srcq+gprsize] | |
| 35 | − mov srcq, [srcq ] | |
| 36 | − sub src1q, srcq | |
| 37 | − mov matrixq, [matrixq ] | |
| 38 | − VBROADCASTSS m4, [matrixq ] | |
| 39 | − VBROADCASTSS m5, [matrixq+4] | |
| 40 | − ALIGN 16 | |
| 41 | −.loop: | |
| 42 | − mulps m0, m4, [srcq ] | |
| 43 | − mulps m1, m5, [srcq+src1q ] | |
| 44 | − mulps m2, m4, [srcq+ mmsize] | |
| 45 | − mulps m3, m5, [srcq+src1q+mmsize] | |
| 46 | − addps m0, m0, m1 | |
| 47 | − addps m2, m2, m3 | |
| 48 | − mova [srcq ], m0 | |
| 49 | − mova [srcq+mmsize], m2 | |
| 50 | − add srcq, mmsize*2 | |
| 51 | − sub lend, mmsize*2/4 | |
| 52 | − jg .loop | |
| 53 | − REP_RET | |
| 54 | −%endmacro | |
| 55 | − | |
| 56 | −INIT_XMM sse | |
| 57 | −MIX_2_TO_1_FLTP_FLT | |
| 58 | −%if HAVE_AVX_EXTERNAL | |
| 59 | −INIT_YMM avx | |
| 60 | −MIX_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 | |
| 69 | −cglobal 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 | − | |
| 102 | −INIT_XMM sse2 | |
| 103 | −MIX_2_TO_1_S16P_FLT | |
| 104 | −INIT_XMM sse4 | |
| 105 | −MIX_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 | − | |
| 112 | −INIT_XMM sse2 | |
| 113 | −cglobal 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 | |
| 154 | −cglobal 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 | − | |
| 175 | −INIT_XMM sse | |
| 176 | −MIX_1_TO_2_FLTP_FLT | |
| 177 | −%if HAVE_AVX_EXTERNAL | |
| 178 | −INIT_YMM avx | |
| 179 | −MIX_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 | |
| 188 | −cglobal 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 | − | |
| 220 | −INIT_XMM sse2 | |
| 221 | −MIX_1_TO_2_S16P_FLT | |
| 222 | −INIT_XMM sse4 | |
| 223 | −MIX_1_TO_2_S16P_FLT | |
| 224 | −%if HAVE_AVX_EXTERNAL | |
| 225 | −INIT_XMM avx | |
| 226 | −MIX_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 | − | |
| 276 | −cglobal 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 | − | |
| 511 | −MIX_3_8_TO_1_2_FLT_FUNCS | |
| @@ -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 | − | |
| 26 | −void ff_mix_2_to_1_fltp_flt_sse(float **src, float **matrix, int len, | |
| 27 | − int out_ch, int in_ch); | |
| 28 | −void ff_mix_2_to_1_fltp_flt_avx(float **src, float **matrix, int len, | |
| 29 | − int out_ch, int in_ch); | |
| 30 | − | |
| 31 | −void ff_mix_2_to_1_s16p_flt_sse2(int16_t **src, float **matrix, int len, | |
| 32 | − int out_ch, int in_ch); | |
| 33 | −void ff_mix_2_to_1_s16p_flt_sse4(int16_t **src, float **matrix, int len, | |
| 34 | − int out_ch, int in_ch); | |
| 35 | − | |
| 36 | −void ff_mix_2_to_1_s16p_q8_sse2(int16_t **src, int16_t **matrix, | |
| 37 | − int len, int out_ch, int in_ch); | |
| 38 | − | |
| 39 | −void ff_mix_1_to_2_fltp_flt_sse(float **src, float **matrix, int len, | |
| 40 | − int out_ch, int in_ch); | |
| 41 | −void ff_mix_1_to_2_fltp_flt_avx(float **src, float **matrix, int len, | |
| 42 | − int out_ch, int in_ch); | |
| 43 | − | |
| 44 | −void ff_mix_1_to_2_s16p_flt_sse2(int16_t **src, float **matrix, int len, | |
| 45 | − int out_ch, int in_ch); | |
| 46 | −void ff_mix_1_to_2_s16p_flt_sse4(int16_t **src, float **matrix, int len, | |
| 47 | − int out_ch, int in_ch); | |
| 48 | −void 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) \ | |
| 52 | −void ff_mix_ ## chan ## _to_1_fltp_flt_sse(float **src, \ | |
| 53 | − float **matrix, int len, \ | |
| 54 | − int out_ch, int in_ch); \ | |
| 55 | −void ff_mix_ ## chan ## _to_2_fltp_flt_sse(float **src, \ | |
| 56 | − float **matrix, int len, \ | |
| 57 | − int out_ch, int in_ch); \ | |
| 58 | − \ | |
| 59 | −void ff_mix_ ## chan ## _to_1_s16p_flt_sse2(int16_t **src, \ | |
| 60 | − float **matrix, int len, \ | |
| 61 | − int out_ch, int in_ch); \ | |
| 62 | −void ff_mix_ ## chan ## _to_2_s16p_flt_sse2(int16_t **src, \ | |
| 63 | − float **matrix, int len, \ | |
| 64 | − int out_ch, int in_ch); \ | |
| 65 | − \ | |
| 66 | −void ff_mix_ ## chan ## _to_1_s16p_flt_sse4(int16_t **src, \ | |
| 67 | − float **matrix, int len, \ | |
| 68 | − int out_ch, int in_ch); \ | |
| 69 | −void ff_mix_ ## chan ## _to_2_s16p_flt_sse4(int16_t **src, \ | |
| 70 | − float **matrix, int len, \ | |
| 71 | − int out_ch, int in_ch); \ | |
| 72 | − \ | |
| 73 | −void ff_mix_ ## chan ## _to_1_fltp_flt_avx(float **src, \ | |
| 74 | − float **matrix, int len, \ | |
| 75 | − int out_ch, int in_ch); \ | |
| 76 | −void ff_mix_ ## chan ## _to_2_fltp_flt_avx(float **src, \ | |
| 77 | − float **matrix, int len, \ | |
| 78 | − int out_ch, int in_ch); \ | |
| 79 | − \ | |
| 80 | −void ff_mix_ ## chan ## _to_1_s16p_flt_avx(int16_t **src, \ | |
| 81 | − float **matrix, int len, \ | |
| 82 | − int out_ch, int in_ch); \ | |
| 83 | −void ff_mix_ ## chan ## _to_2_s16p_flt_avx(int16_t **src, \ | |
| 84 | − float **matrix, int len, \ | |
| 85 | − int out_ch, int in_ch); \ | |
| 86 | − \ | |
| 87 | −void ff_mix_ ## chan ## _to_1_fltp_flt_fma4(float **src, \ | |
| 88 | − float **matrix, int len, \ | |
| 89 | − int out_ch, int in_ch); \ | |
| 90 | −void ff_mix_ ## chan ## _to_2_fltp_flt_fma4(float **src, \ | |
| 91 | − float **matrix, int len, \ | |
| 92 | − int out_ch, int in_ch); \ | |
| 93 | − \ | |
| 94 | −void ff_mix_ ## chan ## _to_1_s16p_flt_fma4(int16_t **src, \ | |
| 95 | − float **matrix, int len, \ | |
| 96 | − int out_ch, int in_ch); \ | |
| 97 | −void ff_mix_ ## chan ## _to_2_s16p_flt_fma4(int16_t **src, \ | |
| 98 | − float **matrix, int len, \ | |
| 99 | − int out_ch, int in_ch); | |
| 100 | − | |
| 101 | −DEFINE_MIX_3_8_TO_1_2(3) | |
| 102 | −DEFINE_MIX_3_8_TO_1_2(4) | |
| 103 | −DEFINE_MIX_3_8_TO_1_2(5) | |
| 104 | −DEFINE_MIX_3_8_TO_1_2(6) | |
| 105 | −DEFINE_MIX_3_8_TO_1_2(7) | |
| 106 | −DEFINE_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 | − | |
| 174 | −av_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 | −} | |
| @@ -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 | − | |
| 24 | −SECTION_RODATA 32 | |
| 25 | − | |
| 26 | −; 1.0f / (2.0f * INT32_MAX) | |
| 27 | −pf_dither_scale: times 8 dd 2.32830643762e-10 | |
| 28 | − | |
| 29 | −pf_s16_scale: times 4 dd 32753.0 | |
| 30 | − | |
| 31 | −SECTION .text | |
| 32 | − | |
| 33 | −;------------------------------------------------------------------------------ | |
| 34 | −; void ff_quantize(int16_t *dst, float *src, float *dither, int len); | |
| 35 | −;------------------------------------------------------------------------------ | |
| 36 | − | |
| 37 | −INIT_XMM sse2 | |
| 38 | −cglobal 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 | |
| 63 | −cglobal 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 | − | |
| 81 | −INIT_XMM sse2 | |
| 82 | −DITHER_INT_TO_FLOAT_RECTANGULAR | |
| 83 | −INIT_YMM avx | |
| 84 | −DITHER_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 | |
| 91 | −cglobal 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 | − | |
| 114 | −INIT_XMM sse2 | |
| 115 | −DITHER_INT_TO_FLOAT_TRIANGULAR | |
| 116 | −INIT_YMM avx | |
| 117 | −DITHER_INT_TO_FLOAT_TRIANGULAR | |
| @@ -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 | − | |
| 26 | −void ff_quantize_sse2(int16_t *dst, const float *src, float *dither, int len); | |
| 27 | − | |
| 28 | −void ff_dither_int_to_float_rectangular_sse2(float *dst, int *src, int len); | |
| 29 | −void ff_dither_int_to_float_rectangular_avx(float *dst, int *src, int len); | |
| 30 | − | |
| 31 | −void ff_dither_int_to_float_triangular_sse2(float *dst, int *src0, int len); | |
| 32 | −void ff_dither_int_to_float_triangular_avx(float *dst, int *src0, int len); | |
| 33 | − | |
| 34 | −av_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 | −} | |
| @@ -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 | |
| @@ -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 | − | |
| 25 | −wrap(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 | −} | |
| @@ -157,7 +157,6 @@ include $(SRC_PATH)/tests/fate/indeo.mak · 156 unmodified lines | ||
| 157 | 157 | include $(SRC_PATH)/tests/fate/libavcodec.mak |
| 158 | 158 | include $(SRC_PATH)/tests/fate/libavdevice.mak |
| 159 | 159 | include $(SRC_PATH)/tests/fate/libavformat.mak |
| 160 | −include $(SRC_PATH)/tests/fate/libavresample.mak | |
| 161 | 160 | include $(SRC_PATH)/tests/fate/libavutil.mak |
| 162 | 161 | include $(SRC_PATH)/tests/fate/libswresample.mak |
| 163 | 162 | include $(SRC_PATH)/tests/fate/libswscale.mak |
| @@ -48,7 +48,6 @@ configure()( · 47 unmodified lines | ||
| 48 | 48 | --samples="${samples}" \ |
| 49 | 49 | --enable-gpl \ |
| 50 | 50 | --enable-memory-poisoning \ |
| 51 | − --enable-avresample \ | |
| 52 | 51 | ${ignore_tests:+--ignore-tests="$ignore_tests"} \ |
| 53 | 52 | ${arch:+--arch=$arch} \ |
| 54 | 53 | ${cpu:+--cpu="$cpu"} \ |
| @@ -1,68 +0,0 @@ | ||
| 1 | −CROSS_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 | − | |
| 7 | −MIX_CHANNELS = 1 2 3 4 5 6 7 8 | |
| 8 | − | |
| 9 | −define MIX | |
| 10 | −FATE_LAVR_MIX += fate-lavr-mix-$(3)-$(1)-$(2) | |
| 11 | −fate-lavr-mix-$(3)-$(1)-$(2): tests/data/asynth-44100-$(1).wav | |
| 12 | −fate-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 - | |
| 13 | −fate-lavr-mix-$(3)-$(1)-$(2): CMP = oneoff | |
| 14 | −fate-lavr-mix-$(3)-$(1)-$(2): REF = $(SAMPLES)/lavr/lavr-mix-$(3)-$(1)-$(2) | |
| 15 | −endef | |
| 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 | |
| 22 | −FATE_LAVR_MIX-$(call FILTERDEMDECENCMUX, CHANNELMAP RESAMPLE, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-lavr-mix-output-zero | |
| 23 | −fate-lavr-mix-output-zero: tests/data/filtergraphs/lavr_mix_output_zero tests/data/asynth-44100-4.wav | |
| 24 | −fate-lavr-mix-output-zero: CMP = oneoff | |
| 25 | −fate-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 - | |
| 26 | −fate-lavr-mix-output-zero: REF = $(SAMPLES)/lavr/lavr-mix-output-zero | |
| 27 | − | |
| 28 | −FATE_LAVR_MIX-$(call FILTERDEMDECENCMUX, RESAMPLE, WAV, PCM_S16LE, PCM_S16LE, WAV) += $(FATE_LAVR_MIX) | |
| 29 | −fate-lavr-mix: $(FATE_LAVR_MIX-yes) | |
| 30 | −#FATE_LAVR += $(FATE_LAVR_MIX-yes) | |
| 31 | − | |
| 32 | −SAMPLERATES = 2626 8000 44100 48000 96000 | |
| 33 | − | |
| 34 | −define RESAMPLE | |
| 35 | −FATE_LAVR_RESAMPLE += fate-lavr-resample-$(3)-$(1)-$(2) | |
| 36 | −fate-lavr-resample-$(3)-$(1)-$(2): tests/data/asynth-$(1)-1.wav | |
| 37 | −fate-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 - | |
| 38 | −fate-lavr-resample-$(3)-$(1)-$(2): CMP = oneoff | |
| 39 | −fate-lavr-resample-$(3)-$(1)-$(2): CMP_UNIT = $(5) | |
| 40 | −fate-lavr-resample-$(3)-$(1)-$(2): FUZZ = 6 | |
| 41 | −fate-lavr-resample-$(3)-$(1)-$(2): REF = $(SAMPLES)/lavr/lavr-resample-$(3)-$(1)-$(2)-v3 | |
| 42 | −endef | |
| 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 | − | |
| 49 | −FATE_LAVR_RESAMPLE += fate-lavr-resample-linear | |
| 50 | −fate-lavr-resample-linear: tests/data/asynth-44100-1.wav | |
| 51 | −fate-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 - | |
| 52 | −fate-lavr-resample-linear: CMP = oneoff | |
| 53 | −fate-lavr-resample-linear: CMP_UNIT = s16 | |
| 54 | −fate-lavr-resample-linear: REF = $(SAMPLES)/lavr/lavr-resample-linear | |
| 55 | − | |
| 56 | −FATE_LAVR_RESAMPLE += fate-lavr-resample-nearest | |
| 57 | −fate-lavr-resample-nearest: tests/data/asynth-48000-1.wav | |
| 58 | −fate-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 - | |
| 59 | −fate-lavr-resample-nearest: CMP = oneoff | |
| 60 | −fate-lavr-resample-nearest: CMP_UNIT = s16 | |
| 61 | −fate-lavr-resample-nearest: REF = $(SAMPLES)/lavr/lavr-resample-nearest | |
| 62 | − | |
| 63 | −FATE_LAVR_RESAMPLE-$(call FILTERDEMDECENCMUX, RESAMPLE, WAV, PCM_S16LE, PCM_S16LE, WAV) += $(FATE_LAVR_RESAMPLE) | |
| 64 | −fate-lavr-resample: $(FATE_LAVR_RESAMPLE-yes) | |
| 65 | −#FATE_LAVR += $(FATE_LAVR_RESAMPLE-yes) | |
| 66 | − | |
| 67 | −FATE_SAMPLES_AVCONV += $(FATE_LAVR) | |
| 68 | −fate-lavr: $(FATE_LAVR) | |
| @@ -43,7 +43,6 @@ EOF · 42 unmodified lines | ||
| 43 | 43 | # gen-rc libavdevice "FFmpeg device handling library" |
| 44 | 44 | # gen-rc libavfilter "FFmpeg audio/video filtering library" |
| 45 | 45 | # gen-rc libpostproc "FFmpeg postprocessing library" |
| 46 | −# gen-rc libavresample "Libav audio resampling library" | |
| 47 | 46 | # gen-rc libswscale "FFmpeg image rescaling library" |
| 48 | 47 | # gen-rc libswresample "FFmpeg audio resampling library" |
| 49 | 48 | |
| @@ -30,7 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | * build the fuzz target. |
| 31 | 31 | Choose the value of FFMPEG_CODEC (e.g. AV_CODEC_ID_DVD_SUBTITLE) and |
| 32 | 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 -pthread | |
| 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 -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 | 34 | * create a corpus directory and put some samples there (empty dir is ok too): |
| 35 | 35 | mkdir CORPUS && cp some-files CORPUS |
| 36 | 36 | |