1/* 2 * Audio resampling 3 * 4 * Copyright (c) 2004-2012 Michael Niedermayer <michaelni@gmx.at> 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 "config.h" 24 25#include "libavutil/attributes.h" 26#include "libavutil/cpu.h" 27#include "libavutil/avassert.h" 28 29#include "libavutil/aarch64/cpu.h" 30#include "libswresample/resample.h" 31 32#define DECLARE_RESAMPLE_COMMON_TEMPLATE(TYPE, DELEM, FELEM, FELEM2, OUT) \ 33 \ 34void ff_resample_common_apply_filter_x4_##TYPE##_neon(FELEM2 *acc, const DELEM *src, \ 35 const FELEM *filter, int length); \ 36 \ 37void ff_resample_common_apply_filter_x8_##TYPE##_neon(FELEM2 *acc, const DELEM *src, \ 38 const FELEM *filter, int length); \ 39 \ 40static int ff_resample_common_##TYPE##_neon(ResampleContext *c, void *dest, const void *source, \ 41 int n, int update_ctx) \ 42{ \ 43 DELEM *dst = dest; \ 44 const DELEM *src = source; \ 45 int dst_index; \ 46 int index = c->index; \ 47 int frac = c->frac; \ 48 int sample_index = 0; \ 49 int x4_aligned_filter_length = c->filter_length & ~3; \ 50 int x8_aligned_filter_length = c->filter_length & ~7; \ 51 \ 52 while (index >= c->phase_count) { \ 53 sample_index++; \ 54 index -= c->phase_count; \ 55 } \ 56 \ 57 for (dst_index = 0; dst_index < n; dst_index++) { \ 58 FELEM *filter = ((FELEM *) c->filter_bank) + c->filter_alloc * index; \ 59 \ 60 FELEM2 val = 0; \ 61 int i = 0; \ 62 if (x8_aligned_filter_length >= 8) { \ 63 ff_resample_common_apply_filter_x8_##TYPE##_neon(&val, &src[sample_index], \ 64 filter, x8_aligned_filter_length); \ 65 i += x8_aligned_filter_length; \ 66 \ 67 } else if (x4_aligned_filter_length >= 4) { \ 68 ff_resample_common_apply_filter_x4_##TYPE##_neon(&val, &src[sample_index], \ 69 filter, x4_aligned_filter_length); \ 70 i += x4_aligned_filter_length; \ 71 } \ 72 for (; i < c->filter_length; i++) { \ 73 val += src[sample_index + i] * (FELEM2)filter[i]; \ 74 } \ 75 OUT(dst[dst_index], val); \ 76 \ 77 frac += c->dst_incr_mod; \ 78 index += c->dst_incr_div; \ 79 if (frac >= c->src_incr) { \ 80 frac -= c->src_incr; \ 81 index++; \ 82 } \ 83 \ 84 while (index >= c->phase_count) { \ 85 sample_index++; \ 86 index -= c->phase_count; \ 87 } \ 88 } \ 89 \ 90 if (update_ctx) { \ 91 c->frac = frac; \ 92 c->index = index; \ 93 } \ 94 \ 95 return sample_index; \ 96} \ 97 98#define OUT(d, v) d = v 99DECLARE_RESAMPLE_COMMON_TEMPLATE(float, float, float, float, OUT) 100#undef OUT 101 102#define OUT(d, v) (v) = ((v) + (1<<(14)))>>15; (d) = av_clip_int16(v) 103DECLARE_RESAMPLE_COMMON_TEMPLATE(s16, int16_t, int16_t, int32_t, OUT) 104#undef OUT 105 106av_cold void swri_resample_dsp_aarch64_init(ResampleContext *c) 107{ 108 int cpu_flags = av_get_cpu_flags(); 109 110 if (!have_neon(cpu_flags)) 111 return; 112 113 switch(c->format) { 114 case AV_SAMPLE_FMT_FLTP: 115 c->dsp.resample_common = ff_resample_common_float_neon; 116 break; 117 case AV_SAMPLE_FMT_S16P: 118 c->dsp.resample_common = ff_resample_common_s16_neon; 119 break; 120 } 121} 122